User Tools

Site Tools


writing_20graphics_20to_20the_20printer

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

writing_20graphics_20to_20the_20printer [2018/03/31 13:19]
127.0.0.1 external edit
writing_20graphics_20to_20the_20printer [2018/04/13 20:06] (current)
richardrussell Added syntax highlighting
Line 3: Line 3:
 //by Richard Russell, May 2006//\\ \\  The only built-in means for writing graphics to the printer provided by //BBC BASIC for Windows// is the ***HARDCOPY** command: this transfers an area of the screen (which may include graphics) to the printer. However this is not a very satisfactory method because the graphics are limited to the resolution of the screen, which is far poorer than the resolution of a typical (laser or inkjet) printer; graphics can therefore appear much coarser than they need to. Whilst this can be partially overcome by creating a sufficiently [[http://​www.bbcbasic.co.uk/​bbcwin/​manual/​bbcwini.html#​hint2|large output '​canvas'​]] (which can be bigger than your screen) it still imposes some limitations.\\ \\  The main Help documentation touches on how one can use the **Windows API** to write graphics to the printer ([[http://​www.bbcbasic.co.uk/​bbcwin/​manual/​bbcwine.html#​grafprint|Drawing graphics to a printer]]) but it barely scratches the surface of what is possible. This article expands on what is written there.\\ \\  //by Richard Russell, May 2006//\\ \\  The only built-in means for writing graphics to the printer provided by //BBC BASIC for Windows// is the ***HARDCOPY** command: this transfers an area of the screen (which may include graphics) to the printer. However this is not a very satisfactory method because the graphics are limited to the resolution of the screen, which is far poorer than the resolution of a typical (laser or inkjet) printer; graphics can therefore appear much coarser than they need to. Whilst this can be partially overcome by creating a sufficiently [[http://​www.bbcbasic.co.uk/​bbcwin/​manual/​bbcwini.html#​hint2|large output '​canvas'​]] (which can be bigger than your screen) it still imposes some limitations.\\ \\  The main Help documentation touches on how one can use the **Windows API** to write graphics to the printer ([[http://​www.bbcbasic.co.uk/​bbcwin/​manual/​bbcwine.html#​grafprint|Drawing graphics to a printer]]) but it barely scratches the surface of what is possible. This article expands on what is written there.\\ \\ 
 ===== Coordinate system ===== ===== Coordinate system =====
-\\  Fundamental to outputting any graphics is the coordinate system by which the positions of lines, objects etc. are described. In the case of the printer the origin (0,0) is the top-left-hand corner of the printable area, with the horizontal (X) coordinate increasing to the right and the vertical (Y) coordinate increasing downwards.\\ \\  The resolution of the printer (usually measured in **dots per inch**) varies between models, and may even be different in the horizontal and vertical directions. Therefore - assuming you want your program to work with a range of different printers - you should not use //​absolute//​ coordinates when outputting graphics. Instead you can either determine what the resolution is and adjust your values accordingly,​ or you can scale your graphics to fit between the page margins.\\ \\  For the first method you call the Windows API as follows:\\ \\ +\\  Fundamental to outputting any graphics is the coordinate system by which the positions of lines, objects etc. are described. In the case of the printer the origin (0,0) is the top-left-hand corner of the printable area, with the horizontal (X) coordinate increasing to the right and the vertical (Y) coordinate increasing downwards.\\ \\  The resolution of the printer (usually measured in **dots per inch**) varies between models, and may even be different in the horizontal and vertical directions. Therefore - assuming you want your program to work with a range of different printers - you should not use //​absolute//​ coordinates when outputting graphics. Instead you can either determine what the resolution is and adjust your values accordingly,​ or you can scale your graphics to fit between the page margins.\\ \\  For the first method you call the Windows API as follows: 
 + 
 +<code bb4w> ​
         SYS "​GetDeviceCaps",​ @prthdc%, 88 TO dpix%         SYS "​GetDeviceCaps",​ @prthdc%, 88 TO dpix%
         SYS "​GetDeviceCaps",​ @prthdc%, 90 TO dpiy%         SYS "​GetDeviceCaps",​ @prthdc%, 90 TO dpiy%
