1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: xfont.cxx,v $
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"
36 #include "xlfd_extd.hxx"
38 #include <tools/string.hxx>
39 #include <vcl/outfont.hxx>
40 #include <saldisp.hxx>
43 // for GetMirroredChar
44 #include <vcl/svapp.hxx>
46 #if OSL_DEBUG_LEVEL > 1
52 #define VCLASS_ROTATE 0
53 #define VCLASS_ROTATE_REVERSE 1
54 #define VCLASS_TRANSFORM1 2
55 #define VCLASS_TRANSFORM2 3
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");
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
),
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
] );
114 ExtendedFontStruct::GetAsciiEncoding( int *pAsciiRange
) const
116 return mpXlfd
->GetAsciiEncoding( pAsciiRange
);
120 ExtendedFontStruct::GetSpacing( rtl_TextEncoding nEncoding
)
122 return mpXlfd
->GetPitch( nEncoding
);
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
);
133 fprintf( stderr
, "XLoadFont \"%s\" => %d\n", pFontName
, (pFont
!= NULL
) );
139 ExtendedFontStruct::LoadEncoding( rtl_TextEncoding nEncoding
)
141 int nIdx
= mpXlfd
->GetEncodingIdx( nEncoding
);
142 if ( (nIdx
< 0) || (mpXFontStruct
[ nIdx
] != NULL
) )
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 )
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
;
174 ExtendedFontStruct::GetFontStruct( rtl_TextEncoding nEncoding
)
176 int nIdx
= LoadEncoding( nEncoding
);
177 return nIdx
< 0 ? NULL
: mpXFontStruct
[nIdx
] ;
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;
195 // check if there is at least one encoding already loaded
197 for ( nIdx
= 0; nIdx
< mpXlfd
->NumEncodings(); nIdx
++ )
198 bEmpty
&= (mpXFontStruct
[nIdx
] == NULL
);
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);
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!!!
274 ExtendedFontStruct::Match( const ExtendedXlfd
*pXlfd
,
275 const Size
& rPixelSize
, sal_Bool bVertical
) const
277 if( mpXlfd
!= pXlfd
)
280 if( bVertical
!= mbVertical
)
283 if( rPixelSize
.Height() != maPixelSize
.Height() )
286 long nReqWidth
= rPixelSize
.Width();
288 nReqWidth
= rPixelSize
.Height();
289 if( nReqWidth
!= maPixelSize
.Width() )
295 // Get an appropriate x-font that contains a glyph for the given unicode
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.
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
);
315 if ( pCvt
->EncodingHasChar(mnCachedEncoding
, nChar
) )
317 *pEncoding
= mnCachedEncoding
;
318 return GetFontStruct (mnCachedEncoding
);
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
;
339 // ---------------------------------------------------------------------------
340 // utility functions to handle xfontstruct information, this is all to
341 // calculate charwidth information
342 // ---------------------------------------------------------------------------
345 CharExists( const XCharStruct
* pChar
)
351 || pChar
->ascent
|| pChar
->descent
352 || pChar
->lbearing
|| pChar
->rbearing
;
355 // this relies on non-null per_char information in the fontstruct
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
) ];
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
;
391 // currently not used
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
;
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
416 ExtendedFontStruct::GetCharWidth8( sal_Unicode nFrom
, sal_Unicode nTo
,
417 sal_Int32
* pWidthArray
, rtl_TextEncoding nEncoding
)
419 if ( !(nFrom
<= nTo
) )
422 XFontStruct
* pXFontStruct
= GetFontStruct( nEncoding
);
423 if ( pXFontStruct
== NULL
)
426 // query the font metrics
427 if ( (pXFontStruct
->max_bounds
.width
== pXFontStruct
->min_bounds
.width
)
428 || (pXFontStruct
->per_char
== NULL
) )
431 for ( int nIdx
= nFrom
; nIdx
<= nTo
; nIdx
++, pWidthArray
++ )
432 *pWidthArray
= pXFontStruct
->max_bounds
.width
;
436 // variable width font
437 int nMinChar
= pXFontStruct
->min_char_or_byte2
;
438 int nMaxChar
= pXFontStruct
->max_char_or_byte2
;
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
459 ExtendedFontStruct::GetCharWidthUTF16( sal_Unicode nFrom
, sal_Unicode nTo
,
460 sal_Int32
* pWidthArray
)
462 if ( !(nFrom
<= nTo
) )
465 XFontStruct
* pXFontStruct
= GetFontStruct( RTL_TEXTENCODING_UNICODE
);
466 FontPitch nSpacing
= mpXlfd
->GetPitch( RTL_TEXTENCODING_UNICODE
);
468 if ( pXFontStruct
== NULL
)
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
);
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
;
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
505 ExtendedFontStruct::GetCharWidth16( sal_Unicode nFrom
, sal_Unicode nTo
,
506 sal_Int32
* pWidthArray
, ExtendedFontStruct
*pFallback
)
511 sal_Char pBuffer
[64];
513 SalConverterCache
*pCvt
= SalConverterCache::GetInstance();
514 for ( sal_Int32 nIdx
= nFrom
; nIdx
<= nTo
; nIdx
++, pWidthArray
++ )
518 sal_Unicode nUniIdx
= (sal_Unicode
)nIdx
;
520 // get a matching fontstruct
521 rtl_TextEncoding nEnc
;
524 if ( (pFont
= GetFontStruct(nUniIdx
, &nEnc
)) != NULL
)
526 nSpacing
= GetSpacing( nEnc
);
529 if ( (pFallback
!= NULL
)
530 && ((pFont
= pFallback
->GetFontStruct(nUniIdx
, &nEnc
)) != NULL
) )
532 nSpacing
= pFallback
->GetSpacing( nEnc
);
535 if ( (pFallback
!= NULL
)
536 && ((pFont
= pFallback
->GetFontStruct(nUniIdx
= '?', &nEnc
)) != NULL
) )
538 nSpacing
= pFallback
->GetSpacing( nEnc
);
542 // TODO What should the default value be?
543 nSpacing
= PITCH_FIXED
;
548 nSize
= pCvt
->ConvertStringUTF16(&nUniIdx
, 1, pBuffer
, sizeof(pBuffer
), nEnc
);
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
);
571 if ( (pFont
->max_bounds
.width
== pFont
->min_bounds
.width
)
572 || (pFont
->per_char
== NULL
) )
575 *pWidthArray
= pFont
->max_bounds
.width
;
579 // get per_char information from the xfontstruct
580 XCharStruct
* pChar
= GetCharinfo( pFont
, nChar
);
581 *pWidthArray
= CharExists(pChar
) ? pChar
->width
: mnDefaultWidth
;
587 *pWidthArray
= mnDefaultWidth
;
591 // return amount of handled chars
592 return nTo
- nFrom
+ 1;
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
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
608 nConverted
= GetCharWidthUTF16( cChar
, cChar
, pPhysicalWidth
);
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
);
634 bool ExtendedFontStruct::HasUnicodeChar( sal_Unicode cChar
) const
636 // #i18818# return false if there are no known encodings
640 // init unicode range cache if needed
641 if( mnRangeCount
< 0 )
643 mnRangeCount
= mpXlfd
->GetFontCodeRanges( NULL
);
646 mpRangeCodes
= new sal_uInt32
[ 2*mnRangeCount
];
647 mpXlfd
->GetFontCodeRanges( mpRangeCodes
);
648 // TODO: make sure everything is sorted
651 // binary search in unicode ranges
653 int nMid
= mnRangeCount
;
654 int nUpper
= 2 * mnRangeCount
- 1;
655 while( nLower
< nUpper
)
657 if( cChar
>= mpRangeCodes
[ nMid
] )
661 nMid
= (nLower
+ nUpper
+ 1) / 2;
663 if( (nMid
== 0) && (cChar
< mpRangeCodes
[0]) )
665 return (nMid
& 1) ? false: true;
668 int ExtendedFontStruct::GetFontCodeRanges( sal_uInt32
* pCodePairs
) const
670 // make sure unicode range cache is initialized
673 // transfer range pairs if requested
676 for( int i
= 0; i
< 2*mnRangeCount
; ++i
)
677 pCodePairs
[i
] = mpRangeCodes
[i
];
683 // =======================================================================
685 X11FontLayout::X11FontLayout( ExtendedFontStruct
& rFont
)
689 // -----------------------------------------------------------------------
691 bool X11FontLayout::LayoutText( ImplLayoutArgs
& rArgs
)
693 Point
aNewPos( 0, 0 );
697 for( nCharPos
= -1; rArgs
.GetNextPos( &nCharPos
, &bRightToLeft
); )
699 sal_UCS4 cChar
= rArgs
.mpStr
[ nCharPos
];
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
);
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
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
;
734 nGlyphFlags
|= GlyphItem::IS_RTL_GLYPH
;
735 GlyphItem
aGI( nCharPos
, nGlyphIndex
, aNewPos
, nGlyphFlags
, nPhysGlyphWidth
);
736 aGI
.mnNewWidth
= nLogGlyphWidth
;
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
)
768 sal_GlyphId aGlyphAry
[ MAXGLYPHS
];
769 sal_Unicode pStr
[ MAXGLYPHS
];
772 int nGlyphCount
= GetNextGlyphs( nMaxGlyphs
, aGlyphAry
, aPos
, nStart
);
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 // =======================================================================