XftFontDescription.st
changeset 6936 1d258b6b9632
parent 6876 b1aa2b47d252
child 6938 0fe07ed7c80f
child 7032 bc8b85059e2b
--- a/XftFontDescription.st	Thu Oct 01 14:00:15 2015 +0200
+++ b/XftFontDescription.st	Fri Oct 02 19:17:42 2015 +0200
@@ -1,3 +1,5 @@
+"{ Encoding: utf8 }"
+
 "{ Package: 'stx:libview' }"
 
 "{ NameSpace: Smalltalk }"
@@ -75,19 +77,19 @@
 
 #ifdef XFT
 
-extern OBJ __GLOBAL_GET_BY_NAME();
+extern OBJ __GLOBAL_GET_BY_NAME(char *);
 
 # define __HANDLE_VAL(type, externalAddress) \
-	((type)__externalAddressVal(externalAddress))
+        ((type)__externalAddressVal(externalAddress))
 
-# define __HANDLE_NEW(ptr, __cls)                \
-	({                                      \
-	    OBJ handle;                         \
-	    handle = __MKEXTERNALADDRESS(ptr);  \
-	    __InstPtr(handle)->o_class =        \
-		__GLOBAL_GET_BY_NAME(__cls);    \
-	    handle;                             \
-	})
+# define __HANDLE_NEW(ptr, __cls)                    \
+        ({                                           \
+            OBJ handle = __MKEXTERNALADDRESS(ptr);   \
+            OBJ clsObj = __GLOBAL_GET_BY_NAME(__cls);\
+            __InstPtr(handle)->o_class = clsObj;     \
+            __STORE(handle, clsObj);                 \
+            handle;                                  \
+        })
 
 
 
@@ -98,9 +100,6 @@
 # define VISUAL(x)     __HANDLE_VAL(Visual*, x)
 # define COLORMAP(x)   __HANDLE_VAL(Colormap, x)
 
-
-
-
 /* FontConfig objects */
 # define FC_PATTERN(x)                  __HANDLE_VAL(XftPattern*, x)
 # define FC_PATTERN_HANDLE_NEW(x)       __HANDLE_NEW(x, "XftFontDescription::FCPatternHandle")
@@ -420,6 +419,19 @@
     "Created: / 30-12-2013 / 19:49:05 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
 
+!XftFontDescription class methodsFor:'primitives'!
+
+xftAvailable
+%{
+#ifdef XFT
+    RETURN ( true )
+#endif
+%}.
+    ^ false
+
+    "Created: / 20-12-2013 / 21:10:25 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
 !XftFontDescription class methodsFor:'queries'!
 
 listOfAvailableFonts
@@ -547,6 +559,23 @@
     "Created: / 02-01-2014 / 23:29:04 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
 
+!XftFontDescription methodsFor:'change & update'!
+
+update:anAspect with:something from:changedObject
+    "I want to be informed when a view that printed something with me is destroyed.
+     Disassociate the view from the XFT drawable"
+
+    |drawableId|
+
+    anAspect == #aboutToDestroy ifTrue:[
+        drawableId := changedObject drawableId.
+        drawableId notNil ifTrue:[
+            self disassociateXftDrawableFrom:drawableId.
+        ].
+        changedObject removeDependent:self.
+    ].
+! !
+
 !XftFontDescription methodsFor:'converting'!
 
 asNonXftFont