-This returns the number of dots-per-inch in the horizontal direction in **dpix%** and the number of dots-per-inch in the vertical direction in **dpiy%**. You will often find that these values are the same. For the second method you read the margin values using //BBC BASIC for Windows//'​s system variables:\\ \\ +</​code>​ 
 + 
 +This returns the number of dots-per-inch in the horizontal direction in **dpix%** and the number of dots-per-inch in the vertical direction in **dpiy%**. You will often find that these values are the same. For the second method you read the margin values using //BBC BASIC for Windows//'​s system variables: 
 + 
 +<code bb4w>
         marginl% = @vdu%!232         marginl% = @vdu%!232
         marginr% = @vdu%!236         marginr% = @vdu%!236
         margint% = @vdu%!240         margint% = @vdu%!240
         marginb% = @vdu%!244         marginb% = @vdu%!244
 +</​code>​
 +
 The first method is more appropriate if you need your graphics to come out a certain size, whatever the size of paper or margin settings, and the second method is more appropriate if you want your graphics to fit the page.\\ \\  The first method is more appropriate if you need your graphics to come out a certain size, whatever the size of paper or margin settings, and the second method is more appropriate if you want your graphics to fit the page.\\ \\ 
 ===== Pens and brushes ===== ===== Pens and brushes =====
 \\  Before you can draw anything you need to create a pen and/or a brush. A pen is used for drawing **lines** and a brush for filling **areas**. Quite often you will need both, even for a single object. For example when drawing a polygon the pen will be used to draw the outline and the brush to fill the inside.\\ \\  You can create all the pens and brushes you need at the start, and delete them at the end, or you can create and delete them one at a time as they are needed. Apart from a small impact on memory usage the choice is yours.\\ \\  \\  Before you can draw anything you need to create a pen and/or a brush. A pen is used for drawing **lines** and a brush for filling **areas**. Quite often you will need both, even for a single object. For example when drawing a polygon the pen will be used to draw the outline and the brush to fill the inside.\\ \\  You can create all the pens and brushes you need at the start, and delete them at the end, or you can create and delete them one at a time as they are needed. Apart from a small impact on memory usage the choice is yours.\\ \\ 
 ==== Pens ==== ==== Pens ====
-\\  There are three main ways to create a pen, depending on what kind you need. The first is to use "SYS "​GetStockObject"":​\\ \\ +\\  There are three main ways to create a pen, depending on what kind you need. The first is to use "SYS "​GetStockObject"":​ 
 + 
 +<code bb4w>
         SYS "​GetStockObject",​ 6 TO pen% : REM. White pen         SYS "​GetStockObject",​ 6 TO pen% : REM. White pen
         SYS "​GetStockObject",​ 7 TO pen% : REM. Black pen         SYS "​GetStockObject",​ 7 TO pen% : REM. Black pen
         SYS "​GetStockObject",​ 8 TO pen% : REM. Null pen         SYS "​GetStockObject",​ 8 TO pen% : REM. Null pen
-These are the most basic kinds of pen. The only one likely to be useful when outputting to the printer is the **Null pen** which you would use when you want to draw an object //without any outline//​.\\ \\  The second method is to use "SYS "​CreatePen""​. This gives you more control over the pen as follows:\\ \\ +</​code>​ 
 + 
 +These are the most basic kinds of pen. The only one likely to be useful when outputting to the printer is the **Null pen** which you would use when you want to draw an object //without any outline//​.\\ \\  The second method is to use "SYS "​CreatePen""​. This gives you more control over the pen as follows: 
 + 
 +<code bb4w>
         SYS "​CreatePen",​ penstyle%, penwidth%, pencolour% TO pen%         SYS "​CreatePen",​ penstyle%, penwidth%, pencolour% TO pen%
 +</​code>​
 +
 Ths possible values of **penstyle%** are:​\\ ​ Ths possible values of **penstyle%** are:​\\ ​
  
-  * 0: PS_SOLID+  ​* **0**: PS_SOLID
   * **1**: PS_DASH   * **1**: PS_DASH
   * **2**: PS_DOT   * **2**: PS_DOT
Line 29: Line 45:
   * **4**: PS_DASHDOTDOT   * **4**: PS_DASHDOTDOT
   * **5**: PS_NULL   * **5**: PS_NULL
-\\  ​The **penwidth%** is specified in pixels (dots) so you may need to change it according to the dots-per-inch value for the printer. The width can be changed only for the PS_SOLID style: it must be 1 otherwise.\\ \\  The **pencolour%** is specified as a value equivalent to the hexadecimal number "&​00BBGGRR"​ where "​BB",​ "​GG"​ and "​RR"​ are the amounts of blue, green and red respectively ("​00"​=none,​ "​FF"​=maximum). So, for example, "&​00008000"​ would be a dark green.\\ \\  The third method of creating a pen is to use "SYS "​ExtCreatePen"";​ this gives you even more control over the pen:\\ \\ + 
 +The **penwidth%** is specified in pixels (dots) so you may need to change it according to the dots-per-inch value for the printer. The width can be changed only for the PS_SOLID style: it must be 1 otherwise.\\ \\  The **pencolour%** is specified as a value equivalent to the hexadecimal number "&​00BBGGRR"​ where "​BB",​ "​GG"​ and "​RR"​ are the amounts of blue, green and red respectively ("​00"​=none,​ "​FF"​=maximum). So, for example, "&​00008000"​ would be a dark green.\\ \\  The third method of creating a pen is to use "SYS "​ExtCreatePen"";​ this gives you even more control over the pen: 
 + 
 +<code bb4w> ​
         DIM lb{style%,​color%,​hatch%}         DIM lb{style%,​color%,​hatch%}
         lb.style% =         lb.style% =
