Fixes to make XftFontDescription>>example1 to render something. Sometimes it segfaults
and also there are some artefacts (invalid font metrics, rendering twice without clearing,
maybe something else)
"{ Package: 'stx:libview' }"
FontDescription subclass:#XftFontDescription
instanceVariableNames:'device fontId drawId lasrFgColor lastFgColorId lastBgColor
lastBgColorId'
classVariableNames:''
poolDictionaries:''
category:'Graphics-Support'
!
!XftFontDescription primitiveDefinitions!
%{
/*
* includes, defines, structure definitions
* and typedefs come here.
*/
#undef True
#undef False
#undef Time
#define Time XTime
#ifdef XFT
# define __externalAddressValCasted(type, externalAddress) \
((type)__externalAddressVal(externalAddress))
# define DISPLAY(x) __externalAddressValCasted(Display*, x)
# define SCREEN(x) ((int)(__intVal(x)))
# define DRAWABLE(x) __externalAddressValCasted(Drawable, x)
# define GC(x) __externalAddressValCasted(GC, x)
# define VISUAL(x) __externalAddressValCasted(Visual*, x)
# define COLORMAP(x) __externalAddressValCasted(Colormap, x)
# define XFT_FONT(x) __externalAddressValCasted(XftFont*, x)
# define XFT_PATTERN(x) __externalAddressValCasted(XftPattern*, x)
# define XFT_DRAW(x) __externalAddressValCasted(XftDraw*, x)
# define XFT_COLOR(x) __externalAddressValCasted(XftColor*, x)
# include <X11/Xft/Xft.h>
# include <X11/Xft/XftCompat.h>
#endif
%}
! !
!XftFontDescription class methodsFor:'documentation'!
documentation
"
WARNING: Unfinished.
Experimental implementation of custom font rendered using
Xft library (UNIX / X Window only), To actually use it,
add following definitions to the end of stx/configurations/myConf
(works on Ubuntu 12.10)
--- snip ---
XDEFS+=-DXFT
XINCLUDE+=$(shell pkg-config --cflags xft)
LIB_XFT=-l:libXft.so.2 -l:libfontconfig.so.1
--- snip --
NOTE: This class should be named XftFont, however then
there would be a name clash with XftFont structure
defined in Xft.h - therefore the class is named
XftFontDescription to avoid that name clash.
[author:]
Jan Vrany <jan.vrany@fit.cvut.cz>
[instance variables:]
[class variables:]
[see also:]
"
! !
!XftFontDescription class methodsFor:'examples'!
example1
"
XftFontDescription example1
"
|top textView|
top := StandardSystemView new.
top extent:300@200.
textView := EditTextView new.
textView origin:0.0 @ 0.0 corner:1.0 @ 1.0.
textView basicFont: (XftFontDescription family: 'helvetica' size: 16).
top addSubView:textView.
textView contents:('/etc/hosts' asFilename contentsOfEntireFile).
top open.
"Created: / 20-12-2013 / 00:04:57 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 29-12-2013 / 10:28:41 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!XftFontDescription methodsFor:'displaying'!
displayString:aString from:index1 to:index2 x:x y:y in:aGC opaque:opaque
"display a partial string at some position in aGC."
| y0 extents |
y0 := y - self ascent.
drawId isNil ifTrue:[
drawId := self xftDrawCreate: device displayId screen: device screen drawable: aGC id.
] ifFalse:[
self xftDrawChange: drawId drawable: aGC id
].
lasrFgColor ~= aGC paint ifTrue:[
lastFgColorId notNil ifTrue:[
self xftColorDestroy: device displayId screen: device screen color: lastFgColorId.
].
lasrFgColor := aGC paint.
lastFgColorId := self xftColorCreate: device displayId screen: device screen color: lasrFgColor.
].
extents := self xftTextExtents: device displayId font: fontId string: aString from: index1 to: index2.
opaque ifTrue:[
lastBgColor ~= aGC backgroundPaint ifTrue:[
lastBgColorId notNil ifTrue:[
self xftColorDestroy: device displayId screen: device screen color: lastBgColorId.
].
lastBgColor := aGC backgroundPaint.
lastBgColorId := self xftColorCreate: device displayId screen: device screen color: lastBgColor.
].
self xftDrawRect: drawId color: lastBgColorId x: x y:y0 width: extents first height: extents second
].
"true"false ifTrue:[
| w p |
w := self widthOf: aString from: index1 to: index2.
p := aGC paint.
aGC paint: Color red.
aGC displayLineFromX: x y: y toX: x + w y: y.
aGC paint: Color blue.
aGC displayLineFromX: x y: y - self ascent toX: x + w y: y - self ascent.
aGC paint: Color yellow.
aGC displayLineFromX: x y: y + self descent toX: x + w y: y + self descent.
aGC paint: p.
].
self xftDrawString: drawId color: lastFgColorId font: fontId x: x y: y string: aString from: index1 to: index2
"Created: / 21-12-2013 / 21:11:07 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 29-12-2013 / 11:38:43 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!XftFontDescription methodsFor:'error reporting'!
primitiveFailedIfNoXft
<resource: #skipInDebuggersWalkBack>
%{
#ifdef XFT
RETURN ( self );
#endif
%}.
self primitiveFailed: 'Xft support not available'
"Created: / 20-12-2013 / 21:13:22 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!XftFontDescription methodsFor:'getting a device font'!
onDevice:aGraphicsDevice
"Create a new XftFont representing the closes font as
myself on aDevice; if one already exists, return the one."
| myPatternId closestPatternId1 closestPatternId2 newFontId |
"if I am already assigned to that device ..."
(device == aGraphicsDevice) ifTrue:[^ self].
(aGraphicsDevice isNil and:[device notNil]) ifTrue:[
^ self
].
aGraphicsDevice deviceFonts do:[:aFont |
(self sameDeviceFontAs:aFont) ifTrue:[
^ aFont
].
].
[
myPatternId := self xftPatternCreate.
self xftPatternAdd: myPatternId attribute: 'family' value: family.
pixelSize notNil ifTrue:[
self xftPatternAdd: myPatternId attribute: 'pixelsize' value: pixelSize.
] ifFalse:[
self xftPatternAdd: myPatternId attribute: 'size' value: size.
].
newFontId := self xftFontOpenPattern: aGraphicsDevice displayId pattern: myPatternId.
newFontId notNil ifTrue:[
"/ Good, this font exist!!
fontId := newFontId.
device := aGraphicsDevice.
self shouldImplement. "/ Register font...
^ self.
] ifFalse:[
| family size |
closestPatternId1 := self xftFontMatch: aGraphicsDevice displayId screen: aGraphicsDevice screen pattern: myPatternId.
closestPatternId1 isNil ifTrue:[
self error: 'No font matches'.
].
"
self xftPatternGet: closestPatternId attribute: 'family' index: 0.
self xftPatternGet: closestPatternId attribute: 'size' index: 0.
"
closestPatternId2 := self xftPatternDuplicate: closestPatternId1.
newFontId := self xftFontOpenPattern: aGraphicsDevice displayId pattern: closestPatternId1.
"/ !!!!!!!! closestPatternId is no longer valid !!!!!!!!
closestPatternId1 := nil.
newFontId isNil ifTrue:[
self error: 'Pattern matched, but font could be open (should not happen)'.
].
^ self class new
setDevice: aGraphicsDevice patternId: closestPatternId2 fontId: newFontId;
yourself.
].
] ensure:[
self xftPatternDestroy: myPatternId.
self xftPatternDestroy: closestPatternId1.
self xftPatternDestroy: closestPatternId2.
].
"
(XftFontDescription family:'monospace' size:16) onDevice:Screen current
"
"Modified: / 14-04-1997 / 18:22:31 / cg"
"Modified: / 21-12-2013 / 01:15:48 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
onDevice:aDevice ifAbsent:exceptionBlock
"Create a new XftFont representing the same font as
myself on aDevice. This does NOT try to look for existing
or replacement fonts (i.e. can be used to get physical fonts)."
^ self shouldImplement
"Modified: / 20-12-2013 / 10:54:56 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!XftFontDescription methodsFor:'initialization'!
setDevice: deviceArg patternId: patternIdArg fontId: fontIdArg
device := deviceArg.
fontId := fontIdArg.
family := self xftPatternGet: patternIdArg attribute: 'family' index: 0.
size := self xftPatternGet: patternIdArg attribute: 'size' index: 0.
face := self xftPatternGet: patternIdArg attribute: 'slant' index: 0.
face == 0 ifTrue:[ face := 'roman'].
face == 100 ifTrue:[ face := 'italic'].
face == 110 ifTrue:[ face := 'oblique'].
style := self xftPatternGet: patternIdArg attribute: 'style' index: 0.
encoding:= self xftPatternGet: patternIdArg attribute: 'encoding' index: 0.
"Created: / 21-12-2013 / 00:46:10 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!XftFontDescription methodsFor:'primitives'!
xftAvailable
%{
#ifdef XFT
RETURN ( true )
#endif
%}.
^ false
"Created: / 20-12-2013 / 21:10:25 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
xftColorCreate: displayId screen: screen color: color
| error r g b a |
self primitiveFailedIfNoXft.
r := color scaledRed.
g := color scaledGreen.
b := color scaledBlue.
a := color alpha * 65535.
%{
#ifdef XFT
XRenderColor xrcolor;
XftColor *xftcolor;
if ( ! __isExternalAddressLike(displayId) ) {
error = @symbol(BadArg1);
goto err;
}
if ( ! __isSmallInteger(screen) ) {
error = @symbol(BadArg2);
goto err;
}
xrcolor.red = __intVal(r);
xrcolor.green = __intVal(g);
xrcolor.blue = __intVal(b);
xrcolor.alpha = __intVal(a);
xftcolor = (XftColor*) malloc( sizeof( XftColor ) );
XftColorAllocValue ( DISPLAY( displayId ) ,
DefaultVisual( DISPLAY( displayId), SCREEN (screen) ) ,
DefaultColormap( DISPLAY( displayId), SCREEN (screen) ),
&xrcolor,
xftcolor );
RETURN ( __MKEXTERNALADDRESS( xftcolor ) );
err:;
#endif
%}.
self primitiveFailed: error
"Created: / 28-12-2013 / 11:55:46 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
xftColorDestroy: displayId screen: screen color: xftColorId
| error |
self primitiveFailedIfNoXft.
%{
#ifdef XFT
XRenderColor xrcolor;
XftColor *xftcolor;
if ( ! __isExternalAddressLike(displayId) ) {
error = @symbol(BadArg1);
goto err;
}
if ( ! __isSmallInteger(screen) ) {
error = @symbol(BadArg2);
goto err;
}
if ( ! __isExternalAddressLike(xftColorId) ) {
error = @symbol(BadArg3);
goto err;
}
XftColorFree ( DISPLAY( displayId ) ,
DefaultVisual( DISPLAY( displayId), SCREEN (screen) ) ,
DefaultColormap( DISPLAY( displayId), SCREEN (screen) ),
XFT_COLOR( xftColorId ) );
free( __externalAddressVal( xftColorId ) );
__externalAddressVal( xftColorId ) = NULL;
RETURN ( self );
err:;
#endif
%}.
self primitiveFailed: error
"Created: / 28-12-2013 / 12:21:22 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
xftDrawChange: xftDrawId drawable: drawableId
| error |
self primitiveFailedIfNoXft.
%{
#ifdef XFT
if ( ! __isExternalAddressLike(xftDrawId) ) {
error = @symbol(BadArg1);
goto err;
}
if ( ! __isExternalAddressLike(drawableId) ) {
error = @symbol(BadArg2);
goto err;
}
if (XftDrawDrawable( XFT_DRAW(xftDrawId) ) != DRAWABLE( drawableId ) ) {
XftDrawChange( XFT_DRAW(xftDrawId) , DRAWABLE( drawableId ) );
}
RETURN ( self );
err:;
#endif
%}.
self primitiveFailed: error
"Created: / 26-12-2013 / 12:17:36 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
xftDrawCreate: displayId screen: screen drawable: drawableId
| error |
self primitiveFailedIfNoXft.
%{
#ifdef XFT
if ( ! __isExternalAddressLike(displayId) ) {
error = @symbol(BadArg1);
goto err;
}
if ( ! __isSmallInteger(screen) ) {
error = @symbol(BadArg2);
goto err;
}
if ( ! __isExternalAddressLike(drawableId) ) {
error = @symbol(BadArg3);
goto err;
}
RETURN ( __MKEXTERNALADDRESS( XftDrawCreate ( DISPLAY( displayId ) ,
DRAWABLE( drawableId ) ,
DefaultVisual( DISPLAY( displayId), SCREEN (screen) ) ,
DefaultColormap( DISPLAY( displayId), SCREEN (screen) ) ) ) );
err:;
#endif
%}.
self primitiveFailed: error
"Created: / 21-12-2013 / 21:12:47 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
xftDrawRect: drawIdArg color: colorIdArg x: x y: y width: w height: h
| error extents |
self primitiveFailedIfNoXft.
%{
#ifdef XFT
if ( ! __isExternalAddressLike(drawIdArg) ) {
error = @symbol(BadArg1);
goto err;
}
if ( ! __isExternalAddressLike(colorIdArg) ) {
error = @symbol(BadArg2);
goto err;
}
if ( ! __isSmallInteger(x) ) {
error = @symbol(BadArg3);
goto err;
}
if ( ! __isSmallInteger(y) ) {
error = @symbol(BadArg4);
goto err;
}
if ( ! __isSmallInteger(w) ) {
error = @symbol(BadArg5);
goto err;
}
if ( ! __isSmallInteger(h) ) {
error = @symbol(BadArg6);
goto err;
}
XftDrawRect(XFT_DRAW(drawIdArg), XFT_COLOR(colorIdArg),
__intVal(x), __intVal(y), __intVal(w) ,__intVal(h));
RETURN ( self );
err:;
#endif
%}.
self primitiveFailed: error.
"Created: / 28-12-2013 / 23:35:42 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
xftDrawString: drawIdArg color: colorIdArg font: fontIdArg x: x y: y string: text from: start to: stop
| error extents |
self primitiveFailedIfNoXft.
%{
#ifdef XFT
int _start, _stop;
int _x, _y;
if ( ! __isExternalAddressLike(drawIdArg) ) {
error = @symbol(BadArg1);
goto err;
}
if ( ! __isExternalAddressLike(colorIdArg) ) {
error = @symbol(BadArg2);
goto err;
}
if ( ! __isExternalAddressLike(fontIdArg) ) {
error = @symbol(BadArg3);
goto err;
}
if ( ! __isSmallInteger(x) ) {
error = @symbol(BadArg4);
goto err;
}
_x = __intVal(x);
if ( ! __isSmallInteger(y) ) {
error = @symbol(BadArg5);
goto err;
}
_y = __intVal(y);
if ( ! __isSmallInteger(start) ) {
error = @symbol(BadArg6);
goto err;
}
_start = __intVal(start);
if ( ! __isSmallInteger(stop) ) {
error = @symbol(BadArg7);
goto err;
}
_stop = __intVal(stop);
if ( __isString(text) ) {
XftDrawString8(XFT_DRAW(drawIdArg), XFT_COLOR(colorIdArg), XFT_FONT(fontIdArg),
_x, _y,
__stringVal(text) + (_start - 1), _stop - _start + 1);
RETURN ( self );
} else {
error = @symbol(BadArg5);
goto err;
}
err:;
#endif
%}.
self primitiveFailed: error.
"Created: / 28-12-2013 / 12:32:18 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 29-12-2013 / 11:29:57 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
xftFontGetAscent: fontIdArg
| error |
self primitiveFailedIfNoXft.
%{
#ifdef XFT
int v;
if ( ! __isExternalAddressLike(fontIdArg) ) {
error = @symbol(BadArg1);
goto err;
}
v = XFT_FONT(fontIdArg)->ascent;
RETURN ( __MKINT( v ) );
err:;
#endif
%}.
self primitiveFailed: error
"Created: / 21-12-2013 / 00:56:13 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
xftFontGetDescent: fontIdArg
| error |
self primitiveFailedIfNoXft.
%{
#ifdef XFT
int v;
if ( ! __isExternalAddressLike(fontIdArg) ) {
error = @symbol(BadArg1);
goto err;
}
v = XFT_FONT(fontIdArg)->descent;
RETURN ( __MKINT( v ) );
err:;
#endif
%}.
self primitiveFailed: error
"Created: / 21-12-2013 / 00:56:23 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
xftFontGetHeight: fontIdArg
| error |
self primitiveFailedIfNoXft.
%{
#ifdef XFT
int v;
if ( ! __isExternalAddressLike(fontIdArg) ) {
error = @symbol(BadArg1);
goto err;
}
v = XFT_FONT(fontIdArg)->height;
RETURN ( __MKINT( v ) );
err:;
#endif
%}.
self primitiveFailed: error
"Created: / 21-12-2013 / 00:56:32 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
xftFontGetPattern: fontIdArg
| error |
self primitiveFailedIfNoXft.
%{
#ifdef XFT
XftPattern* p;
if ( ! __isExternalAddressLike(fontIdArg) ) {
error = @symbol(BadArg1);
goto err;
}
p = XFT_FONT(fontIdArg)->pattern;
if (p == NULL) {
RETURN ( nil );
} else {
RETURN ( __MKEXTERNALADDRESS ( p ) );
}
err:;
#endif
%}.
self primitiveFailed: error
"Created: / 21-12-2013 / 00:55:11 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
xftFontMatch: displayId screen: screen pattern: patternId
| error |
self primitiveFailedIfNoXft.
%{
#ifdef XFT
XftPattern* p;
XftResult r;
if ( ! __isExternalAddressLike(displayId) ) {
error = @symbol(BadArg1);
goto err;
}
if ( ! __isSmallInteger( screen ) ) {
error = @symbol(BadArg2);
goto err;
}
if ( ! __isExternalAddressLike(patternId) ) {
error = @symbol(BadArg3);
goto err;
}
p = XftFontMatch( DISPLAY(displayId) , SCREEN( screen ), XFT_PATTERN( patternId ), &r );
if (r == XftResultMatch) {
RETURN ( __MKEXTERNALADDRESS ( p ) );
} else {
if ( p ) {
XftPatternDestroy( p );
}
RETURN ( nil );
}
err:;
#endif
%}.
self primitiveFailed: error
"Created: / 21-12-2013 / 00:08:48 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
xftFontOpenPattern: displayId pattern: patternId
| error |
self primitiveFailedIfNoXft.
%{
#ifdef XFT
XftFont* f;
if ( ! __isExternalAddressLike(displayId) ) {
error = @symbol(BadArg1);
goto err;
}
if ( ! __isExternalAddressLike(patternId) ) {
error = @symbol(BadArg2);
goto err;
}
f = XftFontOpenPattern( DISPLAY(displayId) , XFT_PATTERN( patternId ) );
if (f == NULL) {
RETURN ( nil );
} else {
RETURN ( __MKEXTERNALADDRESS ( f ) );
}
err:;
#endif
%}.
self primitiveFailed: error
"Created: / 20-12-2013 / 23:53:59 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
xftPatternAdd: pattern attribute: attribute value: value
"Add a value to the specified pattern element after existing values"
^ self xftPatternAdd: pattern attribute: attribute value: value append: true.
"Created: / 20-12-2013 / 23:43:31 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
xftPatternAdd: pattern attribute: attribute value: value append: append
"Add a value to the specified pattern element. If 'append' is true, the value
is added after existing values, otherwise it is added before them."
| error |
self primitiveFailedIfNoXft.
%{
#ifdef XFT
XftValue v;
Bool b;
if ( ! __isExternalAddressLike ( pattern ) ) {
error = @symbol(BadArg1);
goto err;
}
if ( ! __isStringLike ( attribute ) ) {
error = @symbol(BadArg2);
goto err;
}
if ( append != true && append != false ) {
error = @symbol(BadArg4);
goto err;
}
if ( __isStringLike ( value ) ) {
v.type = FcTypeString;
/* Passing pointer inside Smalltalk should be safe,
* Xft/FontConfig libraries seem to allocate and store
* a __copy__ of the string (if I understood the code correctly)
*/
v.u.s = __stringVal( value);
} else if ( __isSmallInteger( value ) ) {
v.type = XftTypeInteger;
v.u.i = (int)__intVal( value );
} else if ( value == true || value == false ) {
v.type = XftTypeBool;
v.u.b = value == true ? True : False;
} else if ( __isFloat ( value ) ) {
v.type = XftTypeDouble;
v.u.d = __floatVal( value );
} else if ( value == nil ) {
v.type = XftTypeVoid;
v.u.f = NULL;
} else {
error = @symbol(BadArg3);
goto err;
}
b = XftPatternAdd( XFT_PATTERN(pattern), __stringVal(attribute), v, append == true ? True : False );
RETURN ( b == True ? true : false );
err:;
#endif
%}.
self primitiveFailed: error
"Created: / 20-12-2013 / 21:50:00 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
xftPatternCreate
self primitiveFailedIfNoXft.
%{
#ifdef XFT
RETURN ( __MKEXTERNALADDRESS( XftPatternCreate() ) );
#endif
%}.
self primitiveFailed.
"Created: / 20-12-2013 / 21:19:00 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
xftPatternDel: pattern attribute: attribute
| error |
self primitiveFailedIfNoXft.
%{
#ifdef XFT
if ( ! __isExternalAddressLike ( pattern ) ) {
error = @symbol(BadArg1);
goto err;
}
if ( ! __isStringLike ( attribute ) ) {
error = @symbol(BadArg2);
goto err;
}
XftPatternDel( XFT_PATTERN(pattern), __stringVal ( attribute ) );
RETURN ( self );
err:;
#endif
%}.
self primitiveFailed: error
"Created: / 20-12-2013 / 21:33:47 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
xftPatternDestroy: addr
| error |
self primitiveFailedIfNoXft.
addr isNil ifTrue:[ ^ self ].
%{
#ifdef XFT
if ( ! __isExternalAddressLike(addr) ) {
error = @symbol(BadArg1);
goto err;
}
XftPatternDestroy( XFT_PATTERN(addr) );
RETURN ( self );
err:;
#endif
%}.
self primitiveFailed: error
"Created: / 20-12-2013 / 21:33:47 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 20-12-2013 / 23:48:45 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
xftPatternDuplicate: addr
| error |
self primitiveFailedIfNoXft.
addr isNil ifTrue:[ ^ self ].
%{
#ifdef XFT
if ( ! __isExternalAddressLike(addr) ) {
error = @symbol(BadArg1);
goto err;
}
RETURN ( __MKEXTERNALADDRESS ( XftPatternDuplicate( XFT_PATTERN(addr) ) ) );
err:;
#endif
%}.
self primitiveFailed: error
"Created: / 21-12-2013 / 01:14:03 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
xftPatternGet: pattern attribute: attribute index: index
"Return a value from the specified element -- multiple values can be indexed
with 'index' starting at zero."
| error |
self primitiveFailedIfNoXft.
%{
#ifdef XFT
XftValue v;
XftResult r;
if ( ! __isExternalAddressLike ( pattern ) ) {
error = @symbol(BadArg1);
goto err;
}
if ( ! __isStringLike ( attribute ) ) {
error = @symbol(BadArg2);
goto err;
}
if ( ! __isSmallInteger( index ) ) {
error = @symbol(BadArg3);
goto err;
}
r = XftPatternGet(XFT_PATTERN(pattern), __stringVal( attribute ), __intVal( index ), &v);
if ( r != XftResultMatch) {
RETURN ( nil );
}
if ( v.type == XftTypeString) {
RETURN ( __MKSTRING(v.u.s) );
} else if ( v.type == XftTypeInteger ) {
RETURN ( __MKINT (v.u.i) );
} else if ( v.type == XftTypeBool ) {
RETURN ( v.u.b == True ? true : false );
} else if ( v.type == XftTypeDouble ) {
RETURN ( __MKFLOAT (v.u.d) );
} else if ( v.type == XftTypeVoid ) {
RETURN ( nil );
} else {
error = @symbol(UnssuportedTypeValue);
goto err;
}
err:;
#endif
%}.
self primitiveFailed: error
"Created: / 20-12-2013 / 21:50:44 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 21-12-2013 / 01:06:25 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
xftTextExtents: displayIdArg font: fontIdArg string: text from: start to: stop
| error extents |
self primitiveFailedIfNoXft.
extents := Array new: 6.
%{
#ifdef XFT
XGlyphInfo info;
int _start, _stop;
if ( ! __isExternalAddressLike(displayIdArg) ) {
error = @symbol(BadArg1);
goto err;
}
if ( ! __isExternalAddressLike(fontIdArg) ) {
error = @symbol(BadArg2);
goto err;
}
if ( ! __isSmallInteger(start) ) {
error = @symbol(BadArg4);
goto err;
}
_start = __intVal(start);
if ( ! __isSmallInteger(stop) ) {
error = @symbol(BadArg5);
goto err;
}
_stop = __intVal(stop);
if ( __isString(text) ) {
XftTextExtents8(DISPLAY(displayIdArg), XFT_FONT(fontIdArg),
__stringVal(text) + (_start - 1), _stop - _start + 1, &info);
} else {
error = @symbol(BadArg3);
goto err;
}
__ArrayInstPtr(extents)->a_element[0] = __MKSMALLINT(info.width);
__ArrayInstPtr(extents)->a_element[1] = __MKSMALLINT(info.height);
__ArrayInstPtr(extents)->a_element[2] = __MKSMALLINT(info.x);
__ArrayInstPtr(extents)->a_element[3] = __MKSMALLINT(info.y);
__ArrayInstPtr(extents)->a_element[4] = __MKSMALLINT(info.xOff);
__ArrayInstPtr(extents)->a_element[5] = __MKSMALLINT(info.yOff);
error = nil;
err:;
#endif
%}.
error notNil ifTrue:[
self primitiveFailed: error.
^ nil.
].
^ extents
"Created: / 21-12-2013 / 10:42:15 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 21-12-2013 / 20:53:28 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!XftFontDescription methodsFor:'queries-dimensions'!
ascent
"return the ascent - the number of pixels above the baseLine."
^ self xftFontGetAscent: fontId
"Created: / 21-12-2013 / 01:19:46 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
descent
"return the descent - the number of pixels below the baseLine."
^ self xftFontGetDescent: fontId
"Created: / 21-12-2013 / 01:20:09 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
height
"return the height - the number of pixels above plus below the baseLine."
^ self xftFontGetHeight: fontId
"Created: / 21-12-2013 / 01:20:21 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
isFixedWidth
"return true, if this is a fixed pitch font (i.e. all characters
are of the same width)"
^ false "/ How to check?
"Created: / 21-12-2013 / 10:38:47 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
widthOf:aString from:start to:stop
"return the width of a sub string"
| extents |
extents := self xftTextExtents: device displayId font: fontId string: aString from: start to: stop.
"/ extents --> #(width height x y xOff yOff)
^ extents first.
"Created: / 21-12-2013 / 10:42:15 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!XftFontDescription class methodsFor:'documentation'!
version
^ '$Header: /cvs/stx/stx/libview/XftFontDescription.st,v 1.4 2013-12-29 11:03:28 vrany Exp $'
!
version_CVS
^ '$Header: /cvs/stx/stx/libview/XftFontDescription.st,v 1.4 2013-12-29 11:03:28 vrany Exp $'
! !