@@ -576,38 +605,38 @@
     "limit the string len, otherwise bad output is generated"
     stringLen := index2Arg - index1 + 1.
     stringLen > 8000 ifTrue:[
-	index2 := index1 + 8000 - 1.
+        index2 := index1 + 8000 - 1.
     ]  ifFalse:[
-	stringLen <= 0 ifTrue:[^ self].
-	index2 := index2Arg.
+        stringLen <= 0 ifTrue:[^ self].
+        index2 := index2Arg.
     ].
     bytesPerCharacter := aString bitsPerCharacter // 8.
     transformation := aGC transformation.
 
     clipR := aGC clippingBoundsOrNil.
     clipR notNil ifTrue:[
-	clipX := clipR left.
-	clipY := clipR top.
-	clipW := clipR width.
-	clipH := clipR height.
-	"/ YES YES YES: this MUST be transformed!!
-	"/ (see htmlView) fix the notebook, please.
-	transformation notNil ifTrue:[
-	    clipPnt := transformation transformPoint:(clipX @ clipY).
-	    clipX := clipPnt x ceiling.
-	    clipY := clipPnt y ceiling.
+        clipX := clipR left.
+        clipY := clipR top.
+        clipW := clipR width.
+        clipH := clipR height.
+        "/ YES YES YES: this MUST be transformed!!
+        "/ (see htmlView) fix the notebook, please.
+        transformation notNil ifTrue:[
+            clipPnt := transformation transformPoint:(clipX @ clipY).
+            clipX := clipPnt x ceiling.
+            clipY := clipPnt y ceiling.
 "/            clipX := (transformation applyToX:clipX) ceiling.
 "/            clipY := (transformation applyToY:clipY) ceiling.
-	].
+        ].
     ].
 
     transformation isNil ifTrue:[
-	drawX := xArg.
-	drawY := yArg.
+        drawX := xArg.
+        drawY := yArg.
     ] ifFalse:[
-	drawPnt := transformation transformPoint:(xArg @ yArg).
-	drawX := drawPnt x ceiling.
-	drawY := drawPnt y ceiling.
+        drawPnt := transformation transformPoint:(xArg @ yArg).
+        drawX := drawPnt x ceiling.
+        drawY := drawPnt y ceiling.
 "/        drawX := (transformation applyToX:xArg) ceiling.
 "/        drawY := (transformation applyToY:yArg) ceiling.
     ].
@@ -615,151 +644,161 @@
     fg  :=  aGC paint.
     fgPixel := fg colorId.
     "/ fgPixel notNil ifTrue:[
-	fgR := fg scaledRed.
-	fgG := fg scaledGreen.
-	fgB := fg scaledBlue.
-	fgA := (fg alpha * 65535) rounded.
+        fgR := fg scaledRed.
+        fgG := fg scaledGreen.
+        fgB := fg scaledBlue.
+        fgA := (fg alpha * 65535) rounded.
     "/].
     fgR isNil ifTrue:[
-	"/ when drawing into a pixmap...
-	fg colorId == 0 ifTrue:[
-	    fgR := fgG := fgB := 0.
-	] ifFalse:[
-	    fgR := fgG := fgB := 16rFFFF.
-	]
+        "/ when drawing into a pixmap...
+        fg colorId == 0 ifTrue:[
+            fgR := fgG := fgB := 0.
+        ] ifFalse:[
+            fgR := fgG := fgB := 16rFFFF.
+        ]
     ].
 
     opaque ifTrue:[
-	bg  := aGC backgroundPaint.
-	bgPixel := bg colorId.
-	"/bgPixel notNil ifTrue:[
-	    bgR := bg scaledRed.
-	    bgG := bg scaledGreen.
-	    bgB := bg scaledBlue.
-	    bgA := (bg alpha * 65535) rounded.
-	"/].
-	bgR isNil ifTrue:[
-	    "/ when drawing into a pixmap...
-	    bg colorId == 0 ifTrue:[
-		bgR := bgG := bgB := 0.
-	    ] ifFalse:[
-		bgR := bgG := bgB := 16rFFFF.
-	    ]
-	].
+        bg  := aGC backgroundPaint.
+        bgPixel := bg colorId.
+        "/bgPixel notNil ifTrue:[
+            bgR := bg scaledRed.
+            bgG := bg scaledGreen.
+            bgB := bg scaledBlue.
+            bgA := (bg alpha * 65535) rounded.
+        "/].
+        bgR isNil ifTrue:[
+            "/ when drawing into a pixmap...
+            bg colorId == 0 ifTrue:[
+                bgR := bgG := bgB := 0.
+            ] ifFalse:[
+                bgR := bgG := bgB := 16rFFFF.
+            ]
+        ].
     ].
     displayId := device displayIdOrErrorIfBroken.
     displayId isNil ifTrue:[
-	^ self.
+        ^ self.
     ].
     screen := device screen.
     drawableId := aGC drawableId.
