#REFACTORING by stefan
class: Icon
class definition
comment/format in: #documentation
"
COPYRIGHT (c) 2006 by eXept Software AG
All Rights Reserved
This software is furnished under a license and may be used
only in accordance with the terms of that license and with the
inclusion of the above copyright notice. This software may not
be provided or otherwise made available to, or used by, any
other person. No title to or ownership of the software is
hereby transferred.
"
"{ Package: 'stx:libview2' }"
"{ NameSpace: Smalltalk }"
PrinterContext subclass:#WinPrinterContext
instanceVariableNames:'deviceFonts hatch supportsColor title'
classVariableNames:'PostScriptBlackWhite'
poolDictionaries:''
category:'Interface-Printing'
!
WinPrinterContext subclass:#WinPrinterGraphicContext
instanceVariableNames:'fontScale printPageNumbers pageNumberFormat pageCounter
needsEndOfPage titleFont width height'
classVariableNames:''
poolDictionaries:''
privateIn:WinPrinterContext
!
!WinPrinterContext primitiveDefinitions!
%{
#undef INT
#define INT WIN_INT
#undef Array
#define Array WIN_Array
#undef Number
#define Number WIN_Number
#undef Method
#define Method WIN_Method
#undef Point
#define Point WIN_Point
#undef Rectangle
/* #define Rectangle WIN_Rectangle */
#undef True
#define True WIN_True
#undef False
#define False WIN_False
#undef Block
#define Block WIN_Block
#undef Context
#define Context WIN_Context
#undef Date
#define Date WIN_Date
#undef Time
#define Time WIN_Time
#undef Delay
#define Delay WIN_Delay
#undef Signal
#define Signal WIN_Signal
#undef Set
#define Set WIN_Set
#undef Process
#define Process WIN_Process
#undef Processor
#define Processor WIN_Processor
#undef Message
#define Message WIN_Message
#undef String
#define String WIN_String
#undef Character
#define Character WIN_Character
#include <stdio.h>
#include <errno.h>
#ifdef __BORLANDC__
# define NOATOM
# define NOGDICAPMASKS
# define NOMETAFILE
# define NOMINMAX
# define NOOPENFILE
# define NOSOUND
# define NOWH
# define NOCOMM
# define NOKANJI
# define NOCRYPT
# define NOMCX
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
# include <shellapi.h>
# include <sys\timeb.h>
# include <dir.h>
#else
# define _USERENTRY /**/
# define NOATOM
# define NOGDICAPMASKS
# define NOMETAFILE
# define NOMINMAX
# define NOOPENFILE
# define NOSOUND
# define NOWH
# define NOCOMM
# define NOKANJI
# define NOCRYPT
# define NOMCX
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
# include <sys\timeb.h>
#endif
#include <process.h>
#ifdef __DEF_Array
# undef Array
# define Array __DEF_Array
#endif
#ifdef __DEF_Number
# undef Number
# define Number __DEF_Number
#endif
#ifdef __DEF_Method
# undef Method
# define Method __DEF_Method
#endif
#ifdef __DEF_Point
# undef Point
# define Point __DEF_Point
#endif
#ifdef __DEF_Rectangle
# undef Rectangle
# define Rectangle __DEF_Rectangle
#else
# undef Rectangle
#endif
#ifdef __DEF_Block
# undef Block
# define Block __DEF_Block
#endif
#ifdef __DEF_Context
# undef Context
# define Context __DEF_Context
#endif
#ifdef __DEF_Date
# undef Date
# define Date __DEF_Date
#endif
#ifdef __DEF_Time
# undef Time
# define Time __DEF_Time
#endif
# ifdef __DEF_Set
# undef Set
# define Set __DEF_Set
# endif
# ifdef __DEF_Signal
# undef Signal
# define Signal __DEF_Signal
# endif
# ifdef __DEF_Delay
# undef Delay
# define Delay __DEF_Delay
# endif
# ifdef __DEF_Process
# undef Process
# define Process __DEF_Process
# endif
# ifdef __DEF_Processor
# undef Processor
# define Processor __DEF_Processor
# endif
# ifdef __DEF_Message
# undef Message
# define Message __DEF_Message
# endif
# ifdef __DEF_String
# undef String
# define String __DEF_String
# endif
# ifdef __DEF_Character
# undef Character
# define Character __DEF_Character
# endif
#undef INT
#define INT STX_INT
#undef UINT
#define UINT STX_UINT
/*
* some defines - tired of typing ...
*/
#define _HANDLEVal(o) (HANDLE)(__MKCP(o))
#define _HBITMAPVAL(o) (HBITMAP)(__MKCP(o))
#define _HWNDVal(o) (HWND)(__MKCP(o))
#define _HPALETTEVal(o) (HPALETTE)(__MKCP(o))
#define _HCURSORVal(o) (HCURSOR)(__MKCP(o))
#define _HGDIOBJVal(o) (HGDIOBJ)(__MKCP(o))
#define _LOGPALETTEVal(o) (LOGPALETTE *)(__MKCP(o))
#define _COLORREFVal(o) (COLORREF)(__MKCP(o))
#define WIDECHAR unsigned short
#define WIN32PADDING 32
#ifdef DEBUG
# define DPRINTF(x) /* printf x */
# define DFPRINTF(x) /* fprintf x */
#else
# define DPRINTF(x) /* */
# define DFPRINTF(x) /* */
#endif
typedef int (*intf)(int);
typedef INT (*INTF)(INT);
%}
! !
!WinPrinterContext class methodsFor:'documentation'!
copyright
"
COPYRIGHT (c) 2006 by eXept Software AG
All Rights Reserved
This software is furnished under a license and may be used
only in accordance with the terms of that license and with the
inclusion of the above copyright notice. This software may not
be provided or otherwise made available to, or used by, any
other person. No title to or ownership of the software is
hereby transferred.
"
!
documentation
"
I am the mediator between the smalltalk printing protocol
(which is the same as the graphics drawing protocol) and the
windows printer.
When you open a printer, you will typically talk to me.
[author:]
Felix Madrid (fm@exept.de)
"
! !
!WinPrinterContext class methodsFor:'instance creation'!
fromPrinterInfo: aPrinterInfo
| printerContext printerDevice hDC|
hDC := aPrinterInfo createDC.
hDC = 0 ifTrue: [ ^self error: 'Error while opening printer.' ].
printerContext := self new.
printerDevice := printerContext.
"/ printerDevice := WinPrinter on: aPrinterInfo.
"/ printerDevice printerDC:hDC.
printerContext printerInfo: aPrinterInfo.
printerContext setDevice:printerDevice id:nil gcId:hDC.
printerContext initExtent.
^printerContext
"Created: / 03-08-2006 / 12:53:52 / fm"
"Modified: / 04-08-2006 / 12:55:01 / fm"
"Modified: / 16-04-2007 / 12:36:26 / cg"
!
newPrinter
| printer printerInfo|
printerInfo := PrintingDialog getPrinterInfo.
printerInfo isNil ifTrue:[^self].
printer := self fromPrinterInfo: printerInfo.
^ printer
!
openGraphicContext
^ self openGraphicContextWithoutDialog:false
!
openGraphicContextWithoutDialog:withoutDialog
^ self openGraphicContextWithoutDialog:withoutDialog jobName:nil
!
openGraphicContextWithoutDialog:withoutDialog jobName:jobName
|printerInfo gc|
printerInfo := PrintingDialog getPrinterInfoWithoutDialog:withoutDialog.
printerInfo isNil ifTrue:[^ nil].
gc := WinPrinterGraphicContext fromPrinterInfo:printerInfo.
gc notNil ifTrue:[
gc startPrintJob:jobName
].
^ gc
! !
!WinPrinterContext class methodsFor:'accessing'!
getPrinterInformation:printerNameString
" Answer the printer information for the printer named printerNameString. If no name is specified,
answer the information for the default printer."
|h|
h := OperatingSystem openPrinter:printerNameString.
^ OperatingSystem
getDocumentProperties:nil
hPrinter:h
pDeviceName:printerNameString.
"Created: / 27-07-2006 / 10:22:32 / fm"
"Modified: / 01-08-2006 / 16:01:44 / fm"
"Modified: / 10-10-2006 / 18:57:45 / cg"
!
getPrinterInformationString: printerNameString
" Answer the printer information string from the WIN.INI file
for the printer named printerNameString. If no name is specified,
answer the information for the default printer. "
| printerInfo result |
printerInfo := ( String new: 80 ).
result := OperatingSystem primGetProfileString: 'windows'
keyName: 'device'
default: ( printerNameString isNil ifTrue: [ '' ] ifFalse: [ printerNameString ] )
returnedString: printerInfo
size: printerInfo size.
^result > 0
ifTrue: [printerInfo copyFrom: 1 to: result]
ifFalse: ['']
!
named: aName
"Answer a new instance of Printer which represents
the printer named aName as specified in the host
Control Panel."
aName isNil ifTrue: [ ^self default ].
^self new printerInfoWithName: aName
"Created: / 27-07-2006 / 17:51:27 / fm"
"Modified: / 02-08-2006 / 17:26:29 / fm"
"Modified: / 10-10-2006 / 17:33:29 / cg"
!
postScriptBlackWhite
"Returns true if the postscript is b&w or returns false if the postscript is color"
^ PostScriptBlackWhite ? false
!
postScriptBlackWhite: aBoolean
PostScriptBlackWhite := aBoolean
! !
!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"
! !
!WinPrinterContext class methodsFor:'testing'!
computeScaleForPrinter:aPrinter
^ Point x:(aPrinter pixelsPerInchOfScreenWidth / Screen current horizontalPixelPerInch)
y:(aPrinter pixelsPerInchOfScreenHeight / Screen current verticalPixelPerInch)
!
testPrintingDo:anOneArgBlock
"Opens a print dialog and invokes the action with the printer"
| printerInfo printer |
printerInfo := PrintingDialog getPrinterInfo.
printerInfo isNil ifTrue:[^self].
printer := self fromPrinterInfo: printerInfo.
printer startPrintJob: 'Testing'.
anOneArgBlock value:printer.
printer endPrintJob.
"
self testPrintingDo:[:aPrinter| |icon|
aPrinter scale:(self computeScaleForPrinter:aPrinter).
aPrinter displayLineFrom:10@10 to:100@10.
aPrinter displayLineFrom:100@10 to:100@100.
aPrinter displayLineFrom:100@100 to:10@100.
aPrinter displayLineFrom:10@100 to:10@10.
icon := XPToolbarIconLibrary eraseXP28x28Icon.
icon displayOn:aPrinter x:10 y:10.
].
self testPrintingDo:[:aPrinter| |scale|
scale := self computeScaleForPrinter:aPrinter.
aPrinter scale:(1 * scale).
aPrinter font:(Font family:'Arial' face:'medium' size:8).
aPrinter displayLineFrom:8@16 to:100@16.
aPrinter displayLineFrom:8@16 to:8@128.
'hallo' displayOn:aPrinter x:8 y:16.
aPrinter scale:(2 * scale).
'hallo' displayOn:aPrinter x:4 y:32.
aPrinter scale:(4 * scale).
'hallo' displayOn:aPrinter x:2 y:32.
].
"
! !
!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"
!
fillHatchCircles: 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 Hatch Circles'.
arrayOfPointsAndRadiusWithContextArray
do:[:pointsAndRadiusWithContextArray |
| point radius color hatch|
point := (pointsAndRadiusWithContextArray at:1).
radius := (pointsAndRadiusWithContextArray at:2).
color := (pointsAndRadiusWithContextArray at:3).
hatch := (pointsAndRadiusWithContextArray at:4).
printer foreground: color;
hatch: hatch.
printer fillCircle:point
radius:radius.
].
printer endPrintJob.
] forkAt: 3
"
WinPrinterContext fillHatchCircles:
(Array with: (Array with: 800@800 with: 600 with:Color red with: #diagonalCross)
with: (Array with: 1500@1500 with: 1000 with:Color blue with: #vertical)
with: (Array with: 4000@2500 with: 2000 with:Color gray with: #bDiagonal))
"
"Created: / 07-08-2006 / 11:46:52 / fm"
"Modified: / 16-04-2007 / 15:37:34 / cg"
!
fillHatchPolygons: 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 Hatch Polygons'.
polygonsWithContextArray
do:[:polygonWithContextArray |
|aPolygon color hatch|
aPolygon := polygonWithContextArray at: 1.
color := (polygonWithContextArray at: 2).
hatch := (polygonWithContextArray at: 3).
printer foreground: color;
hatch: hatch.
aPolygon displayFilledOn: printer.
].
printer endPrintJob.
] forkAt: 3
"
WinPrinterContext fillHatchPolygons:
(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: #cross)
with: (Array with: (Polygon vertices:(
Array
with:1000@1000
with:1000@2000
with:2000@1000))
with: Color blue
with: #none)
)
"
"Created: / 07-08-2006 / 12:09:48 / fm"
"Modified: / 07-08-2006 / 14:11:17 / fm"
"Modified: / 16-04-2007 / 15:37:43 / cg"
!
fillHatchRectangles: rectanglesWithHatch
"Opens a print dialog and prints the given rectangles"
| printerInfo printer |
printerInfo := PrintingDialog getPrinterInfo.
printerInfo isNil ifTrue:[^self].
printer := self fromPrinterInfo: printerInfo.
[
printer startPrintJob: 'Fill Hatch Rectangles'.
printer foreground:Color blue background:Color white.
rectanglesWithHatch
do:[:rectangleWithHatch |
|rectangle hatch|
rectangle := rectangleWithHatch at: 1.
hatch := rectangleWithHatch at: 2.
printer hatch: hatch.
printer fillRectangleX: rectangle origin x
y: rectangle origin y
width: rectangle width
height: rectangle height.
].
printer endPrintJob.
] forkAt: 3
"
WinPrinterContext fillHatchRectangles:
(Array with: (Array with: (Rectangle left:20 top:20 width:400 height:600) with: #horizontal)
with: (Array with: (Rectangle left:500 top:700 width:600 height:400) with: #vertical)
with: (Array with: (Rectangle left:800 top:1000 width:1600 height:2000) with: #cross)
with: (Array with: (Rectangle left:1040 top:1240 width:3000 height:3000) with: #bDiagonal)
)
"
"Created: / 07-08-2006 / 11:40:48 / fm"
"Modified: / 16-04-2007 / 15:37:46 / 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"
| printerInfo printer |
printerInfo := PrintingDialog getPrinterInfo.
printerInfo isNil ifTrue:[^self].
printer := self fromPrinterInfo: printerInfo.
[
printer startPrintJob: 'Fill Rectangles'.
printer foreground:Color blue background:Color white.
rectangles
do:[:rectangle |
printer fillRectangleX: rectangle origin x
y: rectangle origin y
width: rectangle width
height: rectangle height.
].
printer endPrintJob.
] forkAt: 3
"
WinPrinterContext fillRectangles:
(Array with: (Rectangle left:20 top:20 width:400 height:600)
with: (Rectangle left:500 top:700 width:600 height:400)
with: (Rectangle left:800 top:1000 width:1600 height:2000)
with: (Rectangle left:1040 top:1240 width:3000 height:3000)
)
"
"Created: / 07-08-2006 / 11:40:48 / fm"
"Modified: / 16-04-2007 / 15:37:46 / cg"
!
print: aString font: aFont title: aTitle
"Open a print dialog to allow printing of the given string
using the given title & font."
self print: aString font: aFont title: aTitle wordWrap: false
"
WinPrinterContext print: 'Holaaaa!! (from: WinPrinterContext>>print:aString font:aFont title:aTitle)' font: nil title: 'Printing Test'
WinPrinterContext print: (WinPrinterContext class sourceCodeAt:#'print:font:title:wordWrap:') font: nil title: 'Printing Test String'
WinPrinterContext print: (WinPrinterContext class sourceCodeAt:#'print:font:title:wordWrap:') font: (Font family:'Arial' face:'medium' size:8) title: 'Printing Test String'
"
"Created: / 27-07-2006 / 17:52:33 / fm"
"Modified: / 03-08-2006 / 18:52:31 / fm"
"Modified: / 16-04-2007 / 13:54:40 / cg"
!
print: aString font: aFont title: aTitle wordWrap: wordWrap
"Open a print dialog to allow printing of the given string
using the given title & font."
| printerInfo printer |
printerInfo := PrintingDialog getPrinterInfo.
printerInfo isNil ifTrue:[^self].
printer := self fromPrinterInfo: printerInfo.
[
printer
print: aString
font: aFont
title: aTitle
wordWrap: wordWrap
marginsRect: nil
] forkAt: 3
"
WinPrinterContext print: 'Holaaaa!! (from: PrinterContext>>print:aString font:aFont title:aTitle)' font: nil title: 'Printing Test' wordWrap: true
WinPrinterContext print: (WinPrinterContext class sourceCodeAt:#'print:font:title:wordWrap:') font:nil title:'Printing Test String' wordWrap:true
WinPrinterContext print: (WinPrinterContext class sourceCodeAt:#'print:font:title:wordWrap:') font: (Font family:'Arial' face:'medium' size:8) title: 'Printing Test String' wordWrap: true
"
"Created: / 03-08-2006 / 18:51:53 / fm"
"Modified: / 16-04-2007 / 15:37:31 / cg"
!
printCircles: arrayOfPointsAndRadius
"Opens a print dialog and prints the given circles"
| printerInfo printer |
printerInfo := PrintingDialog getPrinterInfo.
printerInfo isNil ifTrue:[^self].
printer := self fromPrinterInfo: printerInfo.
[
printer startPrintJob: 'Circles'.
printer foreground:Color green background:Color white.
arrayOfPointsAndRadius
do:[:pointAndRadius |
printer displayCircle:(pointAndRadius at:1)
radius:(pointAndRadius at:2).
].
printer endPrintJob.
] forkAt: 3
"
WinPrinterContext printCircles:
(Array with: (Array with: 800@800 with: 600)
with: (Array with: 1500@1500 with: 1000)
with: (Array with: 4000@2500 with: 2000))
"
"Created: / 07-08-2006 / 11:46:52 / fm"
"Modified: / 16-04-2007 / 15:37:34 / cg"
!
printCirclesIn: rectangles
"Opens a print dialog and prints the given circles"
| printerInfo printer |
printerInfo := PrintingDialog getPrinterInfo.
printerInfo isNil ifTrue:[^self].
printer := self fromPrinterInfo: printerInfo.
[
printer startPrintJob: 'Circles In Rectangles'.
rectangles
do:[:rectangle |
printer displayCircleIn: rectangle.
].
printer endPrintJob.
] forkAt: 3
"
WinPrinterContext printCirclesIn:
(Array with: (Rectangle left:20 top:20 width:400 height:600)
with: (Rectangle left:40 top:40 width:600 height:400)
)
"
"Created: / 07-08-2006 / 11:48:46 / fm"
"Modified: / 16-04-2007 / 15:37:38 / cg"
!
printImage: anImage
"Opens a print dialog and prints the given image"
self printImage: anImage magnification:1.
"
WinPrinterContext printImage: (Image fromFile:'C:\vsw311\pavheadr.gif').
WinPrinterContext printImage: XPToolbarIconLibrary help32x32Icon.
WinPrinterContext printImage: XPToolbarIconLibrary eraseXP28x28Icon.
WinPrinterContext printImage: XPToolbarIconLibrary saveImageBlack22x22Icon.
WinPrinterContext printImage: XPToolbarIconLibrary changesBrowser18x22Icon.
"
"Created: / 07-08-2006 / 11:46:52 / fm"
"Modified: / 16-04-2007 / 15:37:34 / cg"
!
printImage:anImage magnification:factor
"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 magnifiedBy:factor) displayOn:printer x:0 y:0.
printer endPrintJob.
] forkAt: 3
"
WinPrinterContext printImage: (Image fromFile:'C:\vsw311\pavheadr.gif').
WinPrinterContext printImage: XPToolbarIconLibrary help32x32Icon.
WinPrinterContext printImage: XPToolbarIconLibrary eraseXP28x28Icon.
WinPrinterContext printImage: XPToolbarIconLibrary saveImageBlack22x22Icon.
WinPrinterContext printImage: XPToolbarIconLibrary changesBrowser18x22Icon.
"
"Created: / 07-08-2006 / 11:46:52 / fm"
"Modified: / 16-04-2007 / 15:37:34 / cg"
!
printLines: pairOfPointsWithContextArray
"Opens a print dialog and prints the given lines"
| printerInfo printer |
printerInfo := PrintingDialog getPrinterInfo.
printerInfo isNil ifTrue:[^self].
printer := self fromPrinterInfo: printerInfo.
[
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:(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"
"Modified: / 07-08-2006 / 14:11:17 / fm"
"Modified: / 16-04-2007 / 15:37:41 / cg"
!
printPoints: aCollectionOfPoints
"Opens a print dialog and prints the given points"
| printerInfo printer |
printerInfo := PrintingDialog getPrinterInfo.
printerInfo isNil ifTrue:[^self].
printer := self fromPrinterInfo: printerInfo.
[
printer startPrintJob: 'Points'.
aCollectionOfPoints do:[:each |
printer displayPointX: each x y: each y.
].
printer endPrintJob.
] forkAt: 3
"
WinPrinterContext printPoints:
(Array with: (10 @ 10)
with: (500 @ 700)
with: (900 @ 1000)
with: (1500 @ 1700)
with: (2100 @ 2000)
with: (2500 @ 2700)
)
"
!
printPolygons: polygons
"Opens a print dialog and prints the given polygons"
| printerInfo printer |
printerInfo := PrintingDialog getPrinterInfo.
printerInfo isNil ifTrue:[^self].
printer := self fromPrinterInfo: printerInfo.
[
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: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"
"Modified: / 07-08-2006 / 14:11:17 / fm"
"Modified: / 16-04-2007 / 15:37:43 / cg"
!
printPolylines: evenCollectionOfPoints
"Opens a print dialog and prints the given rectangles"
| printerInfo printer |
printerInfo := PrintingDialog getPrinterInfo.
printerInfo isNil ifTrue:[^self].
printer := self fromPrinterInfo: printerInfo.
[
printer startPrintJob: 'Polylines'.
printer displayPolylines:evenCollectionOfPoints.
printer endPrintJob.
] forkAt: 3
"
WinPrinterContext printPolylines:
(Array with: (10 @ 10)
with: (500 @ 700)
with: (900 @ 1000)
with: (1500 @ 1700)
with: (2100 @ 2000)
with: (2500 @ 2700)
)
"
"Created: / 07-08-2006 / 11:40:48 / fm"
"Modified: / 16-04-2007 / 15:37:46 / cg"
!
printRectangles: rectanglesWithContextArray
"Opens a print dialog and prints the given rectangles"
| printerInfo printer |
printerInfo := PrintingDialog getPrinterInfo.
printerInfo isNil ifTrue:[^self].
printer := self fromPrinterInfo: printerInfo.
[
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: (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"
"Modified: / 16-04-2007 / 15:37:46 / cg"
!
printStrings: stringAndPositionsArray
"Opens a print dialog and prints the given strings"
| printerInfo printer |
printerInfo := PrintingDialog getPrinterInfo.
printerInfo isNil ifTrue:[^self].
printer := self fromPrinterInfo: printerInfo.
[
printer startPrintJob: 'Strings with Position'.
printer foreground:Color black background:Color white.
stringAndPositionsArray
do:[:pairOfPointsAndPosition |
printer displayString:(pairOfPointsAndPosition at: 1)
x:(pairOfPointsAndPosition at: 2) x
y:(pairOfPointsAndPosition at: 2) y
].
printer endPrintJob.
] forkAt: 3
"
WinPrinterContext printStrings:
(Array with: (Array with:'Testing printing with standard method' with:10@10)
with: (Array with:'Another test string to print' with:80@200))
"
"Created: / 07-08-2006 / 12:09:48 / fm"
"Modified: / 07-08-2006 / 14:11:17 / fm"
"Modified: / 16-04-2007 / 15:37:49 / cg"
! !
!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."
|textMetrics answer|
textMetrics := Win32OperatingSystem::TextMetricsStructure new.
"/ (OperatingSystem getTextMetrics:gcId lpMetrics:textMetrics) ifFalse:[ ^ self error ].
"/ Transcript showCR: 'CHAR HEIGHT PRIM ******* ', ' ', (textMetrics tmHeight + textMetrics tmExternalLeading) printString.
"/ Transcript showCR: 'CHAR HEIGHT DEVICE ***** ', ' ', (self font heightOf:'PQWEXCZ' on:self device) printString.
answer := (self font heightOf:'PQWEXCZ' on:self device).
"/ answer := textMetrics tmHeight + textMetrics tmExternalLeading.
^answer
"Created: / 02-08-2006 / 17:47:20 / fm"
"Modified: / 03-08-2006 / 10:09:01 / fm"
"Modified: / 10-10-2006 / 18:15:17 / cg"
!
getLogicalPixelSizeX
^ printerInfo printQuality ? 600
!
getLogicalPixelSizeY
^ printerInfo printQuality ? 600
!
numberOfColorBitsPerPixel
^ OperatingSystem getDeviceCaps:gcId index:12 "Bitspixel"
"Created: / 03-08-2006 / 09:58:18 / fm"
"Modified: / 10-10-2006 / 18:15:40 / cg"
!
physicalOffsetX
^ OperatingSystem getDeviceCaps:gcId index:112 "PhysicalOffsetX"
"Created: / 01-08-2006 / 16:28:34 / fm"
"Modified: / 16-04-2007 / 12:52:06 / cg"
!
physicalOffsetY
^ OperatingSystem getDeviceCaps:gcId index:113 "PhysicalOffsetY"
"Created: / 01-08-2006 / 16:28:34 / fm"
"Modified: / 16-04-2007 / 12:52:01 / cg"
!
pixelsPerInchOfScreenHeight
^ OperatingSystem getDeviceCaps:gcId index:90 "Logpixelsy"
"Created: / 01-08-2006 / 16:29:16 / fm"
!
pixelsPerInchOfScreenWidth
^ OperatingSystem getDeviceCaps:gcId index:88 "Logpixelsx"
"Created: / 01-08-2006 / 16:28:34 / fm"
!
printerHeightArea
^ (OperatingSystem getDeviceCaps:gcId index:10)
"Modified: / 10-10-2006 / 18:18:31 / cg"
!
printerPhysicalHeight
^ OperatingSystem getDeviceCaps:gcId "deviceContext" index:111 "PhysicalHeight"
"Created: / 01-08-2006 / 16:14:08 / fm"
!
printerPhysicalWidth
^ OperatingSystem getDeviceCaps:gcId "deviceContext" index:110 "PhysicalWidth"
"Created: / 01-08-2006 / 16:14:08 / fm"
!
printerWidthArea
^ OperatingSystem getDeviceCaps:gcId "deviceContext" index:8 "Horzres"
"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= __intVal(__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
!
hatch
"The hatch style will define a hatched brush between these patterns:
#none
#horizontal ----- HS_HORIZONTAL = 0
#vertical ||||| HS_VERTICAL = 1
#fDiagonal \\\\\ HS_FDIAGONAL = 2
#bDiagonal ///// HS_BDIAGONAL = 3
#cross +++++ HS_CROSS = 4
#diagonalCross xxxxx HS_DIAGCROSS = 5
"
hatch isNil ifTrue:[^#none].
^ hatch
!
hatch: aSymbol
"The hatch style will define a hatched brush between these patterns:
#none
#horizontal ----- HS_HORIZONTAL = 0
#vertical ||||| HS_VERTICAL = 1
#fDiagonal \\\\\ HS_FDIAGONAL = 2
#bDiagonal ///// HS_BDIAGONAL = 3
#cross +++++ HS_CROSS = 4
#diagonalCross xxxxx HS_DIAGCROSS = 5
"
hatch := aSymbol
!
noClipIn:aWindowId gc:aDC
"disable clipping rectangle"
%{ /* NOCONTEXT */
if (__isExternalAddressLike(aDC)) {
HANDLE hDC = (HANDLE)(__externalAddressVal(aDC));
SelectClipRgn(hDC, NULL);
RETURN (self);
}
%}
!
platformName
"used by #fillRoundRectangleX ...."
^ Smalltalk platformName asUppercase
!
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
"Created: / 01-08-2006 / 16:14:08 / fm"
! !
!WinPrinterContext methodsFor:'drawing'!
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;
OBJ lStyleSymbol;
int 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);
OBJ lStyleSymbol;
int 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;
OBJ lStyleSymbol;
int 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;
OBJ lStyleSymbol;
int 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;
OBJ lStyleSymbol;
int 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
LineTo(hDC, xL+w, yT+h); // move pen one pixel more
SelectObject(hDC, prevPen);
DeleteObject(hPen);
}
RETURN ( self );
}
%}.
self primitiveFailed
"Created: / 28-07-2006 / 20:18:25 / fm"
!
displayRoundRectangleX:left y:top width:width height:height wCorner:wCorn hCorner:hCorn
|right bottom wC hC wHalf hHalf|
right := left + width-1.
bottom := top + height-1.
wC := wCorn.
hC := hCorn.
self scale = 1 ifTrue:[
wHalf := wC // 2.
hHalf := hC // 2.
] ifFalse:[
wHalf := wC / 2.
hHalf := hC / 2.
].
"top left arc"
self displayArcX:left y:top width:wC height:hC from:90 angle:90.
"top right arc"
self displayArcX:(right - wC) y:top width:wC height:hC from:0 angle:90.
"bottom right arc"
self displayArcX:(right - wC) y:(bottom - hC) width:wC height:hC from:270 angle:90.
"bottom left arc"
self displayArcX:left y:(bottom - hC) width:wC height:hC from:180 angle:90.
"top line"
self displayLineFromX:(left + wHalf) y:top toX:(right - wHalf+1) y:top.
"left line"
self displayLineFromX:left y:(top + hHalf - 1) toX:left y:(bottom - hHalf).
"bottom line"
self displayLineFromX:(left + wHalf-1) y:bottom
toX:(right - wHalf ) y:bottom.
"right line"
self displayLineFromX:right y:(top + hHalf) toX:right y:(bottom - hHalf).
"
|v|
(v := View new) extent:200@200; openAndWait.
v displayRoundRectangleX:10 y:10 width:100 height:100 wCorner:20 hCorner:20
"
!
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;
COLORREF fgColor;
pX = __intVal(x);
pY = __intVal(y);
if (opaque == true) {
SetBkMode(hDC, OPAQUE);
} else {
SetBkMode(hDC, TRANSPARENT);
}
fgColor = GetTextColor(hDC);
SetTextColor(hDC, fgColor);
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;
COLORREF fgColor;
pX = __intVal(x);
pY = __intVal(y);
pY -= __intVal(fontAscent);
if (opaque == true) {
SetBkMode(hDC, OPAQUE);
} else {
SetBkMode(hDC, TRANSPARENT);
}
fgColor = GetTextColor(hDC);
SetTextColor(hDC, fgColor);
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."
| hatchSymbol |
hatchSymbol := self hatch.
%{
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;
int hatch, hasHatch;
w = __intVal(width);
h = __intVal(height);
__x = __intVal(x);
__y = __intVal(y);
fgColor = GetTextColor(hDC);
hasHatch= 1;
if (hatchSymbol == @symbol(none)) {
hasHatch= 0;
} else if (hatchSymbol == @symbol(horizontal)) {
hatch= HS_HORIZONTAL;
} else if (hatchSymbol == @symbol(vertical)) {
hatch= HS_VERTICAL;
} else if (hatchSymbol == @symbol(cross)) {
hatch= HS_CROSS;
} else if (hatchSymbol == @symbol(bDiagonal)) {
hatch= HS_BDIAGONAL;
} else if (hatchSymbol == @symbol(fDiagonal)) {
hatch= HS_FDIAGONAL;
} else if (hatchSymbol == @symbol(diagonalCross)) {
hatch= HS_DIAGCROSS;
} else
hasHatch= 0;
if (hasHatch) {
hBrush = CreateHatchBrush(hatch, fgColor);
} else {
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."
|hatchSymbol|
hatchSymbol := self hatch.
%{ /* 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;
int hatch, hasHatch;
fgColor = GetTextColor(hDC);
hasHatch= 1;
if (hatchSymbol == @symbol(none)) {
hasHatch= 0;
} else if (hatchSymbol == @symbol(horizontal)) {
hatch= HS_HORIZONTAL;
} else if (hatchSymbol == @symbol(vertical)) {
hatch= HS_VERTICAL;
} else if (hatchSymbol == @symbol(cross)) {
hatch= HS_CROSS;
} else if (hatchSymbol == @symbol(bDiagonal)) {
hatch= HS_BDIAGONAL;
} else if (hatchSymbol == @symbol(fDiagonal)) {
hatch= HS_FDIAGONAL;
} else if (hatchSymbol == @symbol(diagonalCross)) {
hatch= HS_DIAGCROSS;
} else
hasHatch= 0;
if (hasHatch) {
hBrush = CreateHatchBrush(hatch, fgColor);
} else {
hBrush = CreateSolidBrush(fgColor);
}
rct.left = __intVal(x);
rct.top = __intVal(y);
rct.right = rct.left + w; // + 1;
rct.bottom = rct.top + h; // + 1;
prevBrush = SelectObject(hDC, hBrush);
FillRect(hDC, &rct, hBrush);
SelectObject(hDC, prevBrush);
DeleteObject(hBrush);
}
}
RETURN ( self );
%}
!
primFillPolygon:aPolygon n:numberOfPoints in:ignoredDrawableId with:aDC
|hatchSymbol|
hatchSymbol := self hatch.
%{
OBJ point, px, py;
int i, num;
if (__isExternalAddressLike(aDC)
&& __isSmallInteger(numberOfPoints)) {
HANDLE hDC = (HANDLE)(__externalAddressVal(aDC));
POINT p;
HBRUSH hBrush, prevBrush;
COLORREF fgColor;
int hatch, hasHatch;
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);
hasHatch= 1;
if (hatchSymbol == @symbol(none)) {
hasHatch= 0;
} else if (hatchSymbol == @symbol(horizontal)) {
hatch= HS_HORIZONTAL;
} else if (hatchSymbol == @symbol(vertical)) {
hatch= HS_VERTICAL;
} else if (hatchSymbol == @symbol(cross)) {
hatch= HS_CROSS;
} else if (hatchSymbol == @symbol(bDiagonal)) {
hatch= HS_BDIAGONAL;
} else if (hatchSymbol == @symbol(fDiagonal)) {
hatch= HS_FDIAGONAL;
} else if (hatchSymbol == @symbol(diagonalCross)) {
hatch= HS_DIAGCROSS;
} else
hasHatch= 0;
if (hasHatch) {
hBrush = CreateHatchBrush(hatch, fgColor);
} else {
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: ;
}
%}
!
scaleTest_displayString:aString x:x y:y
"draw a string at the coordinate x/y -
draw foreground-pixels only (in current paint-color),
leaving background as-is. If the transformation involves scaling,
the fonts point-size is scaled as appropriate."
|id pX pY fontUsed sz s fontsEncoding|
"hook for non-strings (i.e. attributed text)"
(aString isString not
or:[aString isText]) ifTrue:[
^ aString displayOn:self x:x y:y
].
gcId isNil ifTrue:[
self initGC
].
fontUsed := font.
transformation notNil ifTrue:[
pX := transformation applyToX:x.
pY := transformation applyToY:y.
transformation noScale ifFalse:[
sz := font size.
sz isNil ifTrue:[
"/ oops - not a real font; use original font
fontUsed := font
] ifFalse:[ |yS|
yS := self pixelsPerInchOfScreenHeight / Screen current verticalPixelPerInch.
yS := self scale y / yS.
fontUsed := font size:(sz * yS) rounded.
]
]
] ifFalse:[
pX := x.
pY := y.
].
pX := pX rounded.
pY := pY rounded.
s := aString.
fontUsed := fontUsed onDevice:device.
fontsEncoding := fontUsed encoding.
(characterEncoding ~~ fontsEncoding) ifTrue:[
[
s := CharacterEncoder encodeString:s from:characterEncoding into:fontsEncoding.
] on:CharacterEncoderError do:[:ex|
"substitute a default value for codes that cannot be represented
in the new character set"
ex proceedWith:ex defaultValue.
].
].
id := fontUsed fontId.
id isNil ifTrue:[
"hook for alien fonts"
fontUsed displayString:s x:x y:y in:self
] ifFalse:[
deviceFont ~~ fontUsed ifTrue:[
device setFont:id in:gcId.
deviceFont := fontUsed
].
device displayString:s x:pX y:pY in:drawableId with:gcId
]
"Modified: 1.7.1997 / 17:08:35 / cg"
! !
!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
!
compressColorMapImage: image
"calculates a new color map for the image, using only used colors"
|depth newColorMap newImage oldImage usedColors oldToNew oldBits newBits tmpBits|
oldImage := image.
depth := oldImage depth.
oldImage photometric ~~ #palette ifTrue:[
Transcript showCR:'Compress colorMap: Only palette images have colormaps.'.
^ image
].
usedColors := oldImage realUsedColors.
usedColors size == (1 bitShift:depth) ifTrue:[
Transcript showCR:'Compress colorMap: All colors are used - no compression.'.
^ image
].
usedColors size == oldImage colorMap size ifTrue:[
Transcript showCR:'Compress colorMap: Colormap already compressed - no compression.'.
^ image
].
"/ translation table
oldToNew := ByteArray new:(1 bitShift:depth).
newColorMap := usedColors asArray.
newColorMap sort:self sortBlockForColors.
oldImage colorMap asArray keysAndValuesDo:[:oldIdx :clr |
|newPixel|
(usedColors includes:clr) ifTrue:[
newPixel := newColorMap indexOf:clr.
oldToNew at:oldIdx put:newPixel-1.
]
].
oldBits := oldImage bits.
newBits := ByteArray new:(oldBits size).
depth ~~ 8 ifTrue:[
"/ expand/compress can only handle 8bits
tmpBits := ByteArray uninitializedNew:(oldImage width*oldImage height).
oldBits
expandPixels:depth
width:oldImage width
height:oldImage height
into:tmpBits
mapping:oldToNew.
tmpBits
compressPixels:depth
width:oldImage width
height:oldImage height
into:newBits
mapping:nil
] ifFalse:[
oldBits
expandPixels:depth
width:oldImage width
height:oldImage height
into:newBits
mapping:oldToNew.
].
newImage := oldImage species new
width:oldImage width
height:oldImage height
depth:depth
fromArray:newBits.
newImage colorMap:newColorMap.
newImage fileName:oldImage fileName.
newImage mask:(oldImage mask copy).
^ newImage
"Created: / 28.7.1998 / 20:03:11 / cg"
"Modified: / 15.9.1998 / 17:53:32 / cg"
!
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;
OBJ 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
!
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 rootDC = CreateDC("DISPLAY", NULL, NULL, NULL);
/*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(rootDC, __intVal(w), __intVal(h) );
}
if (newBitmapHandle) {
RETURN ( __MKEXTERNALADDRESS(newBitmapHandle));
}
/*
DPRINTF(("empty bitmap handle = %x\n", newBitmapHandle));
*/
}
RETURN (nil);
%}
!
destroyPixmap:aDrawableId
%{ /* NOCONTEXT */
if (__isExternalAddress(aDrawableId) /* && ISCONNECTED */ ) {
HANDLE bitmapHandle = _HANDLEVal(aDrawableId);
if (bitmapHandle) {
DeleteObject(bitmapHandle);
/* _DeleteObject(bitmapHandle, __LINE__); */
}
}
%}
!
displayDeviceForm:aForm x:x y:y
|sortedImage formMask bitsWithTransparency redVector greenVector blueVector|
sortedImage := aForm.
"Image 16 bits"
aForm depth = 16 ifTrue:[
bitsWithTransparency := aForm bits.
].
"Image 24 and 32 bits"
aForm depth >= 24 ifTrue:[
|bestFormat|
bestFormat := aForm bestSupportedImageFormatFor: Display.
bitsWithTransparency := aForm rgbImageBitsOn: Display bestFormat: bestFormat.
].
"Image up to 8 bits"
aForm depth <= 8 ifTrue:[
aForm depth < 8 ifTrue:[
sortedImage := aForm asImageWithDepth: 8.
].
"/ sortedImage := self sortColorMapImage: aForm.
sortedImage := self compressColorMapImage: sortedImage.
formMask := sortedImage mask.
formMask isNil
ifTrue:[bitsWithTransparency := sortedImage bits ]
ifFalse:[
|bitsWithTransparencySize|
formMask := formMask asImageWithDepth: sortedImage depth.
bitsWithTransparency := sortedImage bits copy.
bitsWithTransparencySize := bitsWithTransparency size.
formMask bits doWithIndex:[:maskBit :index |
bitsWithTransparencySize >= index ifTrue:[
maskBit == 0 ifTrue:[bitsWithTransparency at: index put: 255 "60" "bitClearAt: index"].
"/ maskBit == 1 ifTrue:[bitsWithTransparency at: index put: (bitsWithTransparency at: index)].
].
].
].
redVector := sortedImage colorMap redVector.
greenVector := sortedImage colorMap greenVector.
blueVector := sortedImage colorMap blueVector.
].
self
drawBits: bitsWithTransparency
redVector: redVector
greenVector: greenVector
blueVector: blueVector
bitsPerPixel: sortedImage bitsPerPixel
depth: sortedImage depth
width: sortedImage width
height: sortedImage height
into: self id
x: x
y: y
width: sortedImage width
height: sortedImage height
with: gcId.
!
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 rounded) y:(dsty rounded)
width:w height:h
with:aGCId)
ifFalse:[
"
also happens, if a segmentation violation occurs in the
XPutImage ...
"
self primitiveFailed
].
!
drawBits:imageBits redVector:redVector greenVector:greenVector blueVector:blueVector bitsPerPixel:bitsPerPixel depth:imageDepth
width:imageWidth height:imageHeight
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 redVector:redVector greenVector:greenVector blueVector:blueVector bitsPerPixel:bitsPerPixel depth:imageDepth
width:imageWidth height:imageHeight
into:ignoredDrawableId
x:(dstx rounded) y:(dsty rounded)
width:w height:h
with:aGCId)
ifFalse:[
self primitiveFailed
].
!
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 (__qIsArrayLike(anArray)) {
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 (__qIsByteArrayLike(anArray)) {
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 ( __MKEXTERNALADDRESS(newBitmapHandle));
}
}
fail: ;
/*
DDPRINTF(("create bitmap FAILED!!!\n"));
*/
if (allocatedBits) {
/*
CPRINTF(("freeing up bitmap bits ...\n"));
*/
free(allocatedBits);
}
/*
CPRINTF(("returning nil ...\n"));
*/
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;
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 = _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)), // x & y coord of destination upper-left corner
__intVal(w), __intVal(h), // width & height of destination rectangle
__intVal(srcx), __intVal(srcy), // x & y coord of source upper-left corner
__intVal(w), __intVal(h), // width & height of source rectangle
(void *)b_bits, // bitmap bits
(BITMAPINFO*)&bitmap, // bitmap data
DIB_RGB_COLORS, // usage options
SRCCOPY // raster operation code
);
*/
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
!
primDrawBits:imageBits redVector:redVector greenVector:greenVector blueVector:blueVector bitsPerPixel:bitsPerPixel depth:imageDepth
width:imageWidth height:imageHeight
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;
unsigned char *__imageBits = 0;
unsigned char *__redVector = 0;
unsigned char *__greenVector = 0;
unsigned char *__blueVector = 0;
int padd = 8;
if (__isByteArray(imageBits)) {
__imageBits = __ByteArrayInstPtr(imageBits)->ba_element;
} else if (__isExternalBytesLike(imageBits)) {
__imageBits = (unsigned char *)(__externalBytesAddress(imageBits));
}
if (__isByteArray(redVector)) {
__redVector = __ByteArrayInstPtr(redVector)->ba_element;
} else if (__isExternalBytesLike(redVector)) {
__redVector = (unsigned char *)(__externalBytesAddress(redVector));
}
if (__isByteArray(greenVector)) {
__greenVector = __ByteArrayInstPtr(greenVector)->ba_element;
} else if (__isExternalBytesLike(greenVector)) {
__greenVector = (unsigned char *)(__externalBytesAddress(greenVector));
}
if (__isByteArray(blueVector)) {
__blueVector = __ByteArrayInstPtr(blueVector)->ba_element;
} else if (__isExternalBytesLike(blueVector)) {
__blueVector = (unsigned char *)(__externalBytesAddress(blueVector));
}
if (/* ISCONNECTED
&& */ __isExternalAddressLike(aGCId)
// && __bothSmallInteger(srcx, srcy)
&& __bothSmallInteger(dstx, dsty)
&& __bothSmallInteger(w, h)
&& __bothSmallInteger(imageWidth, imageHeight)
&& __bothSmallInteger(imageDepth, bitsPerPixel)
&& __imageBits)
{
struct
{
BITMAPINFOHEADER bmiHeader;
RGBQUAD bmiColors[256];
} bitmap;
HANDLE hDC = (HANDLE)(__externalAddressVal(aGCId));
HBITMAP hBitmap = _HBITMAPVAL(__INST(drawableId));
int col;
/*
DDPRINTF(("hDC = %x\n", hDC));
*/
if (padd != WIN32PADDING) {
int row, col;
unsigned char *cp;
unsigned char *pBits;
int b_width, b_height, bytesPerRowST, bytesPerRowWN, padding, nBytes;
int bi = __intVal(bitsPerPixel);
// console_fprintf(stderr, "Non WIN32PADDING");
b_width = __intVal(w);
b_height = __intVal(h);
bytesPerRowST = (b_width * bi + (padd - 1 )) / 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;
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);*/
if (__intVal(imageDepth) <= 8) {
for(col=0;col<256;col++)
{
bitmap.bmiColors[col].rgbBlue = __blueVector[col]; // Microsoft idea: change rgbBlue to rgbRed
bitmap.bmiColors[col].rgbGreen = __greenVector[col];
bitmap.bmiColors[col].rgbRed = __redVector[col]; // Microsoft idea: change rgbRed to rgbBlue
bitmap.bmiColors[col].rgbReserved = 0;
}
}
bitmap.bmiColors[255].rgbBlue=255;
bitmap.bmiColors[255].rgbGreen=255;
bitmap.bmiColors[255].rgbRed =255;
SetDIBitsToDevice(hDC,__intVal(dstx),__intVal(dsty),
__intVal(w), __intVal(h),
0, 0, /* __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)), // x & y coord of destination upper-left corner
__intVal(w), __intVal(h), // width & height of destination rectangle
__intVal(srcx), __intVal(srcy), // x & y coord of source upper-left corner
__intVal(w), __intVal(h), // width & height of source rectangle
(void *)b_bits, // bitmap bits
(BITMAPINFO*)&bitmap, // bitmap data
DIB_RGB_COLORS, // usage options
SRCCOPY // raster operation code
);
*/
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
!
sortBlockForColors
^ [:a :b |
a redByte == b redByte ifTrue:[
a greenByte == b greenByte ifTrue:[
a blueByte < b blueByte
] ifFalse:[
a greenByte < b greenByte
]
] ifFalse:[
a redByte < b redByte
]
].
!
sortColorMapImage: image
"calculates a new color map for the image, sorting colors"
|sortBlock depth newColorMap newImage oldImage usedColors oldToNew oldBits newBits tmpBits|
sortBlock := self sortBlockForColors.
oldImage := image.
depth := oldImage depth.
oldImage photometric ~~ #palette ifTrue:[
Transcript showCR:'Compress colorMap: Only palette images have colormaps.'.
^ image
].
usedColors := oldImage realColorMap.
"/ translation table
oldToNew := ByteArray new:(1 bitShift:depth).
newColorMap := usedColors asArray.
newColorMap sort:sortBlock.
oldImage colorMap asArray keysAndValuesDo:[:oldIdx :clr |
|newPixel|
(usedColors includes:clr) ifTrue:[
newPixel := newColorMap indexOf:clr.
oldToNew at:oldIdx put:newPixel-1.
]
].
oldBits := oldImage bits.
newBits := ByteArray new:(oldBits size).
depth ~~ 8 ifTrue:[
"/ expand/compress can only handle 8bits
tmpBits := ByteArray uninitializedNew:(oldImage width*oldImage height).
oldBits
expandPixels:depth
width:oldImage width
height:oldImage height
into:tmpBits
mapping:oldToNew.
tmpBits
compressPixels:depth
width:oldImage width
height:oldImage height
into:newBits
mapping:nil
] ifFalse:[
oldBits
expandPixels:depth
width:oldImage width
height:oldImage height
into:newBits
mapping:oldToNew.
].
newImage := oldImage species new
width:oldImage width
height:oldImage height
depth:depth
fromArray:newBits.
newImage colorMap:newColorMap.
newImage fileName:oldImage fileName.
newImage mask:(oldImage mask copy).
^newImage
!
transparencyTest_primDrawBits:imageBits redVector:redVector greenVector:greenVector blueVector:blueVector bitsPerPixel:bitsPerPixel depth:imageDepth
width:imageWidth height:imageHeight
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;
unsigned char *__imageBits = 0;
unsigned char *__redVector = 0;
unsigned char *__greenVector = 0;
unsigned char *__blueVector = 0;
int padd = 8;
if (__isByteArray(imageBits)) {
__imageBits = __ByteArrayInstPtr(imageBits)->ba_element;
} else if (__isExternalBytesLike(imageBits)) {
__imageBits = (unsigned char *)(__externalBytesAddress(imageBits));
}
if (__isByteArray(redVector)) {
__redVector = __ByteArrayInstPtr(redVector)->ba_element;
} else if (__isExternalBytesLike(redVector)) {
__redVector = (unsigned char *)(__externalBytesAddress(redVector));
}
if (__isByteArray(greenVector)) {
__greenVector = __ByteArrayInstPtr(greenVector)->ba_element;
} else if (__isExternalBytesLike(greenVector)) {
__greenVector = (unsigned char *)(__externalBytesAddress(greenVector));
}
if (__isByteArray(blueVector)) {
__blueVector = __ByteArrayInstPtr(blueVector)->ba_element;
} else if (__isExternalBytesLike(blueVector)) {
__blueVector = (unsigned char *)(__externalBytesAddress(blueVector));
}
if (/* ISCONNECTED
&& */ __isExternalAddressLike(aGCId)
// && __bothSmallInteger(srcx, srcy)
&& __bothSmallInteger(dstx, dsty)
&& __bothSmallInteger(w, h)
&& __bothSmallInteger(imageWidth, imageHeight)
&& __bothSmallInteger(imageDepth, bitsPerPixel)
&& __imageBits)
{
struct
{
BITMAPINFOHEADER bmiHeader;
RGBQUAD bmiColors[256];
} bitmap;
HANDLE hDC = (HANDLE)(__externalAddressVal(aGCId));
HBITMAP hBitmap = _HBITMAPVAL(__INST(drawableId));
int col;
/*
DDPRINTF(("hDC = %x\n", hDC));
*/
if (padd != WIN32PADDING) {
int row, col;
unsigned char *cp;
unsigned char *pBits;
int b_width, b_height, bytesPerRowST, bytesPerRowWN, padding, nBytes;
int bi = __intVal(bitsPerPixel);
// console_fprintf(stderr, "Non WIN32PADDING");
b_width = __intVal(w);
b_height = __intVal(h);
bytesPerRowST = (b_width * bi + (padd - 1 )) / 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;
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);*/
if (__intVal(imageDepth) <= 8) {
for(col=0;col<256;col++)
{
bitmap.bmiColors[col].rgbBlue = 0;
bitmap.bmiColors[col].rgbGreen = 0;
bitmap.bmiColors[col].rgbRed = 0;
bitmap.bmiColors[col].rgbReserved = 0;
}
}
bitmap.bmiColors[255].rgbBlue=255;
bitmap.bmiColors[255].rgbGreen=255;
bitmap.bmiColors[255].rgbRed =255;
bitmap.bmiColors[255].rgbReserved = 0;
StretchDIBits(hDC,
__intVal(dstx),(__intVal(dsty)), // x & y coord of destination upper-left corner
__intVal(w), __intVal(h), // width & height of destination rectangle
0, 0, /* __intVal(srcx), __intVal(srcy), */ // x & y coord of source upper-left corner
__intVal(w), __intVal(h), // width & height of source rectangle
(void *)b_bits, // bitmap bits
(BITMAPINFO*)&bitmap, // bitmap data
DIB_RGB_COLORS, // usage options
SRCAND // raster operation code
);
/*
if (__intVal(imageDepth) <= 8) {
for(col=0;col<256;col++)
{
bitmap.bmiColors[col].rgbBlue = __blueVector[col]; // Microsoft idea: change rgbBlue to rgbRed
bitmap.bmiColors[col].rgbGreen = __greenVector[col];
bitmap.bmiColors[col].rgbRed = __redVector[col]; // Microsoft idea: change rgbRed to rgbBlue
bitmap.bmiColors[col].rgbReserved = 0;
}
}
bitmap.bmiColors[255].rgbBlue=0;
bitmap.bmiColors[255].rgbGreen=0;
bitmap.bmiColors[255].rgbRed =0;
bitmap.bmiColors[255].rgbReserved = 0;
StretchDIBits(hDC,
__intVal(dstx),(__intVal(dsty)), // x & y coord of destination upper-left corner
__intVal(w), __intVal(h), // width & height of destination rectangle
0, 0, // x & y coord of source upper-left corner
__intVal(w), __intVal(h), // width & height of source rectangle
(void *)b_bits, // bitmap bits
(BITMAPINFO*)&bitmap, // bitmap data
DIB_RGB_COLORS, // usage options
SRCPAINT // raster operation code
);
*/
/*
SetDIBitsToDevice(hDC,__intVal(dstx),__intVal(dsty),
__intVal(w), __intVal(h),
0, 0,
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)), // x & y coord of destination upper-left corner
__intVal(w), __intVal(h), // width & height of destination rectangle
__intVal(srcx), __intVal(srcy), // x & y coord of source upper-left corner
__intVal(w), __intVal(h), // width & height of source rectangle
(void *)b_bits, // bitmap bits
(BITMAPINFO*)&bitmap, // bitmap data
DIB_RGB_COLORS, // usage options
SRCCOPY // raster operation code
);
*/
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
! !
!WinPrinterContext methodsFor:'font stuff'!
createFontFor:aFontName
"a basic method for font allocation; this method allows
any font to be acquired (even those not conforming to
standard naming conventions, such as cursor, fixed or k14)"
%{
HGDIOBJ hFont;
char *fn;
if (__isStringLike(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 ( __MKEXTERNALADDRESS(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
!
getDefaultFontWithEncoding:encoding
"return a default font id - used when class Font cannot
find anything usable"
^ self createFontFor:'fixed'
!
getFontWithFamily:familyString face:faceString style:styleString size:sizeArg encoding:encodingSym
"try to get the specified font, return id.
If not available, try next smaller font.
If no font fits, return nil"
^ self
getFontWithFamily:familyString
face:faceString
style:styleString
size:sizeArg
sizeUnit:#pt
encoding:encodingSym
!
getFontWithFamily:familyString face:faceString
style:styleArgString size:sizeArgOrNil sizeUnit:sizeUnit encoding:encodingSym
"try to get the specified font, if not available, try the next smaller
font."
|styleString theName theId xlatedStyle id spacing|
self assert:(sizeUnit == #pt).
styleString := styleArgString.
"special: if face is nil, allow access to X-fonts"
faceString isNil ifTrue:[
sizeArgOrNil notNil ifTrue:[
theName := familyString , '-' , sizeArgOrNil printString
] ifFalse:[
theName := familyString
].
theName notNil ifTrue:[
theId := self createFontFor:theName.
].
theId isNil ifTrue:[
theId := self getDefaultFontWithEncoding:encodingSym
].
^ 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:sizeArgOrNil
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:sizeArgOrNil
registry:'*'
encoding:encodingSym asUppercase.
id isNil ifTrue:[
id := self
getFontWithFoundry:'*'
family:familyString asLowercase
weight:faceString
slant:styleString "/ xlatedStyle
spacing:spacing
pixelSize:nil
size:sizeArgOrNil
registry:'*'
encoding:encodingSym asLowercase.
id isNil ifTrue:[
id := self
getFontWithFoundry:'*'
family:familyString asLowercase
weight:faceString asLowercase
slant:styleString asLowercase
spacing:spacing
pixelSize:nil
size:sizeArgOrNil
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:encodingArg
"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 encoding|
encoding := encodingArg asSymbol.
pixelSize notNil ifTrue:[
logSize := pixelSize
] ifFalse:[
logSize := (pointSize * (self getLogicalPixelSizeY) / 72.0) rounded.
].
%{
HGDIOBJ hFont;
int 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')
|| encoding == @symbol(*)) {
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 ( __MKEXTERNALADDRESS(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'!
createDC
"Private - Create a device context for the receiver"
gcId := printerInfo createDC
"Created: / 27-07-2006 / 10:21:05 / fm"
"Modified: / 02-08-2006 / 17:30:47 / fm"
"Modified: / 10-10-2006 / 18:14:28 / cg"
!
deleteDC
"Private - Delete a device context for the receiver"
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|
aCopy := WinWorkstation::PrinterDeviceContextHandle basicNew.
aCopy setDevice:device id:nil gcId:gcId.
^ aCopy
"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.
self releaseDeviceFonts
!
releaseDeviceFonts
deviceFonts isEmptyOrNil ifFalse:[
deviceFonts do:[:afont |
afont releaseFromDevice.
].
].
deviceFonts := CachingRegistry new cacheSize:10.
! !
!WinPrinterContext methodsFor:'non standard methods'!
stringWidthOf:aString at:index
"Return the width of aString up to index
when written using the current font; expand tabs out
to 4 spaces for calculations"
|answer str size spaceWidth|
index <= 0 ifTrue:[ ^ 0 ].
str := index >= aString size ifTrue:[ aString ] ifFalse:[ aString copyFrom:1 to:index ].
true "self font isNil" ifTrue:[
"if font not set yet, calculate based on default font"
"/ extString := str asExternalString.
size := Win32OperatingSystem::WinPointStructure new.
(OperatingSystem
getTextExtentPoint:gcId
string:str
size:size) ifFalse:[ ^ self error ].
answer := size x.
"/ Transcript showCR: 'FROM PRIM ******* ', str, ' ', answer printString.
"/ Transcript showCR: 'FROM DEVICE ***** ', str, ' ',(self font widthOf:str on:self device) printString.
#TODO.
] ifFalse:[
answer := self font widthOf:str on:self device
].
index > aString size ifTrue:[
spaceWidth := self font widthOf:Character space on:self device.
answer := answer + ((index - aString size) * spaceWidth)
].
^ answer.
"Created: / 03-08-2006 / 10:27:20 / fm"
"Modified: / 04-08-2006 / 12:27:26 / fm"
"Modified: / 10-10-2006 / 18:20:43 / cg"
! !
!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 );
}
%}
!
gcForBitmap:aDrawableId
%{ /* NOCONTEXT */
if (__isExternalAddress(aDrawableId)){
BITMAP bitmap;
HBITMAP hBitmap = _HBITMAPVAL(aDrawableId);
HBITMAP memBM;
HANDLE compatibleDC, rootDC, hdcScreen;
// HANDLE printerDC = (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;
*/
rootDC = CreateDC("DISPLAY", NULL, NULL, NULL);
compatibleDC = CreateCompatibleDC(rootDC);
SelectObject(compatibleDC, hBitmap);
// hdcScreen= CreateDC("NULL", NULL, NULL, NULL);
// compatibleDC = rootDC;
// compatibleDC = CreateCompatibleDC(printerDC);
// compatibleDC = CreateCompatibleDC(0);
// memBM = CreateCompatibleBitmap ( compatibleDC, bitmap.bmWidth, bitmap.bmHeight );
// SelectObject ( compatibleDC, memBM );
RETURN (__MKEXTERNALADDRESS(compatibleDC));
/*
RETURN ( __MKEXTERNALADDRESS(gcData) );
*/
}
RETURN (nil);
%}
!
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;
OBJ lineStyle, capStyle, joinStyle;
int style;
int lw;
int BK_TRANSPARENT;
BK_TRANSPARENT = 1;
lw= __intVal(__INST(lineWidth));
/* fgColor = __intVal(__INST(foreground)) & 0xffffff; */
fgColor = GetTextColor(hDC);
lineStyle=__INST(lineStyle);
capStyle=__INST(capStyle);
joinStyle=__INST(joinStyle);
hMask= __intVal(__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( __MKEXTERNALADDRESS(hPen) );
}
if (fgColor == 1 /* WhitePixel */) {
hPen = GetStockObject(WHITE_PEN);
prevPen = SelectObject(hDC, hPen);
RETURN( __MKEXTERNALADDRESS(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 (__MKEXTERNALADDRESS(hPen));
%}
!
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
!
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 := 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'!
endPage
"Informs device that we are finished writing to a page."
(OperatingSystem endPage:gcId) > 0 ifFalse:[
self error
]
"Created: / 27-07-2006 / 18:20:48 / fm"
"Modified: / 01-08-2006 / 16:01:34 / fm"
"Modified: / 10-10-2006 / 18:14:44 / cg"
!
endPrintJobWithoutRelease
"End the print job. Everything drawn between startPrintJob
and endPrintJob will become one entry in the print queue."
|result|
self endPage.
result := OperatingSystem endDoc:gcId.
jobid := nil.
result >= 0 ifFalse:[ self error ]
"Created: / 27-07-2006 / 18:21:04 / fm"
"Modified: / 01-08-2006 / 16:01:38 / fm"
"Modified: / 10-10-2006 / 18:50:43 / cg"
!
getSupportsColor
| retVal info |
info := (self class getPrinterInformationString: self name) asUppercase.
(info includesSubString: ',PSCRIPT,')
ifTrue: [
retVal := self class postScriptBlackWhite not.
"/ retVal := (DAPASX::DapasSystemInfo getYesNoInfoApp: 'Printer' profile: 'PostScriptBlackWhite') not.
]
ifFalse: [
retVal := (info includesSubString: 'PDF')
ifTrue: [true]
ifFalse: [self numberOfColorBitsPerPixel > 1].
].
^retVal
!
startPage
"Starts a page."
(OperatingSystem startPage:gcId) > 0 ifFalse:[
^ self error
].
"Created: / 27-07-2006 / 18:25:55 / fm"
"Modified: / 28-07-2006 / 18:19:04 / fm"
"Modified: / 10-10-2006 / 18:19:02 / cg"
!
startPrintJob:aString fileName:aFileName
"Start a print job, using aString as the job title; everything
drawn between startPrintJob and endPrintJob will become
one entry in the print queue."
|docInfoStruct nameAddress fileNameAddress|
gcId isNil ifTrue:[
self buildPrinter
].
abort := false.
title := aString ? 'Smalltalk/X'.
nameAddress := title asExternalBytes unprotectFromGC.
aFileName isNil ifFalse:[
fileNameAddress := aFileName pathName asExternalBytes unprotectFromGC
].
docInfoStruct := Win32OperatingSystem::DocInfoStructure new.
docInfoStruct
cbSize:docInfoStruct sizeInBytes;
lpszDocName:nameAddress address.
fileNameAddress isNil ifFalse:[
docInfoStruct lpszOutput:fileNameAddress address
].
jobid := OperatingSystem startDoc:gcId docInfo:docInfoStruct.
jobid > 0 ifFalse:[
jobid = -1 ifTrue:[
abort := true.
^ nil
].
"/ ^ self error
OpenError raiseErrorString:'Cannot create printer job'.
].
self startPage
"Created: / 27-07-2006 / 18:19:31 / fm"
"Modified: / 03-08-2006 / 15:11:19 / fm"
"Modified: / 10-10-2006 / 18:20:01 / cg"
"Modified: / 07-04-2011 / 12:03:50 / sr"
! !
!WinPrinterContext methodsFor:'queries'!
hasGrayscales
"return true, if this workstation supports grayscales
(also true for color displays)"
^ true
!
isOpen
^ gcId notNil
!
isPersistentInSnapshot
"return true, if resources on this device are to be made
persistent in a snapshot image."
^ false
!
supportsColor
supportsColor isNil ifTrue:[supportsColor := self getSupportsColor].
^supportsColor
!
supportsGraphics
^(OperatingSystem getDeviceCaps: gcId index: 2 "Technology") ~= 4
"Created: / 03-08-2006 / 10:07:43 / fm"
"Modified: / 16-04-2007 / 12:44:03 / cg"
!
supportsVariableHeightFonts
^ false
!
supportsXftFonts
^ false
! !
!WinPrinterContext methodsFor:'registration'!
registerFont:aFont
deviceFonts register:aFont.
!
unregisterFont:aFont
deviceFonts unregister:aFont.
! !
!WinPrinterContext::WinPrinterGraphicContext class methodsFor:'documentation'!
documentation
"
The class is simular to the PSGraphicsContext. It implements a
'what you see is what you get' interface - all is scaled dependent
on the current screen resolution
supports margin, clipping ...
"
!
examples
"
[exBegin]
|gc font|
gc := WinPrinterContext openGraphicContext.
gc isNil ifTrue:[^ self ].
[
gc startPrintJob:'Test'.
gc paint:(Color black).
gc displayLineFromX:10 y:40 toX:100 y:40.
font := (Font family:'helvetica' face:'roman' style:'bold' size:16) onDevice:(gc device).
gc font:font.
gc paint:(Color red).
gc displayString:'hallo' x:10 y:(40 + font ascent).
gc paint:(Color black).
gc displayLineFromX:10 y:(40 + font height) toX:100 y:(40 + font height).
] ensure:[
gc close.
].
[exEnd]
"
! !
!WinPrinterContext::WinPrinterGraphicContext methodsFor:'accessing dimensions'!
bottomMargin
"return the papers bottom margin measured in pixels"
^ 50
!
extent
^ width @ height
!
height
^ height
!
leftMargin
"return the papers left margin measured in pixels"
^ 50
!
rightMargin
"return the papers right margin measured in pixels"
^ 50
!
topMargin
"return the papers top margin measured in pixels"
^ 50
!
width
^ width
! !
!WinPrinterContext::WinPrinterGraphicContext methodsFor:'accessing-hooks'!
pageCounter
"answer the current page number"
pageCounter ~~ 0 ifTrue:[^ pageCounter].
^ 1
!
pageNumberFormat:aFormatString
"set the pageNumber format - the default is 'page %1'"
pageNumberFormat := aFormatString ? ''
!
printPageNumbers:aBoolean
"enable/disable printing of page numbers - the default is on"
printPageNumbers := aBoolean.
! !
!WinPrinterContext::WinPrinterGraphicContext methodsFor:'accessing-transformation'!
clippingRectangle:aRectangle
|tranlate extent lft rgt top bot|
tranlate := self translation negated asPoint.
extent := self extent.
lft := tranlate x.
top := tranlate y.
rgt := lft + extent x.
bot := top + extent y.
aRectangle notNil ifTrue:[
lft := lft max:aRectangle left.
top := top max:aRectangle top.
rgt := rgt min:aRectangle right.
bot := bot min:aRectangle bottom.
].
super clippingRectangle:(Rectangle left:lft top:top right:rgt bottom:bot).
!
scale
"answer the scale excluding the fontScale factor"
^ super scale / fontScale
!
scale:aScale
"set the scale and add the fontScale factor"
super scale:(fontScale * (aScale ? 1.0)).
!
scale:scale translation:aPoint
self
translation:aPoint;
scale:scale.
!
transformation
"answer the transformation excluding the fontScale factor"
^ WindowingTransformation scale:(self scale)
translation:(self translation).
!
transformation:aTransformation
"set the transformation and add the fontScale factor"
|s t|
aTransformation notNil ifTrue:[
s := aTransformation scale.
t := aTransformation translation.
].
self scale:s.
self translation:t.
!
translateBy:aTranslation
"set the translation and add the fontScale factor"
aTranslation isNil ifTrue:[^ self].
self translation:( self translation + (self scale * aTranslation)).
!
translation
"answer the translation excluding the fontScale factor"
|margin trans|
margin := Point x:(self leftMargin) y:(self topMargin).
trans := (super translation / fontScale) rounded.
^ trans - margin
!
translation:aTranslation
"set the translation and add the fontScale factor"
|trans|
trans := Point x:(self leftMargin) y:(self topMargin).
aTranslation notNil ifTrue:[
trans := trans + aTranslation.
].
super translation:((trans * fontScale) rounded).
! !
!WinPrinterContext::WinPrinterGraphicContext methodsFor:'drawing strings'!
displayOpaqueString:aString from:index1 to:index2 x:x y:y
self displayString:aString from:index1 to:index2 x:x y:y.
!
displayOpaqueString:aString x:x y:y
|end|
end := aString size.
end ~~ 0 ifTrue:[
self displayOpaqueString:aString from:1 to:end x:x y:y.
].
!
displayString:aString from:index1 to:index2 x:x y:y
"setup the special scale for strings before drawing"
|tscale fscale yFont xFont|
index2 < index1 ifTrue:[^ self].
transformation isNil ifTrue:[
self initTransformation.
].
tscale := transformation scale.
fscale := tscale / fontScale.
xFont := x * fontScale x.
yFont := (y - font ascent) * fontScale y. "/ MM_TEXT - Ursprung liegt oben links
transformation scale:fscale.
super displayString:aString from:index1 to:index2
x:xFont truncated
y:yFont truncated.
transformation scale:tscale.
!
displayString:aString x:x y:y
|end|
end := aString size.
end ~~ 0 ifTrue:[
self displayString:aString from:1 to:end x:x y:y.
].
!
displayString:aString x:x y:y angle:drawAngle opaque:opaque
"angles other than 0 is not yet supported"
|angle|
angle := drawAngle.
angle >= 360 ifTrue:[
angle := angle - (((angle // 360)) * 360)
] ifFalse:[
angle < 0 ifTrue:[
angle := angle - (((angle // 360)) * 360).
angle := angle + 360.
angle >= 360 ifTrue:[
angle := angle - (((angle // 360)) * 360)
]
].
].
angle == 0 ifTrue:[
super displayString:aString x:x y:y angle:drawAngle opaque:opaque.
].
! !
!WinPrinterContext::WinPrinterGraphicContext methodsFor:'font stuff'!
fontMetricsOf:fontId
"after retrieving the metrics, we have to scale the information"
|metrics|
metrics := super fontMetricsOf:fontId.
metrics isNil ifTrue:[^ nil ].
metrics ascent:((metrics ascent / fontScale y) rounded)
descent:((metrics descent / fontScale y) rounded + 1)
maxAscent:((metrics maxAscent / fontScale y) rounded)
maxDescent:((metrics maxDescent / fontScale y) rounded + 1)
minWidth:((metrics minWidth / fontScale x) rounded)
maxWidth:((metrics maxWidth / fontScale x) rounded)
avgWidth:((metrics averageWidth / fontScale x) rounded).
^ metrics
!
getFontWithFoundry:foundry family:family weight:weight
slant:slant spacing:spc pixelSize:pixelSize size:pointSize
registry:registry encoding:encoding
"compute the pixels dependent on the Screen current resolution"
|psize|
psize := pixelSize.
psize isNil ifTrue:[
psize := (pointSize * (self getLogicalPixelSizeY) / (Screen current getLogicalPixelSizeY)) rounded.
].
^ super getFontWithFoundry:foundry family:family weight:weight
slant:slant spacing:spc pixelSize:psize size:pointSize
registry:registry encoding:encoding
!
titleFont
"answer the font used for displaying page numbers..."
titleFont isNil ifTrue:[
titleFont := Font family:'helvetica' face:'medium' style:'roman' size:10.
titleFont := titleFont onDevice:(self device).
].
^ titleFont
!
titleFont:aFont
"set the font used for displaying page numbers..."
(aFont notNil and:[aFont ~= titleFont]) ifTrue:[
titleFont := aFont onDevice:(self device).
].
!
widthOf:aString from:index1 to:index2 inFont:aFontId
"after retrieving the width, we have to scale the width"
|w|
w := super widthOf:aString from:index1 to:index2 inFont:aFontId.
w := (w / fontScale x) rounded.
^ w
! !
!WinPrinterContext::WinPrinterGraphicContext methodsFor:'initialization & release'!
close
"compatible with PSGraphicsContext"
self endPrintJob.
!
initExtent
"scale the extent"
fontScale := self resolution / Screen current resolution.
width := (self printerWidthArea / fontScale x) rounded.
width := width - self leftMargin - self rightMargin.
height := (self printerHeightArea / fontScale y) rounded.
height := height - self topMargin - self bottomMargin.
self initTransformation.
!
initTransformation
|margin|
transformation isNil ifTrue:[
margin := Point x:(self leftMargin) y:(self topMargin).
transformation := WindowingTransformation scale:fontScale
translation:(margin * fontScale).
].
!
initialize
super initialize.
device := nil. "super initialize did set it to Screen current"
pageCounter := 0.
needsEndOfPage := false.
printPageNumbers := true.
Language == #de ifTrue:[ pageNumberFormat := 'Seite %1' ]
ifFalse:[ pageNumberFormat := 'page %1' ].
! !
!WinPrinterContext::WinPrinterGraphicContext methodsFor:'printing process'!
displayTitleDo:aNoneArgAction
|oldClip oldTrans oldFont|
oldClip := clipRect.
oldClip notNil ifTrue:[ self deviceClippingBounds:nil ].
oldTrans := self translation.
oldFont := font.
self font:(self titleFont).
self translation:0.
aNoneArgAction value.
self translation:oldTrans.
oldFont notNil ifTrue:[ self font:oldFont ].
oldClip notNil ifTrue:[ self deviceClippingBounds:oldClip ].
!
endPage
"ends the current page
if the current page is already closed by endPage, the request will be ignored"
|s|
needsEndOfPage ifFalse:[
^ self
].
needsEndOfPage := false.
printPageNumbers == true ifTrue:[
self displayTitleDo:[
self displayString:title
x:(self extent x - (font widthOf:title)) // 2
y:(self extent y + (font ascent)).
s := pageNumberFormat bindWith:pageCounter.
self displayString:s
x:(self extent x - (font widthOf:s))
y:(self extent y + (font ascent)).
]
].
super endPage.
!
startPage
"starts a new page
if the current page is not closed by endPage, a endPage is forward to the device"
needsEndOfPage ifTrue:[
self endPage.
].
super startPage.
needsEndOfPage := true.
pageCounter := pageCounter + 1.
! !
!WinPrinterContext::WinPrinterGraphicContext methodsFor:'queries'!
pixelPerInch
^ Point x:(self pixelsPerInchOfScreenWidth)
y:(self pixelsPerInchOfScreenHeight).
!
resolution
^ self pixelPerInch
! !
!WinPrinterContext class methodsFor:'documentation'!
version
^ '$Header$'
!
version_CVS
^ '$Header$'
! !