Line 35: Line 54:
         lb.hatch% =         lb.hatch% =
         SYS "​ExtCreatePen",​ penstyle%, penwidth%, lb{}, 0, 0 TO pen%         SYS "​ExtCreatePen",​ penstyle%, penwidth%, lb{}, 0, 0 TO pen%
 +</​code>​
 +
 The **penstyle%** value can be any of those specified for "​CreatePen"​ above, but it can be combined using the **OR** operator with one or more of the following //​geometric//​ styles:​\\ ​ The **penstyle%** value can be any of those specified for "​CreatePen"​ above, but it can be combined using the **OR** operator with one or more of the following //​geometric//​ styles:​\\ ​
  
Line 42: Line 63:
   * **&​11000**:​ PS_GEOMETRIC + PS_JOIN_BEVEL   * **&​11000**:​ PS_GEOMETRIC + PS_JOIN_BEVEL
   * **&​12000**:​ PS_GEOMETRIC + PS_JOIN_MITER   * **&​12000**:​ PS_GEOMETRIC + PS_JOIN_MITER
-\\  The **penwidth%** is specified as for "​CreatePen",​ but for widths greater than 1 you must specify one of the //​geometric//​ pen styles above.\\ \\  The structure **lb{}** specifies the colour and other attributes of the pen. If none of the //​geometric//​ styles is specified **lb.color%** determines the colour (as for "​CreatePen"​) and **lb.style%** must be zero.\\ \\  If one or more of the //​geometric//​ styles is specified then **lb.style%** can be one of the following values:​\\ ​ 
  
-  ​* 0: BS_SOLID (lb.color% specifies the colour, lb.hatch% is ignored)+The **penwidth%** is specified as for "​CreatePen",​ but for widths greater than 1 you must specify one of the //​geometric//​ pen styles above.\\ \\  The structure **lb{}** specifies the colour and other attributes of the pen. If none of the //​geometric//​ styles is specified **lb.color%** determines the colour (as for "​CreatePen"​) and **lb.style%** must be zero.\\ \\  If one or more of the //​geometric//​ styles is specified then **lb.style%** can be one of the following values:\\  
 + 
 +  * **0**: BS_SOLID (lb.color% specifies the colour, lb.hatch% is ignored)
   * **2**: BS_HATCHED (lb.color% specifies the colour, lb.hatch% is one of the values listed below)   * **2**: BS_HATCHED (lb.color% specifies the colour, lb.hatch% is one of the values listed below)
   * **3**: BS_PATTERN (lb.color% is ignored, lb.hatch% is a handle to a bitmap)   * **3**: BS_PATTERN (lb.color% is ignored, lb.hatch% is a handle to a bitmap)
   * **5**: BS_DIBPATTERN (lb.color% is zero, lb.hatch% is a __handle__ to a packed DIB)   * **5**: BS_DIBPATTERN (lb.color% is zero, lb.hatch% is a __handle__ to a packed DIB)
   * **6**: BS_DIBPATTERNPT (lb.color% is zero, lb.hatch% is a __pointer__ to a packed DIB)   * **6**: BS_DIBPATTERNPT (lb.color% is zero, lb.hatch% is a __pointer__ to a packed DIB)
-\\  If **lb.style%** is 0 (BS_SOLID) or 2 (BS_HATCHED) then **lb.color%** specifies the colour in the same format as for "​CreatePen"​ above. \\ \\  If **lb.style%** is 2 (BS_HATCHED) then **lb.hatch%** can be one of the following values:​\\ ​ 
  
-  ​* 0: HS_HORIZONTAL+If **lb.style%** is (BS_SOLID) or 2 (BS_HATCHED) then **lb.color%** specifies the colour in the same format as for "​CreatePen"​ above. \\ \\  If **lb.style%** is 2 (BS_HATCHED) then **lb.hatch%** can be one of the following values:\\  
 + 
 +  * **0**: HS_HORIZONTAL
   * **1**: HS_VERTICAL   * **1**: HS_VERTICAL
   * **2**: HS_FDIAGONAL   * **2**: HS_FDIAGONAL
