--- a/WinPrinterContext.st Mon Apr 23 11:31:34 2007 +0200
+++ b/WinPrinterContext.st Mon Apr 23 11:32:45 2007 +0200
@@ -12,7 +12,7 @@
"{ Package: 'stx:libview2' }"
PrinterContext subclass:#WinPrinterContext
- instanceVariableNames:''
+ instanceVariableNames:'deviceFonts'
classVariableNames:''
poolDictionaries:''
category:'Interface-Printing'
@@ -227,10 +227,12 @@
hDC := aPrinterInfo createDC.
hDC = 0 ifTrue: [ ^self error: 'Error while opening printer.' ].
- printerDevice := WinPrinter on: aPrinterInfo.
- printerDevice printerDC:hDC.
-
printerContext := self new.
+
+ printerDevice := printerContext.
+"/ printerDevice := WinPrinter on: aPrinterInfo.
+"/ printerDevice printerDC:hDC.
+
printerContext printerInfo: aPrinterInfo.
printerContext setDevice:printerDevice id:nil gcId:hDC.
printerContext initExtent.
@@ -273,8 +275,155 @@
"Modified: / 10-10-2006 / 17:33:29 / cg"
! !
+!WinPrinterContext class methodsFor:'not supported yet'!
+
+printAdvancedLines: pairOfPointsArray
+ "Opens a print dialog and prints the given lines"
+
+ | printerInfo printer |
+
+ printerInfo := PrintingDialog getPrinterInfo.
+ printerInfo isNil ifTrue:[^self].
+
+ printer := self fromPrinterInfo: printerInfo.
+ [
+ printer startPrintJob: 'Advanced Lines'.
+ printer foreground:Color red background:Color white.
+ pairOfPointsArray
+ do:[:pairOfPointsAndContext |
+ |pairOfPoints|
+ pairOfPoints := pairOfPointsAndContext at:1.
+ printer
+ lineWidth: (pairOfPointsAndContext at:2);
+ lineStyle: (pairOfPointsAndContext at:3);
+ capStyle: (pairOfPointsAndContext at:4);
+ joinStyle: (pairOfPointsAndContext at:5);
+ foreground: (pairOfPointsAndContext at:6);
+
+ displayAdvanceLineFrom: (pairOfPoints at:1) to: (pairOfPoints at:2).
+ ].
+ printer endPrintJob.
+ ] forkAt: 3
+
+ "
+ WinPrinterContext printAdvancedLines:
+ (Array with: (Array with: (Array with:10@10 with:1000@5000) with: 3 with:#dashed with: #butt with: #miter with: Color green)
+ with: (Array with: (Array with:10@10 with:3500@2000) with: 2 with:#solid with: #butt with: #miter with: Color yellow)
+ with: (Array with: (Array with:1000@800 with:6000@5000) with: 8 with:#dashed with: #butt with: #miter with: Color black)
+ with: (Array with: (Array with:2000@2800 with:2000@5000) with: 1 with:#dashed with: #butt with: #miter with: Color red)
+ )
+ "
+
+ "Created: / 07-08-2006 / 12:09:48 / fm"
+ "Modified: / 07-08-2006 / 14:11:17 / fm"
+ "Modified: / 16-04-2007 / 15:37:41 / cg"
+!
+
+printImage: anImage
+ "Opens a print dialog and prints the given image"
+
+ | printerInfo printer |
+
+ printerInfo := PrintingDialog getPrinterInfo.
+ printerInfo isNil ifTrue:[^self].
+
+ printer := self fromPrinterInfo: printerInfo.
+ [
+ printer startPrintJob: 'Image'.
+ printer background:Color white.
+ anImage displayOn:printer x:100 y:100.
+ printer endPrintJob.
+ ] forkAt: 3
+
+ "
+ WinPrinterContext printImage: (Image fromFile:'C:\vsw311\pavheadr.gif').
+ WinPrinterContext printImage: XPToolbarIconLibrary help32x32Icon.
+ WinPrinterContext printImage: XPToolbarIconLibrary eraseXP28x28Icon.
+
+ "
+
+ "Created: / 07-08-2006 / 11:46:52 / fm"
+ "Modified: / 16-04-2007 / 15:37:34 / cg"
+! !
+
!WinPrinterContext class methodsFor:'testing & examples'!
+fillCircles: arrayOfPointsAndRadiusWithContextArray
+ "Opens a print dialog and prints the given circles"
+
+ | printerInfo printer |
+
+ printerInfo := PrintingDialog getPrinterInfo.
+ printerInfo isNil ifTrue:[^self].
+
+ printer := self fromPrinterInfo: printerInfo.
+ [
+ printer startPrintJob: 'Fill Circles'.
+ arrayOfPointsAndRadiusWithContextArray
+ do:[:pointsAndRadiusWithContextArray |
+ printer foreground:(pointsAndRadiusWithContextArray at:3).
+ printer fillCircle:(pointsAndRadiusWithContextArray at:1)
+ radius:(pointsAndRadiusWithContextArray at:2).
+ ].
+ printer endPrintJob.
+ ] forkAt: 3
+
+ "
+ WinPrinterContext fillCircles:
+ (Array with: (Array with: 800@800 with: 600 with:Color red)
+ with: (Array with: 1500@1500 with: 1000 with:Color blue)
+ with: (Array with: 4000@2500 with: 2000 with:Color gray))
+ "
+
+ "Created: / 07-08-2006 / 11:46:52 / fm"
+ "Modified: / 16-04-2007 / 15:37:34 / cg"
+!
+
+fillPolygons: polygonsWithContextArray
+ "Opens a print dialog and prints the given polygons"
+
+ | printerInfo printer |
+
+ printerInfo := PrintingDialog getPrinterInfo.
+ printerInfo isNil ifTrue:[^self].
+
+ printer := self fromPrinterInfo: printerInfo.
+ [
+ printer startPrintJob: 'Fill Polygons'.
+ polygonsWithContextArray
+ do:[:polygonWithContextArray |
+ |aPolygon|
+ aPolygon := polygonWithContextArray at: 1.
+ printer foreground:(polygonWithContextArray at: 2).
+ aPolygon displayFilledOn: printer.
+ ].
+ printer endPrintJob.
+ ] forkAt: 3
+
+ "
+ WinPrinterContext fillPolygons:
+ (Array with: (Array with: (Polygon vertices:(
+ Array
+ with:100@100
+ with:600@1000
+ with:3500@4000
+ with:100@4000
+ with:100@100))
+ with: Color red)
+ with: (Array with: (Polygon vertices:(
+ Array
+ with:1000@1000
+ with:1000@2000
+ with:2000@1000))
+ with: Color blue)
+ )
+ "
+
+ "Created: / 07-08-2006 / 12:09:48 / fm"
+ "Modified: / 07-08-2006 / 14:11:17 / fm"
+ "Modified: / 16-04-2007 / 15:37:43 / cg"
+!
+
fillRectangles: rectangles
"Opens a print dialog and prints the given rectangles"
@@ -416,7 +565,7 @@
"Modified: / 16-04-2007 / 15:37:38 / cg"
!
-printLines: pairOfPointsArray
+printLines: pairOfPointsWithContextArray
"Opens a print dialog and prints the given lines"
| printerInfo printer |
@@ -426,19 +575,26 @@
printer := self fromPrinterInfo: printerInfo.
[
- printer startPrintJob: 'Lines'.
- printer foreground:Color red background:Color white.
- pairOfPointsArray
- do:[:pairOfPoints |
- printer displayLineFrom: (pairOfPoints at:1) to: (pairOfPoints at:2).
- ].
- printer endPrintJob.
+ printer startPrintJob: 'Lines'.
+ pairOfPointsWithContextArray
+ do:[:pairOfPointsAndContext |
+ |pairOfPoints|
+ pairOfPoints := pairOfPointsAndContext at: 1.
+ printer
+ foreground:(pairOfPointsAndContext at:2);
+ lineWidth: (pairOfPointsAndContext at:3);
+ lineStyle: (pairOfPointsAndContext at:4);
+ displayLineFrom: (pairOfPoints at:1) to: (pairOfPoints at:2).
+ ].
+ printer endPrintJob.
] forkAt: 3
"
WinPrinterContext printLines:
- (Array with: (Array with:10@10 with:1000@5000)
- with: (Array with:10@10 with:3500@2000))
+ (Array with: (Array with:(Array with:10@10 with:1000@5000) with: Color red with:4 with: #solid)
+ with: (Array with:(Array with:10@10 with:3500@2000) with: Color blue with:1 with: #dashed)
+ with: (Array with:(Array with:1000@800 with:6000@5000) with: Color black with: 1 with:#dotted)
+ with: (Array with: (Array with:2000@2800 with:2000@5000) with: Color green with:8 with: nil))
"
"Created: / 07-08-2006 / 12:09:48 / fm"
@@ -485,22 +641,29 @@
printer := self fromPrinterInfo: printerInfo.
[
- printer startPrintJob: 'Polygons'.
- printer foreground:Color black background:Color white.
- polygons
- do:[:aPolygon |
- aPolygon displayStrokedOn: printer.
- ].
- printer endPrintJob.
+ printer startPrintJob: 'Polygons'.
+ printer foreground:Color black background:Color white.
+ polygons
+ do:[:aPolygon |
+ aPolygon displayStrokedOn: printer.
+ ].
+ printer endPrintJob.
] forkAt: 3
"
WinPrinterContext printPolygons:
- (Array with: (Polygon vertices:(
- Array
- with:10@10
- with:60@10
- with:35@60)))
+ (Array with: (Polygon vertices:(
+ Array
+ with:100@100
+ with:600@1000
+ with:3500@4000
+ with:100@4000
+ with:100@100))
+ with: (Polygon vertices:(
+ Array
+ with:1000@1000
+ with:1000@2000
+ with:2000@1000)))
"
"Created: / 07-08-2006 / 12:09:48 / fm"
@@ -538,7 +701,7 @@
"Modified: / 16-04-2007 / 15:37:46 / cg"
!
-printRectangles: rectangles
+printRectangles: rectanglesWithContextArray
"Opens a print dialog and prints the given rectangles"
| printerInfo printer |
@@ -548,23 +711,31 @@
printer := self fromPrinterInfo: printerInfo.
[
- printer startPrintJob: 'Rectangles'.
- printer foreground:Color red background:Color white.
- rectangles
- do:[:rectangle |
- printer displayRectangleX: rectangle origin x
- y: rectangle origin y
- width: rectangle width
- height: rectangle height.
- ].
- printer endPrintJob.
+ printer startPrintJob: 'Rectangles'.
+ printer foreground:Color red background:Color white.
+ rectanglesWithContextArray do:[:rectangleWithContextArray |
+ |rectangle|
+ rectangle := rectangleWithContextArray at: 1.
+ printer
+ foreground:(rectangleWithContextArray at:2);
+ lineWidth: (rectangleWithContextArray at:3);
+ lineStyle: (rectangleWithContextArray at:4);
+ displayRectangleX: rectangle origin x
+ y: rectangle origin y
+ width: rectangle width
+ height: rectangle height.
+ ].
+ printer endPrintJob.
] forkAt: 3
"
WinPrinterContext printRectangles:
- (Array with: (Rectangle left:20 top:20 width:400 height:600)
- with: (Rectangle left:40 top:40 width:600 height:400)
- )
+ (Array with: (Array with: (Rectangle left:30 top:10 width:400 height:600) with: Color red with:4 with: #solid)
+ with: (Array with: (Rectangle left:100 top:140 width:700 height:800) with: Color blue with:1 with: #dashed)
+ with: (Array with: (Rectangle left:800 top:1500 width:2600 height:3400) with: Color green with:1 with: #dotted)
+ with: (Array with: (Rectangle left:1000 top:1200 width:1400 height:1600) with: Color gray with:8 with: #dashed)
+ with: (Array with: (Rectangle left:2600 top:1200 width:1400 height:1600) with: Color darkGray with:1 with: #dashDotDot)
+ )
"
"Created: / 07-08-2006 / 11:40:48 / fm"
@@ -605,6 +776,21 @@
!WinPrinterContext methodsFor:'accessing'!
+depth
+ ^ 24
+!
+
+deviceColors
+
+ ^#()
+!
+
+deviceFonts
+
+ deviceFonts isNil ifTrue:[deviceFonts := CachingRegistry new cacheSize:10.].
+ ^deviceFonts
+!
+
getCharHeight
"Private - answer the height of the font selected in the receiver's
device context."
@@ -625,6 +811,14 @@
"Modified: / 10-10-2006 / 18:15:17 / cg"
!
+getLogicalPixelSizeX
+ ^ printerInfo printQuality ? 600
+!
+
+getLogicalPixelSizeY
+ ^ printerInfo printQuality ? 600
+!
+
numberOfColorBitsPerPixel
^ OperatingSystem getDeviceCaps:gcId index:12 "Bitspixel"
@@ -682,22 +876,3116 @@
"Created: / 01-08-2006 / 16:14:08 / fm"
!
+supportedImageFormats
+ "return an array with supported image formats; each array entry
+ is another array, consisting of depth and bitsPerPixel values."
+
+ |info|
+
+ info := IdentityDictionary new.
+ info at:#depth put:self depth.
+ info at:#bitsPerPixel put:self depth.
+ info at:#padding put:32.
+ ^ Array with:info
+
+ "
+ Disply supportedImageFormats
+ "
+
+ "Modified: / 10.9.1998 / 23:14:05 / cg"
+!
+
+visualType
+ ^ #TrueColor
+! !
+
+!WinPrinterContext methodsFor:'color stuff'!
+
+colorScaledRed:r scaledGreen:g scaledBlue:b
+ "allocate a color with rgb values (0..16rFFFF) - return the color index
+ (i.e. colorID)"
+
+%{ /* NOCONTEXT */
+ int id, ir, ig, ib;
+
+ if (__bothSmallInteger(r, g) && __isSmallInteger(b)) {
+ ir = (__intVal(r) >> 8) & 0xff;
+ ig = (__intVal(g) >> 8) & 0xff;
+ ib = (__intVal(b) >> 8) & 0xff;
+
+ id = RGB( ir, ig, ib);
+
+ RETURN ( __MKSMALLINT(id) );
+ }
+%}.
+ self primitiveFailed.
+ ^ nil
+!
+
+setBackground:bgColorIndex in:aDC
+ "set background color to be drawn with"
+
+%{ /* NOCONTEXT */
+
+ HDC hDC;
+
+ if (__isExternalAddressLike(aDC)) {
+ HANDLE hDC = (HANDLE)(__externalAddressVal(aDC));
+ COLORREF bg, oldBg;
+
+ oldBg = GetBkColor(hDC);
+
+ bg = __intVal(bgColorIndex) & 0xffffff;
+/* bg = (COLORREF)st2RGB(__intVal(bgColorIndex),gcData); */
+
+ if (bg != oldBg) {
+ SetBkColor(hDC, bg);
+ }
+
+ RETURN (self);
+ }
+%}
+!
+
+setBackgroundColor:color in:aGCId
+ "set background color to be drawn with"
+
+ |colorId deviceColor|
+
+ (color isOnDevice:self) ifTrue:[
+ colorId := color colorId.
+ ] ifFalse:[
+ deviceColor := color onDevice:self.
+ deviceColor notNil ifTrue:[
+ colorId := deviceColor colorId.
+ ]
+ ].
+ colorId isNil ifTrue:[
+ 'DeviceWorkstation [warning]: could not set bg color' infoPrintCR.
+ ] ifFalse:[
+ self setBackground:colorId in:aGCId.
+ ]
+!
+
+setForeground:fgColorIndex background:bgColorIndex in:aDC
+ "set foreground and background colors to be drawn with"
+
+%{ /* NOCONTEXT */
+
+ if (__isExternalAddressLike(aDC)) {
+ HANDLE hDC = (HANDLE)(__externalAddressVal(aDC));
+ COLORREF fg, bg, oldFg, oldBg;
+
+/* fg = (COLORREF)st2RGB(__intVal(fgColorIndex),gcData); */
+ fg = __intVal(fgColorIndex) & 0xffffff;
+/* bg = (COLORREF)st2RGB(__intVal(bgColorIndex),gcData); */
+ bg = __intVal(bgColorIndex) & 0xffffff;
+
+ oldFg = GetTextColor(hDC);
+ oldBg = GetBkColor(hDC);
+
+ if ((fg != oldFg) || (bg != oldBg)) {
+ /* Pen only depends upon fg-color */
+ if (fg != oldFg) {
+ SetTextColor(hDC, fg);
+ }
+ if (bg != oldBg) {
+ SetBkColor(hDC, bg);
+ }
+ }
+ RETURN (self);
+ }
+%}
+!
+
+setForeground:fgColorIndex in:aDC
+ "set foreground color to be drawn with"
+
+%{ /* NOCONTEXT */
+
+ HDC hDC;
+
+ if (__isExternalAddressLike(aDC)) {
+ HANDLE hDC = (HANDLE)(__externalAddressVal(aDC));
+ COLORREF fg, oldFg;
+
+ oldFg = GetTextColor(hDC);
+
+ fg = __intVal(fgColorIndex) & 0xffffff;
+/* fg = (COLORREF)st2RGB(__intVal(fgColorIndex),gcData); */
+
+ if (fg != oldFg) {
+ SetTextColor(hDC, fg);
+ }
+
+ RETURN (self);
+ }
+%}
+!
+
+setForegroundColor:color in:aGCId
+ "set the foreground color to be drawn with"
+
+ |colorId deviceColor|
+
+ (color isOnDevice:self) ifTrue:[
+ colorId := color colorId.
+ ] ifFalse:[
+ deviceColor := color onDevice:self.
+ deviceColor notNil ifTrue:[
+ colorId := deviceColor colorId.
+ ]
+ ].
+ colorId isNil ifTrue:[
+ 'DeviceWorkstation [warning]: could not set fg color' infoPrintCR.
+ ] ifFalse:[
+ self setForeground:colorId in:aGCId.
+ ]
+! !
+
+!WinPrinterContext methodsFor:'context stuff'!
+
+getPenFor:aDC
+ "set line attributes"
+
+%{ /* NOCONTEXT */
+
+ if (__isExternalAddressLike(aDC)
+ && __isSmallInteger(__INST(lineWidth))) {
+ HANDLE hDC = (HANDLE)(__externalAddressVal(aDC));
+ COLORREF fgColor;
+ HANDLE hPen, prevPen;
+ int lineStyleInt, capStyleInt, joinStyleInt, lineWidth;
+
+ lineWidth= __INST(lineWidth);
+
+ if (__INST(lineStyle) == @symbol(solid)) {
+ lineStyleInt= PS_SOLID;
+ } else if (__INST(lineStyle) == @symbol(dashed)) {
+ lineStyleInt= PS_DASH;
+ } else if (__INST(lineStyle) == @symbol(dotted)) {
+ lineStyleInt= PS_DOT;
+ } else if (__INST(lineStyle) == @symbol(dashDot)) {
+ lineStyleInt= PS_DASHDOT;
+ } else if (__INST(lineStyle) == @symbol(dashDotDot)) {
+ lineStyleInt= PS_DASHDOTDOT;
+ } else
+ lineStyleInt= PS_SOLID;
+
+ if (__INST(capStyle) == @symbol(round)) {
+ capStyleInt= PS_ENDCAP_ROUND;
+ } else if (__INST(capStyle) == @symbol(square)) {
+ capStyleInt= PS_ENDCAP_SQUARE;
+ } else if (__INST(capStyle) == @symbol(flat)) {
+ capStyleInt= PS_ENDCAP_FLAT;
+ } else
+ capStyleInt= PS_ENDCAP_FLAT;
+
+ if (__INST(joinStyle) == @symbol(bevel)) {
+ joinStyleInt= PS_JOIN_BEVEL;
+ } else if (__INST(joinStyle) == @symbol(miter)) {
+ joinStyleInt= PS_JOIN_MITER;
+ } else if (__INST(joinStyle) == @symbol(round)) {
+ joinStyleInt= PS_JOIN_ROUND;
+ } else
+ joinStyleInt= PS_JOIN_MITER;
+
+
+ fgColor = GetTextColor(hDC);
+
+ hPen = CreatePen(lineStyleInt | capStyleInt | joinStyleInt, lineWidth, fgColor);
+ prevPen = SelectObject(hDC, hPen);
+
+
+ RETURN (self);
+ }
+%}.
+ self primitiveFailed
+!
+
+getPenForContext
+ "set line attributes"
+
+%{ /* NOCONTEXT */
+
+ if (__isExternalAddressLike(__INST(gcId))
+ && __isSmallInteger(__INST(lineWidth))) {
+ HANDLE hDC = (HANDLE)(__externalAddressVal(__INST(gcId)));
+ COLORREF fgColor;
+ HANDLE hPen;
+ int lineStyleInt, capStyleInt, joinStyleInt, lineWidth;
+
+ lineWidth= __INST(lineWidth);
+
+ if (__INST(lineStyle) == @symbol(solid)) {
+ lineStyleInt= PS_SOLID;
+ } else if (__INST(lineStyle) == @symbol(dashed)) {
+ lineStyleInt= PS_DASH;
+ } else if (__INST(lineStyle) == @symbol(dotted)) {
+ lineStyleInt= PS_DOT;
+ } else if (__INST(lineStyle) == @symbol(dashDot)) {
+ lineStyleInt= PS_DASHDOT;
+ } else if (__INST(lineStyle) == @symbol(dashDotDot)) {
+ lineStyleInt= PS_DASHDOTDOT;
+ } else
+ lineStyleInt= PS_SOLID;
+
+ if (__INST(capStyle) == @symbol(round)) {
+ capStyleInt= PS_ENDCAP_ROUND;
+ } else if (__INST(capStyle) == @symbol(square)) {
+ capStyleInt= PS_ENDCAP_SQUARE;
+ } else if (__INST(capStyle) == @symbol(flat)) {
+ capStyleInt= PS_ENDCAP_FLAT;
+ } else
+ capStyleInt= PS_ENDCAP_FLAT;
+
+ if (__INST(joinStyle) == @symbol(bevel)) {
+ joinStyleInt= PS_JOIN_BEVEL;
+ } else if (__INST(joinStyle) == @symbol(miter)) {
+ joinStyleInt= PS_JOIN_MITER;
+ } else if (__INST(joinStyle) == @symbol(round)) {
+ joinStyleInt= PS_JOIN_ROUND;
+ } else
+ joinStyleInt= PS_JOIN_MITER;
+
+
+ fgColor = GetTextColor(hDC);
+
+ hPen = CreatePen(lineStyleInt | capStyleInt | joinStyleInt, lineWidth, fgColor);
+
+ RETURN (self);
+ }
+%}.
+ self primitiveFailed
+!
+
+noClipIn:aWindowId gc:aDC
+ "disable clipping rectangle"
+
+%{ /* NOCONTEXT */
+
+ if (__isExternalAddressLike(aDC)) {
+ HANDLE hDC = (HANDLE)(__externalAddressVal(aDC));
+
+ SelectClipRgn(hDC, NULL);
+ RETURN (self);
+ }
+%}
+!
+
+setBitmapMask:aBitmapId in:aDC
+ "set or clear the drawing mask - a bitmap mask using current fg/bg"
+
+%{ /* NOCONTEXT */
+
+ if (__isExternalAddressLike(aDC)) {
+ HANDLE hDC = (HANDLE)(__externalAddressVal(aDC));
+ HBITMAP oldM;
+
+/* oldM = gcData->hMask;
+ if (__isExternalAddress(aBitmapId))
+ gcData->hMask = _HBITMAPVAL(aBitmapId);
+ else
+ gcData->hMask = 0;
+
+ if (oldM != gcData->hMask) {
+ FLUSH_CACHED_DC(gcData);
+ CPRINTF(("masks set to %x\n",gcData->hMask));
+ } */
+ RETURN (self);
+ }
+%}
+!
+
+setClipX:clipX y:clipY width:clipWidth height:clipHeight in:ignoredDrawableId gc:aDC
+ "clip to a rectangle"
+
+"
+ p--w---
+ | |
+ h | the clipping rectangle
+ | |
+ -------
+ where p = ( clipX, clipY ), w = clipWidth, h = clipHeight
+"
+
+%{ /* NOCONTEXT */
+
+ if (__isExternalAddressLike(aDC)
+ && __bothSmallInteger(clipX, clipY)
+ && __bothSmallInteger(clipWidth, clipHeight) ) {
+ HANDLE hDC;
+ int cX, cY, cW, cH;
+ POINT ptOrg;
+
+
+ hDC = (HANDLE)(__externalAddressVal(aDC));
+
+ GetViewportOrgEx(hDC,&ptOrg);
+
+ // set the clip rectangle
+ // and offset the rectangle by the viewport origin
+
+ cX = __intVal(clipX) + ptOrg.x;
+ cY = __intVal(clipY) + ptOrg.y;
+ cW = __intVal(clipWidth)+ ptOrg.x;
+ cH = __intVal(clipHeight)+ ptOrg.y;
+
+ {
+ HRGN region = CreateRectRgn(cX, cY, cX + cW, cY + cH);
+
+ if (region == NULL ) {
+ console_fprintf(stderr, "WinWorkstat [warning]: clipping region creation failed\n");
+ } else {
+ if (SelectClipRgn(hDC, region) == ERROR ) {
+ console_fprintf(stderr, "WinWorkstat [warning]: select clipping region failed\n");
+ }
+ DeleteObject(region);
+ }
+ }
+ RETURN (self);
+ }
+%}.
+ self primitiveFailed
+!
+
+setDashes:dashList dashOffset:offset in:aGCId
+ "set line attributes"
+
+%{ /* NOCONTEXT */
+
+ if (__isExternalAddressLike(aGCId)) {
+ DPRINTF(("WinWorkstat [warning]: dashes not (yet) implemented\n"));
+ }
+%}
+!
+
+setLineWidth:aNumber style:lineStyle cap:capStyle join:joinStyle in:aDC
+ "set line attributes"
+
+%{ /* NOCONTEXT */
+
+ HDC hDC;
+
+ if (__isExternalAddressLike(aDC)
+ && __isSmallInteger(aNumber)) {
+ HANDLE hDC = (HANDLE)(__externalAddressVal(aDC));
+ int style;
+
+ if (lineStyle == @symbol(solid)) {
+ style = PS_SOLID;
+ } else if (lineStyle == @symbol(dashed)) {
+ style= PS_DASH;
+ } else if (lineStyle == @symbol(dotted)) {
+ style= PS_DOT;
+ } else if (lineStyle == @symbol(dashDot)) {
+ style= PS_DASHDOT;
+ } else if (lineStyle == @symbol(dashDotDot)) {
+ style= PS_DASHDOTDOT;
+ } else
+ style= PS_SOLID;
+
+ if (capStyle == @symbol(round)) {
+ style = PS_ENDCAP_ROUND;
+ } else if (capStyle == @symbol(square)) {
+ style = PS_ENDCAP_SQUARE;
+ } else if (capStyle == @symbol(flat)) {
+ style = PS_ENDCAP_FLAT;
+ } else
+ style = PS_ENDCAP_FLAT;
+
+ if (joinStyle == @symbol(bevel)) {
+ style = PS_JOIN_BEVEL;
+ } else if (joinStyle == @symbol(miter)) {
+ style = PS_JOIN_MITER;
+ } else if (joinStyle == @symbol(round)) {
+ style = PS_JOIN_ROUND;
+ } else
+ style = PS_JOIN_MITER;
+
+
+ RETURN (self);
+ }
+%}.
+ self primitiveFailed
+!
+
+setMaskOriginX:orgX y:orgY in:aDC
+ "set the mask origin"
+
+%{ /* NOCONTEXT */
+
+ if (__isExternalAddress(aDC)
+ && __bothSmallInteger(orgX,orgY)) {
+ HANDLE hDC = (HANDLE)(__externalAddressVal(aDC));
+ int oX, oY, maskOrgX, maskOrgY;
+
+ oX = __intVal(orgX);
+ oY = __intVal(orgY);
+ if ((oX != maskOrgX)
+ || (oY != maskOrgY)) {
+ maskOrgX = __intVal(orgX);
+ maskOrgY = __intVal(orgY);;
+ }
+ RETURN (self);
+ }
+%}
+!
+
setViewportOrg: aPoint
+ "Sets the viewport origin (LOGICAL point (0,0)) of the device context"
+
^ OperatingSystem
- setViewportOrg: gcId "deviceContext"
- x: aPoint x
- y: aPoint y
- oldOrigin: nil
+ setViewportOrg: gcId "deviceContext"
+ x: aPoint x
+ y: aPoint y
+ oldOrigin: nil
"Created: / 01-08-2006 / 16:14:08 / fm"
! !
!WinPrinterContext methodsFor:'drawing'!
+createPixmapWidth:w height:h depth:d
+ "allocate a pixmap on the Xserver, the contents is undefined
+ (i.e. random). Return a bitmap id or nil"
+
+%{
+ HANDLE newBitmapHandle;
+ HANDLE hDC = (HANDLE)(__externalAddressVal(__INST(gcId)));
+
+ /*console_printf("CreateBitmap Color\n");*/
+ if (__bothSmallInteger(w, h) && __isSmallInteger(d) /*&& ISCONNECTED */) {
+ if (__intVal(d) == 1) {
+ newBitmapHandle = CreateBitmap(__intVal(w), __intVal(h) , 1, 1, NULL);
+ } else {
+#if 0
+ if (__intVal(d) != __depth) {
+ console_printf("invalid depth\n");
+ RETURN (nil);
+ }
+#endif
+ newBitmapHandle = CreateCompatibleBitmap(hDC, __intVal(w), __intVal(h) );
+ }
+
+ if (newBitmapHandle) {
+ RETURN ( __MKOBJ(newBitmapHandle));
+ }
+/*
+ DPRINTF(("empty bitmap handle = %x\n", newBitmapHandle));
+*/
+ }
+ RETURN (nil);
+%}
+!
+
+displayArcX:x y:y width:width height:height from:startAngle angle:angle in:ignoredDrawableId with:aDC
+ "draw an arc. If any of x,y, w or h is not an integer, an error is triggered.
+ The angles may be floats or integer - they are given in degrees."
+
+%{
+ int __x, __y, w, h;
+ float angle1, angle2;
+ double f;
+
+ if (__isSmallInteger(startAngle))
+ angle1 = (float)(__intVal(startAngle));
+ else if (__isFloat(startAngle)) {
+ angle1 = (float) __floatVal(startAngle);
+ } else if (__isShortFloat(startAngle)) {
+ angle1 = __shortFloatVal(startAngle);
+ } else goto bad;
+
+ if (__isSmallInteger(angle))
+ angle2 = (float)(__intVal(angle));
+ else if (__isFloat(angle)) {
+ angle2 = (float) __floatVal(angle);
+ } else if (__isShortFloat(angle)) {
+ angle2 = __shortFloatVal(angle);
+ } else goto bad;
+
+ if (angle2 <= 0) {
+ RETURN (self);
+ }
+
+ if (__isExternalAddressLike(aDC)
+ && __bothSmallInteger(x, y)
+ && __bothSmallInteger(width, height))
+ {
+ POINT p;
+ HANDLE hDC = (HANDLE)(__externalAddressVal(aDC));
+ DWORD clr = 0 /* 0xFFFFFFFF */;
+ HANDLE prevPen, hPen;
+ double xB, yB, xE, yE, xR, yR;
+ COLORREF fgColor;
+ int lStyleSymbol, lStyleInt;
+ int lw;
+
+ lw= __intVal(__INST(lineWidth));
+ lStyleSymbol= __INST(lineStyle);
+
+ /* PS_DASH, PS_DOT, PS_DASHDOT, PS_DASHDOTDOT
+ only works with lineWidth = 1 */
+
+ if (lStyleSymbol == @symbol(solid)) {
+ lStyleInt= PS_SOLID;
+ } else if (lStyleSymbol == @symbol(dashed)) {
+ lStyleInt= PS_DASH;
+ } else if (lStyleSymbol == @symbol(dotted)) {
+ lStyleInt= PS_DOT;
+ } else if (lStyleSymbol == @symbol(dashDot)) {
+ lStyleInt= PS_DASHDOT;
+ } else if (lStyleSymbol == @symbol(dashDotDot)) {
+ lStyleInt= PS_DASHDOTDOT;
+ } else if (lStyleSymbol == @symbol(insideFrame)) {
+ lStyleInt= PS_INSIDEFRAME;
+ } else
+ lStyleInt= PS_SOLID;
+
+ fgColor = GetTextColor(hDC);
+ hPen = CreatePen(lStyleInt, lw, fgColor);
+
+ w = __intVal(width);
+ h = __intVal(height);
+ __x = __intVal(x);
+ __y = __intVal(y);
+
+ xR = w / 2;
+ yR = h / 2;
+ if (angle2 - angle1 >= 360) {
+ xB = xE = __x + xR + 0.5;
+ yB = yE = __y /*+ yR + 0.5*/;
+ } else {
+ double sin(), cos();
+ float rad1, rad2;
+
+ if (angle1 <= 180)
+ angle1 = 180 - angle1;
+ else
+ angle1 = 360 + 180 - angle1;
+ angle2 = angle1 - angle2;
+ /* sigh - compute the intersections ... */
+ rad1 = (angle1 * 3.14159265359) / 180.0;
+ rad2 = (angle2 * 3.14159265359) / 180.0;
+ xB = cos(rad1) * xR;
+ yB = sin(rad1) * yR;
+ xE = cos(rad2) * xR;
+ yE = sin(rad2) * yR;
+ xB = __x + xR - xB + 0.5;
+ yB = __y + yR - yB + 0.5;
+ xE = __x + xR - xE + 0.5;
+ yE = __y + yR - yE + 0.5;
+ }
+ prevPen = SelectObject(hDC, hPen);
+ DPRINTF(("Arc x=%d y=%d w=%d h=%d xB=%d xE=%d yB=%d yE=%d a1=%f a2=%f\n",__x,__y,w,h,(int)xB,(int)xE,(int)yB,(int)yE,angle1,angle2));
+ Arc(hDC,
+ __x, __y,
+ __x + w, __y + h,
+ (int)xB, (int)yB,
+ (int)xE, (int)yE);
+
+ SelectObject(hDC, prevPen);
+ DeleteObject(hPen);
+
+ RETURN ( self );
+ }
+ bad: ;
+%}.
+ self primitiveFailed
+
+ "Created: / 07-08-2006 / 10:40:27 / fm"
+ "Modified: / 07-08-2006 / 14:44:21 / fm"
+!
+
+displayLineFromX:x0 y:y0 toX:x1 y:y1 in:ignoredDrawableId with:aDC
+ "draw a line. If the coordinates are not integers, an error is triggered."
+
+%{ /* NOCONTEXT */
+ if (__isExternalAddressLike(aDC)
+ && __bothSmallInteger(x0, y0)
+ && __bothSmallInteger(x1, y1)) {
+ HANDLE hDC = (HANDLE)(__externalAddressVal(aDC));
+ COLORREF fgColor;
+ HANDLE prevPen, hPen;
+ int __x1 = __intVal(x1), __y1 = __intVal(y1);
+ int lStyleSymbol, lStyleInt;
+ int lw;
+
+/* DPRINTF(("displayLine: %d/%d -> %d/%d\n",
+ __intVal(x0), __intVal(y0),
+ __x1, __y1));
+*/
+
+ lw= __intVal(__INST(lineWidth));
+ lStyleSymbol= __INST(lineStyle);
+
+ /* PS_DASH, PS_DOT, PS_DASHDOT, PS_DASHDOTDOT
+ only works with lineWidth = 1 */
+
+ if (lStyleSymbol == @symbol(solid)) {
+ lStyleInt= PS_SOLID;
+ } else if (lStyleSymbol == @symbol(dashed)) {
+ lStyleInt= PS_DASH;
+ } else if (lStyleSymbol == @symbol(dotted)) {
+ lStyleInt= PS_DOT;
+ } else if (lStyleSymbol == @symbol(dashDot)) {
+ lStyleInt= PS_DASHDOT;
+ } else if (lStyleSymbol == @symbol(dashDotDot)) {
+ lStyleInt= PS_DASHDOTDOT;
+ } else if (lStyleSymbol == @symbol(insideFrame)) {
+ lStyleInt= PS_INSIDEFRAME;
+ } else
+ lStyleInt= PS_SOLID;
+
+ fgColor = GetTextColor(hDC);
+ hPen = CreatePen(lStyleInt, lw, fgColor);
+
+ prevPen = SelectObject(hDC, hPen);
+
+ MoveToEx(hDC, __intVal(x0), __intVal(y0), NULL);
+
+ LineTo(hDC, __x1, __y1);
+
+ /*
+ * end-point ...
+ */
+ LineTo(hDC, __x1+1, __y1);
+
+ SelectObject(hDC, prevPen);
+ DeleteObject(hPen);
+
+ RETURN ( self );
+ }
+%}
+!
+
+displayPointX:px y:py in:ignoredDrawableId with:aDC
+ "draw a point. If x/y are not integers, an error is triggered."
+
+%{ /* NOCONTEXT */
+ if (__isExternalAddressLike(aDC)
+ && __bothSmallInteger(px, py)) {
+ HANDLE hDC = (HANDLE)(__externalAddressVal(aDC));
+ POINT p;
+ COLORREF fgColor;
+
+ int __x = __intVal(px), __y = __intVal(py);
+
+ fgColor = GetTextColor(hDC);
+ SetPixelV(hDC, __x, __y, fgColor);
+
+ RETURN ( self );
+ }
+%}
+!
+
+displayPolygon:aPolygon in:aDrawableId with:aDC
+ "draw a polygon, the argument aPolygon is a Collection of individual points,
+ which define the polygon.
+ If any coordinate is not integer, an error is triggered."
+
+ |numberOfPoints|
+
+ numberOfPoints := aPolygon size.
+%{
+ OBJ point, px, py;
+ int i, num;
+
+ if (__isExternalAddressLike(aDC)
+ /* && __isExternalAddress(aDrawableId) */
+ && __isSmallInteger(numberOfPoints)) {
+ HANDLE hDC = (HANDLE)(__externalAddressVal(aDC));
+ POINT p;
+ DWORD clr = 0 /* 0xFFFFFFFF */;
+ HANDLE prevPen, hPen;
+ int lw;
+ COLORREF fgColor;
+ int lStyleSymbol, lStyleInt;
+
+ lw= __intVal(__INST(lineWidth));
+ lStyleSymbol= __INST(lineStyle);
+
+ /* PS_DASH, PS_DOT, PS_DASHDOT, PS_DASHDOTDOT
+ only works with lineWidth = 1 */
+
+ if (lStyleSymbol == @symbol(solid)) {
+ lStyleInt= PS_SOLID;
+ } else if (lStyleSymbol == @symbol(dashed)) {
+ lStyleInt= PS_DASH;
+ } else if (lStyleSymbol == @symbol(dotted)) {
+ lStyleInt= PS_DOT;
+ } else if (lStyleSymbol == @symbol(dashDot)) {
+ lStyleInt= PS_DASHDOT;
+ } else if (lStyleSymbol == @symbol(dashDotDot)) {
+ lStyleInt= PS_DASHDOTDOT;
+ } else if (lStyleSymbol == @symbol(insideFrame)) {
+ lStyleInt= PS_INSIDEFRAME;
+ } else
+ lStyleInt= PS_SOLID;
+
+ num = __intVal(numberOfPoints);
+
+ for (i=0; i<num; i++) {
+ point = __AT_(aPolygon, __MKSMALLINT(i+1));
+ if (! __isPoint(point)) goto fail;
+ px = _point_X(point);
+ py = _point_Y(point);
+ if (! __bothSmallInteger(px, py)) {
+ goto fail;
+ }
+ }
+
+ fgColor = GetTextColor(hDC);
+
+ hPen = CreatePen(lStyleInt, lw, fgColor);
+ prevPen = SelectObject(hDC, hPen);
+
+ for (i=0; i<num; i++) {
+ point = __AT_(aPolygon, __MKSMALLINT(i+1));
+ px = _point_X(point);
+ py = _point_Y(point);
+ p.x = __intVal(px);
+ p.y = __intVal(py);
+ if (i == 0) {
+ MoveToEx(hDC, p.x, p.y, NULL);
+ } else {
+ if (i == (num-1)) {
+ PolylineTo(hDC, &p, 1);
+ } else {
+ LineTo(hDC, p.x, p.y);
+#ifdef PRE_04_JUN_04
+ /*
+ * end-point ...
+ */
+ LineTo(hDC, p.x+1, p.y);
+#endif
+ }
+ }
+ }
+ SelectObject(hDC, prevPen);
+ DeleteObject(hPen);
+
+
+ RETURN ( self );
+ }
+fail: ;
+%}
+
+ "Created: / 07-08-2006 / 14:46:55 / fm"
+!
+
displayPolylines:arrayOfPoints
device displayPolylines:arrayOfPoints in:nil with:gcId
+!
+
+displayPolylines:aPolyline in:ignoredDrawableId with:aDC
+ "draw a polyline, the argument aPolyline is a collection of individual points,
+ which define the lines (p1/p2 pairs); must be even in size.
+ If any coordinate is not integer, an error is triggered."
+
+ |numberOfPoints|
+
+ numberOfPoints := aPolyline size.
+
+%{
+ OBJ point, px, py;
+ int i, num;
+
+ if (__isExternalAddressLike(aDC)
+ && __isSmallInteger(numberOfPoints)) {
+
+ HANDLE hDC = (HANDLE)(__externalAddressVal(aDC));
+ POINT p;
+ HANDLE prevPen, hPen;
+ COLORREF fgColor;
+ int lw;
+ int lStyleSymbol, lStyleInt;
+
+
+ lw= __intVal(__INST(lineWidth));
+ lStyleSymbol= __INST(lineStyle);
+
+ /* PS_DASH, PS_DOT, PS_DASHDOT, PS_DASHDOTDOT
+ only works with lineWidth = 1 */
+
+ if (lStyleSymbol == @symbol(solid)) {
+ lStyleInt= PS_SOLID;
+ } else if (lStyleSymbol == @symbol(dashed)) {
+ lStyleInt= PS_DASH;
+ } else if (lStyleSymbol == @symbol(dotted)) {
+ lStyleInt= PS_DOT;
+ } else if (lStyleSymbol == @symbol(dashDot)) {
+ lStyleInt= PS_DASHDOT;
+ } else if (lStyleSymbol == @symbol(dashDotDot)) {
+ lStyleInt= PS_DASHDOTDOT;
+ } else if (lStyleSymbol == @symbol(insideFrame)) {
+ lStyleInt= PS_INSIDEFRAME;
+ } else
+ lStyleInt= PS_SOLID;
+
+ fgColor = GetTextColor(hDC);
+
+ num = __intVal(numberOfPoints);
+
+ for (i=0; i<num; i++) {
+ point = __AT_(aPolyline, __MKSMALLINT(i+1));
+ if (! __isPoint(point)) goto fail;
+ px = _point_X(point);
+ py = _point_Y(point);
+ if (! __bothSmallInteger(px, py)) {
+ goto fail;
+ }
+ }
+
+ hPen = CreatePen(lStyleInt, lw, fgColor);
+ prevPen = SelectObject(hDC, hPen);
+
+ for (i=0; i<num; i++) {
+ point = __AT_(aPolyline, __MKSMALLINT(i+1));
+ px = _point_X(point);
+ py = _point_Y(point);
+ p.x = __intVal(px);
+ p.y = __intVal(py);
+ DPRINTF(("printing point"));
+ DPRINTF(("displayPolygon: no pen\n"));
+
+ if ((i & 1) == 0) {
+ MoveToEx(hDC, p.x, p.y, NULL);
+ } else {
+ LineTo(hDC, p.x, p.y);
+ /*
+ * end-point ...
+ */
+ LineTo(hDC, p.x+1, p.y);
+ }
+ }
+ SelectObject(hDC, prevPen);
+ DeleteObject(hPen);
+ RETURN ( self );
+ }
+fail: ;
+%}
+!
+
+displayRectangleX:x y:y width:width height:height in:ignoredDrawableId with:aDC
+ "draw a rectangle. If the coordinates are not integers, an error is triggered."
+
+%{
+ int w, h;
+ int xL, yT;
+ if (__isExternalAddressLike(aDC)
+ && __bothSmallInteger(x, y)
+ && __bothSmallInteger(width, height)) {
+
+ xL = __intVal(x);
+ yT = __intVal(y);
+ w = __intVal(width);
+ h = __intVal(height);
+
+ DPRINTF(("displayRectangle: %d/%d -> %d/%d\n", xL, yT, w, h));
+
+ if ((w >= 0) && (h >= 0)) {
+ HANDLE hDC = (HANDLE)(__externalAddressVal(aDC));
+ COLORREF fgColor;
+ HANDLE prevPen, hPen;
+ int lStyleSymbol, lStyleInt;
+
+ int lw;
+
+ lw= __intVal(__INST(lineWidth));
+ lStyleSymbol= __INST(lineStyle);
+
+ /* PS_DASH, PS_DOT, PS_DASHDOT, PS_DASHDOTDOT
+ only works with lineWidth = 1 */
+
+ if (lStyleSymbol == @symbol(solid)) {
+ lStyleInt= PS_SOLID;
+ } else if (lStyleSymbol == @symbol(dashed)) {
+ lStyleInt= PS_DASH;
+ } else if (lStyleSymbol == @symbol(dotted)) {
+ lStyleInt= PS_DOT;
+ } else if (lStyleSymbol == @symbol(dashDot)) {
+ lStyleInt= PS_DASHDOT;
+ } else if (lStyleSymbol == @symbol(dashDotDot)) {
+ lStyleInt= PS_DASHDOTDOT;
+ } else if (lStyleSymbol == @symbol(insideFrame)) {
+ lStyleInt= PS_INSIDEFRAME;
+ } else
+ lStyleInt= PS_SOLID;
+
+ fgColor = GetTextColor(hDC);
+ hPen = CreatePen(lStyleInt, lw, fgColor);
+
+ prevPen = SelectObject(hDC, hPen);
+ MoveToEx(hDC, xL, yT, NULL);
+ LineTo(hDC, xL+w, yT); // to top-right
+ LineTo(hDC, xL+w, yT+h); // to bot-right
+ MoveToEx(hDC, xL, yT, NULL); // back to top-left
+ LineTo(hDC, xL, yT+h); // to bot-left
+ LineTo(hDC, xL+w+1, yT+h); // move pen one pixel more
+
+ SelectObject(hDC, prevPen);
+ DeleteObject(hPen);
+
+ }
+ RETURN ( self );
+ }
+%}.
+ self primitiveFailed
+
+ "Created: / 28-07-2006 / 20:18:25 / fm"
+!
+
+displayString:aString from:index1 to:index2 x:x y:y in:aDrawableId with:aGCId
+ "draw a sub-string - draw foreground only.
+ If the coordinates are not integers, retry with rounded."
+
+ self
+ displayString:aString
+ from:index1
+ to:index2
+ x:x
+ y:y
+ in:aDrawableId
+ with:aGCId
+ opaque:false
+!
+
+displayString:aString from:index1 to:index2 x:x y:y in:ignoredDrawableId with:aDC opaque:opaque
+ "draw a sub-string - if opaque is false, draw foreground only; otherwise, draw both
+ foreground and background characters.
+ If the coordinates are not integers, an error is triggered."
+
+%{ /* NOCONTEXT */
+ unsigned char *cp;
+ OBJ cls;
+ int i1, i2, l, n;
+ int nInstBytes;
+
+ if (__isExternalAddressLike(aDC)
+ && __isNonNilObject(aString)
+ && __bothSmallInteger(index1, index2)
+ && __bothSmallInteger(x, y))
+ {
+ HANDLE hDC = (HANDLE)(__externalAddressVal(aDC));
+ int pX, pY;
+ pX = __intVal(x);
+ pY = __intVal(y);
+
+ if (opaque == true) {
+ SetBkMode(hDC, OPAQUE);
+ } else {
+ SetBkMode(hDC, TRANSPARENT);
+ }
+ SetTextColor(hDC, 0);
+ SetBkColor(hDC, 0xFFFFFFFF);
+
+ cls = __qClass(aString);
+
+ i1 = __intVal(index1) - 1;
+ if (i1 >= 0) {
+ i2 = __intVal(index2) - 1;
+ if (i2 < i1) {
+ goto ret;
+ }
+
+ cp = _stringVal(aString);
+ l = i2 - i1 + 1;
+
+ if ((cls == @global(String)) || (cls == @global(Symbol))) {
+ n = _stringSize(aString);
+ if (i2 < n) {
+ cp += i1;
+ DPRINTF(("string1: %s pos=%d/%d l=%d hDC=%x\n", cp, pX, pY,l,hDC));
+
+ if (l > 32767) {
+ l = 32767;
+ }
+ if (! TextOut(hDC, pX, pY, (char *)cp, l)) {
+ DFPRINTF((stderr, "WinPrinter [warning]: Textout failed. %d\n", GetLastError()));
+ }
+ goto ret;
+ }
+ }
+
+ nInstBytes = __OBJS2BYTES__(__intVal(__ClassInstPtr(cls)->c_ninstvars));
+ cp += nInstBytes;
+ n = __byteArraySize(aString) - nInstBytes;
+
+ if (__isBytes(aString)) {
+ if (i2 < n) {
+ cp += i1;
+ DPRINTF(("string: %s pos=%d/%d\n", cp, pX, pY));
+ if (l > 32767) {
+ l = 32767;
+ }
+ if (! TextOut(hDC, pX, pY, (char *)cp, l)) {
+ DFPRINTF((stderr, "WinPrinter [warning]: Textout failed. %d\n", GetLastError()));
+ }
+ goto ret;
+ }
+ }
+
+ /* Unicode */
+ if (__isWords(aString)) {
+ n = n / 2;
+ if (i2 < n) {
+ WIDECHAR *w_cp = (WIDECHAR *)cp;
+
+ w_cp += i1;
+
+ if (! TextOutW(hDC, pX, pY, w_cp, l)) {
+ DFPRINTF((stderr, "WinPrinter [warning]: TextoutW failed. %d\n", GetLastError()));
+ }
+ goto ret;
+ }
+ }
+ }
+ret:
+ RETURN ( self );
+ }
+%}.
+ self primitiveFailed
+
+ "Created: / 28-07-2006 / 20:35:19 / fm"
+!
+
+displayString:aString from:index1 to:index2 x:x y:y in:ignoredDrawableId with:aDC opaque:opaque fontAscent:fontAscent
+ "draw a sub-string - if opaque is false, draw foreground only; otherwise, draw both
+ foreground and background characters.
+ If the coordinates are not integers, an error is triggered."
+
+%{ /* NOCONTEXT */
+ unsigned char *cp;
+ OBJ cls;
+ int i1, i2, l, n;
+ int nInstBytes;
+
+ if (__isExternalAddressLike(aDC)
+ && __isNonNilObject(aString)
+ && __bothSmallInteger(index1, index2)
+ && __bothSmallInteger(x, y))
+ {
+ HANDLE hDC = (HANDLE)(__externalAddressVal(aDC));
+ int pX, pY;
+ pX = __intVal(x);
+ pY = __intVal(y);
+ pY -= __intVal(fontAscent);
+
+ if (opaque == true) {
+ SetBkMode(hDC, OPAQUE);
+ } else {
+ SetBkMode(hDC, TRANSPARENT);
+ }
+ SetTextColor(hDC, 0);
+ SetBkColor(hDC, 0xFFFFFFFF);
+
+ cls = __qClass(aString);
+
+ i1 = __intVal(index1) - 1;
+ if (i1 >= 0) {
+ i2 = __intVal(index2) - 1;
+ if (i2 < i1) {
+ goto ret;
+ }
+
+ cp = _stringVal(aString);
+ l = i2 - i1 + 1;
+
+ if ((cls == @global(String)) || (cls == @global(Symbol))) {
+ n = _stringSize(aString);
+ if (i2 < n) {
+ cp += i1;
+ DPRINTF(("string1: %s pos=%d/%d l=%d hDC=%x\n", cp, pX, pY,l,hDC));
+
+ if (l > 32767) {
+ l = 32767;
+ }
+ if (! TextOut(hDC, pX, pY, (char *)cp, l)) {
+ DFPRINTF((stderr, "WinPrinter [warning]: Textout failed. %d\n", GetLastError()));
+ }
+ goto ret;
+ }
+ }
+
+ nInstBytes = __OBJS2BYTES__(__intVal(__ClassInstPtr(cls)->c_ninstvars));
+ cp += nInstBytes;
+ n = __byteArraySize(aString) - nInstBytes;
+
+ if (__isBytes(aString)) {
+ if (i2 < n) {
+ cp += i1;
+ DPRINTF(("string: %s pos=%d/%d\n", cp, pX, pY));
+ if (l > 32767) {
+ l = 32767;
+ }
+ if (! TextOut(hDC, pX, pY, (char *)cp, l)) {
+ DFPRINTF((stderr, "WinPrinter [warning]: Textout failed. %d\n", GetLastError()));
+ }
+ goto ret;
+ }
+ }
+
+ /* Unicode */
+ if (__isWords(aString)) {
+ n = n / 2;
+ if (i2 < n) {
+ WIDECHAR *w_cp = (WIDECHAR *)cp;
+
+ w_cp += i1;
+
+ if (! TextOutW(hDC, pX, pY, w_cp, l)) {
+ DFPRINTF((stderr, "WinPrinter [warning]: TextoutW failed. %d\n", GetLastError()));
+ }
+ goto ret;
+ }
+ }
+ }
+ret:
+ RETURN ( self );
+ }
+%}.
+ self primitiveFailed
+
+ "Created: / 28-07-2006 / 20:35:19 / fm"
+!
+
+displayString:aString x:x y:y in:aDrawableId with:aDC
+ "draw a string - draw foreground only.
+ If the coordinates are not integers, retry with rounded."
+
+ self
+ displayString:aString
+ x:x
+ y:y
+ in:aDrawableId
+ with:aDC
+ opaque:false
+!
+
+displayString:aString x:x y:y in:aDrawableId with:aDC opaque:opaque
+ "draw a string"
+
+ self displayString:aString
+ from:1
+ to:aString size
+ x:x
+ y:y
+ in:aDrawableId
+ with:aDC
+ opaque:opaque
+!
+
+fillArcX:x y:y width:width height:height from:startAngle angle:angle
+ in:ignoredDrawableId with:aDC
+ "fill an arc. If any coordinate is not integer, an error is triggered.
+ The angles may be floats or integer - they are given in degrees."
+
+%{
+ int __x, __y, w, h;
+ float angle1, angle2;
+
+ if (__isSmallInteger(startAngle))
+ angle1 = (float)(__intVal(startAngle));
+ else if (__isFloat(startAngle)) {
+ angle1 = __floatVal(startAngle);
+ } else if (__isShortFloat(startAngle)) {
+ angle1 = __shortFloatVal(startAngle);
+ } else goto bad;
+
+ if (__isSmallInteger(angle))
+ angle2 = (float)(__intVal(angle));
+ else if (__isFloat(angle)) {
+ angle2 = __floatVal(angle);
+ } else if (__isShortFloat(angle)) {
+ angle2 = __shortFloatVal(angle);
+ } else goto bad;
+
+ if (angle2 <= 0) {
+ RETURN (self);
+ }
+
+ if (__isExternalAddressLike(aDC)
+ && __bothSmallInteger(x, y)
+ && __bothSmallInteger(width, height))
+ {
+ HANDLE hDC = (HANDLE)(__externalAddressVal(aDC));
+ HBRUSH hBrush, prevBrush;
+ HPEN prevPen = 0;
+ COLORREF fgColor;
+
+ w = __intVal(width);
+ h = __intVal(height);
+ __x = __intVal(x);
+ __y = __intVal(y);
+
+ fgColor = GetTextColor(hDC);
+ hBrush = CreateSolidBrush(fgColor);
+ prevBrush = SelectObject(hDC, hBrush);
+ if (hBrush == 0) {
+ DPRINTF(("fillArc: no brush\n"));
+ } else {
+ HPEN hPen = 0;
+
+ if (0 /* __isWinNT */) {
+ fgColor = GetTextColor(hDC);
+ hPen = CreatePen(PS_SOLID, 1, fgColor);
+ prevPen = SelectObject(hDC, hPen);
+ if (hPen == 0) {
+ DPRINTF(("fillArc: no pen\n"));
+ goto failpen;
+ }
+ } else {
+ prevPen = SelectObject(hDC, GetStockObject(NULL_PEN));
+ w++;
+ h++;
+ }
+
+ {
+ double xB, yB, xE, yE, xR, yR;
+
+ xR = w / 2;
+ yR = h / 2;
+ if (angle2 - angle1 >= 360) {
+ xB = xE = __x + xR + 0.5;
+ yB = yE = __y /*+ yR + 0.5*/;
+ } else {
+ double sin(), cos();
+ float rad1, rad2;
+
+ if (angle1 <= 180)
+ angle1 = 180 - angle1;
+ else
+ angle1 = 360 + 180 - angle1;
+ angle2 = angle1 - angle2;
+ /* sigh - compute the intersections ... */
+ rad1 = (angle1 * 3.14159265359) / 180.0;
+ rad2 = (angle2 * 3.14159265359) / 180.0;
+ xB = cos(rad1) * xR;
+ yB = sin(rad1) * yR;
+ xE = cos(rad2) * xR;
+ yE = sin(rad2) * yR;
+ xB = __x + xR - xB + 0.5;
+ yB = __y + yR - yB + 0.5;
+ xE = __x + xR - xE + 0.5;
+ yE = __y + yR - yE + 0.5;
+ }
+ DPRINTF(("fillArc x=%d y=%d w=%d h=%d xB=%d xE=%d yB=%d yE=%d a1=%f a2=%f\n",__x,__y,w,h,(int)xB,(int)xE,(int)yB,(int)yE,angle1,angle2));
+
+ Pie(hDC,
+ __x, __y,
+ __x + w + 1, __y + h + 1,
+ (int)xB, (int)yB,
+ (int)xE, (int)yE);
+
+ if (hPen) {
+ DeleteObject(hPen);
+ }
+ }
+failpen:
+ if (prevPen) SelectObject(hDC, prevPen);
+ DeleteObject(hPen);
+
+ SelectObject(hDC, prevBrush);
+ DeleteObject(hBrush);
+ }
+ RETURN ( self );
+ }
+ bad: ;
+%}.
+ self primitiveFailed
+!
+
+fillPolygon:aPolygon in:ignoredDrawableId with:aGCId
+ "fill a polygon given by its points.
+ If any coordinate is not integer, an error is triggered."
+
+ |numberOfPoints|
+
+ numberOfPoints := aPolygon size.
+ self
+ primFillPolygon:aPolygon n:numberOfPoints
+ in:ignoredDrawableId with:aGCId
+!
+
+fillRectangleX:x y:y width:width height:height in:ignoredDrawableId with:aDC
+ "fill a rectangle. If any coordinate is not integer, an error is triggered."
+
+%{ /* NOCONTEXT */
+
+ int w, h;
+ if (__isExternalAddressLike(aDC)
+ && __bothSmallInteger(x, y)
+ && __bothSmallInteger(width, height)) {
+ w = __intVal(width);
+ h = __intVal(height);
+
+ if ((w >= 0) && (h >= 0)) {
+ HANDLE hDC = (HANDLE)(__externalAddressVal(aDC));
+ HBRUSH hBrush, prevBrush;
+ RECT rct;
+ COLORREF fgColor;
+
+ fgColor = GetTextColor(hDC);
+ hBrush = CreateSolidBrush(fgColor);
+ rct.left = __intVal(x);
+ rct.top = __intVal(y);
+ rct.right = rct.left + w + 1;
+ rct.bottom = rct.top + h + 1;
+
+/* if ((gcData->rop2 == R2_COPYPEN)
+ && (gcData->bitbltrop2 == BITBLT_COPY)) {
+ AQUIRE_DRAW_MUTEX
+ FillRect(hDC, &rct, hBrush);
+ RELEASE_DRAW_MUTEX
+ GcDataReleaseBrush(hDC, gcData);
+ } else {
+*/
+ prevBrush = SelectObject(hDC, hBrush);
+# undef Rectangle
+ Rectangle(hDC, rct.left, rct.top, rct.right, rct.bottom);
+ /* GcDataReleaseBrush(hDC, gcData); */
+ SelectObject(hDC, prevBrush);
+ DeleteObject(hBrush);
+
+/*
+ }
+*/
+ }
+ }
+ RETURN ( self );
+%}
+!
+
+getPenForMyContext
+ "Get a pen for my context"
+
+ |maskOriginX maskOriginY|
+
+ self maskOrigin isNil ifFalse:[
+ maskOriginX := self maskOrigin x.
+ maskOriginY := self maskOrigin y.
+ ].
+
+%{
+ HPEN hPen = 0;
+ HPEN prevPen;
+ LOGBRUSH Brush;
+ COLORREF fgColor;
+ HANDLE hDC = (HANDLE)(__externalAddressVal(__INST(gcId)));
+ int lStyle, bkMode, hMask, maskOrgX, maskOrgY;
+ int style, lineStyle, capStyle, joinStyle;
+ int lw;
+ int BK_TRANSPARENT;
+
+ BK_TRANSPARENT = 1;
+
+ lw= __INST(lineWidth);
+/* fgColor = __intVal(__INST(foreground)) & 0xffffff; */
+
+ fgColor = GetTextColor(hDC);
+ lineStyle=__INST(lineStyle);
+ capStyle=__INST(capStyle);
+ joinStyle=__INST(joinStyle);
+ hMask= __INST(mask);
+ maskOrgX=__intVal(maskOriginX);
+ maskOrgY=__intVal(maskOriginY);
+
+ if (lineStyle == @symbol(solid)) {
+ style = PS_SOLID;
+ } else if (lineStyle == @symbol(dashed)) {
+ style= PS_DASH;
+ } else if (lineStyle == @symbol(dotted)) {
+ style= PS_DOT;
+ } else if (lineStyle == @symbol(dashDot)) {
+ style= PS_DASHDOT;
+ } else if (lineStyle == @symbol(dashDotDot)) {
+ style= PS_DASHDOTDOT;
+ } else
+ style= PS_SOLID;
+ lStyle &= ~PS_STYLE_MASK;
+ lStyle |= style;
+
+
+ if (capStyle == @symbol(round)) {
+ style = PS_ENDCAP_ROUND;
+ } else if (capStyle == @symbol(square)) {
+ style = PS_ENDCAP_SQUARE;
+ } else if (capStyle == @symbol(flat)) {
+ style = PS_ENDCAP_FLAT;
+ } else
+ style = PS_ENDCAP_FLAT;
+ lStyle &= ~PS_ENDCAP_MASK;
+ lStyle |= style;
+
+ if (joinStyle == @symbol(bevel)) {
+ style = PS_JOIN_BEVEL;
+ } else if (joinStyle == @symbol(miter)) {
+ style = PS_JOIN_MITER;
+ } else if (joinStyle == @symbol(round)) {
+ style = PS_JOIN_ROUND;
+ } else
+ style = PS_JOIN_MITER;
+ lStyle &= ~PS_JOIN_MASK;
+ lStyle |= style;
+
+
+ if (((lStyle & PS_STYLE_MASK) == PS_SOLID)
+ && (hMask == 0)
+ && (lw /* lineWidth */ <= 1)) {
+ if (fgColor == 0 /* BlackPixel */ ) {
+ hPen = GetStockObject(BLACK_PEN);
+ prevPen = SelectObject(hDC, hPen);
+ RETURN( hPen );
+ }
+ if (fgColor == 1 /* WhitePixel */) {
+ hPen = GetStockObject(WHITE_PEN);
+ prevPen = SelectObject(hDC, hPen);
+ RETURN( hPen );
+ }
+ }
+
+ hPen = (HPEN) 0;
+
+ if (0 /* __isWinNT */) {
+
+ if (lw == 0) {
+ lw = 1;
+ }
+ /*
+ * NT supports masked drawing with any lineStyle,
+ * and also non-solid lines with any lineWidth.
+ */
+ if (hMask) {
+ Brush.lbStyle = BS_PATTERN;
+ Brush.lbHatch = (DWORD)hMask;
+ Brush.lbColor = fgColor;
+ } else {
+
+#ifndef PRE_07_APR_04
+
+ hPen = CreatePen((lStyle & PS_STYLE_MASK), lw, fgColor);
+
+/* RESPRINTF(("CreatePen %x %d(%d) %x %x\n",
+ * lStyle,
+ * lw, __INST(lineWidth),
+ * fgColor, hMask));
+ */
+
+ SetBkMode(hDC, TRANSPARENT);
+ bkMode = BK_TRANSPARENT;
+
+#else
+ Brush.lbStyle = BS_SOLID;
+ Brush.lbHatch = 0;
+ Brush.lbColor = fgColor;
+#endif
+ }
+
+ if (! hPen)
+ {
+ hPen = ExtCreatePen(PS_GEOMETRIC | lStyle,
+ lw, /* lineWidth, */
+ &Brush,
+ 0, 0);
+
+/* RESPRINTF(("ExtCreatePen1 %x %d(%d) %x %x\n",
+ * lStyle,
+ * lw, __INST(lineWidth),
+ * fgColor, hMask));
+ */
+ if (hMask) {
+ SetBrushOrgEx(hDC, maskOrgX, maskOrgY, 0);
+ }
+ }
+ } else {
+ /*
+ * W95 only supports masked drawing with SOLID lines
+ * also, we should use COSMETIC pens if possible
+ * with non-solid lineStyles.
+ */
+ if ((lStyle & PS_STYLE_MASK) == PS_SOLID) {
+ int ps = PS_GEOMETRIC;
+
+ if (hMask) {
+ Brush.lbStyle = BS_PATTERN;
+ Brush.lbHatch = (DWORD)hMask;
+ Brush.lbColor = fgColor;
+ } else {
+ Brush.lbStyle = BS_SOLID;
+ Brush.lbHatch = 0;
+ Brush.lbColor = fgColor;
+ if (lw /* lineWidth */ <= 1) {
+ ps = PS_COSMETIC;
+ }
+ }
+
+ hPen = ExtCreatePen(ps | lStyle,
+ lw, /* lineWidth */
+ &Brush,
+ 0, 0);
+
+/* RESPRINTF(("ExtCreatePen1 %x %d %x %x\n",
+ * lStyle,
+ * lw,
+ * fgColor, hMask));
+ */
+ if (hMask) {
+ SetBrushOrgEx(hDC, maskOrgX, maskOrgY, 0);
+ }
+ } else {
+
+ if (lw == 1) {
+ lw = 0;
+ }
+
+ /*
+ * dashes only supported with lineWidth 0
+ */
+
+ hPen = CreatePen((lStyle & PS_STYLE_MASK),
+ lw,
+ fgColor);
+
+/* RESPRINTF(("CreatePen %x %d %x\n",
+ * (lStyle & PS_STYLE_MASK),
+ * lw,
+ * fgColor));
+ */
+ //
+ // CG: wrong; must set to opaque, if doubleDashed
+ //
+ SetBkMode(hDC, TRANSPARENT);
+ bkMode = BK_TRANSPARENT;
+ }
+ }
+
+ prevPen = SelectObject(hDC, hPen);
+
+ RETURN (hPen);
+
+%}
+!
+
+primCreateBitmapFromArray:anArray width:w height:h
+%{
+
+ HBITMAP newBitmapHandle;
+ int b_width, b_height, bytesPerRowST, bytesPerRowWN, padding;
+ int row, col;
+ unsigned char *cp, *bPits;
+ unsigned char *b_bits = 0;
+ int index;
+ OBJ num;
+ unsigned char *allocatedBits = 0;
+ unsigned char fastBits[10000];
+
+ if (__bothSmallInteger(w, h)
+ && _isNonNilObject(anArray)) {
+ OBJ cls = __qClass(anArray);
+
+ b_width = __intVal(w);
+ b_height = __intVal(h);
+ bytesPerRowST = (b_width + 7) / 8;
+ bytesPerRowWN = ((b_width + 15) / 16) * 2;
+ padding = bytesPerRowWN - bytesPerRowST;
+
+ if ((padding == 0) && (cls == @global(ByteArray))) {
+ b_bits = __ByteArrayInstPtr(anArray)->ba_element;
+ cp = 0;
+ } else {
+ int nBytes = b_height * bytesPerRowWN;
+
+ if (nBytes < sizeof(fastBits)) {
+ cp = b_bits = fastBits;
+ } else {
+ cp = b_bits = allocatedBits = (unsigned char *) malloc(nBytes);
+ if (! cp) goto fail;
+ }
+ }
+ if (cp) {
+ if (cls == @global(Array)) {
+ OBJ *op;
+
+ index = 1;
+ op = &(__ArrayInstPtr(anArray)->a_element[index - 1]);
+ for (row = b_height; row; row--) {
+ for (col = bytesPerRowST; col; col--) {
+ num = *op++;
+ if (! __isSmallInteger(num))
+ goto fail;
+ *cp++ = __intVal(num);
+ }
+ cp += padding;
+ }
+ } else if (cls == @global(ByteArray)) {
+ unsigned char *pBits;
+
+ pBits = __ByteArrayInstPtr(anArray)->ba_element;
+ for (row = b_height; row; row--) {
+ for (col = bytesPerRowST; col; col--) {
+ *cp++ = ( *pBits++ /*^ 0xFF*/ );
+ }
+ cp += padding;
+ }
+ } else {
+ goto fail;
+ }
+ }
+/*
+ CPRINTF(("create bitmap ...\n"));
+*/
+ newBitmapHandle = CreateBitmap(b_width, b_height, 1, 1, b_bits );
+
+ if (newBitmapHandle ) {
+/*
+ DDPRINTF(("returning bitmap %x ...\n", newBitmapHandle));
+*/
+ if (allocatedBits) {
+ free(allocatedBits);
+ }
+ RETURN ( __MKOBJ(newBitmapHandle));
+ }
+ }
+fail: ;
+/*
+ DDPRINTF(("create bitmap FAILED!!!\n"));
+*/
+ if (allocatedBits) {
+/*
+ CPRINTF(("freeing up bitmap bits ...\n"));
+*/
+ free(allocatedBits);
+ }
+/*
+ CPRINTF(("returning nil ...\n"));
+*/
+ RETURN ( nil );
+%}
+!
+
+primFillPolygon:aPolygon n:numberOfPoints in:ignoredDrawableId with:aDC
+
+%{
+ OBJ point, px, py;
+ int i, num;
+
+ if (__isExternalAddressLike(aDC)
+ && __isSmallInteger(numberOfPoints)) {
+ HANDLE hDC = (HANDLE)(__externalAddressVal(aDC));
+ POINT p;
+ HBRUSH hBrush, prevBrush;
+ COLORREF fgColor;
+
+ num = __intVal(numberOfPoints);
+ if (num < 3) {
+ RETURN ( self );
+ }
+ for (i=0; i<num; i++) {
+ point = __AT_(aPolygon, __MKSMALLINT(i+1));
+ if (! __isPoint(point)) goto fail;
+ px = _point_X(point);
+ py = _point_Y(point);
+ if (! __bothSmallInteger(px, py))
+ goto fail;
+ }
+
+ fgColor = GetTextColor(hDC);
+ hBrush = CreateSolidBrush(fgColor);
+ if (hBrush == 0) {
+ DPRINTF(("fillPolygon: no brush\n"));
+ } else {
+ HPEN prevPen;
+
+ prevBrush = SelectObject(hDC, hBrush);
+ prevPen = SelectObject(hDC, GetStockObject(NULL_PEN));
+
+ BeginPath(hDC);
+
+ for (i=0; i<num; i++) {
+ point = __AT_(aPolygon, __MKSMALLINT(i+1));
+ px = _point_X(point);
+ py = _point_Y(point);
+ if (i == 0) {
+ MoveToEx(hDC, __intVal(px), __intVal(py), NULL);
+ } else {
+ if (i == (num-1)) {
+ p.x = __intVal(px);
+ p.y = __intVal(py);
+ PolylineTo(hDC, &p, 1);
+ } else {
+ LineTo(hDC, __intVal(px), __intVal(py));
+ }
+ }
+ }
+
+ EndPath(hDC);
+ FillPath(hDC);
+ SelectObject(hDC, prevPen);
+ SelectObject(hDC, prevBrush);
+ DeleteObject(hBrush);
+ }
+ RETURN ( self );
+
+fail: ;
+ }
+%}
+! !
+
+!WinPrinterContext methodsFor:'drawing bitmaps'!
+
+bitsBlue
+ "return the number of valid bits in the red component."
+
+"/ bitsRed isNil ifTrue:[
+"/ "/ not a truecolor display
+"/ ^ bitsPerRGB
+"/ ].
+"/ ^ bitsRed
+
+ ^Display bitsBlue
+!
+
+bitsGreen
+ "return the number of valid bits in the red component."
+
+"/ bitsRed isNil ifTrue:[
+"/ "/ not a truecolor display
+"/ ^ bitsPerRGB
+"/ ].
+"/ ^ bitsRed
+
+ ^Display bitsGreen
+!
+
+bitsRed
+ "return the number of valid bits in the red component."
+
+"/ bitsRed isNil ifTrue:[
+"/ "/ not a truecolor display
+"/ ^ bitsPerRGB
+"/ ].
+"/ ^ bitsRed
+
+ ^Display bitsRed
+!
+
+copyFromId:sourceId x:srcX y:srcY gc:srcGCId to:destId x:dstX y:dstY gc:dstGCId
+ width:w height:h
+ "do a bit-blt; copy bits from the rectangle defined by
+ srcX/srcY and w/h from the sourceId drawable to the rectangle
+ below dstX/dstY in the destId drawable. Trigger an error if any
+ argument is not integer."
+
+%{
+ int dstGcOwnerThreadID;
+ HWND dstGcHWIN;
+ HBITMAP dstGcHBITMAP;
+
+ if (! __isExternalAddressLike(srcGCId)
+ || ! __isExternalAddressLike(dstGCId)) {
+ goto fail;
+ }
+
+ if (__bothSmallInteger(w, h)
+ && __bothSmallInteger(srcX, srcY)
+ && __bothSmallInteger(dstX, dstY)) {
+ HANDLE srcDC = (HANDLE)(__externalAddressVal(srcGCId));
+ HANDLE dstDC = (HANDLE)(__externalAddressVal(dstGCId));
+
+ int fun, aFunctionSymbol;
+ int src_fg, src_bg, dst_fg, dst_bg;
+ char buf[5];
+
+// fun = dstGcData->bitbltrop2;
+
+ aFunctionSymbol= __INST(function);
+
+ if (aFunctionSymbol == @symbol(copy)) {
+ fun = SRCCOPY /* R2_COPYPEN */ ;
+/* bfun = BITBLT_COPY; */
+ } else if (aFunctionSymbol == @symbol(copyInverted)) {
+ fun = NOTSRCCOPY /* R2_NOTCOPYPEN */;
+/* bfun = BITBLT_COPYINVERTED; */
+ } else if (aFunctionSymbol == @symbol(xor)) {
+ fun = SRCINVERT /* R2_XORPEN */;
+/* bfun = BITBLT_XOR; */
+ } else if (aFunctionSymbol == @symbol(and)) {
+ fun = SRCAND /* R2_MASKPEN */ ;
+/* bfun = BITBLT_AND; */
+ } else if (aFunctionSymbol == @symbol(or)) {
+ fun = MERGECOPY /* R2_MERGEPEN */ ;
+/* bfun = BITBLT_OR; */
+ }
+
+ // convert 123 to string [buf]
+ itoa(fun, buf, 10);
+
+ console_printf(" ", buf);
+
+/*
+#if 0
+ switch (fun) {
+ case BITBLT_COPY:
+ console_printf("BITBLT_COPY\n");
+ break;
+ case BITBLT_COPYINVERTED:
+ console_printf("BITBLT_COPYINVERTED\n");
+ break;
+ case BITBLT_XOR:
+ console_printf("BITBLT_XOR\n");
+ break;
+ case BITBLT_AND:
+ console_printf("BITBLT_AND\n");
+ break;
+ case BITBLT_OR:
+ console_printf("BITBLT_OR\n");
+ break;
+ }
+#endif
+*/
+
+// fun = dstGcData->bitbltrop2;
+
+ if (0 /* fun == BITBLT_COPY */) {
+ src_fg = dst_fg = 0xFFFFFF;
+ src_bg = dst_bg = 0x000000;
+ } else {
+ src_fg = GetTextColor(srcDC) /* srcGcData->fgColor */;
+ src_bg = GetBkColor(dstDC) /* srcGcData->bgColor */;
+ dst_fg = GetTextColor(srcDC) /* dstGcData->fgColor */;
+ dst_bg = GetBkColor(dstDC) /* dstGcData->bgColor */;
+ }
+
+ SetBkColor(dstDC, dst_fg);
+ SetTextColor(dstDC, dst_bg);
+
+ SetBkColor(srcDC, src_fg);
+ SetTextColor(srcDC, src_bg);
+
+/*
+ CPRINTF(("bitblt src f:%x b:%x",GetTextColor(srcDC),GetBkColor(srcDC)));
+ CPRINTF(("dst f:%x b:%x\n",GetTextColor(dstDC),GetBkColor(dstDC)));
+*/
+ if (BitBlt(dstDC,
+ __intVal(dstX), __intVal(dstY),
+ __intVal(w), __intVal(h),
+ srcDC,
+ __intVal(srcX), __intVal(srcY),
+ fun)
+ == 0
+ ) {
+ console_fprintf(stderr, "WinWorkstation [info]: ERROR in BitBlt\n");
+ }
+
+/*
+ if (dstGcData != srcGcData) {
+ SetBkColor(dstDC, dstGcData->bgColor);
+ SetTextColor(dstDC, dstGcData->fgColor);
+ }
+ SetBkColor(srcDC, srcGcData->bgColor);
+ SetTextColor(srcDC, srcGcData->fgColor);
+*/
+
+/*
+ if (srcGcData != dstGcData) {
+ _releaseDC(srcGcData);
+ }
+ _releaseDC(dstGcData);
+*/
+ RETURN ( self );
+ }
+
+ fail: ;
+%}.
+ self primitiveFailed.
+ ^ nil
+!
+
+copyFromPixmapId:sourceId x:srcX y:srcY gc:srcGCId to:destId x:dstX y:dstY gc:dstGCId width:w height:h
+ "do a bit-blt from a pix- or bitmap.
+ Here, fall back into copyFromId:, which should also work.
+ Subclasses may redefine this for more performance or if required"
+
+ ^ self copyFromId:sourceId x:srcX y:srcY gc:srcGCId to:destId x:dstX y:dstY gc:dstGCId width:w height:h
+!
+
+copyPlaneFromId:sourceId x:srcX y:srcY gc:srcDCId to:destId x:dstX y:dstY gc:dstDCId
+ width:w height:h
+ "do a bit-blt, but only copy the low-bit plane;
+ copy bits from the rectangle defined by
+ srcX/srcY and w/h from the sourceId drawable to the rectangle
+ below dstX/dstY in the destId drawable. Trigger an error if any
+ argument is not integer."
+
+ ^ self
+ copyFromId:sourceId
+ x:srcX y:srcY gc:srcDCId
+ to:destId x:dstX y:dstY gc:dstDCId
+ width:w height:h
+!
+
+copyPlaneFromPixmapId:sourceId x:srcX y:srcY gc:srcGCId to:destId x:dstX y:dstY gc:dstGCId width:w height:h
+ "do a bit-blt from a pix- or bitmap, using the low-bit plane of the source only.
+ Here, fall back into copyPlaneFromId:, which should also work.
+ Subclasses may redefine this for more performance or if required"
+
+ ^ self copyPlaneFromId:sourceId x:srcX y:srcY gc:srcGCId to:destId x:dstX y:dstY gc:dstGCId width:w height:h
+!
+
+createBitmapFromArray:anArray width:w height:h
+ |bitmapId|
+
+
+ bitmapId := self primCreateBitmapFromArray:anArray width:w height:h.
+
+ bitmapId isNil ifTrue:[
+ 'WINWORKSTATION: cannot create bitmap' errorPrintCR.
+ ].
+ ^ bitmapId
+!
+
+destroyPixmap:aDrawableId
+
+%{ /* NOCONTEXT */
+ if (__isExternalAddress(aDrawableId) /* && ISCONNECTED */ ) {
+ HANDLE bitmapHandle = _HANDLEVal(aDrawableId);
+
+ if (bitmapHandle) {
+ DeleteObject(bitmapHandle);
+ /* _DeleteObject(bitmapHandle, __LINE__); */
+ }
+ }
+%}
+!
+
+drawBits:imageBits bitsPerPixel:bitsPerPixel depth:imageDepth padding:padd
+ width:imageWidth height:imageHeight
+ x:srcx y:srcy
+ into:ignoredDrawableId
+ x:dstx y:dsty
+ width:w height:h
+ with:aGCId
+
+ "draw a bitImage which has depth id, width iw and height ih into
+ the drawable. draw a region of w/h pixels from srcx/srcy to dstx/dsty.
+ Individual source pixels have bitsPerPixel bits, allowing to draw
+ depth and pixel-units to be different.
+ It has to be checked elsewhere, that the server can do it with the given
+ depth - otherwise, primitive failure will be signalled.
+ Also it is assumed, that the colormap is setup correctly and the
+ colors are allocated - otherwise the colors may be wrong."
+
+ "
+ sorry; I had to separate it into 2 methods, since XPutImage needs
+ an unlimited stack, and thus cannot send primitiveFailed
+ "
+ (self primDrawBits:imageBits bitsPerPixel:bitsPerPixel depth:imageDepth padding:padd
+ width:imageWidth height:imageHeight
+ x:srcx y:srcy
+ into:ignoredDrawableId
+ x:dstx y:dsty
+ width:w height:h
+ with:aGCId)
+ ifFalse:[
+ "
+ also happens, if a segmentation violation occurs in the
+ XPutImage ...
+ "
+ self primitiveFailed
+ ].
+!
+
+gcForBitmap:aDrawableId
+
+%{ /* NOCONTEXT */
+
+ if (__isExternalAddress(aDrawableId)) { /* HBITMAP */
+ BITMAP bitmap;
+ HBITMAP hBitmap, memBM = _HBITMAPVAL(aDrawableId);
+ HANDLE compatibleDC, hdcScreen;
+ HANDLE hDC = (HANDLE)(__externalAddressVal(__INST(gcId)));
+
+
+ if (! hBitmap) {
+ RETURN (nil);
+ }
+
+ if (GetObject(hBitmap, sizeof(bitmap), &bitmap)) {
+/*
+ DDPRINTF(("bitmap info:%d\n", bitmap.bmBitsPixel));
+*/
+ } else {
+/*
+ DPRINTF(("noinfo returned for bitmap\n"));
+*/
+ /* mhmh - can this happen ? */
+ bitmap.bmBitsPixel = 1;
+ }
+/*
+ gcData->hBitmap = hBitmap;
+ gcData->bitmapColorBitCount = bitmap.bmBitsPixel;
+*/
+
+ hdcScreen= CreateDC("NULL", NULL, NULL, NULL);
+ // compatibleDC = hdcScreen;
+ // compatibleDC = CreateCompatibleDC(0);
+ // hdcScreen = CreateDC("DISPLAY", NULL, NULL, NULL);
+ compatibleDC = CreateCompatibleDC(hdcScreen);
+ // compatibleDC = CreateCompatibleDC(hDC);
+ memBM = CreateCompatibleBitmap ( compatibleDC, bitmap.bmWidth, bitmap.bmHeight );
+ SelectObject ( compatibleDC, memBM );
+ // SelectObject(compatibleDC, hBitmap);
+ RETURN (__MKOBJ(compatibleDC));
+
+
+/*
+ RETURN ( __MKOBJ(gcData) );
+*/
+ }
+ RETURN (nil);
+%}
+!
+
+primDrawBits:imageBits bitsPerPixel:bitsPerPixel depth:imageDepth padding:padd
+ width:imageWidth height:imageHeight
+ x:srcx y:srcy
+ into:ignoredDrawableId
+ x:dstx y:dsty
+ width:w height:h
+ with:aGCId
+
+ "since XPutImage may allocate huge amount of stack space
+ (some implementations use alloca), this must run with unlimited stack."
+
+%{
+ unsigned char fastBits[10000];
+ unsigned char *b_bits = 0;
+ unsigned char *allocatedBits = 0;
+ HDC hDC = (HDC)0;
+ unsigned char *__imageBits = 0;
+
+ if (__isByteArray(imageBits)) {
+ __imageBits = __ByteArrayInstPtr(imageBits)->ba_element;
+ } else if (__isExternalBytesLike(imageBits)) {
+ __imageBits = (unsigned char *)(__externalBytesAddress(imageBits));
+ }
+
+ if (/* ISCONNECTED
+ && */ __isExternalAddressLike(aGCId)
+ && __bothSmallInteger(srcx, srcy)
+ && __bothSmallInteger(dstx, dsty)
+ && __bothSmallInteger(w, h)
+ && __bothSmallInteger(imageWidth, imageHeight)
+ && __bothSmallInteger(imageDepth, bitsPerPixel)
+ && __isSmallInteger(padd)
+ && __imageBits)
+ {
+ struct
+ {
+ BITMAPINFOHEADER bmiHeader;
+ DWORD r;
+ DWORD g;
+ DWORD b;
+ } bitmap;
+
+ HANDLE hDC = (HANDLE)(__externalAddressVal(aGCId));
+ HBITMAP hBitmap, memBM = _HBITMAPVAL(__INST(drawableId));
+
+/*
+ DDPRINTF(("hDC = %x\n", hDC));
+*/
+ if (__intVal(padd) != WIN32PADDING) {
+ int row, col;
+ unsigned char *cp;
+ unsigned char *pBits;
+ int b_width, b_height, bytesPerRowST, bytesPerRowWN, padding, nBytes;
+ int bi = __intVal(bitsPerPixel);
+
+ b_width = __intVal(w);
+ b_height = __intVal(h);
+ bytesPerRowST = (b_width * bi + (__intVal(padd)-1)) / __intVal(padd);
+ bytesPerRowWN = (b_width * bi + (WIN32PADDING-1)) / WIN32PADDING * (WIN32PADDING/8);
+ padding = bytesPerRowWN - bytesPerRowST;
+ nBytes = b_height * bytesPerRowWN;
+ /*console_printf("padd %d bs %d bw %d p %d\n",__intVal(padd),bytesPerRowST,bytesPerRowWN,padding);*/
+ if (padding) {
+ if (nBytes < sizeof(fastBits)) {
+ cp = b_bits = fastBits;
+ } else {
+ cp = b_bits = allocatedBits = (unsigned char *) malloc(nBytes);
+ }
+ if (cp) {
+ pBits = __imageBits;
+ for (row = b_height; row; row--) {
+ for (col = bytesPerRowST; col; col--) {
+ *cp++ = *pBits++;
+ }
+ cp += padding;
+ }
+ } else
+ goto fail;
+ }
+ }
+
+ if (b_bits == 0) {
+ b_bits = __imageBits;
+ }
+
+ bitmap.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ bitmap.bmiHeader.biPlanes = 1;
+ if (__intVal(imageDepth) == 24) {
+ /*bitmap.bmiHeader.biCompression = BI_BITFIELDS;
+ bitmap.r = 0xff0000;
+ bitmap.g = 0x00ff00;
+ bitmap.b = 0x0000ff;*/
+ bitmap.bmiHeader.biCompression = BI_RGB;
+ } else if (__intVal(imageDepth) == 16) {
+ /*bitmap.bmiHeader.biCompression = BI_RGB;
+ bitmap.bmiHeader.biCompression = BI_BITFIELDS;
+ bitmap.b = 0x001f;
+ bitmap.g = 0x07e0;
+ bitmap.r = 0xf800;*/
+ bitmap.b = 0;
+ bitmap.g = 0;
+ bitmap.r = 0;
+ bitmap.bmiHeader.biCompression = BI_RGB;
+ }
+ bitmap.bmiHeader.biSizeImage = 0;
+ bitmap.bmiHeader.biXPelsPerMeter = 0;
+ bitmap.bmiHeader.biYPelsPerMeter = 0;
+ bitmap.bmiHeader.biClrUsed = 0;
+ bitmap.bmiHeader.biClrImportant = 0;
+ bitmap.bmiHeader.biWidth = __intVal(imageWidth);
+ bitmap.bmiHeader.biHeight = -(__intVal(imageHeight));
+ bitmap.bmiHeader.biBitCount = __intVal(bitsPerPixel);
+ /*console_printf("drawBits depth:%d bitsPerPixel:%d IW%d W:%d H:%d\n",__intVal(imageDepth),bitmap.bmiHeader.biBitCount,bitmap.bmiHeader.biWidth,__intVal(w),bitmap.bmiHeader.biHeight);*/
+/* SetDIBitsToDevice(hDC,__intVal(dstx),__intVal(dsty),
+ __intVal(w), __intVal(h),
+ __intVal(srcx), __intVal(srcy),
+ 0,__intVal(h),
+ (void *)b_bits,
+ (BITMAPINFO*)&bitmap,DIB_RGB_COLORS);
+*/
+ SetDIBits(hDC,hBitmap,
+ 0,__intVal(h),
+ (void *)b_bits,
+ (BITMAPINFO*)&bitmap,DIB_RGB_COLORS);
+
+
+/*
+ StretchDIBits(hDC,__intVal(dstx),__intVal(dsty),
+ __intVal(w), __intVal(h),
+ __intVal(srcx), __intVal(srcy),
+ 0,__intVal(h),
+ (void *)b_bits,
+ (BITMAPINFO*)&bitmap,DIB_RGB_COLORS, SRCCOPY);
+*/
+ if (allocatedBits) {
+ free(allocatedBits);
+ }
+/*
+#ifndef CACHE_LAST_DC
+ _releaseDC(gcData);
+#endif
+*/
+ RETURN ( true );
+ }
+
+fail: ;
+/*
+ PRINTF(("create temp bitmap FAILED!!!\n"));
+*/
+ if (allocatedBits) {
+/*
+ PRINTF(("freeing up temp bitmap bits ...\n"));
+*/
+ free(allocatedBits);
+ }
+/*
+#ifndef CACHE_LAST_DC
+ if (hDC) {
+ _releaseDC(gcData);
+ }
+#endif
+*/
+%}
+.
+ ^ false
+!
+
+setFunction:aFunctionSymbol in:aGCId
+ "set alu function to be drawn with"
+
+ Transcript showCR: aFunctionSymbol printString.
+ function := aFunctionSymbol.
+
+"/%{ /* NOCONTEXT */
+"/
+"/ if (__isExternalAddress(aGCId)) {
+"/ struct gcData *gcData = _GCDATA(aGCId);
+"/ int fun = -1;
+"/ int bfun = -1;
+"/
+"/ if (aFunctionSymbol == @symbol(copy)) {
+"/ fun = R2_COPYPEN;
+"/ bfun = BITBLT_COPY;
+"/ } else if (aFunctionSymbol == @symbol(copyInverted)) {
+"/ fun = R2_NOTCOPYPEN;
+"/ bfun = BITBLT_COPYINVERTED;
+"/ } else if (aFunctionSymbol == @symbol(xor)) {
+"/ fun = R2_XORPEN;
+"/ bfun = BITBLT_XOR;
+"/ } else if (aFunctionSymbol == @symbol(and)) {
+"/ fun = R2_MASKPEN;
+"/ bfun = BITBLT_AND;
+"/ } else if (aFunctionSymbol == @symbol(or)) {
+"/ fun = R2_MERGEPEN;
+"/ bfun = BITBLT_OR;
+"/ }
+"/
+"/ if (fun
+!
+
+setGraphicsExposures:aBoolean in:aGCId
+ "set or clear the graphics exposures flag"
+!
+
+shiftBlue
+ "return the number of valid bits in the red component."
+
+"/ bitsRed isNil ifTrue:[
+"/ "/ not a truecolor display
+"/ ^ bitsPerRGB
+"/ ].
+"/ ^ bitsRed
+
+ ^Display shiftBlue
+!
+
+shiftGreen
+ "return the number of valid bits in the red component."
+
+"/ bitsRed isNil ifTrue:[
+"/ "/ not a truecolor display
+"/ ^ bitsPerRGB
+"/ ].
+"/ ^ bitsRed
+
+ ^Display shiftGreen
+!
+
+shiftRed
+ "return the number of valid bits in the red component."
+
+"/ bitsRed isNil ifTrue:[
+"/ "/ not a truecolor display
+"/ ^ bitsPerRGB
+"/ ].
+"/ ^ bitsRed
+
+ ^Display shiftRed
+!
+
+xprimDrawBits:imageBits bitsPerPixel:bitsPerPixel depth:imageDepth padding:padd width:imageWidth height:imageHeight
+ x:srcx y:srcy
+ into:ignoredDrawableId
+ x:dstx y:dsty
+ width:w height:h
+ with:aDC
+
+ "since XPutImage may allocate huge amount of stack space
+ (some implementations use alloca), this must run with unlimited stack."
+
+%{
+ unsigned char fastBits[10000];
+ unsigned char *b_bits = 0;
+ unsigned char *allocatedBits = 0;
+ unsigned char *__imageBits = 0;
+
+ if (__isByteArray(imageBits)) {
+ __imageBits = __ByteArrayInstPtr(imageBits)->ba_element;
+ } else if (__isExternalBytesLike(imageBits)) {
+ __imageBits = (unsigned char *)(__externalBytesAddress(imageBits));
+ }
+
+ if (/* ISCONNECTED
+ && */ __isExternalAddressLike(aDC)
+ && __bothSmallInteger(srcx, srcy)
+ && __bothSmallInteger(dstx, dsty)
+ && __bothSmallInteger(w, h)
+ && __bothSmallInteger(imageWidth, imageHeight)
+ && __bothSmallInteger(imageDepth, bitsPerPixel)
+ && __isSmallInteger(padd)
+ && __imageBits)
+ {
+ HANDLE hDC = (HANDLE)(__externalAddressVal(aDC));
+ struct
+ {
+ BITMAPINFOHEADER bmiHeader;
+ DWORD r;
+ DWORD g;
+ DWORD b;
+ } bitmap;
+
+ if (__intVal(padd) != WIN32PADDING) {
+ int row, col;
+ unsigned char *cp;
+ unsigned char *pBits;
+ int b_width, b_height, bytesPerRowST, bytesPerRowWN, padding, nBytes;
+ int bi = __intVal(bitsPerPixel);
+
+ b_width = __intVal(w);
+ b_height = __intVal(h);
+ bytesPerRowST = (b_width * bi + (__intVal(padd)-1)) / __intVal(padd);
+ bytesPerRowWN = (b_width * bi + (WIN32PADDING-1)) / WIN32PADDING * (WIN32PADDING/8);
+ padding = bytesPerRowWN - bytesPerRowST;
+ nBytes = b_height * bytesPerRowWN;
+ /*console_printf("padd %d bs %d bw %d p %d\n",__intVal(padd),bytesPerRowST,bytesPerRowWN,padding);*/
+ if (padding) {
+ if (nBytes < sizeof(fastBits)) {
+ cp = b_bits = fastBits;
+ } else {
+ cp = b_bits = allocatedBits = (unsigned char *) malloc(nBytes);
+ }
+ if (cp) {
+ pBits = __imageBits;
+ for (row = b_height; row; row--) {
+ for (col = bytesPerRowST; col; col--) {
+ *cp++ = *pBits++;
+ }
+ cp += padding;
+ }
+ } else
+ goto fail;
+ }
+ }
+
+ if (b_bits == 0) {
+ b_bits = __imageBits;
+ }
+
+ bitmap.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ bitmap.bmiHeader.biPlanes = 1;
+ if (__intVal(imageDepth) == 24) {
+ /*bitmap.bmiHeader.biCompression = BI_BITFIELDS;
+ bitmap.r = 0xff0000;
+ bitmap.g = 0x00ff00;
+ bitmap.b = 0x0000ff;*/
+ bitmap.bmiHeader.biCompression = BI_RGB;
+ } else if (__intVal(imageDepth) == 16) {
+ /*bitmap.bmiHeader.biCompression = BI_RGB;
+ bitmap.bmiHeader.biCompression = BI_BITFIELDS;
+ bitmap.b = 0x001f;
+ bitmap.g = 0x07e0;
+ bitmap.r = 0xf800;*/
+ bitmap.b = 0;
+ bitmap.g = 0;
+ bitmap.r = 0;
+ bitmap.bmiHeader.biCompression = BI_RGB;
+ }
+ bitmap.bmiHeader.biSizeImage = 0;
+ bitmap.bmiHeader.biXPelsPerMeter = 0;
+ bitmap.bmiHeader.biYPelsPerMeter = 0;
+ bitmap.bmiHeader.biClrUsed = 0;
+ bitmap.bmiHeader.biClrImportant = 0;
+ bitmap.bmiHeader.biWidth = __intVal(imageWidth);
+ bitmap.bmiHeader.biHeight = -(__intVal(imageHeight));
+ bitmap.bmiHeader.biBitCount = __intVal(bitsPerPixel);
+ /*console_printf("drawBits depth:%d bitsPerPixel:%d IW%d W:%d H:%d\n",__intVal(imageDepth),bitmap.bmiHeader.biBitCount,bitmap.bmiHeader.biWidth,__intVal(w),bitmap.bmiHeader.biHeight);*/
+ SetDIBitsToDevice(hDC,__intVal(dstx),__intVal(dsty),
+ __intVal(w), __intVal(h),
+ __intVal(srcx), __intVal(srcy),
+ 0,__intVal(h),
+ (void *)b_bits,
+ (BITMAPINFO*)&bitmap,DIB_RGB_COLORS);
+ if (allocatedBits) {
+ free(allocatedBits);
+ }
+ RETURN ( true );
+ }
+
+fail: ;
+/*
+ PRINTF(("create temp bitmap FAILED!!!\n"));
+*/
+ if (allocatedBits) {
+/*
+ PRINTF(("freeing up temp bitmap bits ...\n"));
+*/
+ free(allocatedBits);
+ }
+%}
+.
+ ^ false
+! !
+
+!WinPrinterContext methodsFor:'font stuff'!
+
+createFontFor:aFontName
+ "a basic method for font allocation; this method allows
+ any font to be aquired (even those not conforming to
+ standard naming conventions, such as cursor, fixed or k14)"
+
+%{
+ HGDIOBJ hFont;
+ char *fn;
+
+ if (__isString(aFontName) || __isSymbol(aFontName)) {
+ fn = __stringVal(aFontName);
+ if ((strcmp(fn, "fixed") == 0) || (strcmp(fn, "ANSI_FIXED_FONT") == 0)) {
+ hFont = GetStockObject(ANSI_FIXED_FONT);
+ } else if ((strcmp(fn, "variable") == 0) || (strcmp(fn, "ANSI_VAR_FONT") == 0)) {
+ hFont = GetStockObject(ANSI_VAR_FONT);
+ } else if ((strcmp(fn, "system") == 0) || (strcmp(fn, "SYSTEM_FONT") == 0)) {
+ hFont = GetStockObject(SYSTEM_FONT);
+ } else if ((strcmp(fn, "systemFixed") == 0) || (strcmp(fn, "SYSTEM_FIXED_FONT") == 0)) {
+ hFont = GetStockObject(SYSTEM_FIXED_FONT);
+ } else if ((strcmp(fn, "deviceDefault") == 0) || (strcmp(fn, "DEVICE_DEFAULT_FONT") == 0)) {
+ hFont = GetStockObject(DEVICE_DEFAULT_FONT);
+ } else {
+ hFont = GetStockObject(ANSI_FIXED_FONT);
+ }
+ if (hFont) {
+ DPRINTF(("createFontFor:%s -> %x\n", fn, hFont));
+ RETURN ( __MKOBJ(hFont) );
+ }
+ }
+%}.
+ ^ nil
+!
+
+fontMetricsOf:fontId
+ "return a fonts metrics info object"
+
+ |rawData info|
+
+ rawData := Array new:15.
+ (self primFontMetricsOf:fontId hdc:gcId intoArray:rawData) isNil ifTrue:[
+ self primitiveFailed.
+ ^ self
+ ].
+
+ rawData at:11 put:#'ms-ansi'.
+
+ info := DeviceWorkstation::DeviceFontMetrics new.
+ info
+ ascent:(rawData at:1)
+ descent:(rawData at:2)
+ maxAscent:(rawData at:3)
+ maxDescent:(rawData at:4)
+ minWidth:(rawData at:5)
+ maxWidth:(rawData at:6)
+ avgWidth:(rawData at:7)
+ minCode:(rawData at:8)
+ maxCode:16rFFFF "(rawData at:9)"
+ direction:nil
+ encoding:(rawData at:11).
+
+
+ ^ info
+!
+
+getDefaultFont
+ "return a default font id - used when class Font cannot
+ find anything usable"
+
+ ^ self createFontFor:'fixed'
+!
+
+getFontWithFamily:familyString face:faceString
+ style:styleArgString size:sizeArg encoding:encodingSym
+
+ "try to get the specified font, if not available, try the next smaller
+ font."
+
+ |styleString theName theId xlatedStyle id spacing|
+
+ styleString := styleArgString.
+
+ "special: if face is nil, allow access to X-fonts"
+ faceString isNil ifTrue:[
+ sizeArg notNil ifTrue:[
+ theName := familyString , '-' , sizeArg printString
+ ] ifFalse:[
+ theName := familyString
+ ].
+ theName isNil ifTrue:[
+ "
+ mhmh - fall back to the default font
+ "
+ theName := 'fixed'
+ ].
+ theId := self createFontFor:theName.
+ theId isNil ifTrue:[
+ theId := self getDefaultFont
+ ].
+ ^ theId
+ ].
+
+ "/ spacing other than 'normal' is contained as last component
+ "/ in style
+ styleString notNil ifTrue:[
+ ((styleString endsWith:'-narrow')
+ or:[styleString endsWith:'-semicondensed']) ifTrue:[
+ |i|
+ i := styleString lastIndexOf:$-.
+ spacing := styleString copyFrom:(i+1).
+ styleString := styleString copyTo:(i-1).
+ ] ifFalse:[
+ spacing := 'normal'.
+ ].
+ ].
+
+ xlatedStyle := styleString.
+ xlatedStyle notNil ifTrue:[
+ xlatedStyle := xlatedStyle first asString
+ ].
+
+ id := self
+ getFontWithFoundry:'*'
+ family:familyString asLowercase
+ weight:faceString
+ slant:styleString "/ xlatedStyle
+ spacing:spacing
+ pixelSize:nil
+ size:sizeArg
+ registry:'*'
+ encoding:encodingSym.
+
+ id isNil ifTrue:[
+ (encodingSym notNil and:[encodingSym ~= '*']) ifTrue:[
+ "/ too stupid: encodings come in both cases
+ "/
+ id := self
+ getFontWithFoundry:'*'
+ family:familyString asLowercase
+ weight:faceString
+ slant:styleString "/ xlatedStyle
+ spacing:spacing
+ pixelSize:nil
+ size:sizeArg
+ registry:'*'
+ encoding:encodingSym asUppercase.
+ id isNil ifTrue:[
+ id := self
+ getFontWithFoundry:'*'
+ family:familyString asLowercase
+ weight:faceString
+ slant:styleString "/ xlatedStyle
+ spacing:spacing
+ pixelSize:nil
+ size:sizeArg
+ registry:'*'
+ encoding:encodingSym asLowercase.
+
+ id isNil ifTrue:[
+ id := self
+ getFontWithFoundry:'*'
+ family:familyString asLowercase
+ weight:faceString asLowercase
+ slant:styleString asLowercase
+ spacing:spacing
+ pixelSize:nil
+ size:sizeArg
+ registry:'*'
+ encoding:encodingSym asLowercase.
+ ]
+ ]
+ ]
+ ].
+ ^ id
+
+ "Modified: 24.2.1996 / 22:37:24 / cg"
+ "Modified: 4.7.1996 / 11:38:47 / stefan"
+!
+
+getFontWithFoundry:foundry family:family weight:weight
+ slant:slant spacing:spc pixelSize:pixelSize size:pointSize
+ registry:registry encoding:encoding
+
+ "get the specified font, if not available, return nil.
+ For now, this is a poor (incomplete) emulation of the X code ...
+ Individual attributes can be left empty (i.e. '') or nil to match any.
+
+ foundry: 'adobe', 'misc', 'dec', 'schumacher' ... usually '*'
+ family: 'helvetica' 'courier' 'times' ...
+ weight: 'bold' 'medium' 'demi' ...
+ slant: 'r(oman)' 'i(talic)' 'o(blique)'
+ spacing: 'narrow' 'normal' semicondensed' ... usually '*'
+ pixelSize: 16,18 ... usually left empty
+ size: size in point (1/72th of an inch)
+ registry: iso8859, sgi ... '*'
+ encoding: vendor specific encoding (usually '*')
+ "
+
+ "
+ Windows-NT/95 allows the creation of a font with the following parameters
+
+ nHeight
+ nWidth
+ nEscapement
+ nOrientation
+ fnWeight FW_DONTCARE, FW_NORMAL, FW_MEDIUM, FW_BOLD, ...
+ fdwItalic TRUE or FALSE
+ fdwUnderline TRUE or FALSE
+ fdwStrikeOut TRUE or FALSE
+ fdwCharSet ANSI_CHARSET, UNICODE_, SYMBOL_, SHIFTJIS_,...
+ fdwOutputPrecision DEFAULT, STRING, CHAR, ...
+ fdwClipPrecision DEFAULT, CHAR, STROKE, MASK, ...
+ fdwQuality DEFAULT, DRAFT, or PROOF.
+ fdwPitchAndFamily
+ DEFAULT, FIXED or VARIABLE pitch
+ DECORATIVE, DONTCASE, MODERN, ROMAN, SCRIPT, or SWISS.
+ lpszFace
+ Typeface Name
+
+ These two above descriptions will be matched as follows:
+
+ foundry - ignored
+ family - mapped to type face name.
+ weight - mapped to fnWeight
+ slant - used for style
+ spacing - NOT USED INITIALLY
+ pixelSize - NOT USED INITIALLY
+ size - mapped to nHeight
+ registry - NOT USED INITIALLY
+ encoding - mapped to fdwCharSet
+ "
+
+ |logSize|
+
+ pixelSize notNil ifTrue:[
+ logSize := pixelSize
+ ] ifFalse:[
+ logSize := (pointSize * (self getLogicalPixelSizeY) / 72.0) rounded.
+ ].
+%{
+ HGDIOBJ hFont;
+ int pointSize, nHeight, nWidth, nEscapement, nOrientation;
+ char* work;
+ char* work2;
+ DWORD fnWeight;
+ DWORD fdwItalic;
+ DWORD fdwUnderline;
+ DWORD fdwStrikeOut;
+ DWORD fdwCharSet;
+ DWORD fdwOutputPrecision;
+ DWORD fdwClipPrecision;
+ DWORD fdwQuality;
+ DWORD fdwPitchAndFamily;
+ static char faceName[256];
+
+/* INITIALIZE */
+ strcpy( faceName, "NULL" );
+ nHeight = 0;
+ nWidth = 0;
+ nEscapement = 0;
+ nOrientation = 0;
+ fnWeight = FW_NORMAL;
+ fdwItalic = FALSE;
+ fdwUnderline = FALSE;
+ fdwStrikeOut = FALSE;
+ fdwOutputPrecision = OUT_DEFAULT_PRECIS;
+ fdwClipPrecision = CLIP_DEFAULT_PRECIS;
+ fdwQuality = DEFAULT_QUALITY;
+ fdwPitchAndFamily = FF_DONTCARE;
+
+ fdwCharSet = ANSI_CHARSET;
+ if ((encoding == @symbol('ms-ansi'))) {
+ fdwCharSet = ANSI_CHARSET;
+ } else if (encoding == @symbol('ms-default')) {
+ fdwCharSet = DEFAULT_CHARSET;
+ } else if ((encoding == @symbol('ms-symbol'))
+ || (encoding == @symbol('misc-fontspecific'))) {
+ fdwCharSet = SYMBOL_CHARSET;
+ } else if ((encoding == @symbol('ms-shiftjis'))
+ || (encoding == @symbol('jisx0208.1983-0'))){
+ fdwCharSet = SHIFTJIS_CHARSET;
+ } else if ((encoding == @symbol('ms-gb2312'))
+ || (encoding == @symbol('gb2312.1980-0'))) {
+ fdwCharSet = GB2312_CHARSET;
+ } else if ((encoding == @symbol('ms-hangeul'))
+ || (encoding == @symbol('ksc5601.1987-0'))) {
+ fdwCharSet = HANGEUL_CHARSET;
+ } else if ((encoding == @symbol('ms-chinesebig5'))
+ || (encoding == @symbol('big5'))) {
+ fdwCharSet = CHINESEBIG5_CHARSET;
+ } else if (encoding == @symbol('ms-oem')) {
+ fdwCharSet = OEM_CHARSET;
+ } else if (encoding == @symbol('ms-johab')) {
+ fdwCharSet = JOHAB_CHARSET;
+ } else if ((encoding == @symbol('ms-hebrew'))
+ || (encoding == @symbol('ms-cp1255'))) {
+ fdwCharSet = HEBREW_CHARSET;
+ } else if ((encoding == @symbol('ms-arabic'))
+ || (encoding == @symbol('ms-cp1256'))) {
+ fdwCharSet = ARABIC_CHARSET;
+ } else if ((encoding == @symbol('ms-greek'))
+ || (encoding == @symbol('ms-cp1253'))) {
+ fdwCharSet = GREEK_CHARSET;
+ } else if ((encoding == @symbol('ms-turkish'))
+ || (encoding == @symbol('ms-cp1254'))) {
+ fdwCharSet = TURKISH_CHARSET;
+ } else if ((encoding == @symbol('ms-russian'))
+ || (encoding == @symbol('ms-cp1251'))) {
+ fdwCharSet = RUSSIAN_CHARSET;
+ } else if ((encoding == @symbol('ms-easteurope'))
+ || (encoding == @symbol('ms-cp1250'))) {
+ fdwCharSet = EASTEUROPE_CHARSET;
+ } else if ((encoding == @symbol('ms-baltic'))
+ || (encoding == @symbol('ms-cp1257'))) {
+ fdwCharSet = BALTIC_CHARSET;
+ } else if ((encoding == @symbol('ms-vietnamese'))) {
+ fdwCharSet = VIETNAMESE_CHARSET;
+ } else if ((encoding == @symbol('ms-thai'))) {
+ fdwCharSet = THAI_CHARSET;
+ } else if ((encoding == @symbol('ms-mac'))) {
+ fdwCharSet = MAC_CHARSET;
+#ifdef UNICODE_CHARSET
+ } else if ((encoding == @symbol('ms-unicode'))) {
+ fdwCharSet = UNICODE_CHARSET;
+#endif
+ }
+
+ if ( __isString( family ) ) {
+ work = __stringVal( family );
+ if (strcmp( work, "nil" ) != 0 ) {
+ strncpy( faceName, work, sizeof(faceName)-1 );
+ }
+ }
+
+ /* Q: should we allow those ? (they make ST/X programs less portable to X */
+ if( __isString( weight ) ) {
+ work = __stringVal( weight );
+ if (strcmp( work, "bold" ) == 0 ) {
+ fnWeight = FW_BOLD;
+ } else if (strcmp( work, "medium" ) == 0 ) {
+ fnWeight = FW_MEDIUM;
+ } else if (strcmp( work, "normal" ) == 0 ) {
+ fnWeight = FW_NORMAL;
+ } else if (strcmp( work, "light" ) == 0 ) {
+ fnWeight = FW_LIGHT;
+ } else if (strcmp( work, "demi" ) == 0 ) {
+ fnWeight = FW_LIGHT;
+ } else if (strcmp( work, "heavy" ) == 0 ) {
+ fnWeight = FW_HEAVY;
+ } else if (strcmp( work, "extraBold" ) == 0 ) {
+ fnWeight = FW_EXTRABOLD;
+ } else if (strcmp( work, "semiBold" ) == 0 ) {
+ fnWeight = FW_SEMIBOLD;
+ } else if (strcmp( work, "thin" ) == 0 ) {
+ fnWeight = FW_THIN;
+ } else if (strcmp( work, "extraLight" ) == 0 ) {
+ fnWeight = FW_EXTRALIGHT;
+ }
+ } else if (__isSmallInteger(weight)) {
+ fnWeight = __intVal(weight);
+ }
+
+ if(__isSmallInteger( logSize )) {
+ nHeight = __intVal( logSize );
+ }
+
+ if (__isString(slant)) {
+ work2 = __stringVal( slant );
+ work = __stringVal( slant );
+
+ if (strncmp(work2, "italic", 6) == 0) {
+ fdwItalic = TRUE;
+ if ( work2[6] == '-' )
+ strncpy( work, &work2[7], ( strlen( work2) - 7) );
+ } else {
+ if (strncmp(work2, "oblique", 7) == 0) {
+ fdwItalic = TRUE;
+ if ( work2[7] == '-' )
+ strncpy( work, &work2[8], ( strlen( work2) - 8) );
+ }
+ }
+ if (strncmp( work, "underline", 9 ) == 0 ) {
+ fdwUnderline = TRUE;
+ if( work[10] == '-' )
+ strncpy( work2, &work[11], ( strlen( work ) - 10 ) );
+ }
+ if (strncmp( work2, "strikeOut", 9 ) == 0 ) {
+ fdwStrikeOut = TRUE;
+ }
+ }
+
+ DPRINTF(("CreateFont face:%s h=%d w=%d wght=%d\n",
+ faceName, nHeight, nWidth, fnWeight));
+
+ hFont = CreateFont( -nHeight, /* character height - not cell height */
+ nWidth,
+ nEscapement,
+ nOrientation,
+ fnWeight,
+ fdwItalic,
+ fdwUnderline,
+ fdwStrikeOut,
+ fdwCharSet,
+ fdwOutputPrecision,
+ fdwClipPrecision,
+ fdwQuality,
+ fdwPitchAndFamily,
+ faceName );
+
+ if (hFont != NULL) {
+ DPRINTF(("createFont: %x\n", hFont));
+/*
+ #ifdef COUNT_RESOURCES
+ __cnt_font++;
+ RES1PRINTF(("CreateFont %d\n", __cnt_font));
+ #endif
+*/
+ RETURN ( __MKOBJ(hFont) );
+ }
+
+ DPRINTF(("***** ERROR createFontWithFoundry failed ERROR *****\n" ));
+%}.
+ ^ nil
+
+ "
+ Display getFontWithFoundry:'*'
+ family:'courier'
+ weight:'medium'
+ slant:'r'
+ spacing:nil
+ pixelSize:nil
+ size:13
+ registry:'iso8859'
+ encoding:'*'
+ "
+
+ "new NT Version: 20.2.1997 / 22:33:29 / dq"
+!
+
+primFontMetricsOf:fontId hdc:aDC intoArray:rawData
+ "evaluate aBlock, passing a fonts metrics as arguments.
+ fill passed array as:
+ ascent -> (data at:1)
+ descent -> (data at:2)
+ maxAscent -> (data at:3)
+ maxDescent -> (data at:4)
+ minWidth -> (data at:5)
+ maxWidth -> (data at:6)
+ avgWidth -> (data at:7).
+ minChar -> (data at:8).
+ maxChar -> (data at:9).
+ defaultChar-> (data at:10).
+ charSet -> (data at:11).
+"
+
+%{
+
+ if (__isExternalAddress(fontId)
+ && __isExternalAddressLike(aDC)
+ && __isArray(rawData)
+ && (__arraySize(rawData) >= 11)) {
+ SIZE size;
+ int avgWidth;
+ HGDIOBJ hFont;
+ HGDIOBJ prevFont;
+ TEXTMETRIC tmet;
+ static char *s = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+ static int len;
+ OBJ t;
+ HANDLE hDC;
+
+ hFont = _HGDIOBJVal(fontId);
+ hDC = (HANDLE)(__externalAddressVal(aDC));
+
+ /*
+ * temporarily set this font in the tmpDC (root-) context
+ */
+
+ prevFont = SelectObject(hDC, hFont);
+
+ GetTextMetricsW(hDC, &tmet);
+ if (len == 0) {
+ len = strlen(s);
+ }
+#if 0
+ GetTextExtentPoint32(hDC, s, len, &size);
+ avgWidth = (size.cx / (len / 2) + 1) / 2;
+#else
+ avgWidth = tmet.tmAveCharWidth;
+#endif
+
+ __ArrayInstPtr(rawData)->a_element[0] = __MKSMALLINT(tmet.tmAscent); /* ascent -> (data at:1) */
+ __ArrayInstPtr(rawData)->a_element[1] = __MKSMALLINT(tmet.tmDescent); /* descent -> (data at:2) */
+ __ArrayInstPtr(rawData)->a_element[2] = __MKSMALLINT(tmet.tmAscent); /* maxAscent -> (data at:3) */
+ __ArrayInstPtr(rawData)->a_element[3] = __MKSMALLINT(tmet.tmDescent); /* maxDescent -> (data at:4) */
+ __ArrayInstPtr(rawData)->a_element[4] = __MKSMALLINT(avgWidth); /* minWidth -> (data at:5) */
+ __ArrayInstPtr(rawData)->a_element[5] = __MKSMALLINT(tmet.tmMaxCharWidth); /* maxWidth -> (data at:6) */
+ __ArrayInstPtr(rawData)->a_element[6] = __MKSMALLINT(avgWidth); /* avgWidth -> (data at:7) */
+ __ArrayInstPtr(rawData)->a_element[7] = __MKSMALLINT(tmet.tmFirstChar); /* min -> (data at:8) */
+ __ArrayInstPtr(rawData)->a_element[8] = __MKSMALLINT(tmet.tmLastChar); /* max -> (data at:9) */
+ __ArrayInstPtr(rawData)->a_element[9] = __MKSMALLINT(tmet.tmDefaultChar); /* default -> (data at:10) */
+#if 0
+ t = __charSetSymbolFor(tmet.tmCharSet);
+ __ArrayInstPtr(rawData)->a_element[10]= t; __STORE(rawData, t); /* charSet -> (data at:11) */
+#endif
+
+ DPRINTF(("textMetrics h=%x avgAsc=%d avgDesc=%d minW=%d maxW=%d avgW=%d\n",
+ hFont, tmet.tmAscent, tmet.tmDescent, avgWidth, tmet.tmMaxCharWidth,
+ tmet.tmAveCharWidth));
+
+ SelectObject(hDC, prevFont);
+ RETURN (self);
+ }
+ RETURN (nil);
+%}
+!
+
+releaseFont:aFontId
+
+%{ /* NOCONTEXT */
+ if (__isExternalAddress(aFontId)) {
+ HGDIOBJ hFont = _HGDIOBJVal(aFontId);
+
+ if (hFont) {
+ DPRINTF(("ReleaseFont: %x\n", hFont));
+ DeleteObject(hFont);
+ }
+ }
+%}
+!
+
+setFont:aFontId in:aDC
+ "set font to be drawn in"
+
+%{ /* NOCONTEXT */
+
+ if (__isExternalAddressLike(aDC)
+ && __isExternalAddress(aFontId))
+ {
+ HANDLE hDC = (HANDLE)(__externalAddressVal(aDC));
+ HGDIOBJ prevFont, hFont;
+
+ hFont = _HGDIOBJVal(aFontId);
+ prevFont = SelectObject(hDC, hFont);
+
+ RETURN ( self );
+ }
+%}.
+ self primitiveFailed
+
+ "Created: / 04-08-2006 / 12:32:53 / fm"
+!
+
+widthOf:aString from:index1 to:index2 inFont:aFontId
+
+%{ /* NOCONTEXT */
+ unsigned char *cp;
+ int len, n, i1, i2, l;
+ OBJ cls;
+ int nInstBytes;
+
+ if (__bothSmallInteger(index1, index2)
+ && __isExternalAddress(aFontId)
+ && __isExternalAddressLike(__INST(gcId))
+ && __isNonNilObject(aString)) {
+ HGDIOBJ hFont,prevFont;
+ HANDLE hDC;
+ SIZE tsize;
+
+#ifndef PRE_22_FEP_2007
+# define N_QUICK_CHARS 1024
+ unsigned short quickWchars[N_QUICK_CHARS];
+ unsigned short *wcharPtr;
+ int mustFree = 0;
+ int i;
+#endif
+
+ hFont = _HGDIOBJVal(aFontId);
+ hDC = (HANDLE)(__externalAddressVal(__INST(gcId)));
+
+ prevFont = SelectObject(hDC, hFont);
+
+ i1 = __intVal(index1) - 1;
+ cls = __qClass(aString);
+
+ if (i1 >= 0) {
+ i2 = __intVal(index2) - 1;
+ if (i2 < i1) {
+ RETURN ( __MKSMALLINT( 0 ) );
+ }
+
+ cp = (char *) _stringVal(aString);
+ l = i2 - i1 + 1;
+
+ if ((cls == @global(String)) || (cls == @global(Symbol))) {
+ n = _stringSize(aString);
+ commonWidthChars:
+ if (i2 < n) {
+ cp += i1;
+
+#ifdef PRE_22_FEP_2007
+ GetTextExtentPoint32(hDC, cp, l, &tsize);
+#else
+ if (l <= N_QUICK_CHARS) {
+ wcharPtr = quickWchars;
+ mustFree = 0;
+ } else {
+ wcharPtr = malloc(sizeof(short)*l);
+ if (! wcharPtr) RETURN (__MKSMALLINT(0));
+ mustFree = 1;
+ }
+ for (i=0; i<l; i++) wcharPtr[i] = ((unsigned char *)cp)[i];
+ GetTextExtentPoint32W(hDC, wcharPtr, l, &tsize);
+ if (mustFree) free(wcharPtr);
+#endif
+
+#ifdef SUPERDEBUG
+ if (__debug__) {
+ char buf[80];
+
+ GetTextFace(hDC,80,buf);
+ console_printf("font1 %x %s >%s< l=%d dx=%d\n",hFont,buf,cp,l,tsize.cx);
+ }
+#endif
+ SelectObject(hDC, prevFont);
+ RETURN ( __MKSMALLINT(tsize.cx) );
+ }
+ RETURN (__MKSMALLINT(0));
+ }
+
+ nInstBytes = __OBJS2BYTES__(__intVal(__ClassInstPtr(cls)->c_ninstvars));
+ cp += nInstBytes;
+ n = __byteArraySize(aString) - nInstBytes;
+
+ if (__isBytes(aString)) {
+ goto commonWidthChars;
+ }
+
+ /* Unicode */
+ if (__isWords(aString)) {
+ n = n / 2;
+ if (i2 < n) {
+ WIDECHAR *w_cp = (WIDECHAR *)cp;
+
+ w_cp += i1;
+
+ GetTextExtentPoint32W(hDC, w_cp, l, &tsize);
+ SelectObject(hDC, prevFont);
+ RETURN ( __MKSMALLINT(tsize.cx) );
+ }
+ RETURN (__MKSMALLINT(0));
+ }
+ }
+ }
+%}.
+ self primitiveFailed.
+ ^ 0
+!
+
+widthOf:aString inFont:aFontId
+ "return the width in pixels of a string in a specific font"
+
+ ^ self widthOf:aString from:1 to:(aString size) inFont:aFontId
! !
!WinPrinterContext methodsFor:'initialization & release'!
@@ -718,6 +4006,38 @@
OperatingSystem deletePrinterDC: gcId.
!
+destroy
+ "Destroy the GC."
+
+ |id|
+
+ id := gcId.
+ id notNil ifTrue:[
+ gcId := nil.
+ self deleteDC.
+ ].
+"/ Lobby unregister:self.
+!
+
+destroyGC:aDC
+%{
+ if (__isExternalAddressLike(aDC)) {
+ HANDLE hDC = (HANDLE)(__externalAddressVal(aDC));
+
+ DeleteDC(hDC);
+
+/*
+#ifdef CACHE_LAST_DC
+ if (lastGcData == gcData) {
+ _releaseDC(gcData);
+ }
+#endif
+*/
+
+ }
+%}
+!
+
executor
|aCopy|
@@ -728,12 +4048,278 @@
"Created: / 16-04-2007 / 12:39:02 / cg"
!
+initialize
+ super initialize.
+"/ deviceForms := Registry new.
+"/ deviceColors := Registry new.
+ deviceFonts := CachingRegistry new cacheSize:10.
+!
+
releaseDC
"Private - Delete and clear the device context of the receiver."
self deleteDC.
"/ device close.
- gcId := nil
+ gcId := nil.
+ self releaseDeviceFonts
+!
+
+releaseDeviceFonts
+ deviceFonts isEmptyOrNil ifFalse:[
+ deviceFonts do:[:afont |
+ afont releaseFromDevice.
+ ].
+ ].
+ deviceFonts := CachingRegistry new cacheSize:10.
+! !
+
+!WinPrinterContext methodsFor:'not supported yet'!
+
+displayAdvanceLineFrom:point1 to:point2
+ "draw a line"
+
+ self displayAdvanceLineFromX:(point1 x) y:(point1 y)
+ toX:(point2 x) y:(point2 y)
+!
+
+displayAdvanceLineFromX:x0 y:y0 toX:x1 y:y1
+ "draw a line (with current paint-color); apply transformation if nonNil"
+
+ |pX0 pY0 pX1 pY1 easy fgId bgId|
+
+ gcId isNil ifTrue:[
+ self initGC
+ ].
+
+ lineStyle == #doubleDashed ifTrue:[
+ "
+ if bgPaint or paint is not a real color, we have to do it the hard way ...
+ "
+ easy := true.
+ paint isColor ifFalse:[
+ easy := false
+ ] ifTrue:[
+ fgId := paint colorId.
+ fgId isNil ifTrue:[
+ easy := false
+ ]
+ ].
+ bgPaint isColor ifFalse:[
+ easy := false
+ ] ifTrue:[
+ bgId := bgPaint colorId.
+ bgId isNil ifTrue:[
+ easy := false
+ ]
+ ].
+
+ easy ifTrue:[
+ ((foreground ~~ paint) or:[background ~~ bgPaint]) ifTrue:[
+ device setForeground:fgId background:bgId in:gcId.
+ foreground := paint.
+ background := bgPaint.
+ ].
+ ] ifFalse:[
+ 'DeviceGraphicsContext [warning]: cannot draw dashes with dithered colors' errorPrintCR
+ ].
+ ].
+
+ transformation notNil ifTrue:[
+ pX0 := transformation applyToX:x0.
+ pY0 := transformation applyToY:y0.
+ pX1 := transformation applyToX:x1.
+ pY1 := transformation applyToY:y1.
+ ] ifFalse:[
+ pX0 := x0.
+ pY0 := y0.
+ pX1 := x1.
+ pY1 := y1
+ ].
+
+ pX0 := pX0 rounded.
+ pY0 := pY0 rounded.
+ pX1 := pX1 rounded.
+ pY1 := pY1 rounded.
+
+ device displayAdvanceLineFromX:pX0 y:pY0 toX:pX1 y:pY1 in:drawableId with:gcId
+
+ "Modified: 10.1.1997 / 17:46:32 / cg"
+!
+
+displayAdvanceLineFromX:x0 y:y0 toX:x1 y:y1 in:ignoredDrawableId with:aDC
+ "draw a line. If the coordinates are not integers, an error is triggered."
+
+ self getPenForMyContext.
+
+%{ /* NOCONTEXT */
+ if (__isExternalAddressLike(aDC)
+ && __bothSmallInteger(x0, y0)
+ && __bothSmallInteger(x1, y1)) {
+ HANDLE hDC = (HANDLE)(__externalAddressVal(aDC));
+ COLORREF fgColor;
+ int __x1 = __intVal(x1), __y1 = __intVal(y1);
+
+
+/* DPRINTF(("displayLine: %d/%d -> %d/%d\n",
+ __intVal(x0), __intVal(y0),
+ __x1, __y1));
+*/
+
+/* fgColor = GetTextColor(hDC);
+ * hPen = CreatePen(PS_SOLID, 1, fgColor);
+ */
+
+ MoveToEx(hDC, __intVal(x0), __intVal(y0), NULL);
+
+ LineTo(hDC, __x1, __y1);
+
+ /*
+ * end-point ...
+ */
+ LineTo(hDC, __x1+1, __y1);
+
+
+
+ RETURN ( self );
+ }
+%}
+!
+
+xxdisplayLineFromX:x0 y:y0 toX:x1 y:y1 in:ignoredDrawableId with:aDC
+ "draw a line. If the coordinates are not integers, an error is triggered."
+
+ |pen|
+
+ pen := self getPenForMyContext.
+
+%{ /* NOCONTEXT */
+ if (__isExternalAddressLike(aDC)
+ && __bothSmallInteger(x0, y0)
+ && __bothSmallInteger(x1, y1)) {
+ HANDLE hDC = (HANDLE)(__externalAddressVal(aDC));
+ COLORREF fgColor;
+ HANDLE prevPen, hPen;
+ int __x1 = __intVal(x1), __y1 = __intVal(y1);
+ /* Obtaining Pen */
+ int style, styleInt, lineWidth;
+
+ lineWidth= __INST(lineWidth);
+
+ if (__INST(lineStyle) == @symbol(solid)) {
+ style= PS_SOLID;
+ } else if (__INST(lineStyle) == @symbol(dashed)) {
+ style= PS_DASH;
+ } else if (__INST(lineStyle) == @symbol(dotted)) {
+ style= PS_DOT;
+ } else if (__INST(lineStyle) == @symbol(dashDot)) {
+ style= PS_DASHDOT;
+ } else if (__INST(lineStyle) == @symbol(dashDotDot)) {
+ style= PS_DASHDOTDOT;
+ } else
+ style= PS_SOLID;
+ styleInt &= ~PS_STYLE_MASK;
+ styleInt |= style;
+
+
+ if (__INST(capStyle) == @symbol(round)) {
+ style= PS_ENDCAP_ROUND;
+ } else if (__INST(capStyle) == @symbol(square)) {
+ style= PS_ENDCAP_SQUARE;
+ } else if (__INST(capStyle) == @symbol(flat)) {
+ style= PS_ENDCAP_FLAT;
+ } else
+ style= PS_ENDCAP_FLAT;
+ styleInt &= ~PS_ENDCAP_MASK;
+ styleInt |= style;
+
+
+ if (__INST(joinStyle) == @symbol(bevel)) {
+ style= PS_JOIN_BEVEL;
+ } else if (__INST(joinStyle) == @symbol(miter)) {
+ style= PS_JOIN_MITER;
+ } else if (__INST(joinStyle) == @symbol(round)) {
+ style= PS_JOIN_ROUND;
+ } else
+ style= PS_JOIN_MITER;
+ styleInt &= ~PS_JOIN_MASK;
+ styleInt |= style;
+
+
+ fgColor = GetTextColor(hDC);
+ hPen = CreatePen((styleInt & PS_STYLE_MASK), lineWidth, fgColor);
+
+ /* Finish Obtaining Pen */
+
+
+/* DPRINTF(("displayLine: %d/%d -> %d/%d\n",
+ __intVal(x0), __intVal(y0),
+ __x1, __y1));
+*/
+
+ prevPen = SelectObject(hDC, hPen);
+
+ MoveToEx(hDC, __intVal(x0), __intVal(y0), NULL);
+
+ LineTo(hDC, __x1, __y1);
+
+ /*
+ * end-point ...
+ */
+ LineTo(hDC, __x1+1, __y1);
+
+ SelectObject(hDC, prevPen);
+
+
+ RETURN ( self );
+ }
+%}
+!
+
+xxxdisplayLineFromX:x0 y:y0 toX:x1 y:y1 in:ignoredDrawableId with:aDC
+ "draw a line. If the coordinates are not integers, an error is triggered."
+
+ |penHandle|
+
+ penHandle := ExternalBytes address: self getPenForMyContext.
+
+%{ /* NOCONTEXT */
+ if (__isExternalAddressLike(aDC)
+ && __isExternalAddressLike(penHandle)
+ && __bothSmallInteger(x0, y0)
+ && __bothSmallInteger(x1, y1)) {
+ HANDLE hDC = (HANDLE)(__externalAddressVal(aDC));
+ HANDLE hPen = (HANDLE)(__externalAddressVal(penHandle));
+ COLORREF fgColor;
+ HANDLE prevPen;
+ int __x1 = __intVal(x1), __y1 = __intVal(y1);
+
+
+/* DPRINTF(("displayLine: %d/%d -> %d/%d\n",
+ __intVal(x0), __intVal(y0),
+ __x1, __y1));
+*/
+
+/* fgColor = GetTextColor(hDC);
+ * hPen = CreatePen(PS_SOLID, 1, fgColor);
+ */
+
+ prevPen = SelectObject(hDC, hPen);
+
+ MoveToEx(hDC, __intVal(x0), __intVal(y0), NULL);
+
+ LineTo(hDC, __x1, __y1);
+
+ /*
+ * end-point ...
+ */
+ LineTo(hDC, __x1+1, __y1);
+
+ SelectObject(hDC, prevPen);
+
+
+ RETURN ( self );
+ }
+%}
! !
!WinPrinterContext methodsFor:'printing process'!
@@ -818,6 +4404,18 @@
!WinPrinterContext methodsFor:'queries'!
+hasGrayscales
+ "return true, if this workstation supports grayscales
+ (also true for color displays)"
+
+ ^ true
+!
+
+isOpen
+
+ ^ gcId notNil
+!
+
supportsColor
"/ | retVal info |
@@ -849,6 +4447,16 @@
"Modified: / 16-04-2007 / 12:44:03 / cg"
! !
+!WinPrinterContext methodsFor:'registration'!
+
+registerFont:aFont
+ deviceFonts register:aFont.
+!
+
+unregisterFont:aFont
+ deviceFonts unregister:aFont.
+! !
+
!WinPrinterContext methodsFor:'text printing'!
stringWidthOf:aString at:index
@@ -889,5 +4497,5 @@
!WinPrinterContext class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libview2/WinPrinterContext.st,v 1.7 2007-04-18 12:52:36 cg Exp $'
+ ^ '$Header: /cvs/stx/stx/libview2/WinPrinterContext.st,v 1.8 2007-04-23 09:32:45 fm Exp $'
! !