writing_20graphics_20to_20the_20printer
Differences
This shows you the differences between two versions of the page.
Next revision | Previous revision | ||
writing_20graphics_20to_20the_20printer [2018/03/31 13:19] – external edit 127.0.0.1 | writing_20graphics_20to_20the_20printer [2024/01/05 00:21] (current) – external edit 127.0.0.1 | ||
---|---|---|---|
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:// | //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:// | ||
===== 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 // | + | \\ 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 // |
+ | |||
+ | <code bb4w> | ||
SYS " | SYS " | ||
SYS " | SYS " | ||
- | 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//' | + | </ |
+ | |||
+ | 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//' | ||
+ | |||
+ | <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 | ||
+ | </ | ||
+ | |||
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 " | + | \\ There are three main ways to create a pen, depending on what kind you need. The first is to use "SYS " |
+ | |||
+ | <code bb4w> | ||
SYS " | SYS " | ||
SYS " | SYS " | ||
SYS " | SYS " | ||
- | 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// | + | </ |
+ | |||
+ | 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// | ||
+ | |||
+ | <code bb4w> | ||
SYS " | SYS " | ||
+ | </ | ||
+ | |||
Ths possible values of **penstyle%** are: | Ths possible values of **penstyle%** are: | ||
- | * 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 "& | ||
+ | |||
+ | <code bb4w> | ||
DIM lb{style%, | DIM lb{style%, | ||
lb.style% = | lb.style% = | ||
Line 35: | Line 54: | ||
lb.hatch% = | lb.hatch% = | ||
SYS " | SYS " | ||
+ | </ | ||
+ | |||
The **penstyle%** value can be any of those specified for " | The **penstyle%** value can be any of those specified for " | ||
Line 42: | Line 63: | ||
* **& | * **& | ||
* **& | * **& | ||
- | \\ The **penwidth%** is specified as for " | ||
- | | + | The **penwidth%** is specified as for " |
+ | |||
+ | * **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 " | ||
- | | + | If **lb.style%** is 0 (BS_SOLID) or 2 (BS_HATCHED) then **lb.color%** specifies the colour in the same format as for " |
+ | |||
+ | * **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 " | + | \\ There are three main ways to create a brush, depending on what kind you need. The first is to use "SYS " |
+ | |||
+ | <code bb4w> | ||
SYS " | SYS " | ||
SYS " | SYS " | ||
Line 66: | Line 91: | ||
SYS " | SYS " | ||
SYS " | SYS " | ||
- | You would use a **Null brush** when you want to draw //just the outline// of an object.\\ \\ The second method is to use "SYS " | + | </ |
+ | |||
+ | You would use a **Null brush** when you want to draw //just the outline// of an object.\\ \\ The second method is to use "SYS " | ||
+ | |||
+ | <code bb4w> | ||
SYS " | SYS " | ||
- | The **brushcolour%** is specified as a value equivalent to the hexadecimal number "& | + | </ |
+ | |||
+ | The **brushcolour%** is specified as a value equivalent to the hexadecimal number "& | ||
+ | |||
+ | <code bb4w> | ||
DIM lb{style%, | DIM lb{style%, | ||
lb.style% = | lb.style% = | ||
Line 74: | Line 107: | ||
lb.hatch% = | lb.hatch% = | ||
SYS " | SYS " | ||
+ | </ | ||
+ | |||
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) | + | |
* **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 " | ||
- | | + | If **lb.style%** is 0 (BS_SOLID) or 2 (BS_HATCHED) then **lb.color%** specifies the colour in the same format as for " |
+ | |||
+ | * **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 " | ||
===== 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 | ||
- | \\ | + | </ |
==== 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 " | SYS " | ||
SYS " | SYS " | ||
SYS " | SYS " | ||
- | 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 " | + | </ |
+ | |||
+ | 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 " | ||
+ | |||
+ | <code bb4w> | ||
SYS " | SYS " | ||
SYS " | SYS " | ||
Line 105: | Line 152: | ||
SYS " | SYS " | ||
REM. etc........ | REM. etc........ | ||
- | However if there are a large number of connected lines it may be easier to use the " | + | </ |
+ | |||
+ | However if there are a large number of connected lines it may be easier to use the " | ||
+ | |||
+ | <code bb4w> | ||
SYS " | SYS " | ||
SYS " | SYS " | ||
- | 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:\\ \\ | + | </ |
+ | |||
+ | 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, | DIM points%(npoints%-1, | ||
points%() = x1%, | points%() = x1%, | ||
- | In practice it is rather more likely that the coordinates will be initialised in a **FOR...NEXT** loop:\\ \\ | + | </ |
+ | |||
+ | In practice it is rather more likely that the coordinates will be initialised in a **FOR...NEXT** loop: | ||
+ | |||
+ | <code bb4w> | ||
DIM points%(npoints%-1, | DIM points%(npoints%-1, | ||
FOR I% = 0 TO npoints%-1 | FOR I% = 0 TO npoints%-1 | ||
Line 117: | Line 176: | ||
points%(I%, | points%(I%, | ||
NEXT | NEXT | ||
- | As well as straight lines you can draw smooth curves:\\ \\ | + | </ |
+ | |||
+ | As well as straight lines you can draw smooth curves: | ||
+ | |||
+ | <code bb4w> | ||
SYS " | SYS " | ||
SYS " | SYS " | ||
- | 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:\\ \\ | + | </ |
+ | |||
+ | 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 " | SYS " | ||
SYS " | SYS " | ||
+ | </ | ||
+ | |||
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 " | SYS " | ||
SYS " | SYS " | ||
SYS " | SYS " | ||
- | A rectangle is a special case of a polygon. Other polygons can be drawn as follows:\\ \\ | + | </ |
+ | |||
+ | A rectangle is a special case of a polygon. Other polygons can be drawn as follows: | ||
+ | |||
+ | <code bb4w> | ||
SYS " | SYS " | ||
SYS " | SYS " | ||
SYS " | SYS " | ||
- | Here **vertices%()** is a 2D array of coordinates of the polygon' | + | </ |
+ | |||
+ | Here **vertices%()** is a 2D array of coordinates of the polygon' | ||
+ | |||
+ | <code bb4w> | ||
DIM vertices%(nvertices%-1, | DIM vertices%(nvertices%-1, | ||
vertices%() = x1%, | vertices%() = x1%, | ||
- | In practice it is rather more likely that the coordinates will be initialised in a **FOR...NEXT** loop:\\ \\ | + | </ |
+ | |||
+ | In practice it is rather more likely that the coordinates will be initialised in a **FOR...NEXT** loop: | ||
+ | |||
+ | <code bb4w> | ||
DIM vertices%(nvertices%-1, | DIM vertices%(nvertices%-1, | ||
FOR I% = 0 TO nvertices%-1 | FOR I% = 0 TO nvertices%-1 | ||
Line 145: | Line 229: | ||
vertices%(I%, | vertices%(I%, | ||
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:\\ \\ | + | </ |
+ | |||
+ | 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 " | SYS " | ||
+ | </ | ||
+ | |||
where **fmode%** is **1** for // | where **fmode%** is **1** for // | ||
* 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: | ||
+ | |||
+ | <code bb4w> | ||
SYS " | SYS " | ||
SYS " | SYS " | ||
SYS " | SYS " | ||
- | Here the parameters are exactly the same as for the **arc** described earlier. For a **segment** you do the following:\\ \\ | + | </ |
+ | |||
+ | Here the parameters are exactly the same as for the **arc** described earlier. For a **segment** you do the following: | ||
+ | |||
+ | <code bb4w> | ||
SYS " | SYS " | ||
SYS " | SYS " | ||
SYS " | SYS " | ||
- | 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).\\ | + | </ |
+ | |||
+ | 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 " | SYS " | ||
REM. Define the outline here, for example using combinations | REM. Define the outline here, for example using combinations | ||
Line 168: | Line 270: | ||
SYS " | SYS " | ||
SYS " | SYS " | ||
- | \\ | + | </ |
===== 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 " | SYS " | ||
SYS " | SYS " | ||
SYS " | SYS " | ||
SYS " | SYS " | ||
- | 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:\\ \\ | + | </ |
+ | |||
+ | 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 " | SYS " | ||
SYS " | SYS " | ||
SYS " | SYS " | ||
SYS " | SYS " | ||
- | \\ | + | </ |
==== 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 | ||
+ | </ | ||
+ | |||
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, | * Replace the final "VDU 2, | ||
- | \\ | + | |
+ | <code bb4w> | ||
SYS " | SYS " | ||
+ | </ |
writing_20graphics_20to_20the_20printer.1522502391.txt.gz · Last modified: 2024/01/05 00:16 (external edit)