Line 57: Line 80:
   * **4**: HS_CROSS   * **4**: HS_CROSS
   * **5**: HS_DIAGCROSS   * **5**: HS_DIAGCROSS
-\\ +
 ==== Brushes ==== ==== Brushes ====
-\\  There are three main ways to create a brush, depending on what kind you need. The first is to use "SYS "​GetStockObject"":​\\ \\ +\\  There are three main ways to create a brush, depending on what kind you need. The first is to use "SYS "​GetStockObject"":​ 
 + 
 +<code bb4w>
         SYS "​GetStockObject",​ 0 TO brush% : REM. White brush         SYS "​GetStockObject",​ 0 TO brush% : REM. White brush
         SYS "​GetStockObject",​ 1 TO brush% : REM. Light grey brush         SYS "​GetStockObject",​ 1 TO brush% : REM. Light grey brush
Line 66: Line 91:
         SYS "​GetStockObject",​ 4 TO brush% : REM. Black brush         SYS "​GetStockObject",​ 4 TO brush% : REM. Black brush
         SYS "​GetStockObject",​ 5 TO brush% : REM. Null brush         SYS "​GetStockObject",​ 5 TO brush% : REM. Null brush
-You would use a **Null brush** when you want to draw //just the outline// of an object.\\ \\  The second method is to use "SYS "​CreateSolidBrush"":​\\ \\ +</​code>​ 
 + 
 +You would use a **Null brush** when you want to draw //just the outline// of an object.\\ \\  The second method is to use "SYS "​CreateSolidBrush"":​ 
 + 
 +<code bb4w>
         SYS "​CreateSolidBrush",​ brushcolour% TO brush%         SYS "​CreateSolidBrush",​ brushcolour% TO brush%
-The **brushcolour%** is specified as a value equivalent to the hexadecimal number "&​00BBGGRR"​ where "​BB",​ "​GG"​ and "​RR"​ are the amounts of blue, green and red respectively ("​00"​=none,​ "​FF"​=maximum). So, for example, "&​000080FF"​ would be orange.\\ \\  The third method is to use "SYS "​CreateBrushIndirect"":​\\ \\ +</​code>​ 
 + 
 +The **brushcolour%** is specified as a value equivalent to the hexadecimal number "&​00BBGGRR"​ where "​BB",​ "​GG"​ and "​RR"​ are the amounts of blue, green and red respectively ("​00"​=none,​ "​FF"​=maximum). So, for example, "&​000080FF"​ would be orange.\\ \\  The third method is to use "SYS "​CreateBrushIndirect"":​ 
 + 
 +<code bb4w>
         DIM lb{style%,​color%,​hatch%}         DIM lb{style%,​color%,​hatch%}
         lb.style% =         lb.style% =
Line 74: Line 107:
         lb.hatch% =         lb.hatch% =
         SYS "​CreateBrushIndirect",​ lb{} TO brush%         SYS "​CreateBrushIndirect",​ lb{} TO brush%
 +</​code>​
 +
 The structure **lb{}** specifies the colour and other attributes of the brush. The member **lb.style%** can be one of the following values:​\\ ​ The structure **lb{}** specifies the colour and other attributes of the brush. The member **lb.style%** can be one of the following values:​\\ ​
  
-  * 0: BS_SOLID (lb.color% specifies the colour, lb.hatch% is ignored)+  ​* **0**: BS_SOLID (lb.color% specifies the colour, lb.hatch% is ignored)
   * **2**: BS_HATCHED (lb.color% specifies the colour, lb.hatch% is one of the values listed below)   * **2**: BS_HATCHED (lb.color% specifies the colour, lb.hatch% is one of the values listed below)
   * **3**: BS_PATTERN (lb.color% is ignored, lb.hatch% is a handle to a bitmap)   * **3**: BS_PATTERN (lb.color% is ignored, lb.hatch% is a handle to a bitmap)
   * **5**: BS_DIBPATTERN (lb.color% is zero, lb.hatch% is a __handle__ to a packed DIB)   * **5**: BS_DIBPATTERN (lb.color% is zero, lb.hatch% is a __handle__ to a packed DIB)
   * **6**: BS_DIBPATTERNPT (lb.color% is zero, lb.hatch% is a __pointer__ to a packed DIB)   * **6**: BS_DIBPATTERNPT (lb.color% is zero, lb.hatch% is a __pointer__ to a packed DIB)
