; ; Draw module specification ; ========================= ; ; ; ; The following specification should be regarded as an ultimate aim: many of ; the facilities in it will not exist for quite a long time. ; ; ; ; Path format ; =========== ; ; A path is a sequence of one or more of the following path elements, each of ; which is a sequence of words: ; 0 n = end of path, with n bytes remaining in buffer ; (n is only important for output buffers, and ; will not be read for input paths). ; 1 ptr = pointer to continuation of path. ; 2 x y = move to (x,y), starting new subpath. This ; subpath will affect winding numbers and so ; is filled normally. ; 3 x y = move to (x,y), starting new subpath. This ; subpath does not affect winding numbers when ; filling (used internally for thin-stroking ; paths). Note that any subpath started by ; this element will always be considered ; "closed" and so will never be closed by the ; "close open subpaths" operation. ; 4 = close current subpath with a gap (c.f. element ; type 7). ; 5 = close current subpath with a line (c.f. ; element type 8). ; 6 x1 y1 x2 y2 x3 y3 = Bezier curve to (x3,y3), with control points ; at (x1,y1) and (x2,y2); ; 7 x y = gap to (x,y), not starting new subpath - used ; internally for non-thickened dashed lines. ; 8 x y = line to (x,y). ; ; Only the bottom byte of the element type (i.e. the first word in each of ; the sequences above) is significant: the remaining three bytes are free for ; use in any way a client of the Draw module sees fit. (On output to the ; input path, the Draw module will leave these three bytes unchanged; on ; output to a standard output path, the Draw module will store zeroes in ; these three bytes.) ; The element types noted as being used internally above can quite ; legitimately be used externally - the notes are simply to explain why these ; types exist at all. ; Note that there are order constraints on these elements - in particular, ; element types 4 to 8 may not be used when there is no current subpath. ; ; ; ; The Draw module SWIs ; ==================== ; ; All calls come in two versions, one a fixed point version and the other ; floating point. The former is faster but allows a smaller range of user ; co-ordinate systems and is sometimes less accurate. ; ; For the fixed point versions, all numbers that relate to distances in the ; co-ordinate space (e.g. co-ordinates, line widths, etc.) are expressed in ; user-defined units before transformation. When the transformed path is ; output to the screen (in particular, when Draw_Fill or Draw_Stroke is ; called), the units after transformation are 1/256 of an OS unit (i.e. ; approx. 1/(256*180) inch = 1/46080 inch = 1/640 point). The default ; flatness is 512 (2 OS units), which produces reasonable results when ; output is to the screen and the identity matrix is used. All dimensionless ; quantities have 16 binary places (i.e. &10000 represents the constant 1.0). ; Note that in the standard matrix ; ; ( a b 0 ) ; ( c d 0 ) ; ( e f 1 ), ; ; a, b, c and d are dimensionless quantities (so have 16 binary places), ; while e and f represent a translation in the co-ordinate space and so are ; expressed in user-defined units. This varying interpretation of matrix ; elements is unpleasant, but necessary to retain reasonable behaviour (e.g. ; we want the inverses of all sensible matrices to be representable with ; reasonable accuracy). ; ; The floating point versions use IEEE single precision floating point ; numbers in all circumstances. They are distinguished by the suffix FP on ; the name of the call. The default flatness is 2.0, for the same reason as ; above. ; They will not be implemented in initial versions of the Draw module. My ; belief is that they will eventually be required, but if this should turn ; out not to be the case, they may never be implemented. ; ; Note: unless otherwise specified below, all co-ordinates are user ; co-ordinates. PostScript concepts that are not redefined here should be ; interpreted as PostScript interprets them. ; ; A further note: all calls use the colour (both pixel pattern and operation) ; set up for the OS VDU routines. ; This means in particular that they can do things that PostScript cannot ; do - e.g. fill using operations such as AND, OR, EOR that pay attention to ; the current contents of the screen. Given this fact, I see no reason to ; restrict the module to PostScript's capabilities in other areas. This has ; resulted in the following additional non-PostScript abilities for the Draw ; module: ; (a) Choice of fill style - e.g. fill including/excluding boundary, fill ; to halfway through boundary, fill exterior, etc. ; (b) "Positive winding number" and "negative winding number" rules as well ; as PostScript's "non-zero winding number" and "even-odd winding number" ; rules. ; (c) Line cap enhancements - particularly differing "leading" and ; "trailing" line caps and triangular line caps (together, these allow ; arrowed lines and similar effects). ; ; Any program which wants to remain PostScript-compatible will of course have ; to avoid using these enhancements. ; ; ; ; Draw_Fill, Draw_FillFP ; ====================== ; ; These imitate the PostScript "fill" operator - i.e. they close open ; subpaths, flatten the path, transform it to standard co-ordinates, fix it ; if the call is Draw_FillFP and fill the result. ; ; Entry: R0 points to the path. ; R1 contains the fill style: ; ; Bits 0,1: 0 = non-zero winding number rule; ; 1 = negative winding number rule; ; 2 = even-odd winding number rule; ; 3 = positive winding number rule; ; Bit 2: Set if non-boundary exterior pixels are to be ; plotted, clear if they are not; ; Bit 3: Set if boundary exterior pixels are to be plotted, ; clear if they are not; ; Bit 4: Set if boundary interior pixels are to be plotted, ; clear if they are not. ; Bit 5: Set if non-boundary interior pixels are to be ; plotted, clear if they are not; ; Bits 6-31 are reserved and should be zero. ; ; R1=0 is a special case. According to the above, it means "don't ; fill anything, non-zero rule" - a pretty useless operation. For ; convenience, it specifies a sensible default fill style, namely ; &30 (i.e. "fill to halfway through boundary, non-zero rule"). ; R2 points to the matrix, held as 6 words in memory (in the order ; a,b,c,d,e,f for the matrix above); R2=0 means the identity ; matrix. Note that the code assumes that one user-defined unit is ; a small fraction of a pixel, and matrices that multiply ; distances by large factors may lead to inaccurate results. ; R3 contains the flatness, in user co-ordinates; R3=0 means default ; flatness. ; ; Exit: R0 is corrupt (if V clear), ; or points to error block (if V set). ; R1-R11 preserved. ; ; ; ; Draw_Stroke, Draw_StrokeFP ; ========================== ; ; These emulate the PostScript "stroke" operator - i.e. they: ; (a) flatten the path; ; (b) apply a dash pattern to the path; ; (c) thicken the path, using the current line joins and caps; ; (d) re-flatten the path; ; (e) transform the path to standard co-ordinates; ; (f) fix the path if the call is Draw_StrokeFP; ; (g) fill the resulting path. ; ; Except in the special case of the line width being 0 (which means that ; as thin a path as possible is plotted, with line caps and joins being ; ignored), thickening the path is likely to result in a path that winds ; multiply around some pixels and/or in multiple plotting of some pixels. ; It is therefore inadvisable to use winding number rules other than the ; non-zero one, or non-idempotent colour operations (e.g. EOR). It is also ; inadvisable to try plotting the non-boundary exterior pixels. The on-screen ; results of doing any of these are undefined. ; ; Entry: R0 points to the path. ; R1 contains the fill style, as for Draw_Fill, except that R1=0 has ; a slightly different interpretation. If the line width is ; non-zero, it means &30 as above. If the line width is zero, it ; means &18 (i.e. "fill boundary"), as the flattened and thickened ; path will in fact have no interior in this case! For zero width ; lines, the default fill style is usually the only sensible one. ; In addition, the top bit of R1 can be set to require the Draw ; module to plot the stroke all at once (i.e. using the "plot ; normally" option of Draw_ProcessPath rather than the "plot ; subpath by subpath" option). The main effects of this change ; are that the code will never double-plot a pixel, but also that ; it uses more workspace - possibly quite a lot more! ; R2 points to the matrix or contains 0, as for Draw_Fill. ; R3 contains the flatness or contains 0, as for Draw_Fill. ; R4 contains the line thickness, or 0 for a thin stroke (one pixel ; wide, with line caps and joins being ignored). ; R5 points to a line cap and join specification, which is a word- ; aligned four word area containing: ; Offset 0: Byte 0 holds join style: ; 0 = mitered joins; ; 1 = round joins; ; 2 = bevelled joins. ; Byte 1 holds leading cap style: ; 0 = butt caps; ; 1 = round caps; ; 2 = projecting square caps; ; 3 = triangular caps. ; Byte 2 holds trailing cap style, with the ; same allowed values as for leading caps. ; Byte 3 is reserved and should be zero. ; Offset 4: This holds a parameter associated with joins. For ; mitered joins, this is the miter limit. It is not ; used for the other join types. Note that the miter ; limit is a dimensionless quantity and so has 16 ; binary places. ; Offset 8: This holds a parameter associated with leading ; caps. For triangular caps, this contains two 16 bit ; unsigned numbers, each of which should be regarded ; as having 8 binary places. The most significant ; part of the number specifies how many line widths ; the cap goes beyond the end of the line, and the ; least significant part how many line widths it goes ; to the side of the centre of the line. Thus e.g. ; &1000100 means a cap going 1 line width beyond the ; end of the line and 1 line width to each side of ; its centre - i.e. the cap width is twice the line ; width, and its shape is a 45/90/45 degree triangle. ; This parameter is not used for the other cap ; styles. ; Offset 12: This holds a similar parameter associated with ; trailing caps. ; The module will make no attempt to read the last three words if ; the corresponding cap or join style does not use them, so it is ; legitimate to use a smaller area than four words if the ; parameters are not required. ; R6 points to a dash pattern, or contains 0 if an undashed line is ; required. A dash pattern must be word-aligned and has the ; following format: ; Offset 0: Distance into the dash pattern to start. ; Offset 4: Number N of elements in the dash pattern. ; Offsets 8 to 4N+4: Elements of the dash pattern, each of ; which is a distance. ; The dash pattern starts with a dash of length equal to the first ; element above, then a gap of length equal to the second element ; above, etc. When the last element of the dash pattern has been ; used, the module starts again from the beginning. Note that if ; the number of elements of the dash pattern is odd, the distances ; will be interpreted differently the second time through, with ; the first element being a gap, the second a dash, etc. ; ; Exit: R0 is corrupt (if V clear), ; or points to error block (if V set). ; R1-R11 preserved. ; ; ; ; Draw_StrokePath, Draw_StrokePathFP ; ================================== ; ; Entry: R0, R2-R6 set as for Draw_Stroke. ; R1 points to a word-aligned output buffer (which holds words 0, N, ; then N free bytes), or contains 0 to ask for the required output ; buffer size (i.e. N+8). ; ; Exit: If V set, R0 points to an error block. ; If V clear and R1 was non-zero, the output path has been inserted ; into the buffer, ending with an end of path indicator (i.e. words ; 0, N, where N is the number of free bytes following in the ; buffer). R0 points to this end of path indicator (and so is a ; suitable output buffer value for a subsequent path generating ; call that is to append to the path). ; If V clear and R1 was zero, R0 holds the required length. ; R1-R11 preserved. ; ; ; ; Draw_FlattenPath, Draw_FlattenPathFP ; ==================================== ; ; Entry: R0 points to the input path. ; R1 points to a word-aligned output buffer (which holds words 0, N, ; then N free bytes), or contains 0 to ask for the required output ; buffer size (i.e. N+8). ; R2 contains the flatness, or 0 if the default flatness is to be ; used. ; ; Exit: If V set, R0 points to an error block. ; If V clear and R1 was non-zero, the output path has been inserted ; into the buffer, ending with an end of path indicator (i.e. words ; 0, N, where N is the number of free bytes following in the ; buffer). R0 points to this end of path indicator. ; If V clear and R1 was zero, R0 holds the required length. ; R1-R11 preserved. ; ; ; ; Draw_TransformPath, Draw_TransformPathFP ; ======================================== ; ; Entry: R0 points to the input path. ; R1 points to a word-aligned output buffer (which holds words 0, N, ; then N free bytes), or contains 0 to transform the path in situ. ; R2 points to the matrix or contains 0, as for Draw_Fill. ; R3 is zero for fixed point output, &80000000 for floating point ; output. All other values are reserved. ; ; Exit: If V set, R0 points to an error block. ; If V clear and R1 was 0, R0 is corrupt. ; If V clear and R1 pointed to an output buffer, the output path has ; been inserted into the buffer, ending with an end of path ; indicator (i.e. words 0, N, where N is the number of free bytes ; following in the buffer). R0 points to this end of path ; indicator. ; R1-R11 preserved. ; ; ; ; Draw_ProcessPath, Draw_ProcessPathFP ; ==================================== ; ; This allows a path to be put through a general set of the processes used ; when doing Stroke or Fill. One or more of the following can be requested, ; in the order given: ; (a) close open subpaths; ; (b) flatten the path; ; (c) apply a dash pattern to the path; ; (d) thicken the path; ; (e) re-flatten the path; ; (f) transform the path by a matrix; ; (g) fix a floating point path or float a fixed point one; ; (h) output the resulting path by one of six techniques: ; (i) output to a specified output buffer; ; (ii) count how long an output buffer is required for the given path ; and operations. ; (iii) fill the path normally - not legitimate for a floating point ; path; ; (iv) fill the path subpath by subpath (this option saves workspace ; and can sometimes be used legitimately - for example, Stroke ; may use it). Also not legitimate for a floating point path. ; (v) output to the input buffer (i.e. modify the path in situ). Only ; valid if the path's length cannot be changed by the call - i.e. ; if steps (a) to (e) above are not requested. ; (vi) output the path's bounding box, in transformed co-ordinates. ; This bounding box does not pay attention to pixel boundaries ; and is "inclusive" on all sides. ; ; All combinations of these are allowed, other than the exceptions noted ; above. However, some are likely to produce errors (e.g. thickening a non- ; flattened path) and others are likely to produce strange results (e.g. ; filling a path containing open subpaths). ; All the calls above (Draw_Fill, etc.) translate into specific calls to ; Draw_ProcessPath or Draw_ProcessPathFP: they are provided to ensure that ; suitable names exist for common operations and to reduce the number of ; registers requiring setting up and/or preserving. ; ; Entry: R0 points to the input path. ; R1 contains a fill style in its bottom 6 bits, as for Draw_Fill, ; except that R1=0 has no special meaning. Other bits have the ; following meanings: ; Bits 6-26 are reserved and should be zero. ; Bit 27: set if open subpaths are to be closed (step (a) ; above). ; Bit 28: set if the path is to be flattened initially (step ; (b) above). ; Bit 29: set if the path is to be thickened (step (d) above). ; Bit 30: set if path is to be re-flattened (step (e) above). ; Bit 31: set if output path should be floating point, clear if ; it should be fixed point (step (g) above). ; R2 points to a matrix, or contains 0 if no transformation by a ; matrix is to be done (step (f) above). ; R3 contains the flatness, or 0 for the default flatness (used in ; steps (b) and (e) above). ; R4 contains the line thickness (used in step (d) above). R5 points ; to a line join and cap specification (used in step (d) above). ; R6 points to a dash pattern, or contains 0 if the path is not to be ; dashed (step (c) above). ; R7 points to a word-aligned output buffer (which holds words 0, N, ; then N free bytes), or contains one of the following special ; values: ; 0: output to the input path. This will only be accepted if the ; requested operations on the path are ones that cannot ; change its length - i.e. transforming the path by a matrix ; and fixing or floating it. ; 1: fill the path normally. ; 2: fill the path subpath by subpath. ; 3: count the size of output buffer required. ; &80000000+address: output the bounding box of the processed ; path to the (word-aligned) address and the three following ; words, in the order lowX, lowY, highX, highY. Note: should ; this option be applied to an non-flat path, a valid but not ; minimal bounding box will be produced. ; ; Exit: R1-R11 preserved. ; If V set, R0 points to an error block. ; If V clear: ; If R7 was 0, 1 or 2 on entry, R0 is corrupt. ; If R7 was 3 on entry, R0 holds the size of output buffer required ; (i.e. N+8 if the output buffer should be words 0, N, followed ; by N free bytes). ; If R7 pointed to an output buffer, the output path will have been ; inserted into the buffer and R0 points to the new end of path ; indicator. ; ; ; ; Other calls ; =========== ; ; The module will probably contain other calls - e.g. an arc to Bezier ; converting call. I have not designed these yet. ; ; ; ; The Draw module vector ; ====================== ; ; This provides a means of indirecting the calls above. ; ; Entry: R0-R7 hold values appropriate for the call concerned. ; R8 specifies which call is involved: ; 0: Draw_ProcessPath ; 1: Draw_ProcessPathFP ; 2: Draw_Fill ; 3: Draw_FillFP ; 4: Draw_Stroke ; 5: Draw_StrokeFP ; 6: Draw_StrokePath ; 7: Draw_StrokePathFP ; 8: Draw_FlattenPath ; 9: Draw_FlattenPathFP ; 10: Draw_TransformPath ; 11: Draw_TransformPathFP ; ; Exit: R0 holds a suitable return value. ; V set or clear as appropriate. ; R1-R11 corrupt. ;