+    aGC addDependent:self.      "I need to be informed, when the GC is destroyed"
 
 %{
 #ifdef XFT
-    XftFont *font;
-    XftDraw *draw;
     XftColor color;
     XGlyphInfo extents;
     XRectangle clipRX;
-    char* string;
+    char *string;
     int len;
     int __bytesPerCharacter;
+    XftDraw *__sharedDrawId;
+    XftFont *__xftFont = XFT_FONT(__INST(fontId));
 
     if (!(__bothSmallInteger(drawX, drawY)
-	  && __bothSmallInteger(index1, index2)
-	  && __isSmallInteger(bytesPerCharacter)
-	  && (__isSmallInteger(fgPixel) || (__bothSmallInteger(fgR, fgG) && __bothSmallInteger(fgB, fgA)))
-	  && (opaque == false || __isSmallInteger(bgPixel) || (__bothSmallInteger(bgR, bgG) && __bothSmallInteger(bgB, bgA)))
-	  && __isNonNilObject(aString)
+          && __bothSmallInteger(index1, index2)
+          && __isSmallInteger(bytesPerCharacter)
+          && (__isSmallInteger(fgPixel) || (__bothSmallInteger(fgR, fgG) && __bothSmallInteger(fgB, fgA)))
+          && (opaque == false || __isSmallInteger(bgPixel) || (__bothSmallInteger(bgR, bgG) && __bothSmallInteger(bgB, bgA)))
+          && __isNonNilObject(aString)
     )) {
-	goto err;
+        goto err;
     }
 
     __bytesPerCharacter = __intVal(bytesPerCharacter);
 
-    if ( __INST(sharedDrawId) == nil ) {
-	__INST(sharedDrawId) = XFT_DRAW_HANDLE_NEW ( XftDrawCreate ( DISPLAY( displayId ) ,
-					       DRAWABLE( drawableId ) ,
-					       DefaultVisual( DISPLAY( displayId), SCREEN (screen) ) ,
-					       DefaultColormap( DISPLAY( displayId), SCREEN (screen) ) ) );
-	__STORE(self, __INST(sharedDrawId));
+    if (__INST(sharedDrawId) == nil) {
+        __sharedDrawId = XftDrawCreate(DISPLAY(displayId),
+                                       DRAWABLE(drawableId),
+                                       DefaultVisual(DISPLAY(displayId), SCREEN(screen)),
+                                       DefaultColormap(DISPLAY(displayId), SCREEN(screen)));
+        __INST(sharedDrawId) = XFT_DRAW_HANDLE_NEW(__sharedDrawId);
+        __STORE(self, __INST(sharedDrawId));
+    } else if (XftDrawDrawable(__sharedDrawId = XFT_DRAW(__INST(sharedDrawId))) != DRAWABLE(drawableId)) {
+        XftDrawChange(__sharedDrawId, DRAWABLE(drawableId));
     }
 
-    if ( XftDrawDrawable ( XFT_DRAW ( __INST(sharedDrawId) ) ) != DRAWABLE( drawableId ) ) {
-	XftDrawChange( XFT_DRAW( __INST(sharedDrawId) ) , DRAWABLE( drawableId ) );
-    }
-
-    string = __stringVal( aString ) + (( __intVal(index1) - 1 ) * __bytesPerCharacter);
+    string = __stringVal(aString) + ((__intVal(index1) - 1 ) * __bytesPerCharacter);
     len = __intVal(index2) - __intVal(index1) + 1;
 
     if (clipR != nil) {
-	clipRX.x = __intVal(clipX);
-	clipRX.y = __intVal(clipY);
-	clipRX.width = __intVal(clipW);
-	clipRX.height = __intVal(clipH);
-	XftDrawSetClipRectangles( XFT_DRAW( __INST( sharedDrawId ) ) , 0, 0, &clipRX, 1);
+        clipRX.x = __intVal(clipX);
+        clipRX.y = __intVal(clipY);
+        clipRX.width = __intVal(clipW);
+        clipRX.height = __intVal(clipH);
+        XftDrawSetClipRectangles(__sharedDrawId, 0, 0, &clipRX, 1);
     } else {
-	XftDrawSetClip( XFT_DRAW( __INST( sharedDrawId ) ) , 0);
+        XftDrawSetClip(__sharedDrawId, 0);
     }
 
     if (opaque == true) {
-	if (bgPixel != nil) {
-	    color.pixel = (unsigned long)__intVal(bgPixel);
-	}
-	// else {
-	    color.color.red = __intVal(bgR);
-	    color.color.green = __intVal(bgG);
-	    color.color.blue = __intVal(bgB);
-	    color.color.alpha = __intVal(bgA);
-	// }
-	switch (__bytesPerCharacter) {
-	case 1:
-	    XftTextExtents8( DISPLAY( displayId ), XFT_FONT( __INST( fontId ) ), (FcChar8*)string, len, &extents);
-	    break;
-	case 2:
-	    XftTextExtents16( DISPLAY( displayId ), XFT_FONT( __INST( fontId ) ), (FcChar16*)string, len, &extents);
-	    break;
-	case 4:
-	    XftTextExtents32( DISPLAY( displayId ), XFT_FONT( __INST( fontId ) ), (FcChar32*)string, len, &extents);
-	    break;
-	}
-	XftDrawRect( XFT_DRAW ( __INST( sharedDrawId ) ), &color, __intVal(drawX) - extents.x, __intVal(drawY) - XFT_FONT( __INST( fontId ) )->ascent, extents.width, XFT_FONT(__INST (fontId ) )->height);
+        if (bgPixel != nil) {
+            color.pixel = (unsigned long)__intVal(bgPixel);
+        }
+        // else {
+            color.color.red = __intVal(bgR);
+            color.color.green = __intVal(bgG);
+            color.color.blue = __intVal(bgB);
+            color.color.alpha = __intVal(bgA);
+        // }
+        switch (__bytesPerCharacter) {
+        case 1:
+            XftTextExtents8(DISPLAY(displayId), __xftFont, (FcChar8*)string, len, &extents);
+            break;
+        case 2:
+            XftTextExtents16(DISPLAY(displayId), __xftFont, (FcChar16*)string, len, &extents);
+            break;
+        case 4:
+            XftTextExtents32(DISPLAY(displayId), __xftFont, (FcChar32*)string, len, &extents);
+            break;
+        }
+        XftDrawRect(__sharedDrawId, &color, __intVal(drawX) - extents.x, __intVal(drawY) - __xftFont->ascent, extents.width, __xftFont->height);
     }
     if (fgPixel != nil) {
-	color.pixel = (unsigned long)__intVal(fgPixel);
+        color.pixel = (unsigned long)__intVal(fgPixel);
     }
     // else {
-	color.color.red = __intVal(fgR);
-	color.color.green = __intVal(fgG);
-	color.color.blue = __intVal(fgB);
-	color.color.alpha = __intVal(fgA);
+        color.color.red = __intVal(fgR);
+        color.color.green = __intVal(fgG);
+        color.color.blue = __intVal(fgB);
+        color.color.alpha = __intVal(fgA);
     // }
     switch (__bytesPerCharacter) {
     case 1:
-	XftDrawString8( XFT_DRAW ( __INST( sharedDrawId ) ), &color, XFT_FONT( __INST( fontId ) ),
-			__intVal(drawX),
-			__intVal(drawY),
-			(FcChar8*)string,
-			len);
-	RETURN ( self );
-	break;
+        XftDrawString8(__sharedDrawId, &color,__xftFont,
+                        __intVal(drawX),
+                        __intVal(drawY),
+                        (FcChar8*)string,
+                        len);
+        break;
+
     case 2:
-	XftDrawString16( XFT_DRAW ( __INST( sharedDrawId ) ), &color, XFT_FONT( __INST( fontId ) ),
-			__intVal(drawX),
-			__intVal(drawY),
-			(FcChar16*)string,
-			len);
-	RETURN ( self );
-	break;
+        XftDrawString16(__sharedDrawId, &color, __xftFont,
+                        __intVal(drawX),
+                        __intVal(drawY),
+                        (FcChar16*)string,
+                        len);
+        break;
+
     case 4:
-	XftDrawString32( XFT_DRAW ( __INST( sharedDrawId ) ), &color, XFT_FONT( __INST( fontId ) ),
-			__intVal(drawX),
-			__intVal(drawY),
-			(FcChar32*)string,
-			len);
-	RETURN ( self );
-	break;
+        XftDrawString32(__sharedDrawId, &color, __xftFont,
+                        __intVal(drawX),
+                        __intVal(drawY),
+                        (FcChar32*)string,
+                        len);
+        break;
+
+    default:
+        goto err;
     }
+
+# if 0 // this has been superseeded by receiving change messages on view destroy
+    // Have to disassociate the drawableId - otherwise we get an X11 error 'RenderBadPicture (invalid Picture parameter)'
+    // when the drawable (the window) is destroyed.
+    XftDrawChange(__sharedDrawId, None);
+# endif
+    RETURN(self);
+
     err:;
 #endif
 %}.
@@ -774,8 +813,8 @@
 primitiveFailed
     <resource: #skipInDebuggersWalkBack>
 
-    self xftAvailable ifFalse:[
-	super primitiveFailed:'Xft support is not configured'.
+    self class xftAvailable ifFalse:[
+        super primitiveFailed:'Xft support is not configured'.
     ].
     super primitiveFailed
 !
@@ -783,8 +822,8 @@
 primitiveFailed:errorString
     <resource: #skipInDebuggersWalkBack>
 
-    self xftAvailable ifFalse:[
-	super primitiveFailed:'Xft support is not configured'.
+    self class xftAvailable ifFalse:[
+        super primitiveFailed:'Xft support is not configured'.
     ].
     super primitiveFailed:errorString
 ! !
@@ -941,35 +980,58 @@
 
 !XftFontDescription methodsFor:'primitives'!
 
-xftAvailable
+disassociateXftDrawableFrom:drawableId
+    "Disassociate the XftDrawable from drawableId.
+     This mist be done before the drawable is destroyed,
+     otherwise the XftDrawable is destroyed together with the drawable,
+     and X11 errors will be signaled."
+
+    | error |
+
 %{
 #ifdef XFT
-    RETURN ( true )
+    if (!__isExternalAddressLike(__INST(sharedDrawId))) {
+        // nothing to disasassociate from...
+        RETURN(self);
+    }
+    if (!__isExternalAddressLike(drawableId)) {
+        error = @symbol(BadArg);
+        goto err;
+    }
+    if (XftDrawDrawable(XFT_DRAW(__INST(sharedDrawId))) == DRAWABLE(drawableId)) {
+        XftDrawChange(XFT_DRAW(__INST(sharedDrawId)), None);
+    }
+    RETURN(self);
+err:;
 #endif
 %}.
-    ^ false
+    self primitiveFailed: error
 
-    "Created: / 20-12-2013 / 21:10:25 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Created: / 26-12-2013 / 12:17:36 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 !
 
-xftDrawChange: xftDrawId drawable: drawableId
+xftDrawChange:xftDrawId drawable:drawableId
     | error |
 
 %{
 #ifdef XFT
     if ( ! __isExternalAddressLike(xftDrawId) ) {
-	error = @symbol(BadArg1);
-	goto err;
+        error = @symbol(BadArg1);
+        goto err;
+    }
+    if (drawableId == nil) {
+        XftDrawChange(XFT_DRAW(xftDrawId), None);
+        RETURN (self);
     }
     if ( ! __isExternalAddressLike(drawableId) ) {
-	error = @symbol(BadArg2);
-	goto err;
+        error = @symbol(BadArg2);
+        goto err;
     }
     if (XftDrawDrawable( XFT_DRAW(xftDrawId) ) != DRAWABLE( drawableId ) ) {
-	XftDrawChange( XFT_DRAW(xftDrawId) , DRAWABLE( drawableId ) );
+        XftDrawChange( XFT_DRAW(xftDrawId) , DRAWABLE( drawableId ) );
     }
-    RETURN ( self );
-    err:;
+    RETURN (self);
+err:;
 #endif
 %}.
     self primitiveFailed: error
@@ -1771,6 +1833,12 @@
 
 !XftFontDescription methodsFor:'testing'!
 
+isScaledFont
+    "Xft fonts are always scaled"
+
+    ^ true
+!
+
 isUsed
     ^ sharedDrawId notNil
 !
@@ -2094,11 +2162,11 @@
 !XftFontDescription class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libview/XftFontDescription.st,v 1.70 2015-05-31 09:29:15 cg Exp $'
+    ^ '$Header$'
 !
 
 version_CVS
-    ^ '$Header: /cvs/stx/stx/libview/XftFontDescription.st,v 1.70 2015-05-31 09:29:15 cg Exp $'
+    ^ '$Header$'
 ! !