-\\  If **lb.style%** is 0 (BS_SOLID) or 2 (BS_HATCHED) then **lb.color%** specifies the colour in the same format as for "​CreateSolidBrush"​ above. \\ \\  If **lb.style%** is 2 (BS_HATCHED) then **lb.hatch%** can be one of the following values:​\\ ​ 
  
-  ​* 0: HS_HORIZONTAL+If **lb.style%** is (BS_SOLID) or 2 (BS_HATCHED) then **lb.color%** specifies the colour in the same format as for "​CreateSolidBrush"​ above. \\ \\  If **lb.style%** is 2 (BS_HATCHED) then **lb.hatch%** can be one of the following values:\\  
 + 
 +  * **0**: HS_HORIZONTAL
   * **1**: HS_VERTICAL   * **1**: HS_VERTICAL
   * **2**: HS_FDIAGONAL   * **2**: HS_FDIAGONAL
Line 89: Line 125:
   * **4**: HS_CROSS   * **4**: HS_CROSS
   * **5**: HS_DIAGCROSS   * **5**: HS_DIAGCROSS
-\\  ​There are other methods of creating brushes but they mainly duplicate the options available from "​CreateBrushIndirect"​.\\ \\ + 
 +There are other methods of creating brushes but they mainly duplicate the options available from "​CreateBrushIndirect"​. 
 ===== Writing graphics ===== ===== Writing graphics =====
-\\  Before you can output any graphics you must have enabled the printer using **VDU 2** and have printed at least one conventional text character. You may in any case want to print a title or something similar, but if not you can send just a single space character to the printer as follows:\\ \\ +\\  Before you can output any graphics you must have enabled the printer using **VDU 2** and have printed at least one conventional text character. You may in any case want to print a title or something similar, but if not you can send just a single space character to the printer as follows: 
 + 
 +<code bb4w>
         VDU 2,1,32,3         VDU 2,1,32,3
-\\ +</​code>​ 
 ==== Lines and curves ==== ==== Lines and curves ====
-\\  The simplest thing you can draw is a straight line; to do that use code similar to the following:\\ \\ +\\  The simplest thing you can draw is a straight line; to do that use code similar to the following: 
 + 
 +<code bb4w>
         SYS "​SelectObject",​ @prthdc%, pen%         SYS "​SelectObject",​ @prthdc%, pen%
         SYS "​MoveToEx",​ @prthdc%, x1%, y1%, 0         SYS "​MoveToEx",​ @prthdc%, x1%, y1%, 0
         SYS "​LineTo",​ @prthdc%, x2%, y2%         SYS "​LineTo",​ @prthdc%, x2%, y2%
-Here **x1%,y1%** are the coordinates of the start of the line and **x2%,y2%** are the coordinates of the end of the line. If you need to draw more lines with the same pen you don't need to reselect it.\\ \\  If you want to draw a number of connected lines, for example as a graph, then you can simply add additional calls to "​LineTo":​\\ \\ +</​code>​ 
 + 
 +Here **x1%,y1%** are the coordinates of the start of the line and **x2%,y2%** are the coordinates of the end of the line. If you need to draw more lines with the same pen you don't need to reselect it.\\ \\  If you want to draw a number of connected lines, for example as a graph, then you can simply add additional calls to "​LineTo":​ 
 + 
 +<code bb4w>
         SYS "​SelectObject",​ @prthdc%, pen%         SYS "​SelectObject",​ @prthdc%, pen%
         SYS "​MoveToEx",​ @prthdc%, x1%, y1%, 0         SYS "​MoveToEx",​ @prthdc%, x1%, y1%, 0
Line 105: Line 152:
         SYS "​LineTo",​ @prthdc%, x3%, y3%         SYS "​LineTo",​ @prthdc%, x3%, y3%
         REM. etc........         REM. etc........
-However if there are a large number of connected lines it may be easier to use the "​Polyline"​ function:\\ \\ +</​code>​ 
 + 
 +However if there are a large number of connected lines it may be easier to use the "​Polyline"​ function: 
 + 
 +<code bb4w>
         SYS "​SelectObject",​ @prthdc%, pen%         SYS "​SelectObject",​ @prthdc%, pen%
         SYS "​Polyline",​ @prthdc%, ^points%(0,​0),​ npoints%         SYS "​Polyline",​ @prthdc%, ^points%(0,​0),​ npoints%
