merge the formfield patch from ooo-build
[ooovba.git] / vcl / unx / source / gdi / xfont.cxx
blob09c879b297e575bea509b77b9e5735a21bf0e8aa
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: xfont.cxx,v $
10 * $Revision: 1.51 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
34 #include <salunx.h>
35 #include "xfont.hxx"
36 #include "xlfd_extd.hxx"
37 #include "salcvt.hxx"
38 #include <tools/string.hxx>
39 #include <vcl/outfont.hxx>
40 #include <saldisp.hxx>
41 #include <salgdi.h>
43 // for GetMirroredChar
44 #include <vcl/svapp.hxx>
46 #if OSL_DEBUG_LEVEL > 1
47 #include <cstdio>
48 #endif
50 #include <algorithm>
52 #define VCLASS_ROTATE 0
53 #define VCLASS_ROTATE_REVERSE 1
54 #define VCLASS_TRANSFORM1 2
55 #define VCLASS_TRANSFORM2 3
56 #define VCLASS_CJK 4
57 #define VCLASS_DONTKNOW 5
58 #define VCLASS_FONT_NUM 2 // Other than rotate and rotate_reverse,
59 // don't have spacial font
61 // Select the max size of a font, which is token for real
62 // This routine is (and should be) called only once, the result should be
63 // stored in some static variable
65 static int GetMaxFontHeight()
67 static int nMaxFontHeight = 0;
68 if( nMaxFontHeight <= 0 )
70 const char *pFontHeight = getenv ("SAL_MAXFONTHEIGHT");
71 if( pFontHeight )
72 nMaxFontHeight = atoi( pFontHeight );
73 static const int DEFAULT_MAXFONTHEIGHT = 250;
74 if (nMaxFontHeight <= 20)
75 nMaxFontHeight = DEFAULT_MAXFONTHEIGHT;
78 return nMaxFontHeight;
82 ExtendedFontStruct::ExtendedFontStruct( Display* pDisplay, const Size& rPixelSize,
83 sal_Bool bVertical, ExtendedXlfd* pXlfd ) :
84 mpDisplay( pDisplay ),
85 maPixelSize( rPixelSize ),
86 mfXScale(1.0), mfYScale(1.0),
87 mbVertical( bVertical ),
88 mnCachedEncoding( RTL_TEXTENCODING_DONTKNOW ),
89 mpXlfd( pXlfd ),
90 mpRangeCodes(NULL),
91 mnRangeCount(-1)
93 if( !maPixelSize.Width() )
94 maPixelSize.Width() = maPixelSize.Height();
95 mnAsciiEncoding = GetAsciiEncoding (NULL);
96 mnDefaultWidth = GetDefaultWidth();
98 mpXFontStruct = (XFontStruct**)calloc( mpXlfd->NumEncodings(),
99 sizeof(XFontStruct*) );
102 ExtendedFontStruct::~ExtendedFontStruct()
104 delete[] mpRangeCodes;
106 for ( int nIdx = 0; nIdx < mpXlfd->NumEncodings(); nIdx++ )
107 if ( mpXFontStruct[nIdx] != NULL )
108 XFreeFont( mpDisplay, mpXFontStruct[nIdx] );
110 free(mpXFontStruct);
113 rtl_TextEncoding
114 ExtendedFontStruct::GetAsciiEncoding( int *pAsciiRange ) const
116 return mpXlfd->GetAsciiEncoding( pAsciiRange );
119 FontPitch
120 ExtendedFontStruct::GetSpacing( rtl_TextEncoding nEncoding )
122 return mpXlfd->GetPitch( nEncoding );
125 static XFontStruct*
126 LoadXFont (Display* pDisplay, const char* pFontName)
128 XFontStruct* pFont = XLoadQueryFont (pDisplay, pFontName);
129 if ((pFont != NULL) && (pFont->fid == 0))
130 pFont->fid = XLoadFont(pDisplay, pFontName);
132 #ifdef HDU_DEBUG
133 fprintf( stderr, "XLoadFont \"%s\" => %d\n", pFontName, (pFont!= NULL) );
134 #endif
135 return pFont;
139 ExtendedFontStruct::LoadEncoding( rtl_TextEncoding nEncoding )
141 int nIdx = mpXlfd->GetEncodingIdx( nEncoding );
142 if ( (nIdx < 0) || (mpXFontStruct[ nIdx ] != NULL) )
143 return nIdx;
145 // limit font height that gets requested from the XServer
146 // see BugId #44528# FontWork (-> #45038#) and as well Bug #47127#
147 int nReqPixelHeight = maPixelSize.Height();
148 if( nReqPixelHeight > GetMaxFontHeight() )
149 nReqPixelHeight = GetMaxFontHeight();
150 else if( nReqPixelHeight < 2 )
151 nReqPixelHeight = 2;
153 // get the X11 font from a matching XLFD
154 ByteString aFontName;
155 mpXlfd->ToString( aFontName, nReqPixelHeight, nEncoding );
156 mpXFontStruct[ nIdx ] = LoadXFont( mpDisplay, aFontName.GetBuffer() );
157 if (mpXFontStruct[nIdx] == NULL)
158 mpXFontStruct[nIdx] = LoadXFont( mpDisplay, "fixed" );
160 // calculate correction factors to improve matching
161 // the selected font size to the used bitmap font
162 int nRealPixelSize = mpXlfd->GetPixelSize();
163 if( !nRealPixelSize ) // check for scalable mpXlfd
164 nRealPixelSize = nReqPixelHeight;
165 if( nRealPixelSize && (nRealPixelSize != maPixelSize.Width()) )
166 mfXScale = (float)maPixelSize.Width() / nRealPixelSize;
167 if( nRealPixelSize && (nRealPixelSize != maPixelSize.Height()) )
168 mfYScale = (float)maPixelSize.Height() / nRealPixelSize;
170 return nIdx;
173 XFontStruct*
174 ExtendedFontStruct::GetFontStruct( rtl_TextEncoding nEncoding )
176 int nIdx = LoadEncoding( nEncoding );
177 return nIdx < 0 ? NULL : mpXFontStruct[nIdx] ;
180 bool
181 ExtendedFontStruct::GetFontBoundingBox( XCharStruct *pCharStruct,
182 int *pAscent, int *pDescent )
184 pCharStruct->lbearing = 0;
185 pCharStruct->rbearing = 0;
186 pCharStruct->width = 0;
187 pCharStruct->ascent = 0;
188 pCharStruct->descent = 0;
190 *pAscent = 0;
191 *pDescent = 0;
193 int nIdx;
195 // check if there is at least one encoding already loaded
196 bool bEmpty = true;
197 for ( nIdx = 0; nIdx < mpXlfd->NumEncodings(); nIdx++ )
198 bEmpty &= (mpXFontStruct[nIdx] == NULL);
199 if ( bEmpty )
200 LoadEncoding( mpXlfd->GetAsciiEncoding() );
202 // get the max bounding box from all font structs
203 for ( nIdx = 0; nIdx < mpXlfd->NumEncodings(); nIdx++ )
204 if ( mpXFontStruct[ nIdx ] != NULL )
206 *pAscent = std::max( mpXFontStruct[nIdx]->ascent, *pAscent );
207 *pDescent = std::max( mpXFontStruct[nIdx]->descent, *pDescent );
209 XCharStruct* pMaxBounds = &(mpXFontStruct[nIdx]->max_bounds);
211 pCharStruct->lbearing = std::max( pMaxBounds->lbearing,
212 pCharStruct->lbearing );
213 pCharStruct->rbearing = std::max( pMaxBounds->rbearing,
214 pCharStruct->rbearing );
215 pCharStruct->width = std::max( pMaxBounds->width,
216 pCharStruct->width );
217 pCharStruct->ascent = std::max( pMaxBounds->ascent,
218 pCharStruct->ascent );
219 pCharStruct->descent = std::max( pMaxBounds->descent,
220 pCharStruct->descent );
223 // apply correction factors to better match selected size to available size
224 if( mfYScale != 1.0 )
226 *pAscent = int(*pAscent * mfYScale);
227 *pDescent = int(*pDescent * mfYScale);
228 pCharStruct->ascent = (short int)(pCharStruct->ascent * mfYScale);
229 pCharStruct->descent = (short int)(pCharStruct->descent * mfYScale);
231 if( mfXScale != 1.0 )
233 pCharStruct->lbearing = (short int)(pCharStruct->lbearing * mfXScale);
234 pCharStruct->rbearing = (short int)(pCharStruct->rbearing * mfXScale);
235 pCharStruct->width = (short int)(pCharStruct->width * mfXScale);
238 return (pCharStruct->width > 0);
241 bool
242 ExtendedFontStruct::ToImplFontMetricData(ImplFontMetricData *pFontMetric)
244 pFontMetric->mnOrientation = 0;
245 pFontMetric->mnSlant = 0;
246 pFontMetric->mbDevice = true;
247 pFontMetric->mbScalableFont = mpXlfd->IsScalable();
248 pFontMetric->mbKernableFont = false;
249 pFontMetric->mbSymbolFlag= mpXlfd->IsSymbolFont();
250 pFontMetric->meFamily = mpXlfd->GetFamilyType();
251 pFontMetric->meWeight = mpXlfd->GetWeight();
252 pFontMetric->mePitch = mpXlfd->GetPitch();
253 pFontMetric->meItalic = mpXlfd->GetSlant();
255 int nAscent, nDescent;
256 XCharStruct aBoundingBox;
257 if ( GetFontBoundingBox(&aBoundingBox, &nAscent, &nDescent) )
259 pFontMetric->mnWidth = aBoundingBox.width;
260 pFontMetric->mnAscent = aBoundingBox.ascent;
261 pFontMetric->mnDescent = aBoundingBox.descent;
262 pFontMetric->mnIntLeading = std::max(0, aBoundingBox.ascent - nAscent
263 + aBoundingBox.descent - nDescent );
264 pFontMetric->mnExtLeading = 0; // TODO!!!
265 return true;
267 else
269 return false;
273 bool
274 ExtendedFontStruct::Match( const ExtendedXlfd *pXlfd,
275 const Size& rPixelSize, sal_Bool bVertical ) const
277 if( mpXlfd != pXlfd )
278 return false;
280 if( bVertical != mbVertical )
281 return FALSE;
283 if( rPixelSize.Height() != maPixelSize.Height() )
284 return FALSE;
286 long nReqWidth = rPixelSize.Width();
287 if( !nReqWidth )
288 nReqWidth = rPixelSize.Height();
289 if( nReqWidth != maPixelSize.Width() )
290 return FALSE;
292 return true;
295 // Get an appropriate x-font that contains a glyph for the given unicode
296 // code point.
297 // This routine is designed to be called for each character in a text.
298 // It first checks the given encoding to optimize for the fact that two
299 // adjacent characters in a text most probably have the same encoding
300 // In the first call initialize pEncodingInOut to dontknow, this causes
301 // EncodingHasChar() to fail and thus bootstraps the encoding, otherwise
302 // make sure that the initial value of pFontInOut matches the encoding and
303 // that the encoding is valid for the font.
304 XFontStruct*
305 ExtendedFontStruct::GetFontStruct( sal_Unicode nChar, rtl_TextEncoding *pEncoding )
307 SalConverterCache *pCvt = SalConverterCache::GetInstance();
309 if ( pCvt->EncodingHasChar(mnAsciiEncoding, nChar) )
311 *pEncoding = mnAsciiEncoding;
312 return GetFontStruct (mnAsciiEncoding);
314 else
315 if ( pCvt->EncodingHasChar(mnCachedEncoding, nChar) )
317 *pEncoding = mnCachedEncoding;
318 return GetFontStruct (mnCachedEncoding);
320 else
322 for ( int nIdx = 0; nIdx < mpXlfd->NumEncodings(); nIdx++ )
324 rtl_TextEncoding nEnc = mpXlfd->GetEncoding(nIdx);
325 if ( (nEnc != mnCachedEncoding) && (nEnc != mnAsciiEncoding)
326 && pCvt->EncodingHasChar(nEnc, nChar))
328 mnCachedEncoding = nEnc;
329 *pEncoding = mnCachedEncoding;
330 return GetFontStruct (mnCachedEncoding);
335 *pEncoding = RTL_TEXTENCODING_DONTKNOW;
336 return NULL;
339 // ---------------------------------------------------------------------------
340 // utility functions to handle xfontstruct information, this is all to
341 // calculate charwidth information
342 // ---------------------------------------------------------------------------
344 static bool
345 CharExists( const XCharStruct* pChar )
347 if ( pChar == NULL )
348 return false;
350 return pChar->width
351 || pChar->ascent || pChar->descent
352 || pChar->lbearing || pChar->rbearing;
355 // this relies on non-null per_char information in the fontstruct
356 static XCharStruct*
357 GetCharinfo( const XFontStruct *pXFontStruct, sal_MultiByte nChar )
359 unsigned int nRow = nChar >> 8;
360 unsigned int nCol = nChar & 0xFF;
362 unsigned int nMinRow = pXFontStruct->min_byte1;
363 unsigned int nMaxRow = pXFontStruct->max_byte1;
364 unsigned int nMinCol = pXFontStruct->min_char_or_byte2;
365 unsigned int nMaxCol = pXFontStruct->max_char_or_byte2;
367 if ( nRow >= nMinRow && nRow <= nMaxRow
368 && nCol >= nMinCol && nCol <= nMaxCol )
370 return &pXFontStruct->per_char[
371 (nRow-nMinRow) * (nMaxCol-nMinCol+1) + (nCol-nMinCol) ];
374 return NULL;
377 static sal_Size
378 QueryCharWidth16( Display* pDisplay, XLIB_Font nFontID, sal_MultiByte nChar,
379 sal_Size nDefaultWidth )
381 int nDirection, nFontAscent, nFontDescent;
382 XCharStruct aBoundingBox;
384 XQueryTextExtents16( pDisplay, nFontID, (XChar2b*)&nChar, 1,
385 &nDirection, &nFontAscent, &nFontDescent, &aBoundingBox );
387 return CharExists( &aBoundingBox ) ? aBoundingBox.width : nDefaultWidth;
390 #if 0
391 // currently not used
392 static sal_Size
393 QueryCharWidth8( XFontStruct* pXFontStruct, sal_Char nChar,
394 sal_Size nDefaultWidth )
396 int nDirection, nFontAscent, nFontDescent;
397 XCharStruct aBoundingBox;
399 XTextExtents( pXFontStruct, &nChar, 1,
400 &nDirection, &nFontAscent, &nFontDescent, &aBoundingBox );
402 return CharExists( &aBoundingBox ) ? aBoundingBox.width : nDefaultWidth;
404 #endif
406 sal_Size
407 ExtendedFontStruct::GetDefaultWidth()
409 return (maPixelSize.Width() + 1) / 2;
412 // Handle single byte fonts which do not require conversion, this exploits
413 // the fact that unicode equals latin1 or ansi1252 in the range [0..0xff] and
414 // is compatible with iso8859-X at least in the range to 0x7f
415 sal_Size
416 ExtendedFontStruct::GetCharWidth8( sal_Unicode nFrom, sal_Unicode nTo,
417 sal_Int32* pWidthArray, rtl_TextEncoding nEncoding )
419 if ( !(nFrom <= nTo) )
420 return 0;
422 XFontStruct* pXFontStruct = GetFontStruct( nEncoding );
423 if ( pXFontStruct == NULL )
424 return 0;
426 // query the font metrics
427 if ( (pXFontStruct->max_bounds.width == pXFontStruct->min_bounds.width)
428 || (pXFontStruct->per_char == NULL) )
430 // fixed width font
431 for ( int nIdx = nFrom; nIdx <= nTo; nIdx++, pWidthArray++ )
432 *pWidthArray = pXFontStruct->max_bounds.width;
434 else
436 // variable width font
437 int nMinChar = pXFontStruct->min_char_or_byte2;
438 int nMaxChar = pXFontStruct->max_char_or_byte2;
440 int nIdx = nFrom;
442 for ( ; nIdx < std::min((int)nTo, nMinChar); nIdx++, pWidthArray++ )
443 *pWidthArray = mnDefaultWidth;
444 for ( ; nIdx <= std::min((int)nTo, nMaxChar); nIdx++, pWidthArray++ )
446 XCharStruct* pChar = &(pXFontStruct->per_char[nIdx - nMinChar]);
447 *pWidthArray = CharExists(pChar) ? pChar->width : mnDefaultWidth;
449 for ( ; nIdx <= nTo; nIdx++, pWidthArray++ )
450 *pWidthArray = mnDefaultWidth;
453 // return amount of handled chars
454 return nTo - nFrom + 1;
457 // Handle utf16 encoded fonts, which do not require conversion
458 sal_Size
459 ExtendedFontStruct::GetCharWidthUTF16( sal_Unicode nFrom, sal_Unicode nTo,
460 sal_Int32* pWidthArray )
462 if ( !(nFrom <= nTo) )
463 return 0;
465 XFontStruct* pXFontStruct = GetFontStruct( RTL_TEXTENCODING_UNICODE );
466 FontPitch nSpacing = mpXlfd->GetPitch( RTL_TEXTENCODING_UNICODE );
468 if ( pXFontStruct == NULL )
469 return 0;
471 // query the font metrics
472 if ( nSpacing == PITCH_VARIABLE
473 && pXFontStruct->per_char == NULL)
475 // get per_char information from the server
476 for ( sal_Int32 nIdx = nFrom; nIdx <= nTo; nIdx++, pWidthArray++ )
477 *pWidthArray = QueryCharWidth16( mpDisplay, pXFontStruct->fid,
478 nIdx, mnDefaultWidth );
480 else
481 if ( (pXFontStruct->max_bounds.width == pXFontStruct->min_bounds.width)
482 || (pXFontStruct->per_char == NULL) )
484 // really a fixed width font
485 for ( sal_Int32 nIdx = nFrom; nIdx <= nTo; nIdx++, pWidthArray++ )
486 *pWidthArray = pXFontStruct->max_bounds.width;
488 else
490 // get per_char information from the xfontstruct
491 for ( sal_Int32 nIdx = nFrom; nIdx <= nTo; nIdx++, pWidthArray++ )
493 XCharStruct* pChar = GetCharinfo( pXFontStruct, nIdx );
494 *pWidthArray = CharExists(pChar) ? pChar->width : mnDefaultWidth;
498 // return amount of handled chars
499 return nTo - nFrom + 1;
502 // handle non unicode fonts that are converted into encoding matching the
503 // font in fontstruct, 8 and 16 bit fonts are handled the same way
504 sal_Size
505 ExtendedFontStruct::GetCharWidth16( sal_Unicode nFrom, sal_Unicode nTo,
506 sal_Int32* pWidthArray, ExtendedFontStruct *pFallback )
508 if ( nFrom > nTo )
509 return 0;
511 sal_Char pBuffer[64];
513 SalConverterCache *pCvt = SalConverterCache::GetInstance();
514 for ( sal_Int32 nIdx = nFrom ; nIdx <= nTo ; nIdx++, pWidthArray++ )
516 FontPitch nSpacing;
517 sal_Size nSize;
518 sal_Unicode nUniIdx = (sal_Unicode)nIdx;
520 // get a matching fontstruct
521 rtl_TextEncoding nEnc;
522 XFontStruct *pFont;
524 if ( (pFont = GetFontStruct(nUniIdx, &nEnc)) != NULL )
526 nSpacing = GetSpacing( nEnc );
528 else
529 if ( (pFallback != NULL)
530 && ((pFont = pFallback->GetFontStruct(nUniIdx, &nEnc)) != NULL) )
532 nSpacing = pFallback->GetSpacing( nEnc );
534 else
535 if ( (pFallback != NULL)
536 && ((pFont = pFallback->GetFontStruct(nUniIdx = '?', &nEnc)) != NULL) )
538 nSpacing = pFallback->GetSpacing( nEnc );
540 else
542 // TODO What should the default value be?
543 nSpacing = PITCH_FIXED;
546 if ( pFont )
548 nSize = pCvt->ConvertStringUTF16(&nUniIdx, 1, pBuffer, sizeof(pBuffer), nEnc);
549 // XXX FIXME
550 if ((nEnc == RTL_TEXTENCODING_GB_2312) || (nEnc == RTL_TEXTENCODING_EUC_KR))
552 for (unsigned int n_char = 0; n_char < nSize; n_char++ )
553 pBuffer[ n_char ] &= 0x7F;
557 // query font metrics
558 if ( pFont && (nSize == 1 || nSize == 2) )
560 sal_MultiByte nChar = (nSize == 1) ? (unsigned char)pBuffer[0] :
561 ((sal_MultiByte)pBuffer[0] << 8) + (sal_MultiByte)pBuffer[1];
563 if ( nSpacing == PITCH_VARIABLE
564 && pFont->per_char == NULL)
566 // get per_char information from the x-server
567 *pWidthArray = QueryCharWidth16( mpDisplay, pFont->fid,
568 nChar, mnDefaultWidth );
570 else
571 if ( (pFont->max_bounds.width == pFont->min_bounds.width)
572 || (pFont->per_char == NULL) )
574 // fixed width font
575 *pWidthArray = pFont->max_bounds.width;
577 else
579 // get per_char information from the xfontstruct
580 XCharStruct* pChar = GetCharinfo( pFont, nChar );
581 *pWidthArray = CharExists(pChar) ? pChar->width : mnDefaultWidth;
584 else
586 // conversion error
587 *pWidthArray = mnDefaultWidth;
591 // return amount of handled chars
592 return nTo - nFrom + 1;
595 sal_Size
596 ExtendedFontStruct::GetCharWidth( sal_Unicode cChar, sal_Int32 *pPhysicalWidth,
597 sal_Int32 *pLogicalWidth )
599 sal_Size nConverted = 0;
601 // dispatch querying of metrics to most promising encoding candidate
602 int nAsciiRange;
603 rtl_TextEncoding nEncoding = mpXlfd->GetAsciiEncoding(&nAsciiRange);
604 if ( nEncoding == RTL_TEXTENCODING_UNICODE )
606 // if we have a unicode encoded system font than we get the charwidth
607 // straight forward
608 nConverted = GetCharWidthUTF16( cChar, cChar, pPhysicalWidth );
610 else
612 if ( cChar < nAsciiRange )
614 // optimize the most frequent case, requesting only the latin1
615 // chars which are mappable to a single encoding
616 nConverted = GetCharWidth8( cChar, cChar, pPhysicalWidth, nEncoding );
619 // if further requests are pending, then the according unicode
620 // codepoint has to be dispatched to one of the system fonts and
621 // converted to this fonts encoding
622 nConverted += GetCharWidth16( cChar + nConverted, cChar,
623 pPhysicalWidth + nConverted, NULL );
626 // convert physical width to logical width, apply correction factor if needed
627 *pLogicalWidth = *pPhysicalWidth;
628 if( mfXScale != 1.0 )
629 *pLogicalWidth = sal_Int32(*pLogicalWidth * mfXScale);
631 return nConverted;
634 bool ExtendedFontStruct::HasUnicodeChar( sal_Unicode cChar ) const
636 // #i18818# return false if there are no known encodings
637 if( !mnRangeCount )
638 return false;
640 // init unicode range cache if needed
641 if( mnRangeCount < 0 )
643 mnRangeCount = mpXlfd->GetFontCodeRanges( NULL );
644 if( !mnRangeCount )
645 return false;
646 mpRangeCodes = new sal_uInt32[ 2*mnRangeCount ];
647 mpXlfd->GetFontCodeRanges( mpRangeCodes );
648 // TODO: make sure everything is sorted
651 // binary search in unicode ranges
652 int nLower = 0;
653 int nMid = mnRangeCount;
654 int nUpper = 2 * mnRangeCount - 1;
655 while( nLower < nUpper )
657 if( cChar >= mpRangeCodes[ nMid ] )
658 nLower = nMid;
659 else
660 nUpper = nMid - 1;
661 nMid = (nLower + nUpper + 1) / 2;
663 if( (nMid == 0) && (cChar < mpRangeCodes[0]) )
664 return false;
665 return (nMid & 1) ? false: true;
668 int ExtendedFontStruct::GetFontCodeRanges( sal_uInt32* pCodePairs ) const
670 // make sure unicode range cache is initialized
671 HasUnicodeChar(0);
673 // transfer range pairs if requested
674 if( pCodePairs )
676 for( int i = 0; i < 2*mnRangeCount; ++i )
677 pCodePairs[i] = mpRangeCodes[i];
680 return mnRangeCount;
683 // =======================================================================
685 X11FontLayout::X11FontLayout( ExtendedFontStruct& rFont )
686 : mrFont( rFont )
689 // -----------------------------------------------------------------------
691 bool X11FontLayout::LayoutText( ImplLayoutArgs& rArgs )
693 Point aNewPos( 0, 0 );
694 bool bRightToLeft;
695 int nCharPos;
697 for( nCharPos = -1; rArgs.GetNextPos( &nCharPos, &bRightToLeft ); )
699 sal_UCS4 cChar = rArgs.mpStr[ nCharPos ];
700 if( bRightToLeft )
701 cChar = GetMirroredChar( cChar );
702 int nGlyphIndex = cChar | GF_ISCHAR;
704 // check if the font supports the char
705 if( !mrFont.HasUnicodeChar( cChar ) )
707 // try to replace the failing char using the same font
708 const char* pApproxUTF8 = GetAutofallback( cChar );
709 cChar = 0;
710 if( pApproxUTF8 )
712 String aApproxStr( pApproxUTF8, RTL_TEXTENCODING_UTF8 );
713 if( aApproxStr.Len() == 1 )
715 // TODO: support Autofallback for len>1
716 sal_Unicode cApprox = aApproxStr.GetChar( 0 );
717 if( mrFont.HasUnicodeChar( cApprox ) )
718 nGlyphIndex = (cChar = cApprox) | GF_ISCHAR;
721 // request fallback glyph if necessary
722 if( !cChar )
724 rArgs.NeedFallback( nCharPos, bRightToLeft );
725 if( rArgs.mnFlags & SAL_LAYOUT_FOR_FALLBACK )
726 nGlyphIndex = 0; // drop NotDef fallback glyphs
730 sal_Int32 nPhysGlyphWidth, nLogGlyphWidth;
731 mrFont.GetCharWidth( cChar, &nPhysGlyphWidth, &nLogGlyphWidth );
732 int nGlyphFlags = (nPhysGlyphWidth > 0) ? 0 : GlyphItem::IS_IN_CLUSTER;
733 if( bRightToLeft )
734 nGlyphFlags |= GlyphItem::IS_RTL_GLYPH;
735 GlyphItem aGI( nCharPos, nGlyphIndex, aNewPos, nGlyphFlags, nPhysGlyphWidth );
736 aGI.mnNewWidth = nLogGlyphWidth;
737 AppendGlyph( aGI );
739 aNewPos.X() += nLogGlyphWidth;
742 return (nCharPos >= 0);
745 // -----------------------------------------------------------------------
747 void X11FontLayout::AdjustLayout( ImplLayoutArgs& rArgs )
749 GenericSalLayout::AdjustLayout( rArgs );
750 SetOrientation( 0 ); // X11 fonts are to be rotated in upper layers
753 // -----------------------------------------------------------------------
755 void X11FontLayout::DrawText( SalGraphics& rSalGraphics ) const
757 static const int MAXGLYPHS = 160;
758 int nMaxGlyphs = GetOrientation() ? 1 : MAXGLYPHS;
760 // workaround for #i49902# similar to #b6228733 with XDrawText items
761 // => output each item separately for non-unicode font encodings!
762 // this is done here instead of in DrawStringUCS2MB() because
763 // it needs the item positions and they are easily available here
764 if( mrFont.GetAsciiEncoding() != RTL_TEXTENCODING_UNICODE )
765 nMaxGlyphs = 1;
767 Point aPos;
768 sal_GlyphId aGlyphAry[ MAXGLYPHS ];
769 sal_Unicode pStr[ MAXGLYPHS ];
770 for( int nStart=0;;)
772 int nGlyphCount = GetNextGlyphs( nMaxGlyphs, aGlyphAry, aPos, nStart );
773 if( !nGlyphCount )
774 break;
776 for( int i = 0; i < nGlyphCount; ++i )
777 pStr[ i ] = aGlyphAry[ i ] & GF_IDXMASK;
779 static_cast<X11SalGraphics&>(rSalGraphics).DrawStringUCS2MB( mrFont, aPos, pStr, nGlyphCount );
783 // =======================================================================