# HG changeset patch # User Jan Vrany # Date 1388315008 -3600 # Node ID 8bf2372670d971a1c5e27bbf777bcd37bd6da156 # Parent d90dd329fe6af0be9ffab37c166011a652234ab4 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) diff -r d90dd329fe6a -r 8bf2372670d9 XftFontDescription.st --- a/XftFontDescription.st Tue Dec 24 12:16:04 2013 +0100 +++ b/XftFontDescription.st Sun Dec 29 12:03:28 2013 +0100 @@ -1,7 +1,8 @@ "{ Package: 'stx:libview' }" FontDescription subclass:#XftFontDescription - instanceVariableNames:'device fontId drawId' + instanceVariableNames:'device fontId drawId lasrFgColor lastFgColorId lastBgColor + lastBgColorId' classVariableNames:'' poolDictionaries:'' category:'Graphics-Support' @@ -20,13 +21,24 @@ #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 # include -# define __XftFontVal(handle) ((XftFont*)__externalAddressVal(handle)) -# define __XftPatternVal(handle) ((XftPattern*)__externalAddressVal(handle)) -# define __XftDrawVal(handle) ((XftDraw*)__externalAddressVal(handle)) -# define __XftColorVal(handle) ((XftColor*)__externalAddressVal(handle)) + #endif %} @@ -81,7 +93,7 @@ textView := EditTextView new. textView origin:0.0 @ 0.0 corner:1.0 @ 1.0. - textView basicFont: (XftFontDescription family: 'helvetica' size: 30). + textView basicFont: (XftFontDescription family: 'helvetica' size: 16). top addSubView:textView. @@ -90,6 +102,65 @@ top open. "Created: / 20-12-2013 / 00:04:57 / Jan Vrany " + "Modified: / 29-12-2013 / 10:28:41 / Jan Vrany " +! ! + +!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 " + "Modified: / 29-12-2013 / 11:38:43 / Jan Vrany " ! ! !XftFontDescription methodsFor:'error reporting'! @@ -135,7 +206,7 @@ ] ifFalse:[ self xftPatternAdd: myPatternId attribute: 'size' value: size. ]. - newFontId := self xftFontOpenPattern: aGraphicsDevice displayId pattern: myPatternId. + newFontId := self xftFontOpenPattern: aGraphicsDevice displayId pattern: myPatternId. newFontId notNil ifTrue:[ "/ Good, this font exist!! fontId := newFontId. @@ -159,7 +230,7 @@ newFontId isNil ifTrue:[ self error: 'Pattern matched, but font could be open (should not happen)'. ]. - ^ self class new + ^ self class new setDevice: aGraphicsDevice patternId: closestPatternId2 fontId: newFontId; yourself. ]. @@ -194,7 +265,7 @@ device := deviceArg. fontId := fontIdArg. - family := self xftPatternGet: patternIdArg attribute: 'family' index: 0. + 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']. @@ -219,6 +290,251 @@ "Created: / 20-12-2013 / 21:10:25 / Jan Vrany " ! +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 " +! + +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 " +! + +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 " +! + +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 " +! + +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 " +! + +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 " + "Modified: / 29-12-2013 / 11:29:57 / Jan Vrany " +! + xftFontGetAscent: fontIdArg | error | @@ -231,7 +547,7 @@ error = @symbol(BadArg1); goto err; } - v = ((XftFont*)__externalAddressVal(fontIdArg))->ascent; + v = XFT_FONT(fontIdArg)->ascent; RETURN ( __MKINT( v ) ); err:; #endif @@ -253,7 +569,7 @@ error = @symbol(BadArg1); goto err; } - v = ((XftFont*)__externalAddressVal(fontIdArg))->descent; + v = XFT_FONT(fontIdArg)->descent; RETURN ( __MKINT( v ) ); err:; #endif @@ -275,7 +591,7 @@ error = @symbol(BadArg1); goto err; } - v = ((XftFont*)__externalAddressVal(fontIdArg))->height; + v = XFT_FONT(fontIdArg)->height; RETURN ( __MKINT( v ) ); err:; #endif @@ -297,7 +613,7 @@ error = @symbol(BadArg1); goto err; } - p = ((XftFont*)__externalAddressVal(fontIdArg))->pattern; + p = XFT_FONT(fontIdArg)->pattern; if (p == NULL) { RETURN ( nil ); } else { @@ -334,7 +650,7 @@ goto err; } - p = XftFontMatch( __externalAddressVal(displayId) , __intVal( screen ), __externalAddressVal( patternId ), &r ); + p = XftFontMatch( DISPLAY(displayId) , SCREEN( screen ), XFT_PATTERN( patternId ), &r ); if (r == XftResultMatch) { RETURN ( __MKEXTERNALADDRESS ( p ) ); } else { @@ -368,7 +684,7 @@ goto err; } - f = XftFontOpenPattern( __externalAddressVal(displayId) , __externalAddressVal( patternId ) ); + f = XftFontOpenPattern( DISPLAY(displayId) , XFT_PATTERN( patternId ) ); if (f == NULL) { RETURN ( nil ); } else { @@ -438,7 +754,7 @@ error = @symbol(BadArg3); goto err; } - b = XftPatternAdd( __externalAddressVal(pattern), __stringVal(attribute), v, append == true ? True : False ); + b = XftPatternAdd( XFT_PATTERN(pattern), __stringVal(attribute), v, append == true ? True : False ); RETURN ( b == True ? true : false ); err:; @@ -477,7 +793,7 @@ error = @symbol(BadArg2); goto err; } - XftPatternDel( __externalAddressVal(pattern), __stringVal ( attribute ) ); + XftPatternDel( XFT_PATTERN(pattern), __stringVal ( attribute ) ); RETURN ( self ); err:; @@ -501,7 +817,7 @@ error = @symbol(BadArg1); goto err; } - XftPatternDestroy( __externalAddressVal(addr) ); + XftPatternDestroy( XFT_PATTERN(addr) ); RETURN ( self ); err:; @@ -526,7 +842,7 @@ error = @symbol(BadArg1); goto err; } - RETURN ( __MKEXTERNALADDRESS ( XftPatternDuplicate( __externalAddressVal(addr) ) ) ); + RETURN ( __MKEXTERNALADDRESS ( XftPatternDuplicate( XFT_PATTERN(addr) ) ) ); err:; #endif %}. @@ -559,7 +875,7 @@ error = @symbol(BadArg3); goto err; } - r = XftPatternGet(__externalAddressVal( pattern ), __stringVal( attribute ), __intVal( index ), &v); + r = XftPatternGet(XFT_PATTERN(pattern), __stringVal( attribute ), __intVal( index ), &v); if ( r != XftResultMatch) { RETURN ( nil ); } @@ -584,6 +900,61 @@ "Created: / 20-12-2013 / 21:50:44 / Jan Vrany " "Modified: / 21-12-2013 / 01:06:25 / Jan Vrany " +! + +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 " + "Modified: / 21-12-2013 / 20:53:28 / Jan Vrany " ! ! !XftFontDescription methodsFor:'queries-dimensions'! @@ -610,15 +981,36 @@ ^ self xftFontGetHeight: fontId "Created: / 21-12-2013 / 01:20:21 / Jan Vrany " +! + +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 " +! + +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 " ! ! !XftFontDescription class methodsFor:'documentation'! version - ^ '$Header: /cvs/stx/stx/libview/XftFontDescription.st,v 1.3 2013-12-21 00:21:22 vrany Exp $' + ^ '$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.3 2013-12-21 00:21:22 vrany Exp $' + ^ '$Header: /cvs/stx/stx/libview/XftFontDescription.st,v 1.4 2013-12-29 11:03:28 vrany Exp $' ! !