-Here **points%()** is a 2D array of coordinates between which the lines will be drawn, where the second subscript is **zero** for the X-coordinate and **one** for the Y-coordinate. So for example you might declare and initialise the array as follows:\\ \\ +</​code>​ 
 + 
 +Here **points%()** is a 2D array of coordinates between which the lines will be drawn, where the second subscript is **zero** for the X-coordinate and **one** for the Y-coordinate. So for example you might declare and initialise the array as follows: 
 + 
 +<code bb4w>
         DIM points%(npoints%-1,​1)         DIM points%(npoints%-1,​1)
         points%() = x1%,​y1%,​x2%,​y2%,​x3%,​y3%,​x4%,​y4%,​x5%,​y5%......         points%() = x1%,​y1%,​x2%,​y2%,​x3%,​y3%,​x4%,​y4%,​x5%,​y5%......
-In practice it is rather more likely that the coordinates will be initialised in a **FOR...NEXT** loop:\\ \\ +</​code>​ 
 + 
 +In practice it is rather more likely that the coordinates will be initialised in a **FOR...NEXT** loop: 
 + 
 +<code bb4w>
         DIM points%(npoints%-1,​1)         DIM points%(npoints%-1,​1)
         FOR I% = 0 TO npoints%-1         FOR I% = 0 TO npoints%-1
Line 117: Line 176:
           points%(I%,​1) = ... : REM y coordinate           points%(I%,​1) = ... : REM y coordinate
         NEXT         NEXT
-As well as straight lines you can draw smooth curves:\\ \\ +</​code>​ 
 + 
 +As well as straight lines you can draw smooth curves: 
 + 
 +<code bb4w>
         SYS "​SelectObject",​ @prthdc%, pen%         SYS "​SelectObject",​ @prthdc%, pen%
         SYS "​PolyBezier",​ @prthdc%, ^points%(0,​0),​ npoints%         SYS "​PolyBezier",​ @prthdc%, ^points%(0,​0),​ npoints%
-The **points%()** array is declared exactly as before, but instead of drawing straight line segments Windows draws Bezier curves using the set of control points. In this case the number of points must be at least four.\\ \\  Another kind of curve is an (axis-aligned) elliptical arc:\\ \\ +</​code>​ 
 + 
 +The **points%()** array is declared exactly as before, but instead of drawing straight line segments Windows draws Bezier curves using the set of control points. In this case the number of points must be at least four.\\ \\  Another kind of curve is an (axis-aligned) elliptical arc: 
 + 
 +<code bb4w>
         SYS "​SelectObject",​ @prthdc%, pen%         SYS "​SelectObject",​ @prthdc%, pen%
         SYS "​Arc",​ @prthdc%, xmin%,​ymin%,​ xmax%,​ymax%,​ xstart%,​ystart%,​ xend%,yend%         SYS "​Arc",​ @prthdc%, xmin%,​ymin%,​ xmax%,​ymax%,​ xstart%,​ystart%,​ xend%,yend%
 +</​code>​
 +
 You specify the position and size of the ellipse in terms of its //bounding rectangle// and you specify the start and end of the arc as the end-points of two radial lines which intersect it. The arc is drawn anticlockwise:​\\ ​ You specify the position and size of the ellipse in terms of its //bounding rectangle// and you specify the start and end of the arc as the end-points of two radial lines which intersect it. The arc is drawn anticlockwise:​\\ ​
  
   * {{arclabel.gif}}   * {{arclabel.gif}}
-\\  You can draw a complete ellipse or circle by specifying the same point for the start and the end (often the point 0,0 is suitable).\\ \\ +\\  You can draw a complete ellipse or circle by specifying the same point for the start and the end (often the point 0,0 is suitable). 
 ==== 2D objects ==== ==== 2D objects ====
-\\  Lines and curves are drawn with a pen. 2D objects are drawn with both a pen (for the outline) and a brush (to fill the interior). As mentioned earlier if you don't want to draw the outline you can select a //Null pen//; similarly if you don't want to fill the interior you can select a //Null brush//. A simple example of a 2D object is a rectangle:\\ \\ +\\  Lines and curves are drawn with a pen. 2D objects are drawn with both a pen (for the outline) and a brush (to fill the interior). As mentioned earlier if you don't want to draw the outline you can select a //Null pen//; similarly if you don't want to fill the interior you can select a //Null brush//. A simple example of a 2D object is a rectangle: 
 + 
 +<code bb4w>
         SYS "​SelectObject",​ @prthdc%, pen%         SYS "​SelectObject",​ @prthdc%, pen%
         SYS "​SelectObject",​ @prthdc%, brush%         SYS "​SelectObject",​ @prthdc%, brush%
         SYS "​Rectangle",​ @prthdc%, xmin%, ymin%, xmax%, ymax%         SYS "​Rectangle",​ @prthdc%, xmin%, ymin%, xmax%, ymax%
