summaryrefslogtreecommitdiff
path: root/vcl/unx/source/gdi/xfont.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'vcl/unx/source/gdi/xfont.cxx')
-rw-r--r--vcl/unx/source/gdi/xfont.cxx559
1 files changed, 559 insertions, 0 deletions
diff --git a/vcl/unx/source/gdi/xfont.cxx b/vcl/unx/source/gdi/xfont.cxx
new file mode 100644
index 000000000000..edf1f02f4cfc
--- /dev/null
+++ b/vcl/unx/source/gdi/xfont.cxx
@@ -0,0 +1,559 @@
+/*************************************************************************
+ *
+ * $RCSfile: xfont.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: hr $ $Date: 2000-09-18 17:05:43 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#include <salunx.h>
+
+#ifndef EXTENDED_FONTSTRUCT_HXX
+#include "xfont.hxx"
+#endif
+#ifndef XLFD_EXTENDED_HXX
+#include "xlfd_extd.hxx"
+#endif
+#ifndef SAL_CONVERTER_CACHE_HXX_
+#include "salcvt.hxx"
+#endif
+#ifndef _STRING_HXX
+#include <tools/string.hxx>
+#endif
+#ifndef _SV_OUTFONT_HXX
+#include <outfont.hxx>
+#endif
+
+#ifdef DEBUG
+#include <stdio.h>
+#endif
+
+ExtendedFontStruct::ExtendedFontStruct( Display* pDisplay,
+ unsigned short nPixelSize, ExtendedXlfd* pXlfd,
+ SalConverterCache* pCvt ) :
+ mpDisplay( pDisplay ),
+ mnPixelSize( nPixelSize ),
+ mpXlfd( pXlfd )
+{
+ // member functions rely on zero initialized pointer for checking of
+ // already loaded fonts
+ mpXFontStruct = (XFontStruct**)calloc( mpXlfd->NumEncodings(),
+ sizeof(XFontStruct*) );
+ mnDefaultWidth = GetDefaultWidth( pCvt );
+}
+
+ExtendedFontStruct::~ExtendedFontStruct()
+{
+ for ( int nIdx = 0; nIdx < mpXlfd->NumEncodings(); nIdx++ )
+ {
+ if ( mpXFontStruct[nIdx] != NULL )
+ XFreeFont( mpDisplay, mpXFontStruct[nIdx] );
+ }
+}
+
+rtl_TextEncoding
+ExtendedFontStruct::GetAsciiEncoding( int *pAsciiRange ) const
+{
+ return mpXlfd->GetAsciiEncoding( pAsciiRange );
+}
+
+int
+ExtendedFontStruct::LoadEncoding( rtl_TextEncoding nEncoding )
+{
+ int nIdx = mpXlfd->GetEncodingIdx( nEncoding );
+ if ( (nIdx < 0) || (mpXFontStruct[ nIdx ] != NULL) )
+ return nIdx;
+
+ ByteString aFontName;
+ mpXlfd->ToString( aFontName, mnPixelSize, nEncoding );
+
+ mpXFontStruct[ nIdx ] = XLoadQueryFont( mpDisplay, aFontName.GetBuffer() );
+ if ( (mpXFontStruct[nIdx] != NULL) && (mpXFontStruct[nIdx]->fid == 0) )
+ mpXFontStruct[nIdx]->fid = XLoadFont(mpDisplay, aFontName.GetBuffer());
+ return nIdx;
+}
+
+XFontStruct*
+ExtendedFontStruct::GetFontStruct( rtl_TextEncoding nEncoding )
+{
+ int nIdx = LoadEncoding( nEncoding );
+ return nIdx < 0 ? NULL : mpXFontStruct[nIdx] ;
+}
+
+Bool
+ExtendedFontStruct::GetFontBoundingBox( XCharStruct *pCharStruct,
+ int *pAscent, int *pDescent )
+{
+ pCharStruct->lbearing = 0;
+ pCharStruct->rbearing = 0;
+ pCharStruct->width = 0;
+ pCharStruct->ascent = 0;
+ pCharStruct->descent = 0;
+
+ *pAscent = 0;
+ *pDescent = 0;
+
+ int nIdx;
+
+ // check whether there is at least one encoding allready loaded
+ Bool bEmpty = True;
+ for ( nIdx = 0; nIdx < mpXlfd->NumEncodings(); nIdx++ )
+ bEmpty = bEmpty && (mpXFontStruct[nIdx] == NULL);
+ if ( bEmpty )
+ LoadEncoding( mpXlfd->GetAsciiEncoding() );
+
+ // get the max bounding box from all font structs
+ for ( nIdx = 0; nIdx < mpXlfd->NumEncodings(); nIdx++ )
+ if ( mpXFontStruct[ nIdx ] != NULL )
+ {
+ *pAscent = max( mpXFontStruct[nIdx]->ascent, *pAscent );
+ *pDescent = max( mpXFontStruct[nIdx]->descent, *pDescent );
+
+ XCharStruct* pMaxBounds = &(mpXFontStruct[nIdx]->max_bounds);
+
+ pCharStruct->lbearing = max( pMaxBounds->lbearing,
+ pCharStruct->lbearing );
+ pCharStruct->rbearing = max( pMaxBounds->rbearing,
+ pCharStruct->rbearing );
+ pCharStruct->width = max( pMaxBounds->width,
+ pCharStruct->width );
+ pCharStruct->ascent = max( pMaxBounds->ascent,
+ pCharStruct->ascent );
+ pCharStruct->descent = max( pMaxBounds->descent,
+ pCharStruct->descent );
+ }
+
+ return (pCharStruct->width > 0);
+}
+
+Bool
+ExtendedFontStruct::ToImplFontMetricData(ImplFontMetricData *pFontMetric)
+{
+ pFontMetric->mnOrientation = 0;
+ pFontMetric->mnSlant = 0;
+ pFontMetric->mbDevice = TRUE;
+
+ pFontMetric->meCharSet = mpXlfd->GetEncoding( );
+ pFontMetric->meFamily = mpXlfd->GetFamily();
+ pFontMetric->meWeight = mpXlfd->GetWeight();
+ pFontMetric->mePitch = mpXlfd->GetSpacing();
+ pFontMetric->meItalic = mpXlfd->GetItalic();
+ pFontMetric->meType = mpXlfd->GetFontType();
+
+ int nAscent, nDescent;
+ XCharStruct aBoundingBox;
+ if ( GetFontBoundingBox(&aBoundingBox, &nAscent, &nDescent) )
+ {
+ pFontMetric->mnWidth = aBoundingBox.width;
+ pFontMetric->mnAscent = aBoundingBox.ascent;
+ pFontMetric->mnDescent = aBoundingBox.descent;
+ pFontMetric->mnLeading = max(0, aBoundingBox.ascent - nAscent
+ + aBoundingBox.descent - nDescent );
+ // XXX Fix me
+ pFontMetric->mnFirstChar = 0;
+ pFontMetric->mnLastChar = 255;
+
+ return True;
+ }
+ else
+ {
+ return False;
+ }
+}
+
+Bool
+ExtendedFontStruct::Match( const ExtendedXlfd *pXlfd, int nPixelSize ) const
+{
+ if( mpXlfd != pXlfd )
+ return FALSE;
+
+ return mnPixelSize == nPixelSize;
+}
+
+// Get an appropriate x-font that contains a glyph for the given unicode
+// code point.
+// This routine is designed to be called for each character in a text.
+// It first checks the given encoding to optimize for the fact that two
+// adjacent characters in a text most probably have the same encoding
+// In the first call initialize pEncodingInOut to dontknow, this causes
+// EncodingHasChar() to fail and thus bootstraps the encoding, otherwise
+// make sure that the initial value of pFontInOut matches the encoding and
+// that the encoding is valid for the font.
+Bool
+ExtendedFontStruct::GetFontStruct( sal_Unicode nChar,
+ rtl_TextEncoding *pEncodingInOut, XFontStruct **pFontInOut,
+ SalConverterCache *pCvt )
+{
+ if ( pCvt->EncodingHasChar(*pEncodingInOut, nChar) )
+ {
+ return True;
+ }
+ else
+ {
+ for ( int nIdx = 0; nIdx < mpXlfd->NumEncodings(); nIdx++ )
+ {
+ rtl_TextEncoding nEnc = mpXlfd->GetEncoding(nIdx);
+ if ( (nEnc != *pEncodingInOut)
+ && pCvt->EncodingHasChar(nEnc, nChar) )
+ {
+ *pEncodingInOut = nEnc;
+ *pFontInOut = GetFontStruct( nEnc );
+ return True;
+ }
+ }
+ }
+
+ return False;
+}
+
+
+// ---------------------------------------------------------------------------
+// utility functions to handle xfontstruct information, this is all to
+// calculate charwidth information
+// ---------------------------------------------------------------------------
+
+static Bool
+CharExists( const XCharStruct* pChar )
+{
+ if ( pChar == NULL )
+ return False;
+
+ return pChar->width
+ || pChar->ascent || pChar->descent
+ || pChar->lbearing || pChar->rbearing;
+}
+
+// this relies on non-null per_char information in the fontstruct
+static XCharStruct*
+GetCharinfo( const XFontStruct *pXFontStruct, sal_MultiByte nChar )
+{
+ unsigned int nRow = nChar >> 8;
+ unsigned int nCol = nChar & 0xFF;
+
+ int nMinRow = pXFontStruct->min_byte1;
+ int nMaxRow = pXFontStruct->max_byte1;
+ int nMinCol = pXFontStruct->min_char_or_byte2;
+ int nMaxCol = pXFontStruct->max_char_or_byte2;
+
+ if ( nRow >= nMinRow && nRow <= nMaxRow
+ && nCol >= nMinCol && nCol <= nMaxCol )
+ {
+ return &pXFontStruct->per_char[
+ (nRow-nMinRow) * (nMaxCol-nMinCol+1) + (nCol-nMinCol) ];
+ }
+
+ return NULL;
+}
+
+static sal_Size
+QueryCharWidth16( Display* pDisplay, XLIB_Font nFontID, sal_MultiByte nChar,
+ sal_Size nDefaultWidth )
+{
+ int nDirection, nFontAscent, nFontDescent;
+ XCharStruct aBoundingBox;
+
+ XQueryTextExtents16( pDisplay, nFontID, (XChar2b*)&nChar, 1,
+ &nDirection, &nFontAscent, &nFontDescent, &aBoundingBox );
+
+ return CharExists( &aBoundingBox ) ? aBoundingBox.width : nDefaultWidth;
+}
+
+static sal_Size
+QueryCharWidth8( XFontStruct* pXFontStruct, sal_Char nChar,
+ sal_Size nDefaultWidth )
+{
+ int nDirection, nFontAscent, nFontDescent;
+ XCharStruct aBoundingBox;
+
+ XTextExtents( pXFontStruct, &nChar, 1,
+ &nDirection, &nFontAscent, &nFontDescent, &aBoundingBox );
+
+ return CharExists( &aBoundingBox ) ? aBoundingBox.width : nDefaultWidth;
+}
+
+// the default width is the width of the question mark since this is the
+// character which is displayed for unconvertable unicode chars
+sal_Size
+ExtendedFontStruct::GetDefaultWidth( SalConverterCache* pCvt )
+{
+ rtl_TextEncoding nEncoding = mpXlfd->GetAsciiEncoding();
+ XFontStruct* pXFontStruct = GetFontStruct( nEncoding );
+
+ if ( pXFontStruct != NULL )
+ {
+ sal_Unicode nQuestionMark = 0x3f;
+ sal_MultiByte nChar;
+ sal_Char pBuffer[8];
+
+ sal_Size nSize = ConvertStringUTF16( &nQuestionMark, 1, pBuffer,
+ sizeof(pBuffer), pCvt->GetU2TConverter(nEncoding) );
+ if ( nSize == 2 )
+ {
+ nChar = ((sal_MultiByte)pBuffer[0] << 8)
+ + (sal_MultiByte)pBuffer[1];
+ return QueryCharWidth16( mpDisplay, pXFontStruct->fid, nChar, 0 );
+ }
+ else
+ if ( nSize == 1 )
+ {
+ return QueryCharWidth8( pXFontStruct, pBuffer[0], 0 );
+ }
+ else
+ {
+ return QueryCharWidth8( pXFontStruct, nQuestionMark, 0 );
+ }
+ }
+
+ return 0;
+}
+
+// Handle single byte fonts which do not require conversion, this exploits
+// the fact that unicode equals latin1 or ansi1252 in the range [0..0xff] and
+// is compatible with iso8859-X at least in the range to 0x7f
+sal_Size
+ExtendedFontStruct::GetCharWidth8( sal_Unicode nFrom, sal_Unicode nTo,
+ long *pWidthArray, rtl_TextEncoding nEncoding )
+{
+ if ( !(nFrom <= nTo) )
+ return 0;
+
+ XFontStruct* pXFontStruct = GetFontStruct( nEncoding );
+ if ( pXFontStruct == NULL )
+ return 0;
+
+ // query the font metrics
+ if ( (pXFontStruct->max_bounds.width == pXFontStruct->min_bounds.width)
+ || (pXFontStruct->per_char == NULL) )
+ {
+ // fixed width font
+ for ( int nIdx = nFrom; nIdx <= nTo; nIdx++, pWidthArray++ )
+ *pWidthArray = mnDefaultWidth;
+ }
+ else
+ {
+ // variable width font
+ int nMinChar = pXFontStruct->min_char_or_byte2;
+ int nMaxChar = pXFontStruct->max_char_or_byte2;
+
+ int nIdx = nFrom;
+
+ for ( ; nIdx < min(nTo, nMinChar); nIdx++, pWidthArray++ )
+ *pWidthArray = mnDefaultWidth;
+ for ( ; nIdx <= min(nTo, nMaxChar); nIdx++, pWidthArray++ )
+ {
+ XCharStruct* pChar = &(pXFontStruct->per_char[nIdx - nMinChar]);
+ *pWidthArray = CharExists(pChar) ? pChar->width : mnDefaultWidth;
+ }
+ for ( ; nIdx <= nTo; nIdx++, pWidthArray++ )
+ *pWidthArray = mnDefaultWidth;
+ }
+
+ // return amount of handled chars
+ return nTo - nFrom + 1;
+}
+
+// Handle utf16 encoded fonts, which do not require conversion
+sal_Size
+ExtendedFontStruct::GetCharWidthUTF16( sal_Unicode nFrom, sal_Unicode nTo,
+ long *pWidthArray )
+{
+ if ( !(nFrom <= nTo) )
+ return 0;
+
+ XFontStruct* pXFontStruct = GetFontStruct( RTL_TEXTENCODING_UNICODE );
+ FontPitch nSpacing = mpXlfd->GetSpacing( RTL_TEXTENCODING_UNICODE );
+
+ if ( pXFontStruct == NULL )
+ return 0;
+
+ // query the font metrics
+ if ( nSpacing == PITCH_VARIABLE
+ && pXFontStruct->per_char == NULL)
+ {
+ // get per_char information from the server
+ for ( sal_Unicode nIdx = nFrom; nIdx <= nTo; nIdx++, pWidthArray++ )
+ *pWidthArray = QueryCharWidth16( mpDisplay, pXFontStruct->fid,
+ nIdx, mnDefaultWidth );
+ }
+ else
+ if ( (pXFontStruct->max_bounds.width == pXFontStruct->min_bounds.width)
+ || (pXFontStruct->per_char == NULL) )
+ {
+ // really a fixed width font
+ for ( sal_Unicode nIdx = nFrom; nIdx <= nTo; nIdx++, pWidthArray++ )
+ *pWidthArray = mnDefaultWidth;
+ }
+ else
+ {
+ // get per_char information from the xfontstruct
+ for ( sal_Unicode nIdx = nFrom; nIdx <= nTo; nIdx++, pWidthArray++ )
+ {
+ XCharStruct* pChar = GetCharinfo( pXFontStruct, nIdx );
+ *pWidthArray = CharExists(pChar) ? pChar->width : mnDefaultWidth;
+ }
+ }
+
+ // return amount of handled chars
+ return nTo - nFrom + 1;
+}
+
+// handle non unicode fonts that are converted into encoding mathing the
+// font in fontstruct, 8 and 16 bit fonts are handled the same way
+sal_Size
+ExtendedFontStruct::GetCharWidth16( SalConverterCache *pCvt,
+ sal_Unicode nFrom, sal_Unicode nTo, long *pWidthArray )
+{
+ if ( !(nFrom <= nTo) )
+ return 0;
+
+ rtl_TextEncoding nEncoding = mpXlfd->GetAsciiEncoding();
+ XFontStruct *pXFontStruct = GetFontStruct( nEncoding );
+
+ if ( pXFontStruct == NULL )
+ return 0;
+
+ unsigned char pBuffer[16];
+ sal_MultiByte nChar;
+
+ for ( sal_Unicode nIdx = nFrom ; nIdx <= nTo ; nIdx++, pWidthArray++ )
+ {
+ Bool bValid;
+ FontPitch nSpacing;
+ sal_Size nSize;
+
+ // get a matching fontstruct
+ if ( bValid = GetFontStruct( nIdx, &nEncoding, &pXFontStruct, pCvt ) )
+ {
+ nSpacing = mpXlfd->GetSpacing( nEncoding );
+ nSize = ConvertStringUTF16( &nIdx, 1,
+ (sal_Char*)pBuffer, sizeof(pBuffer),
+ pCvt->GetU2TConverter(nEncoding) );
+ }
+
+ // query font metrics
+ if ( bValid && (nSize == 1 || nSize == 2) )
+ {
+ nChar = nSize == 1 ? (sal_MultiByte)pBuffer[0] :
+ ((sal_MultiByte)pBuffer[0] << 8) + (sal_MultiByte)pBuffer[1];
+
+ if ( nSpacing == PITCH_VARIABLE
+ && pXFontStruct->per_char == NULL)
+ {
+ // get per_char information from the x-server
+ *pWidthArray = QueryCharWidth16( mpDisplay, pXFontStruct->fid,
+ nChar, mnDefaultWidth );
+ }
+ else
+ if ( ( pXFontStruct->max_bounds.width
+ == pXFontStruct->min_bounds.width)
+ || (pXFontStruct->per_char == NULL) )
+ {
+ // fixed width font
+ *pWidthArray = pXFontStruct->min_bounds.width;
+ }
+ else
+ {
+ // get per_char information from the xfontstruct
+ XCharStruct* pChar = GetCharinfo( pXFontStruct, nChar );
+ *pWidthArray = CharExists(pChar) ? pChar->width : mnDefaultWidth;
+ }
+ }
+ else
+ {
+ // conversion error
+ *pWidthArray = mnDefaultWidth;
+ }
+ }
+
+ // return amount of handled chars
+ return nTo - nFrom + 1;
+}
+
+sal_Size
+ExtendedFontStruct::GetCharWidth( SalConverterCache *pCvt,
+ sal_Unicode nFrom, sal_Unicode nTo, long *pWidthArray )
+{
+ int nAsciiRange;
+ sal_Size nConverted = 0;
+
+ rtl_TextEncoding nEncoding = mpXlfd->GetAsciiEncoding(&nAsciiRange);
+
+ // dispatch querying of metrics to most promising encoding candidate
+ if ( nEncoding == RTL_TEXTENCODING_UNICODE )
+ {
+ // if we have a unicode encoded system font than we get the charwidth
+ // straight forward
+ nConverted = GetCharWidthUTF16( nFrom, nTo, pWidthArray );
+ }
+ else
+ {
+ if ( nFrom < nAsciiRange )
+ {
+ // optimize the most frequent case, requesting only the latin1
+ // chars which are mappable to a single encoding
+ nConverted = GetCharWidth8( nFrom, min(nAsciiRange, nTo),
+ pWidthArray, nEncoding );
+ }
+
+ // if further requests are pending, then the according unicode
+ // codepoint has to be dispatched to one of the system fonts and
+ // converted to this fonts encoding
+ nConverted += GetCharWidth16( pCvt, nFrom + nConverted, nTo,
+ pWidthArray + nConverted );
+ }
+
+ return nConverted;
+}