-A rectangle is a special case of a polygon. Other polygons can be drawn as follows:\\ \\ +</​code>​ 
 + 
 +A rectangle is a special case of a polygon. Other polygons can be drawn as follows: 
 + 
 +<code bb4w>
         SYS "​SelectObject",​ @prthdc%, pen%         SYS "​SelectObject",​ @prthdc%, pen%
         SYS "​SelectObject",​ @prthdc%, brush%         SYS "​SelectObject",​ @prthdc%, brush%
         SYS "​Polygon",​ @prthdc%, ^vertices%(0,​0),​ nvertices%         SYS "​Polygon",​ @prthdc%, ^vertices%(0,​0),​ nvertices%
-Here **vertices%()** is a 2D array of coordinates of the polygon'​s vertices, where the second subscript is **zero** for the X-coordinate and **one** for the Y-coordinate. So for example you might declare and initialise the array as follows:\\ \\ +</​code>​ 
 + 
 +Here **vertices%()** is a 2D array of coordinates of the polygon'​s vertices, where the second subscript is **zero** for the X-coordinate and **one** for the Y-coordinate. So for example you might declare and initialise the array as follows: 
 + 
 +<code bb4w>
         DIM vertices%(nvertices%-1,​1)         DIM vertices%(nvertices%-1,​1)
         vertices%() = x1%,​y1%,​x2%,​y2%,​x3%,​y3%,​x4%,​y4%,​x5%,​y5%......         vertices%() = x1%,​y1%,​x2%,​y2%,​x3%,​y3%,​x4%,​y4%,​x5%,​y5%......
-In practice it is rather more likely that the coordinates will be initialised in a **FOR...NEXT** loop:\\ \\ +</​code>​ 
 + 
 +In practice it is rather more likely that the coordinates will be initialised in a **FOR...NEXT** loop: 
 + 
 +<code bb4w>
         DIM vertices%(nvertices%-1,​1)         DIM vertices%(nvertices%-1,​1)
         FOR I% = 0 TO nvertices%-1         FOR I% = 0 TO nvertices%-1
Line 145: Line 229:
           vertices%(I%,​1) = ... : REM y coordinate           vertices%(I%,​1) = ... : REM y coordinate
         NEXT         NEXT
-This is fine for normal polygons where none of the sides intersect one other, but there is a slight complication if you try to draw, for example, a five-pointed star. In this case you should specify the required //fill mode// as follows:\\ \\ +</​code>​ 
 + 
 +This is fine for normal polygons where none of the sides intersect one other, but there is a slight complication if you try to draw, for example, a five-pointed star. In this case you should specify the required //fill mode// as follows: 
 + 
 +<code bb4w>
         SYS "​SetPolyFillMode",​ @prthdc%, fmode%         SYS "​SetPolyFillMode",​ @prthdc%, fmode%
 +</​code>​
 +
 where **fmode%** is **1** for //​alternate//​ and **2** for //​winding//​. The effect of the different modes can be seen below:​\\ ​ where **fmode%** is **1** for //​alternate//​ and **2** for //​winding//​. The effect of the different modes can be seen below:​\\ ​
  
   * Alternate: {{alternate.gif}} Winding: {{winding.gif}}   * Alternate: {{alternate.gif}} Winding: {{winding.gif}}
-\\  ​Other 2D objects you can draw are sectors and segments. For a **sector** you would use:\\ \\ + 
 +Other 2D objects you can draw are sectors and segments. For a **sector** you would use: 
 + 
 +<code bb4w>
         SYS "​SelectObject",​ @prthdc%, pen%         SYS "​SelectObject",​ @prthdc%, pen%
         SYS "​SelectObject",​ @prthdc%, brush%         SYS "​SelectObject",​ @prthdc%, brush%
         SYS "​Pie",​ @prthdc%, xmin%,​ymin%,​ xmax%,​ymax%,​ xstart%,​ystart%,​ xend%,yend%         SYS "​Pie",​ @prthdc%, xmin%,​ymin%,​ xmax%,​ymax%,​ xstart%,​ystart%,​ xend%,yend%
-Here the parameters are exactly the same as for the **arc** described earlier. For a **segment** you do the following:\\ \\ +</​code>​ 
 + 
 +Here the parameters are exactly the same as for the **arc** described earlier. For a **segment** you do the following: 
 + 
 +<code bb4w>
         SYS "​SelectObject",​ @prthdc%, pen%         SYS "​SelectObject",​ @prthdc%, pen%
         SYS "​SelectObject",​ @prthdc%, brush%         SYS "​SelectObject",​ @prthdc%, brush%
         SYS "​Chord",​ @prthdc%, xmin%,​ymin%,​ xmax%,​ymax%,​ xstart%,​ystart%,​ xend%,yend%         SYS "​Chord",​ @prthdc%, xmin%,​ymin%,​ xmax%,​ymax%,​ xstart%,​ystart%,​ xend%,yend%
-Again the parameters are the same as for the **arc** and the **sector**.\\ \\  For a complete (filled) ellipse or circle draw a **sector** but specify the same point for the start and the end (often the point 0,0 is suitable).\\ ​\\ +</​code>​ 
 + 
 +Again the parameters are the same as for the **arc** and the **sector**.\\ \\  For a complete (filled) ellipse or circle draw a **sector** but specify the same point for the start and the end (often the point 0,0 is suitable).\\ ​ 
 ==== Arbitrary shapes ==== ==== Arbitrary shapes ====
-\\  You can draw an arbitrary filled shape by first defining its outline and then instructing Windows to fill it:\\ \\ +\\  You can draw an arbitrary filled shape by first defining its outline and then instructing Windows to fill it: 
 + 
 +<code bb4w>
         SYS "​BeginPath",​ @prthdc%         SYS "​BeginPath",​ @prthdc%
         REM. Define the outline here, for example using combinations         REM. Define the outline here, for example using combinations
Line 168: Line 270:
         SYS "​SelectObject",​ @prthdc%, brush%         SYS "​SelectObject",​ @prthdc%, brush%
         SYS "​StrokeAndFillPath",​ @prthdc%         SYS "​StrokeAndFillPath",​ @prthdc%
-\\ +</​code>​ 
 ===== Completing the printout ===== ===== Completing the printout =====
 \\  After you've output all the graphics, along with any text and/or images on the same page, you are ready to commit it to paper.\\ \\  \\  After you've output all the graphics, along with any text and/or images on the same page, you are ready to commit it to paper.\\ \\ 
 ==== Tidying up ==== ==== Tidying up ====
-\\  You must delete all the pens and brushes you created. Firstly ensure that none of them is still selected:\\ \\ +\\  You must delete all the pens and brushes you created. Firstly ensure that none of them is still selected: 
 + 
 +<code bb4w>
         SYS "​GetStockObject",​ 5 TO nullbrush%         SYS "​GetStockObject",​ 5 TO nullbrush%
         SYS "​SelectObject",​ @prthdc%, nullbrush%         SYS "​SelectObject",​ @prthdc%, nullbrush%
         SYS "​GetStockObject",​ 8 TO nullpen%         SYS "​GetStockObject",​ 8 TO nullpen%
         SYS "​SelectObject",​ @prthdc%, nullpen%         SYS "​SelectObject",​ @prthdc%, nullpen%
-If you created your pens and brushes as you needed them, and deleted them as soon as they were finished with, there will probably be no more than one of each left to delete. If however you created them all at the start there may be several to delete, for example:\\ \\ +</​code>​ 
 + 
 +If you created your pens and brushes as you needed them, and deleted them as soon as they were finished with, there will probably be no more than one of each left to delete. If however you created them all at the start there may be several to delete, for example: 
 + 
 +<code bb4w>
         SYS "​DeleteObject",​ pen1%         SYS "​DeleteObject",​ pen1%
         SYS "​DeleteObject",​ pen2%         SYS "​DeleteObject",​ pen2%
         SYS "​DeleteObject",​ brush1%         SYS "​DeleteObject",​ brush1%
         SYS "​DeleteObject",​ brush2%         SYS "​DeleteObject",​ brush2%
-\\ +</​code>​ 
 ==== Ejecting the page ==== ==== Ejecting the page ====
-\\  Now you're ready to tell the printer to go ahead and print everything you've output. You do that as follows:\\ \\ +\\  Now you're ready to tell the printer to go ahead and print everything you've output. You do that as follows: 
 + 
 +<code bb4w>
         VDU 2,1,12,3         VDU 2,1,12,3
 +</​code>​
 +
 That's all there is to it!\\ \\ That's all there is to it!\\ \\
 ---- ----
Line 195: Line 309:
   * Use screen (pixel) coordinates rather than printer coordinates   * Use screen (pixel) coordinates rather than printer coordinates
   * Replace the final "VDU 2,​1,​12,​3"​ with the following code:   * Replace the final "VDU 2,​1,​12,​3"​ with the following code:
-\\ + 
 +<code bb4w>
         SYS "​InvalidateRect",​ @hwnd%, 0, 0         SYS "​InvalidateRect",​ @hwnd%, 0, 0
 +</​code>​
writing_20graphics_20to_20the_20printer.txt · Last modified: 2018/04/13 20:06 by richardrussell