home *** CD-ROM | disk | FTP | other *** search
/ The Datafile PD-CD 3 / PDCD_3.iso / utilities / utilsm / mkdrawf / Doc / ManualT < prev    next >
Encoding:
Text File  |  1995-04-30  |  71.9 KB  |  1,895 lines

  1. [[ Note: This text-only version of the manual was produced by hand from
  2.    the Impression version. It is therefore likely that there are lots of
  3.    infelicities in the formatting; in particular, font changes have been
  4.    lost. If a sentence doesn’t seem to make any sense, see whether it’s
  5.    any better if you pretend some of the words in it are in italics. :-) ]]
  6.  
  7. Contents
  8. ========
  9.  
  10. Introduction
  11.   Legal rubbish
  12.   Who am I?
  13.   How to read this manual
  14.  
  15. How to use mkdrawf
  16.   Errors
  17.  
  18. How to get mkdrawf
  19.  
  20. An introduction to drawfiles
  21.   Object type 0: font table
  22.   Object type 1: text
  23.   Object type 2: path
  24.   Object type 5: sprite
  25.   Object type 6: group
  26.   Object type 7: tagged
  27.   Object type 9: text area
  28.   Object type 10: text column
  29.   Object type 11: options
  30.   Object type 12: transformed text
  31.   Object type 13: transformed sprite
  32.   Object type 16: JPEG image
  33.  
  34. The drawfile description language I
  35.   Tokens
  36.   Numbers
  37.   Comments
  38.   Braces
  39.   Numbers
  40.   Comments
  41.   Braces
  42.   Points, dimensions and things
  43.   Colours
  44.   Keywords and special keywords
  45.   Token lists
  46.  
  47. The drawfile description language II
  48.   Global variables
  49.   Macros
  50.   Macro parameters and local variables
  51.   Arithmetic and things
  52.   String operations
  53.   Conversions
  54.   Conditionals
  55.   Iteration
  56.   File inclusion
  57.  
  58. The drawfile description language III
  59.   The format of an object description
  60.   Bounding boxes
  61.   The Header pseudo-object
  62.   The FontTable object
  63.   The Text object
  64.   The Path object
  65.   The Sprite object
  66.   The Group object
  67.   The Tagged object
  68.   The TextArea object
  69.   The Options object
  70.   The XfText object
  71.   The XfSprite object
  72.   The JPEG object
  73.  
  74. Some sample drawfile descriptions
  75.   The Koch snowflake curve
  76.   A Lissajous figure
  77.   A typical text area
  78.   Circular arcs using Bezier curves
  79.   A silly spiral
  80.  
  81. Tagfiles
  82.  
  83. Technical issues
  84.   Memory management
  85.   Variables
  86.   Problems
  87.   Arbitrary restrictions
  88.  
  89. Differences from the previous version of mkdrawf
  90.   Points don’t have commas
  91.   Strings have quotation marks
  92.   No implicit hexadecimal
  93.  
  94. Revision history
  95.  
  96. Decoding drawfiles
  97.   Using decdrawf
  98.   The output from decdrawf
  99.  
  100.  
  101. ----------------------------------------------------------------------------
  102.  
  103.  
  104. Introduction
  105. ============
  106.  
  107. This is the user manual for mkdrawf, a program for creating drawfiles.
  108. Of course there are other programs for creating drawfiles, notably !Draw,
  109. but mkdrawf is unusual in  that it allows you complete control over what
  110. goes into the drawfile. It takes as input a text file describing the objects
  111. that should go into the drawfile; the description language it uses is quite
  112. powerful, having  variables, macros and some mathematical functions.
  113.  
  114. This manual describes the process of creating a drawfile using mkdrawf, and
  115. includes several sample mkdrawf input files and the resulting output.
  116.  
  117. This manual also describes its much simpler companion program decdrawf,
  118. which performs the inverse process: it converts drawfiles to mkdrawf
  119. descriptions.
  120.  
  121. Before reading this manual you might want to read the mkdrawf tutorial.
  122. You might also want to look at the manual for !Drawf, a Wimp front end
  123. for mkdrawf and decdrawf.
  124.  
  125.  
  126. Legal rubbish
  127. -------------
  128.  
  129. 1. These programs are not public domain; they are mine.
  130.  
  131. 2. You are welcome to distribute them exactly unchanged (where “them”
  132. includes all the source code and both versions (text and Impression) of
  133. this documentation). You are also welcome to make changes to your own
  134. copy of the programs.
  135.  
  136. 3. However, you are not permitted to distribute modified versions without
  137. my permission.
  138.  
  139. 4. Furthermore, you are not permitted to charge money for copies of this
  140. software; it is free software, and I intend that it should remain free.
  141. And I certainly don’t want anyone other than me making money from it!
  142.  
  143. If you make improvements to the programs, I am very unlikely to object to
  144. your distributing the improved version provided it is made clear what
  145. changes you have made; the point is that I don’t want to be blamed for
  146. other people’s bad programming or credited with their good programming,
  147. and that I want the documentation for mkdrawf to be consistent with the
  148. program. So if you improve mkdrawf, get in touch with me so that I can
  149. give you an updated version of the documentation to go with your improved
  150. version.
  151.  
  152. If you have somehow acquired an incomplete or modified version of these
  153. programs, you may distribute it; but I’d prefer you to get in touch with
  154. me and get a complete, up-to-date version of the programs. At the time of
  155. writing, the current version is version 2.35.
  156.  
  157.  
  158. Who am I?
  159. ---------
  160. If you want to get in touch (to moan about problems, to suggest improvements,
  161. to thank me for doing such a truly wonderful job, ...), you will need the
  162. following information.
  163.  
  164. I have an e-mail address and a snail-mail address. Both are valid as of
  165. April 1995, and both are likely to continue working for some time yet.
  166. E-mail is preferred, but I’ll try to answer snail-mail too.
  167.  
  168. e-mail:    gjm11@pmms.cam.ac.uk
  169.  
  170. snail-mail:
  171.     Gareth McCaughan
  172.     Trinity College
  173.     Cambridge CB2 1TQ
  174.  
  175. I would be really happy to hear from you. If you have complaints or
  176. suggestions, they may help me to make mkdrawf better; and if you have
  177. neither, presumably that’s because mkdrawf is completely perfect for
  178. your needs… I’d be very glad to be told!
  179.  
  180.  
  181. How to read this manual
  182. -----------------------
  183.  
  184. Of course it’s up to you; and it’s not a very long manual, so you could
  185. probably read it in any order you like without causing yourself much trouble.
  186. However, I would suggest the following procedure:
  187.  
  188.   • Have a look at the “sample drawfile descriptions”, to give you some idea
  189.     about how mkdrawf works.
  190.   • If you don’t have much idea of just what goes into a drawfile, read “An
  191.     introduction to drawfiles”.
  192.   • If you’ve used the earlier version of mkdrawf, read “Differences
  193.     from the previous version...”.
  194.   • Read the three chapters on “The drawfile description language”, skipping
  195.     bits you don’t understand. The second contains the most obscurities; you
  196.     might well want to skim the third before reading the other two.
  197.   • Read “How to use mkdrawf”, and create a few files yourself, referring to
  198.     the DDL chapters.
  199.  
  200. At this point you’re on your own. You should be able to do anything you
  201. want, referring to this manual as necessary.
  202.  
  203. If you find this manual heavy going, you might like to read the mkdrawf
  204. tutorial.
  205.  
  206.  
  207. ----------------------------------------------------------------------------
  208.  
  209.  
  210. How to use mkdrawf
  211. ==================
  212.  
  213. This is pretty easy. Just create a suitable input file, and type
  214.   mkdrawf <input-file-name> <output-file-name>
  215. to make the output file. This will create the output file if it doesn’t
  216. already exist, and will set its filetype to DrawFile.
  217.  
  218. The only other way of invoking mkdrawf is to type
  219.   mkdrawf −v
  220. which displays the version number and date of your copy of mkdrawf. This
  221. will be useful if I make further improvements. This version of the manual
  222. describes version 2.35.
  223.  
  224. Alternatively, you can use the !Drawf application to give you a Wimp front
  225. end to both mkdrawf and decdrawf.
  226.  
  227.  
  228. Errors
  229. ------
  230.  
  231. mkdrawf produces three kinds of diagnostic: warnings, errors and fatal
  232. errors. I hope the distinction between them is clear. If any errors or
  233. fatal errors are produced, you should not rely on the resulting drawfile
  234. containing anything sensible, though in most cases it will at any rate
  235. be a valid drawfile. mkdrawf tries hard to carry on reading your input
  236. file even if there are errors (because that may help you to spot several
  237. problems at once); but you should not rely on anything after the first error
  238. making sense. Just as with C, a single error can produce a cascade of
  239. error messages.
  240.  
  241. All this is an improvement on versions 2.10 and earlier, which simply stopped
  242. dead the first time they found anything they couldn’t parse.
  243.  
  244. The command-line option -e will make mkdrawf omit the filename in error and
  245. warning messages. You are unlikely to need this.
  246.  
  247.  
  248. ----------------------------------------------------------------------------
  249.  
  250.  
  251. How to get mkdrawf
  252. ==================
  253.  
  254. If you’re reading this manual, you probably already have a copy. But perhaps
  255. you want to be sure you have the latest version, or you've accidentally
  256. formatted your hard disc, or something. Or perhaps you stole the manual.
  257. Anyway, you can get mkdrawf:
  258.  
  259.   • from me, electronically or postally. If you want a copy sent to you by
  260.     post, please send me either a floppy disc and whatever sort of packaging
  261.     you think is suitable for the return journey, plus £1stg to cover postage
  262.     and make me bother to send it; or £2stg, for which you will get an HD disc
  263.     (or a DD disc if you request that), in what seems to me to be suitable
  264.     packaging. If you add another £4 you can also have a nicely printed
  265.     version of the documentation.
  266.   • from some FTP sites. I know mkdrawf is available at micros.hensa.ac.uk
  267.     (at least from academic sites in the UK), and I’m pretty sure it’s also
  268.     available at ftp.demon.co.uk. Please try any suitable FTP sites you can
  269.     think of before trying to get a copy from me!
  270.  
  271.  
  272. ----------------------------------------------------------------------------
  273.  
  274.  
  275. An introduction to drawfiles
  276. ============================
  277.  
  278. This chapter describes briefly what sort of stuff goes into a drawfile.
  279. If you already know all about that (for instance, if you’ve read the
  280. relevant section of the PRMs), you can skip it. If not, read on...
  281.  
  282. A drawfile consists of a short header followed by a sequence of objects.
  283. Each object consists, in turn, of a short header (similar but not identical
  284. in structure to the header of the whole drawfile) followed by some more
  285. interesting stuff. Exactly what that “more interesting stuff” is depends
  286. on the object; in some cases, it can include other objects (and so
  287. recursively...); see the sections on Group and Tagged objects.
  288.  
  289. There are 12 types of object; several are not understood by the version of
  290. !Draw distributed with RISC OS 2, and one is so recent that no existing
  291. version of !Draw understands it. There is no guarantee that yet more object
  292. types will not be added in later versions of !Draw. Each type has an
  293. associated number, by which objects of that type are identified in drawfiles.
  294. The numbers are not consecutive; the apparent gaps are not mistakes.
  295.  
  296.  
  297. Object type 0: font table
  298. -------------------------
  299.  
  300. When you use !Draw you never see a font table object. That’s because it
  301. doesn’t actually describe any particular part of the drawing. A drawfile
  302. may contain text in several different fonts; internally these fonts are
  303. referred to by magic numbers rather than by names, and the font table
  304. establishes a correspondence between names and numbers. I don’t know for
  305. certain why it’s done this way, but here are some possible reasons:
  306.  
  307. 1. It saves a bit of space in the drawfile if one font is referred to
  308.    many times: only one byte needs to be repeated each time, rather than
  309.    a long font name.
  310. 2. It makes things easier for applications that have to render drawfiles:
  311.    they can call Font_FindFont once for each font in the table, and then
  312.    set up a table of font handles and use that.
  313. 3. It means that if you want to make wholesale changes to the fonts in a
  314.    drawfile (say, replacing Trinity with Homerton throughout), you only
  315.    have to change the font table.
  316.  
  317. (Reason number 3 here is irrelevant if you’re using !Draw, but if you’re
  318. using mkdrawf or something like it it might be significant. My money is on
  319. reason number 2 being the main one, though.)
  320.  
  321. There may only be one font table in a drawfile; if there are any text
  322. objects, there must be exactly one, and it must appear before they do.
  323. Actually !Draw doesn’t cope correctly if the font table is not the very
  324. first object in the file.
  325.  
  326.  
  327. Object type 1: text
  328. -------------------
  329.  
  330. If you select the text tool in !Draw and type some text, you are creating
  331. a text object. A text object specifies, as well as the text to be contained
  332. in it:
  333.   • the colour in which the text is to appear;
  334.   • the background it’s likely to be on;
  335.   • the font it is to appear in;
  336.   • the size and aspect ratio of the font;
  337.   • where the text is to start (that is, its bottom-left corner).
  338.   
  339. The background colour is just a hint. It doesn’t actually cause anything
  340. to be drawn in that colour, but it helps the anti-aliasing code in (for
  341. instance) !Draw to improve the appearance of the text.
  342.  
  343.  
  344. Object type 2: path
  345. -------------------
  346.  
  347. This is the commonest object type. A path is made up of a number of
  348. subpaths. Each subpath is drawn, and perhaps filled, separately (but
  349. the same options for things like path width, fill colour and so on are
  350. common to all the subpaths). A subpath consists of simple elements:
  351.   • move to a given place
  352.   • draw a line to a given place
  353.   • draw a Bezier curve to a given place, with given control points
  354.   • close the current subpath.
  355. Each subpath starts with a move, and each move begins a new subpath.
  356.  
  357. It’s possible to specify the following things for a path object:
  358.   • the colour to use for filling it in (may be “none”)
  359.   • the rule used to determined what gets filled and what doesn’t
  360.   • the colour to use for drawing the outline (may be “none”)
  361.   • the width of the outline
  362.   • how to join up adjacent sections of path
  363.   • what to do at the ends of the path
  364.   • whether the path outline should be “dashed”, and what dash pattern to use
  365.  
  366.  
  367. Object type 5: sprite
  368. ---------------------
  369.  
  370. A sprite object simply consists of an object header and a sprite. (The
  371. object header determines exactly where the sprite will appear and how big
  372. it will be.)
  373.  
  374.  
  375. Object type 6: group
  376. --------------------
  377.  
  378. A group object contains any number of other objects. (It’s possible to
  379. work out from the object header where in the drawfile the list of
  380. objects in the group ends.) The only other information in a group
  381. object is a name; the name has no effect on the rendition of the object,
  382. but it may be used for identification purposes by some applications.
  383.  
  384.  
  385. Object type 7: tagged
  386. ---------------------
  387.  
  388. A tagged object consists of a 4-byte identifier, an object and some quantity
  389. of extra data. A tagged object is rendered simply by rendering the object
  390. it contains; the other stuff may be used by certain applications. (The PRM
  391. says: “This allows specific programs to attach meaning to certain objects,
  392. while keeping the image renderable”.)
  393.  
  394.  
  395. Object type 9: text area
  396. ------------------------
  397.  
  398. A text area object consists of a number of columns and a quantity of text
  399. (and a little extra data). The text contains various escape sequences which
  400. control how it will be formatted. A text area object is rendered by
  401. formatting the text in the columns (using the columns in sequence); users
  402. of DTP packages may like to think of the columns as being linked text frames.
  403.  
  404. A complete list of the escape sequences and their meanings is contained
  405. in the next chapter of this manual.
  406.  
  407.  
  408. Object type 10: text column
  409. ---------------------------
  410.  
  411. Text column objects appear only inside text area objects. They describe
  412. the columns into which the text will be placed.
  413.  
  414.  
  415. Object type 11: options
  416. -----------------------
  417.  
  418. An options object describes the following things, most of which are
  419. specific to !Draw.
  420.   • The size of paper on which the objects are supposed to appear
  421.   • Some information about “paper limits”
  422.   • The set-up of the grid (shown? locked? what spacing? ...)
  423.   • The zoom ratio
  424.   • Whether the toolbox is to be shown or not
  425.   • What “entry mode” to use initially
  426.   • The size of !Draw’s undo buffer
  427.  
  428. If more than one options object appears, !Draw ignores all but the first.
  429. The RISC OS 2 version of !Draw ignores options objects (and doesn’t save
  430. them).
  431.  
  432.  
  433. Object type 12: transformed text
  434. --------------------------------
  435.  
  436. A transformed text object is a text object with bells on. The bells specify:
  437.   • what affine transformation to apply to the text
  438.   • whether to apply kerning to the text
  439.   • whether to render the text right-to-left
  440. An affine transformation is specified by a 2×2 matrix and a vector.
  441. More on this later.
  442.  
  443.  
  444. Object type 13: transformed sprite
  445. ----------------------------------
  446.  
  447. A transformed sprite object bears the same relationship to a sprite object
  448. as a transformed text object does to a text object, except that kerning and
  449. right-to-left aren’t issues. In other words, a transformed sprite object
  450. contains a transformation matrix (erm, and vector) and a sprite.
  451.  
  452.  
  453. Object type 16: JPEG image
  454. --------------------------
  455.  
  456. A JPEG image object consists of a small amount of header data and a JPEG image
  457. in JFIF format. (JPEG is a standard method of compressing images; JFIF is the
  458. name of the commonest file format for JPEG-compressed images. What is usually
  459. called a “JPEG file” should strictly be called a JFIF file.) No current
  460. version of !Draw understands this object type, but future versions might
  461. well do.
  462.  
  463.  
  464. ----------------------------------------------------------------------------
  465.  
  466.  
  467. The drawfile description language I
  468. ===================================
  469.  
  470. This chapter and the next two describe, in some detail, the language
  471. understood by mkdrawf. To be more precise: this chapter is a brief
  472. description of the syntax of the language, the next deals with variables
  473. and macros and things, and the next describes what gets done with the
  474. tokens produced when all the macro expansion and variable substitution
  475. are finished. (So it’s that chapter that actually discusses drawfile
  476. objects.)
  477.  
  478.  
  479. Tokens
  480. ------
  481.  
  482. As mkdrawf reads an input file, it parses it into tokens. A token might be
  483. a keyword like FontTable, or a number like 1.23456, or a colour like
  484. r200g100b123, or whatever. Except in funny circumstances -- strings and
  485. things -- tokens are delimited by whitespace and are not case-sensitive.
  486.  
  487. Here is a list of the token types understood by mkdrawf, with an example
  488. of each. Some of these are not explained until the next chapter.
  489.   • Number        123.456e2    
  490.   • String        "foo bar"
  491.   • Colour        r123g0b255
  492.   • Keyword        Width
  493.   • Special keyword    Define
  494.   • Global variable    $myvar1
  495.   • Local variable    %length
  496.   • Macro name        Snowflake
  497.   • Opening brace    {
  498.   • Closing brace    }
  499.  
  500. Internally, mkdrawf actually uses a couple of other keyword types, but
  501. they aren’t things you can put into the file yourself.
  502.  
  503. Here’s a brief account of how mkdrawf decides what type each token it sees
  504. has:
  505.  
  506. Opening and closing braces are easy. Anything that starts with a $ is
  507. a global variable; anything that starts with a % is a local variable;
  508. anything that starts with a " is a string. Numbers are things that can
  509. be parsed successfully by the strtod function in the C library; colours
  510. are things matching the scanf format r%dg%db%d. Anything else is one of
  511. the other types. mkdrawf has a list of keywords and “specials”; anything
  512. else must be a macro name. Simple!
  513.  
  514.  
  515. Numbers
  516. -------
  517.  
  518. You can enter a number either in a form that the C library function strtod()
  519. can understand, or in the form 0x1234FEDC (meaning hexadecimal). Both get
  520. dealt with in the program as “double”s, should this be relevant.
  521.  
  522.  
  523. Comments
  524. --------
  525.  
  526. If a token begins with a # then that token, and everything else up to the
  527. end of the line, is ignored by mkdrawf. This is useful for making your
  528. mkdrawf input files more comprehensible, and also for “commenting out”
  529. sections that you don’t want to use but don’t want to throw away completely
  530. either.
  531.  
  532. I suppose that strictly speaking this means there’s another type of token
  533. (comment start), but that’s not how mkdrawf thinks about it internally.
  534. Something that would be a token but begins with a # never makes it as far
  535. as tokenhood; the token-maker just reads a new input line and tries again.
  536.  
  537.  
  538. Braces
  539. ------
  540.  
  541. The language understood by mkdrawf is a structured one; its structure
  542. reflects the structure of drawfiles. For instance, a Group object actually
  543. contains other objects; so the description of a Group object in a mkdrawf
  544. input file actually contains descriptions of other objects. Groupings of
  545. this sort are done with braces. Since braces are tokens, they must have
  546. whitespace on either side. (A brief note for the hitherto ignorant:
  547. “whitespace” includes newlines as well as spaces and tabs!)
  548.  
  549. Whenever it’s stated that something is delimited by braces, this means
  550. it’s delimited by matching braces. For instance, you can’t put unmatched
  551. braces into a macro definition.
  552.  
  553.  
  554. Points, dimensions and things
  555. -----------------------------
  556.  
  557. A point (meaning a location in 2-dimensional space, rather than a pixel)
  558. is represented by two numbers. By convention, the point 0 0 is at the
  559. bottom-left corner of the image. The unit for these numbers, and indeed
  560. for almost all dimensions, is the point; for our purposes a point is
  561. exactly 1/72 of an inch. (Historically the printer’s point is a slightly
  562. smaller unit than this; but the definition of the drawfile format says
  563. that its points are exactly this size. I think this accords with usage
  564. in PostScript and on the Apple Macintosh; it differs from that of TeX.)
  565.  
  566. A bounding box is represented by two points, which should be the bottom-left
  567. and top-right coordinates of the box.
  568.  
  569. In a drawfile, most dimensions are stored as integer multiples of 1/640 of
  570. a point; so giving dimensions to 10000 significant figures is probably not
  571. sensible.
  572.  
  573.  
  574. Colours
  575. -------
  576.  
  577. A colour is specified by giving its red, green and blue intensities. The
  578. format is as described above; the numbers should be between 0 and 255
  579. inclusive. There is also a special colour, called None or Transparent
  580. (these are synonyms), which means just what you would expect it to.
  581.  
  582. As of version 2.33, wherever a colour is required you may instead give
  583. three integers in the correct range. They will be used as the red, green
  584. and blue intensities of the colour. This makes it possible to do things
  585. like shading.
  586.  
  587.  
  588. Keywords and special keywords
  589. -----------------------------
  590.  
  591. Keywords are bits of drawfile object specification. Some of them name
  592. object types; some name parameters of objects; some are “flags” (their
  593. presence or absence determines something about an object); some are
  594. possible parameter values, when those values form a finite set. Examples
  595. (in order): Path, OutlineColour, Kerned, Mitred.
  596.  
  597. Special keywords do not directly describe drawfile objects. They are
  598. dealt with earlier, by the macro-and-variable machinery described in the
  599. next chapter. They are used in defining macros, doing arithmetic
  600. calculations, and so on.
  601.  
  602.  
  603. Token lists
  604. -----------
  605.  
  606. I’m not sure whether I should count these as tokens. They are treated as
  607. such in the program. A token list is, errm, a list of tokens; the expansion
  608. text of a macro is a token list, and the value of a variable can be too.
  609. The only thing you really need to know about these is that there’s an
  610. implementation limit on the depth of nesting of token lists, namely 256
  611. levels of nesting.
  612.  
  613. You get a token list into a variable by doing, say,
  614.   Set %womble { 1 2 3 4 }
  615. which gives the local variable womble the token list 1 2 3 4 as its value.
  616. (What’s a local variable? See the next chapter.)
  617.  
  618. Note: the body of a For loop is not actually a token list, although it
  619. looks like one; nor are the brace-delimited bits of drawfile objects.
  620.  
  621.  
  622. ----------------------------------------------------------------------------
  623.  
  624.  
  625. The drawfile description language II
  626. ====================================
  627.  
  628. The drawfile format, unlike (say) PostScript, has no “language” features
  629. at all. A drawfile cannot use variables, looping constructs and so on.
  630. mkdrawf allows you to use some (fairly weak) programming features of this
  631. kind in a way that fits quite well with its underlying language; for
  632. instance, you can give values to variables and define macros.
  633.  
  634. mkdrawf splits your input file into tokens, as discussed in the previous
  635. chapter. However, most of the time it isn’t just reading tokens; it’s
  636. expanding them too. This means that if it sees an expandable token
  637. (I’ll explain this in a moment) it replaces it with its expansion, which
  638. is usually another token or a whole sequence of tokens.
  639.  
  640. The tokens resulting from expansion are then expanded again, and so on;
  641. thus, what eventually emerges is a stream of unexpandable (i.e., simple)
  642. tokens. What happens to those is the subject of the next chapter.
  643.  
  644. Here’s a list of expandable token types, together with what happens to them
  645. on expansion. There’s more detailed information in the next few sections.
  646.  
  647.   • A variable (local or global) is replaced by its value.
  648.   • A macro, together with its parameters, is replaced by its text; while
  649.     that’s being processed, local variables are set up corresponding to
  650.     the parameter values given.
  651.   • A token list is replaced by the tokens in the list, in order.
  652.   • A For, together with its parameters, is replaced by several copies of
  653.     the loop body.
  654.   • An If vanishes, together with any conditional stuff in the “wrong”
  655.     arm of the If.
  656.   • A Define or Set vanishes, together with the thing being defined and
  657.     the value it’s being given; of course the defining or setting happens
  658.     too.
  659.   • An Include, together with the filename following it, is replaced by
  660.     the contents of that file. (This is slightly inaccurate: see below.)
  661.   • An operator (like Plus or Sin), together with 1 or 2 tokens following it,
  662.     is replaced by the result of applying that operator to the appropriate
  663.     values.
  664.  
  665.  
  666. Global variables
  667. ----------------
  668.  
  669. A global variable is named by a token that starts with a dollar sign $.
  670. When mkdrawf sees a global-variable token in its input stream it replaces
  671. it with the current value associated with that variable. Of course this
  672. isn’t quite true, since it must be possible to set the variable in the
  673. first place; when mkdrawf sees the special keyword Set it doesn’t expand
  674. the following token, but treats it as a variable name. It then sets the
  675. variable’s value to be the token that follows, or (if that’s an open-brace
  676. token) the token-list that follows.
  677.  
  678. The value of a variable can be any single token, or a token list. Note
  679. that if you do
  680.   Set $foo { 1 2 3 }
  681. the value of $foo is the list
  682.   1 2 3
  683. rather than the list
  684.   { 1 2 3 }.
  685. When you set a variable to a token list, the tokens in the list are not
  686. expanded as they are being read. (But of course they will be expanded later
  687. when the variable name is read and expanded.) See the comments below on the
  688. same feature for macro parameters if you want to know why.
  689.  
  690.  
  691. Macros
  692. ------
  693.  
  694. A macro’s name can be any token that doesn’t already have some other
  695. significance. So you can’t name a macro Width or 123 or $foo or %zog,
  696. but you could call it Fred or 2a or ^^!"£@. A macro expands to a list of
  697. tokens. You call a macro by giving its name followed by { }. (Why? See the
  698. next section.) Macros are defined with the Define special keyword, which
  699. behaves very much like the Set special keyword: give it the name of the
  700. macro, followed by the text of the macro enclosed in braces.
  701.  
  702.  
  703. Macro parameters and local variables
  704. ------------------------------------
  705.  
  706. There’s more, though: macros can take parameters, and can use local
  707. variables. I’m lumping these together because they have the same syntax
  708. and use the same internal machinery.
  709.  
  710. A parameter or local variable is named by a token that starts with a
  711. percent sign %. It has a value local to the macro containing it; local,
  712. in fact, to the macro invocation containing it. (The point is that you
  713. can call a macro many times; it’s a different variable each time.)
  714.  
  715. Local variables get their values in two ways. The first is by the Set
  716. special keyword, just as for global variables; the second is by being
  717. used as parameters when the macro is called. To call a macro with
  718. parameters, put some stuff between those braces. The stuff should look
  719. like this:
  720.   Fred { %foo 123 %aardvark Width %%% %foo }
  721. which means that macro Fred should be called, and three of its local
  722. variables given values. The local variables are called %foo, %aardvark
  723. and %%%; the values are, respectively, the number 123, the keyword Width,
  724. and whatever the value of local variable %foo is when Fred is called.
  725. (The procedure is: read a token without expansion, check it’s a local
  726. variable name, then read a token with expansion and assign it to the
  727. appropriate local variable for the macro about to be called.)
  728.  
  729. A local variable (or macro parameter) can have a token list as its value.
  730. To do this with a macro parameter, you say (for instance):
  731.   Fred { %foo 123 %bar { Width 1 OutlineColour r0g0b0 } %baz "Hello" }
  732. which means that %foo gets the value 123 and %baz the value "Hello",
  733. as before, but %bar gets that list as its value. Within the macro body,
  734. %bar will expand to Width 1 OutlineColour r0g0b0. Note again that whatever’s
  735. inside the braces doesn’t get expanded until %bar is expanded.
  736.  
  737. This allows you to do something very like anonymous functions (!), and
  738. if you need something variable in there you can always do
  739.   Fred { %list { Set %zog Plus %zog %foo } %foo $zoo }
  740. since the value given to %foo will be expanded at invocation time.
  741.  
  742. The fact that a local variable is local to a macro invocation rather than
  743. to a macro definition, as it were, makes it possible to do recursion. See
  744. the snowflake curve example later.
  745.  
  746. Note that the following will not work:
  747.   Define Foo { FontTable }
  748.   Foo {
  749.     1 "Trinity.Medium"
  750.     2 "Homerton.Bold"
  751.   }
  752. but the following will:
  753.   Define Foo { FontTable }
  754.   Foo { } {
  755.     1 "Trinity.Medium"
  756.     2 "Homerton.Bold"
  757.   }
  758. And so will:
  759.   Set $Foo { FontTable }     # or, Set $Foo FontTable
  760.   Foo {
  761.     1 "Trinity.Medium"
  762.     2 "Homerton.Bold"
  763.   }
  764.  
  765.  
  766. Positional parameters
  767. ---------------------
  768.  
  769. Sometimes you need or want a less cumbersome way of getting parameters into
  770. macros. Macro parameters of the form %number are special: %1 is the first token
  771. after the macro’s parameter list, %2 is the next and so on. As many of these are
  772. read as are needed. (This number may be different for different invocations of
  773. the same macro, please note.)
  774.  
  775. This allows you, for instance, to produce your own functions with syntax the same
  776. as that for the arithmetic functions described below.
  777.  
  778.  
  779. Arithmetic and things
  780. ---------------------
  781.  
  782. You can do some (very limited) mathematical operations on numbers. This
  783. is all done by the token-expansion machinery: for instance, expanding the
  784. Plus special keyword reads two more tokens (with expansion), checks that
  785. they’re numbers, and yields a numerical token whose value is the sum of
  786. their values. The special keywords that do this sort of thing are:
  787.   Plus Minus Times Over Sqrt Sin Cos Tan Floor.
  788. I’m afraid that mathematical expressions look a bit ugly when written
  789. like this; for instance, what you might like to write as “sin(2(x+3))”
  790. becomes
  791.   Sin Times 2 Plus $x 3
  792. which I agree is nasty. Those used to LISP will probably find it a bit
  793. more manageable than most...
  794.  
  795. There is also Random, which reads no more tokens and expands to a random
  796. number between 0 (inclusive) and 1 (exclusive). Unless you are very unlucky
  797. you will get a different sequence of random numbers every time you run
  798. mkdrawf.
  799.  
  800.  
  801. String operations
  802. -----------------
  803.  
  804. It’s possible to do some things with strings, too. Two things, in fact.
  805. Firstly, you can append them to form new strings. Append 3 "foo" "bar " "baz"
  806. expands to "foobar baz". Secondly, you can feed them to the OS_GSTrans SWI,
  807. to get variable substitution and things. (Try making a text object including
  808. the line Text GSTrans "<Sys$Time>".)
  809.  
  810.  
  811. Conversions
  812. -----------
  813.  
  814. It’s sometimes useful to be able to convert strings to numbers, and vice
  815. versa. There are three operators for doing this. Str2Num and Num2Str do just
  816. what you would expect them to (Str2Num will give an error and a result of
  817. zero if given a string that wouldn’t be recognised as a number by the
  818. token-parsing routines). Font "foo" expands to the number of the font whose
  819. name is "foo", if there is any such in the font table. If there is a font
  820. table and it doesn’t contain a font called foo then the expansion is 0 and an
  821. error message is given; if no font table at all has been given, mkdrawf will
  822. insert the font name into an internal table and remember to build a font
  823. table for you when it finishes.
  824.  
  825.  
  826. Conditionals
  827. ------------
  828.  
  829. Expanding the token IfExists does the following: First it reads one token,
  830. without expansion. If this is the name of a variable that exists (i.e., has
  831. had a value assigned to it with Set or as a macro parameter), the next bunch
  832. of tokens will be read from whatever follows it, until an EndIf or Else
  833. token is seen. If an Else token is seen first, everything from there to the
  834. matching EndIf will be skipped. On the other hand, if what it reads is not
  835. the name of an existing variable, everything up to the matching EndIf or
  836. Else is skipped.
  837.  
  838. This is easier than it sounds; the behaviour is just the same as that of
  839. an If in BASIC or C or whatever. Tokens are not expanded while skipping;
  840. they are expanded while not skipping. This means that if you define a macro
  841. with unbalanced If and Else and EndIf things in it, you can cause chaos.
  842. So don’t.
  843.  
  844. As well as IfExists, there are two other sorts of If: IfLess reads two
  845. tokens, with expansion; they must be numbers, and it does what you think
  846. it does; and IfEqual reads two tokens, with expansion, and again does just
  847. what you think it does. If there’s a need for other sorts of conditional,
  848. I can put them in pretty easily.
  849.  
  850.  
  851. Iteration
  852. ---------
  853.  
  854. Finally, and most nastily of all, there is a For construct that behaves
  855. a little like the similarly-named things in other languages. Remember,
  856. though, that this works by macro-expansion; it doesn’t “compile” to a
  857. block of stuff followed by a test and a conditional jump. All the testing
  858. and jumping happens in the macro-expansion mechanism.
  859.  
  860. The syntax is
  861.   For variable initial limit { stuff }.
  862.  
  863. The variable, which may be local or global, is initially given the value
  864. initial. Then stuff is spliced into the token stream. When the end of the
  865. stuff is reached, the variable has its value increased by 1. If that value
  866. is now less than limit, then stuff is spliced into the token stream again,
  867. and it all repeats; otherwise we’re finished. Note that this has more the
  868. semantics of C’s do loop than of its while loop: the stuff is always read
  869. at least once.
  870.  
  871. Relevant facts: the variable is of course not expanded; the stuff is not
  872. expanded before it’s spliced into the token stream, so it can refer to
  873. variable and have that expand differently each time round the loop; it
  874. is legal to change the value of variable within the stuff, and this behaves
  875. in the way you would expect.
  876.  
  877.  
  878. File inclusion
  879. --------------
  880.  
  881. This is not really a “language feature”, but it seems to belong here more
  882. than it does anywhere else. If your mkdrawf code contains a line like
  883. Include "$.Zog.Wombat", the contents of that file will effectively be
  884. included at that point in the input file. You can nest these inclusions;
  885. mkdrawf can cope with having up to 17 input files open at once (although
  886. the Shared C Library or the operating system may impose other restrictions).
  887.  
  888. This allows you to have a “header file” containing frequently used variable
  889. and macro definitions, or to have a mostly-unchanging file with a few
  890. variable bits read from other files.
  891.  
  892. I advise you, for reasons of clarity, to put each Include on a line by
  893. itself. If you don’t, the precise behaviour is as follows: The remainder
  894. of the line on which the Include (with its associated string) finishes is
  895. read, and then input switches to the named file until that is exhausted.
  896.  
  897. You might also want to know that Include doesn’t do anything if it’s read at
  898. a time when tokens aren’t being expanded. The most notable such case is when
  899. the a macro definition is being read. So you can, if you must, have a macro
  900. called Include (although that would stop you using the Include feature from
  901. then onwards). And you can define a macro that includes a file every time it
  902. is expanded; but you can’t read the contents of a file into the definition of
  903. a macro.
  904.  
  905.  
  906. ----------------------------------------------------------------------------
  907.  
  908.  
  909. The drawfile description language III
  910. =====================================
  911.  
  912. This chapter (finally!) describes what happens to the “simple” tokens
  913. that are spat out by the macro-expansion stuff. Here the correspondence
  914. between your input file and the final output file is extremely close.
  915.  
  916. After expansion, your input file should look like a succession of object
  917. descriptions. An object description describes a single drawfile object;
  918. when one object contains another, its object description will contain the
  919. object description for that other object.
  920.  
  921.  
  922. The format of an object description
  923. -----------------------------------
  924.  
  925. An object description consists of a keyword naming the object type,
  926. followed by a left brace, followed by some stuff describing the object,
  927. followed by a right brace. The details of the “stuff” depend, of course,
  928. on just what sort of object it is; in broad terms, though, it’s very much
  929. like what goes into the parameter list for a macro invocation, but instead
  930. of local variable names you put appropriate keywords. I shall refer to
  931. the keyword/value pairs as items.
  932.  
  933. In what follows, a “complete” (in the sense of showing all the possible
  934. keywords and the sort of values they take) description for each object
  935. type is given.
  936.  
  937.  
  938. Bounding boxes
  939. --------------
  940.  
  941. Almost any object can contain an item of the form BoundingBox 0 0 100 200;
  942. this overrides the bounding box mkdrawf would otherwise have given it. This
  943. is not usually a good thing to do, since mkdrawf calculates its bounding
  944. boxes very sensibly. Sprite and transformed sprite objects need a bounding
  945. box (see below); font table and options objects have no bounding boxes. You
  946. also can’t specify explicitly the bounding box of a text area object, because
  947. that is absolutely determined, with no room for disagreement, by its text
  948. columns.
  949.  
  950.  
  951. The Header pseudo-object
  952. ------------------------
  953.  
  954. There is one sort of object description that doesn’t actually describe
  955. a real object. Rather, it describes what goes into the header at the start
  956. of the drawfile. Here’s a “complete” Header object description.
  957.  
  958. Header {
  959.   Version 201 0
  960.   Creator "Aardvark"
  961.   BoundingBox 0 0  500 500
  962. }
  963.  
  964. The Version item takes two integers, the major and minor version numbers.
  965. Changes to the major number indicate incompatible changes in the file format,
  966. so you shouldn’t give a major number other than 201 unless you have also
  967. modified mkdrawf to make it produce the new format. The default is 201 0.
  968.  
  969. The Creator item takes a string, which must be at most 12 characters long.
  970. If it’s less than that, it will be padded with spaces. It’s usual to make
  971. it no more than 8 characters. The default is mkdrawf2 (this is the second
  972. version of the mkdrawf program; the first was much simpler and lacked
  973. variables, macros and things).
  974.  
  975. The BoundingBox item takes four numbers; their significance was explained
  976. two chapters ago. You don’t have to give this; generally mkdrawf does a
  977. good job of working out bounding boxes. You might want to change it for
  978. special effects, though, but you should be warned that applications are
  979. perfectly within their rights to misbehave horribly if given dishonest
  980. bounding boxes!
  981.  
  982.  
  983. The FontTable object
  984. --------------------
  985.  
  986. Here’s a complete FontTable object description.
  987.  
  988. FontTable {
  989.   1 "Trinity.Medium.Italic"
  990.   2 "Helvetica.Medium.Exploding.Strawberry"
  991.   3 "Corpus.Oblique"
  992. }
  993.  
  994. Font number 0 is always the bitmapped system font; you should not try to
  995. redefine it. Also, font numbers are only 1 byte long. In other words, the
  996. numbers you give must be integers between 1 and 255, inclusive.
  997.  
  998. Incidentally, I have lost my only copy of the
  999. Helvetica.Medium.Exploding.Strawberry font; if you know where I might
  1000. find another, please let me know.
  1001.  
  1002. If you don’t put a FontTable object in your drawfile description,
  1003. mkdrawf will construct one for you. However, if you do have a FontTable
  1004. it must contain all the fonts you use in Text and XfText objects.
  1005.  
  1006.  
  1007. The Text object
  1008. ---------------
  1009.  
  1010. Here’s a complete Text object description.
  1011.  
  1012. Text {
  1013.   Colour r0g0b0            # black
  1014.   Background r255g255b255  # white; remember this is just a hint
  1015.   Style 1                  # in other words, font number 1
  1016.   Size 10 12               # x-size 10 points, y-size 12 points
  1017.   StartAt 100 100          # start at (100,100)
  1018.   Text "This is a text"
  1019. }
  1020.  
  1021. If you find Style unpleasant in this context, let me know. It’s what the
  1022. description in the PRM uses. It might be relevant that the “style” here is
  1023. a 4-byte word; one byte is used for the font number, and the rest is
  1024. reserved. So perhaps one day it will mean something other than just “font”...
  1025.  
  1026. You can specify the placing of the text in another way besides StartAt: if
  1027. you replace it with an item CentreIn 100 100 500 300 (say), then the text
  1028. will be placed so that its bounding box has its centre at the centre of that
  1029. box. Alternatively you can give both StartAt point and HCentreIn box; this
  1030. computes the horizontal position from the box and the vertical position from
  1031. the StartAt. (This seems a bit wasteful, but the alternative syntaxes seem
  1032. worse. Comments?)
  1033.  
  1034. The Path object
  1035. ---------------
  1036.  
  1037. This one is rather complicated; glance at the description in the drawfile
  1038. summary earlier to see why! Anyway, here’s a complete Path object
  1039. description.
  1040.  
  1041. Path {
  1042.   FillColour None
  1043.   OutlineColour r0g0b255
  1044.   Width 1                  # in points. 0 means as thin as possible
  1045.   Style {
  1046.     Mitred                 # join style. Options: Mitred, Round, Bevelled
  1047.     EndCap Round           # Options: Butt, Round, Square, Triangular
  1048.     StartCap Triangular
  1049.     WindingRule NonZero    # determines how filling is done. Alternative: EvenOdd
  1050.     CapWidth 32            # for triangular caps only.
  1051.                            # 0..255, in 1/16ths of the line width
  1052.     CapLength 64           # ditto
  1053.     Dash {
  1054.       1 3 2 5 3            # if you have no idea what this means, experiment!
  1055.       Offset 2 }           # ditto
  1056.   }
  1057.   # Now the path itself
  1058.   Move 100 100
  1059.   Line 200 100
  1060.   Curve 250 100  200 300  400 400      # Bezier curve. Two control points, endpoint
  1061.   Close                    # this subpath
  1062.   Move 200 200
  1063.   Line 300 200
  1064.   Move 500 500             # this begins a new subpath too,
  1065.                            # even though no Close before it
  1066.   Line 0 0
  1067. }
  1068.  
  1069. If the Style item specifies a dash pattern, it must come before any path
  1070. elements. This is a consequence of the way in which the information is
  1071. arranged in the drawfile: the dash pattern, if present, comes before the
  1072. path elements, and it’s of variable size.
  1073.  
  1074. There are also “relative motion” keywords RMove, RLine and RCurve. These
  1075. are just like the R-less versions, except that the numbers they mention are
  1076. relative to the last point visited: thus they behave exactly like the
  1077. similarly-named PostScript operators.
  1078.  
  1079.  
  1080. The Sprite object
  1081. -----------------
  1082.  
  1083. I’m afraid the way you specify a sprite is pretty nasty; this is more or
  1084. less inevitable, but it’s possibly nastier than it ought to be. A sprite
  1085. object description contains a BoundingBox item (like that in the drawfile
  1086. header), and a load of numbers. I strongly advise you to specify the numbers
  1087. in hexadecimal; don’t forget that if you do this the 0x on the front is not
  1088. optional!
  1089.  
  1090. The bounding box is not optional. It specifies where the sprite is to be
  1091. placed, and how big it is to be.
  1092.  
  1093. The numbers are simply the words that will be placed into the file, in
  1094. order. See the PRMs for details of the sprite format.
  1095.  
  1096. Here’s an example.
  1097.  
  1098. Sprite {
  1099.   BoundingBox 100 100 200 200
  1100.   0x000002D4 0x745F6369 0x6C706D65 0x00006465
  1101.   several lines of hexadecimal rubbish deleted
  1102.   0x00000077
  1103. }
  1104.  
  1105. As of version 2.20, there is another way of specifying a sprite: the
  1106. BoundingBox item is still needed, but instead of the load of numbers
  1107. you write FromFile followed by two strings. The first should be the name of a
  1108. sprite file, and the second the name of a sprite in that file. The resulting
  1109. behaviour should be obvious. I recommend that you use the old method where
  1110. possible, because this keeps all the information necessary to recreate the
  1111. drawfile in one place.
  1112.  
  1113. The Group object
  1114. ----------------
  1115.  
  1116. Here’s a typical Group object description.
  1117.  
  1118. Group {
  1119.   Name "ThisIsAGroup"      # maximum 12 characters here
  1120.   Text {
  1121.     Size 10 10
  1122.     StartAt 100 100
  1123.     Style 2
  1124.     Text "Foo"
  1125.   }
  1126.   Group {                  # a group may contain another group
  1127.     Path {                 # All the path style options have sensible defaults
  1128.       Move 100 100
  1129.       Line 200 100
  1130.     }
  1131.     Path {
  1132.       FillColour r200g200b200
  1133.       Move 200 200
  1134.       Line 300 300
  1135.       Line 100 300
  1136.       Close
  1137.     }
  1138.   }                        # a group doesn't need to be given a name
  1139. }
  1140.  
  1141.  
  1142. The Tagged object
  1143. -----------------
  1144.  
  1145. A tagged object, remember, consists of a 4-byte tag identifier, an object,
  1146. and some other (optional, word-aligned) data. Here’s what it looks like:
  1147.  
  1148. Tagged {
  1149.   Identifier 0x12345678
  1150.   Text {
  1151.     blah blah blah
  1152.   }
  1153.   OtherData 0x9ABCDEF0
  1154.   OtherData 0x11111111
  1155.   OtherData 12345          # this is decimal 12345
  1156. }
  1157.  
  1158. Strictly speaking, you should register tag identifiers with Acorn. Unless
  1159. you’re planning to use them in a commercial product, there’s not much need
  1160. to bother, since they aren’t used much. Just pick a random number and hope
  1161. it doesn’t clash with anything.
  1162.  
  1163.  
  1164. The TextArea object
  1165. -------------------
  1166.  
  1167. Here’s a fairly complete text area object description. The only
  1168. incompleteness is in the fact that there should really be some control
  1169. sequences in the text.
  1170.  
  1171. TextArea {
  1172.   Column 100 400  200 500
  1173.   Column 220 400  320 500
  1174.   Colour r0g0b0
  1175.   Background r255g255b255
  1176.   Text {
  1177.     Really there should be some escape sequences at the start of this; too
  1178.     bad. This text will be formatted in the 2 columns specified at the
  1179.     start of the object description, or would be if the escape sequences
  1180.     were there.
  1181.   }
  1182. }
  1183.  
  1184. Note that the text is not quoted. The processing of text in a text area is
  1185. an exception to the way in which input is processed: it is just read
  1186. character by character, and terminated by the first line containing nothing
  1187. other than a closing brace and whitespace. The extra space at the starts of
  1188. lines in the example above isn’t a problem, because multiple whitespace
  1189. characters are treated as single spaces in text areas (unless there’s more
  1190. than one consecutive newline; see later).
  1191.  
  1192. This unusual processing has certain unfortunate consequences: you cannot get
  1193. anything into the text of a text area using macros or variables, and
  1194. comments don’t work. Also, anything following the open-brace token after
  1195. Text and on the same line is simply ignored.
  1196.  
  1197. All the columns must come before the text.
  1198.  
  1199. Silly implementation restriction (my fault, not Acorn’s): you may have
  1200. at most 16 columns. If you need more, it’s a trivial matter to change the
  1201. program to allow more.
  1202.  
  1203. Multiple spaces and tabs are treated as single spaces. A single newline is
  1204. treated as a single space (including absorbtion into multiple spaces);
  1205. extra newlines insert extra vertical space (for paragraphs). Newlines
  1206. occurring before any printing text are considered to be multiple newlines
  1207. for this purpose.
  1208.  
  1209. Here’s a list of escape sequences. Each starts with a backslash; the escape
  1210. sequences themselves are case-sensitive, but their arguments aren’t. Any
  1211. argument may be terminated with a /, and variable-length ones must be
  1212. (except that a newline will do instead). Dimensions should be given in
  1213. points.
  1214.  
  1215. \! <version number>    This must appear at the start of the text, and may
  1216.         not appear anywhere else. The version number must be
  1217.         1, and must be followed by / or a newline.
  1218. \A<code>    Determines alignment. <code> is L, R, C or D, indicating
  1219.         left, right, centred or double (i.e., L and R). Default is L.
  1220. \B<colour>    Set background colour hint for following text. <colour> might
  1221.         be 200 3 150; range is 0..255, at least one space is needed
  1222.         between successive numbers, and a / or newline is needed at
  1223.         the end.
  1224. \C<colour>    Set foreground colour for following text.
  1225. \D<number>    Indicates number of columns. This must be given, before any
  1226.         printing text, unless the number is 1.
  1227. \F<fontspec>    Defines a font reference number. Typical use:
  1228.           \F 1 Trinity.Medium 12
  1229.         means number 1 is Trinity Medium, 12 point. Font numbers
  1230.         are 1 or 2 digits, and are entirely separate from the
  1231.         numbers used for text objects. You may specify a font width
  1232.         as well: \F 1 <name> 12 10 means 12pt high, 10pt wide. Don’t
  1233.         forget the slash or newline. (This last goes for \C, \D, and
  1234.         most other escape sequences. I shall now stop mentioning it.)
  1235. \<number>    Means “now use font number ...”.
  1236. \L<leading>    Defines the leading; i.e., the vertical distance between
  1237.         baselines of successive lines of text. The default is 10pt;
  1238.         specify it in points.
  1239. \M<lt><spaces><rt>    Margin sizes; must be positive; default is 1 (point).
  1240. \P<leading>    Paragraph leading; i.e., the amount of extra space left from
  1241.         each newline after the first in any consecutive sequence.
  1242.         Default is 10pt.
  1243. \U<ulspec>    Switches on underlining. \U 10 2 means 10 units above (or
  1244.         is it below?) the baseline, 2 units thick. One unit is 1/256
  1245.         of the font size. Ranges -128..127, 0..255 respectively.
  1246.         Switch off either by giving a thickness of 0 or by using
  1247.         “\U.”.
  1248. \V[-]<digit>    Vertical move. In points.
  1249. \-        Allow a line break here, inserting a hyphen if one happens
  1250.         (and nothing otherwise).
  1251. \<newline>    Force a line break here.
  1252. \;        Everything from here to next newline is ignored.
  1253.  
  1254. Note:    there is no such thing as a TextColumn object descriptor. Text
  1255. column objects only occur inside text area objects, and are produced
  1256. automatically by mkdrawf.
  1257.  
  1258.  
  1259. The Options object
  1260. ------------------
  1261.  
  1262. Here’s an options object description illustrating just about everything.
  1263. Almost all of this is specific information for !Draw telling it how to
  1264. behave when it has the file loaded.
  1265.  
  1266. Options {
  1267.   PaperSize 4              # meaning: A4
  1268.   Limits {
  1269.     Shown                  # not sure what this does. Omit to negate
  1270.     Landscape              # Omit for portrait
  1271.     NonDefault             # not sure what this does. Omit to negate
  1272.   }
  1273.   Grid {
  1274.     Spacing 1.2345         # cm, unless "Inches" given; see below
  1275.     Divisions 5
  1276.     Isometric              # omit for rectangular
  1277.     AutoAdjust             # Omit to turn this off
  1278.     Shown                  # Omit if you don't want grid visible
  1279.     Lock                   # Omit if you don't want grid lock on
  1280.     Inches                 # Omit for centimetres
  1281.   }
  1282.   Zoom {
  1283.     Ratio 3 2              # means 3:2. Both numbers should be in range 1..8
  1284.     Lock                   # to powers of 2. !Draw seems to ignore it anyway
  1285.   }
  1286.   NoToolbox                # omit if you want toolbox shown when file loaded
  1287.   Mode Line                # initial entry mode. Possibilities are
  1288.                            # Line,ClosedLine,Curve,ClosedCurve,Rectangle,
  1289.                            # Ellipse,Text,Select.
  1290.   UndoSize 1234            # size of undo buffer, in bytes
  1291. }
  1292.  
  1293.  
  1294. The XfText object
  1295. -----------------
  1296.  
  1297. That is, transformed text. An XfText object description is just like a
  1298. Text object description, but it has up to three extra items. The most
  1299. important is one that looks like
  1300.   Matrix 0.5 1 2 -0.1  30 0
  1301. which means that the text should be transformed by the 2x2 matrix given as
  1302. the first 4 numbers, and then translated by the vector given as the last 2.
  1303. To be more precise, the transformation done is
  1304.   (x y)  |-->  (x y)  / 0.5    1  \   +  (30 0) .
  1305.                      |             |
  1306.                       \  2   -0.1 /
  1307.  
  1308. The other two items available are “flags”: Kerned and RightToLeft. You can
  1309. probably work out what they do. Incidentally, I think text in text objects
  1310. is never kerned, and text in text area objects is always kerned.
  1311.  
  1312. The position of the text in an XfText object may be specified using CentreIn,
  1313. but not using HCentreIn because that doesn’t make much sense.
  1314.  
  1315.  
  1316. The XfSprite object
  1317. -------------------
  1318.  
  1319. An XfSprite object is just like a sprite object except that it can (and
  1320. should) also contain a transformation matrix, exactly like those used for
  1321. XfText objects. The sprite itself can (as for sprite objects) be given
  1322. either directly or in terms of a sprite file and a sprite name.
  1323.  
  1324. The placing and size of a transformed sprite are not determined by the
  1325. bounding box, but by the transformation matrix and the contents of the
  1326. sprite itself. However, mkdrawf doesn’t understand sprites (it just treats
  1327. a sprite as a lump of data), so it can’t make any sort of attempt at
  1328. computing a bounding box. So give it one.
  1329.  
  1330. For the record, an identity matrix with zero translation puts the
  1331. sprite’s bottom-left corner at (0,0) and its top right corner at (w.ex,h.ey)
  1332. where w,h are the width and height of the sprite in pixels and ex,ey are
  1333. the “eigenfactors” for the mode in which the sprite was defined.
  1334.  
  1335.  
  1336. The JPEG object
  1337. ---------------
  1338.  
  1339. A JPEG object is in several ways rather like a transformed sprite object.
  1340. Here is a “complete” JPEG object description:
  1341. JPEG {
  1342.   BoundingBox 100 100 300 200   # this is needed
  1343.   Size 200 100                  # and so is this; I'm not sure why
  1344.   DPI 90 45                     # in x,y directions. Default is 90,90
  1345.   Matrix 2 0 0 1 100 0          # Default is identity, of course
  1346.   FromFile "a_jpeg"
  1347. }
  1348.  
  1349. You must specify the Size; I’m not sure exactly what it means and how it
  1350. relates to the BoundingBox; I don’t have anything capable of displaying
  1351. drawfiles containing JPEG objects, so your guess is as good as mine. Instead
  1352. of giving a filename, you can in principle include the contents of the
  1353. JPEG file in the object description (as with sprites and transformed sprites),
  1354. but JPEGs are usually big enough that you really don’t want to do this. If
  1355. you do do this, you need to provide an item like
  1356.   Length 12345
  1357. giving the exact length of the JPEG image in bytes; mkdrawf will not try to
  1358. guess from the number of integers you give, because the size of a JPEG image
  1359. need not be a whole number of words.
  1360.  
  1361. A reminder: no current version of !Draw understands JPEG image objects.
  1362.  
  1363.  
  1364. ----------------------------------------------------------------------------
  1365.  
  1366.  
  1367. Some sample drawfile descriptions
  1368. =================================
  1369.  
  1370. Here are some examples of what can be done with mkdrawf. Only the input
  1371. files are given below, for obvious reasons; the results are in the “Examples”
  1372. directory.
  1373.  
  1374.  
  1375. The Koch snowflake curve
  1376. ------------------------
  1377.  
  1378. The fractal everybody knows. Dead easy. This takes just under 10 seconds
  1379. on my machine, by the way.
  1380.  
  1381. # Snowflake curve
  1382.  
  1383. Set $r3/2 Over Sqrt 3 2
  1384.  
  1385. # Side { %x0 .. %y0 .. %x1 .. %y1 .. %n .. }
  1386. # this should be inserted into a Path
  1387. # The assumption is that we’re
  1388. # already "at" (x0,y0).
  1389. Define Side {
  1390.   IfLess %n 1
  1391.     Line %x1 %y1
  1392.   Else
  1393.     Set %dx Over Minus %x1 %x0 3
  1394.     Set %dy Over Minus %y1 %y0 3
  1395.     Set %xa Plus %x0 %dx         Set %ya Plus %y0 %dy
  1396.     Set %xb Minus %x1 %dx        Set %yb Minus %y1 %dy
  1397.     Set %xh Over Plus %x0 %x1 2  Set %yh Over Plus %y0 %y1 2
  1398.     Set %xt Plus %xh Times %dy $r3/2
  1399.     Set %yt Minus %yh Times %dx $r3/2
  1400.     Set %m Minus %n 1
  1401.     Side { %x0 %x0 %y0 %y0  %x1 %xa %y1 %ya  %n %m }
  1402.     Side { %x0 %xa %y0 %ya  %x1 %xt %y1 %yt  %n %m }
  1403.     Side { %x0 %xt %y0 %yt  %x1 %xb %y1 %yb  %n %m }
  1404.     Side { %x0 %xb %y0 %yb  %x1 %x1 %y1 %y1  %n %m }
  1405.   EndIf
  1406. }
  1407.  
  1408. Set $x0 100  Set $y0 100
  1409. Set $x1 400  Set $y1 100
  1410. Set $x2 250  Set $y2 Plus 100 Times 300 $r3/2
  1411.  
  1412. Path {
  1413.   Move $x0 $y0
  1414.   Side { %x0 $x0 %y0 $y0  %x1 $x1 %y1 $y1  %n 5 }
  1415.   Side { %x0 $x1 %y0 $y1  %x1 $x2 %y1 $y2  %n 5 }
  1416.   Side { %x0 $x2 %y0 $y2  %x1 $x0 %y1 $y0  %n 5 }
  1417.   Close      # not really needed unless you want to fill it
  1418. }
  1419.  
  1420.  
  1421. A Lissajous figure
  1422. ------------------
  1423.  
  1424. You might have produced things slightly like this at school by connecting
  1425. a couple of signal generators to an oscilloscope. (Except I bet it didn’t
  1426. do the pretty chequered pattern.) The drawfile this produces could certainly
  1427. be made smaller by using Bezier curves instead of straight lines, but it’s
  1428. not very big anyway. mkdrawf takes about 3.5 seconds to process this file on
  1429. my machine.
  1430.  
  1431. Set $Pi 3.141592653589793
  1432. Set $Factor Over $Pi 400
  1433. Path {
  1434.   Fillcolour r255g0b0
  1435.   Style { WindingRule EvenOdd }
  1436.   For $i 0 801 {
  1437.     Set $j Times $i $Factor
  1438.     Set $p Cos Times 9 $j
  1439.     Set $q Sin Times 13 $j
  1440.     IfEqual $i 0 Move Else Line EndIf
  1441.       Plus 400 Times $p 300
  1442.       Plus 400 Times $q 300
  1443.   }
  1444.   Close
  1445. }
  1446.  
  1447.  
  1448. A typical text area
  1449. -------------------
  1450.  
  1451. This drawfile contains nothing but a text area. I apologise for the inanity
  1452. of the text in it; this was typed in at random one evening while I was
  1453. testing an earlier version of the program, and I just wanted a certain
  1454. amount of text.
  1455.  
  1456. TextArea {
  1457.   Column 100 400 200 500
  1458.   Column 220 400 320 500
  1459.   Colour r0g0b0
  1460.   Text {
  1461.     \! 1
  1462.     \F 1 Trinity.Medium.Italic 12
  1463.     \F 2 Trinity.Medium 12
  1464.     \1
  1465.     \AD
  1466.     \D2
  1467.     \L12
  1468.     This is some text I'm putting in a text area.
  1469.     I have no idea how it will look, nor indeed whether
  1470.     it will work at all. For all I know \2 mkdrawf\1 will
  1471.     just choke utterly on it, or corrupt my file, or
  1472.     cause demons to fly out of the monitor.
  1473.  
  1474.     This should be a new paragraph; it will still be in italics.
  1475.     \2 Now we should be in roman type. (Isn't this fun, boys
  1476.     and girls?)
  1477.     
  1478.     Apparently the 1998 World Cup will be decided, in the event
  1479.     of a draw, by a sudden-death playoff instead of by a penalty
  1480.     shootout. How interesting.
  1481.   }
  1482. }
  1483.  
  1484.  
  1485. Circular arcs using Bezier curves
  1486. ---------------------------------
  1487.  
  1488. Here’s a useful macro you may want to use in your own mkdrawf code. It
  1489. produces (an approximation to) an arc of a circle using Bezier curves. I
  1490. don’t know whether the particular approximation it uses is the same as the
  1491. one used in !Draw, but it gives good results. This takes about 0.5 seconds
  1492. on my machine, by the way.
  1493.  
  1494. # %x0,%y0 is centre
  1495. # %r      is radius
  1496. # %a0,%a1 are starting and ending angles in radians
  1497. # %n      if set, indicates how many arcs to use
  1498. Define Arc {
  1499.   Set %da Minus %a1 %a0
  1500.   IfExists %n Else
  1501.     Set %n Floor Plus .99 Over %da .75
  1502.   EndIf
  1503.   Set %da Over %da %n
  1504.   Set %t Over Minus 1 Cos Over %da 2
  1505.               Times .75 Sin Over %da 2
  1506.   Move Plus %x0 Times %r Cos %a0
  1507.        Plus %y0 Times %r Sin %a0
  1508.   Set %aa %a0
  1509.   Set %cc Cos %aa
  1510.   Set %ss Sin %aa
  1511.   For %k 0 %n {
  1512.     Set %a %aa
  1513.     Set %aa Plus %a %da
  1514.     Set %c %cc        Set %s %ss
  1515.     Set %cc Cos %aa   Set %ss Sin %aa
  1516.     Curve Plus %x0 Times %r Minus %c Times %t %s
  1517.           Plus %y0 Times %r Plus %s Times %t %c
  1518.           Plus %x0 Times %r Plus %cc Times %t %ss
  1519.           Plus %y0 Times %r Minus %ss Times %t %cc
  1520.           Plus %x0 Times %r %cc
  1521.           Plus %y0 Times %r %ss
  1522.   }
  1523. }
  1524.  
  1525. Set $Pi 3.141592653589793
  1526.  
  1527. Path {
  1528.   Arc { %x0 300 %y0 300 %r 200 %a0 0 %a1 Times 2 $Pi %n 2 }
  1529.   # very inaccurate: only 2 arcs
  1530.   Close
  1531. }
  1532. Path {
  1533.   Arc { %x0 300 %y0 300 %r 200 %a0 0 %a1 Times 2 $Pi }
  1534.   # I think this does 9 arcs
  1535.   Close
  1536. }
  1537.  
  1538.  
  1539. A silly spiral
  1540. --------------
  1541.  
  1542. I first drew pictures like this on an old Hewlett-Packard desktop computer,
  1543. back in 1982 or so. I still think they rate quite highly for
  1544. prettiness-to-effort ratio. This is really an excuse for demonstrating
  1545. RLine. Oh, and it takes about 2.2s.
  1546.  
  1547. Set $2Pi 6.2831853071795864769
  1548. Set $Conv Over $2Pi 360
  1549.  
  1550. Define Spiral {
  1551.   Set %theta 0
  1552.   Set %r %dr
  1553.   For %i 0 %n {
  1554.     RLine Times %r Cos Times $Conv %theta
  1555.           Times %r Sin Times $Conv %theta
  1556.     Set %r Plus %r %dr
  1557.     Set %theta Plus %theta %dt
  1558.     IfLess 360 %theta
  1559.       Set %theta Minus %theta 360
  1560.     EndIf
  1561.   }
  1562. }
  1563.  
  1564. Path {
  1565.   Outlinecolour r0g0b0  Width 0
  1566.   Move 250 250
  1567.   Spiral { %dr .5 %dt 65 %n 500 }
  1568. }
  1569.  
  1570.  
  1571. ----------------------------------------------------------------------------
  1572.  
  1573.  
  1574. Tagfiles
  1575. ========
  1576.  
  1577. NOTE: This describes an optional feature of mkdrawf, which is not included in
  1578. the ready-compiled version of mkdrawf distributed with this manual. You’ll
  1579. have to recompile if you want to use it. This is because I expect most people
  1580. not to need it — it was added because one particular user asked for it. If
  1581. you don’t use it, why should it take up space in your executable? To make a
  1582. version of mkdrawf with tagfiles enabled, compile mkdrawf.c with the
  1583. preprocessor symbol TAGS defined.
  1584.  
  1585. Suppose you have a mkdrawf “script” which gets used repeatedly, but with
  1586. slight changes made to some of the strings. (If you don’t, you don’t need
  1587. tagfiles.) You could go through and change the file every time, but that
  1588. would be tedious. You could have the strings put into variables by an
  1589. Included file, and use different files on different occasions, but that would
  1590. be a waste of variables. The tagfile feature provides an alternative.
  1591.  
  1592. A tagfile consists of a number of lines, each containing a tag and an associated value. There is a mkdrawf operator which takes a string, looks for a
  1593. matching tag and replaces it with the corresponding value. There are also
  1594. mkdrawf “specials” for opning and closing tagfiles. This is getting terribly
  1595. abstract: here’s a concrete example.
  1596.  
  1597. A tagfile:
  1598.   One:un
  1599.   Two:deux
  1600.   # This is a comment; it will be ignored.
  1601.   Saturday:samedi # ceci n'est pas une remarque
  1602.   ThoughtPolice:Academie Francaise
  1603.  
  1604. A mkdrawf file:
  1605.   TagOpen "tagfile"
  1606.   ...
  1607.   Text { ...
  1608.     Text Append 3 "The " TagLookup "ThoughtPolice:FBI" " will get you!"
  1609.   }
  1610.   ...
  1611.   TagClose
  1612.  
  1613. This will behave exactly as if you’d had instead a line saying
  1614.   Text "The Academie Francaise will get you!".
  1615. If your tagfile contained a line
  1616.   ThoughtPolice:Child Support Agency
  1617. instead of the one above, then the effect would be as if the Text item was
  1618.   Text "The Child Support Agency will get you!".
  1619. If it didn’t contain any ThoughtPolice line at all, you’d get
  1620.   Text "The FBI will get you!".
  1621. You are allowed to miss off the default (“:FBI” above) in a TagLookup; if the
  1622. tag is not found you will get an error message and the expansion of the
  1623. TagLookup will be the empty string.
  1624.  
  1625. You may only have one tagfile “open” at a time. (In fact it is only really
  1626. open while the TagOpen is doing its work; its contents are read into memory,
  1627. and TagClose means “free the memory used for tagfile data”.) Its lines are,
  1628. in effect, searched in order when looking for a tag. 
  1629.  
  1630. The similarity between tagfiles and RISC OS message files is deliberate.
  1631. However, tagfiles don’t provide any of the fancy wildcarding features
  1632. provided by MessageTrans. They may do in the future.
  1633.  
  1634. If you put “-t foo” on the mkdrawf command line, the effect will be as if the
  1635. very first line of the file had been TagOpen "foo". This can be useful if you
  1636. want to run something with several different tagfiles without changing the
  1637. mkdrawf file itself; for instance, in makefiles.
  1638.  
  1639.  
  1640. ----------------------------------------------------------------------------
  1641.  
  1642.  
  1643. Technical issues
  1644. ================
  1645.  
  1646. If you’re interested in mkdrawf, you’re quite likely to be interested in
  1647. its internals. (Wimps use !Draw. Real Men use mkdrawf. Or something.) So
  1648. here is some information about how it works, with particular emphasis on
  1649. things that need improving. (After all, *you* might be able to make it
  1650. better...)
  1651.  
  1652.  
  1653. Memory management
  1654. -----------------
  1655.  
  1656. Oh dear.
  1657.  
  1658. This is a real mess, basically because it’s seldom trivial to know when
  1659. a piece of memory is finished with and can be thrown away. Every time a
  1660. string is created, a new block of memory is malloced; these blocks are
  1661. never freed. (Once upon a time this was true for numbers as well!) There
  1662. are some places in the program where we could free things, but there are
  1663. so many memory leaks that it is probably more sensible to wait until I
  1664. have the time and energy, and fix it all properly.
  1665.  
  1666. The real problem is that there is no guarantee that any particular token
  1667. will not get included in a token list. If that happens, we can’t afford
  1668. to throw it away. So we can’t, for instance, always free the memory used
  1669. by an old variable value. One solution to this problem would be to make
  1670. sure that we always copy tokens when we use them, but this would be terribly
  1671. time-inefficient. The best solution is probably to implement a
  1672. garbage-collector. Hmmm.
  1673.  
  1674. Fortunately, most drawfiles are quite small; and the amount of memory that
  1675. gets wasted at any one time is also small. There’s only likely to be a
  1676. practical problem here if you do complicated recursive things. At the
  1677. moment, that snowflake curve program needs about 500k (the mkdrawf program
  1678. itself being 48k), which I feel is rather excessive. I’ll work on it.
  1679.  
  1680.  
  1681. Variables
  1682. ---------
  1683.  
  1684. ... are stored in hash tables. There is a fairly big global hash table for
  1685. the entire program, and a rather smaller local hash table for each macro
  1686. invocation. Out of sheer cheapskate-ness, I haven’t made mkdrawf check for
  1687. the tables overflowing; if this happens, the next attempt to reference
  1688. something not in the table will loop for ever.
  1689.  
  1690. The hash scheme used is a very simple-minded linear hash; it’s not worth
  1691. doing anything more complicated, since in most cases the tables will never
  1692. get anything like full.
  1693.  
  1694. There are actually two different sorts of local variable token: resolved
  1695. and unresolved. A resolved token contains an integer giving the location
  1696. in the hash table of the variable; an unresolved one contains (a pointer to)
  1697. a string naming the variable. Of course resolved local variables can be
  1698. looked up much faster, but (1) this can only be done when it’s known (when
  1699. the token is created) what macro the variable is local to, and (2) resolving
  1700. a variable establishes a place in the macro’s hash table for it, for all
  1701. time; this can cause a performance hit, and also reduces the amount of room
  1702. for other local variables. I am by no means certain that I have actually
  1703. written the code for all this correctly, by the way.
  1704.  
  1705.  
  1706. Problems
  1707. --------
  1708.  
  1709. This is quite a complicated program, and I’m not a very reliable programmer.
  1710. There are bound to be a few bugs left, though I think I’d have spotted
  1711. anything really big. Fortunately, I am both a fast bug-fixer and a helpful
  1712. person; so if you spot any bugs and let me know, I can probably let you have
  1713. a fixed version of mkdrawf pretty quickly.
  1714.  
  1715. Similar remarks apply if you have features to suggest. Of course I don’t
  1716. guarantee to implement every (or any!) feature that is suggested to me, but
  1717. I am always open to suggestions.
  1718.  
  1719.  
  1720. Arbitrary restrictions
  1721. ----------------------
  1722.  
  1723. The following aren’t bugs, but do represent limitations of which you should
  1724. be aware. I don’t guarantee robustness in the event of your violating
  1725. these...
  1726.  
  1727.   • Token lists cannot be nested more than 256 deep. This mainly affects
  1728.     macros.
  1729.   • In any case, macros cannot be nested more than 256 deep. Nor (but
  1730.     independently) can Fors or Ifs.
  1731.   • An instance of a macro must not have more than 61 local variables
  1732.     (including parameters). Violating this one may cause mkdrawf to crash.
  1733.   • There must not be more than 677 global things-with-names. That means
  1734.      • keywords and specials;
  1735.      • global variables;
  1736.      • macros.
  1737.     This is another one that can crash mkdrawf, but it’s not likely to be
  1738.     a problem.
  1739.   • A text area may not have more than 16 columns.
  1740.   • The drawfile produced by mkdrawf must be at most 4 megabytes long.
  1741.   • A macro may not use more than 9 positional parameters.
  1742.   • Include files cannot be nested more than 17 deep.
  1743.  
  1744.  
  1745. ----------------------------------------------------------------------------
  1746.  
  1747.  
  1748. Differences from the previous version of mkdrawf
  1749. ================================================
  1750.  
  1751. An earlier version of this program was distributed to a small number of
  1752. people. I have no idea whether it spread any further. The version described
  1753. in this manual is very considerably superior, and if you have been using
  1754. the old version you should change to the new one.
  1755.  
  1756. Unfortunately the two programs are not entirely compatible. They are
  1757. deliberately very similar, but there have had to be a few incompatible
  1758. changes. I think I’ve described them all in this chapter.
  1759.  
  1760. Changes since the transition to version 2 of mkdrawf are documented later,
  1761. in the section entitled “Revision history”.
  1762.  
  1763.  
  1764. Points don’t have commas
  1765. ------------------------
  1766.  
  1767. In the older version, points were entered as (for instance) 200,100. In
  1768. this version the comma is replaced by whitespace. This change was made to
  1769. make it possible for points to be computed using arithmetic and similar
  1770. operations; in the older version of mkdrawf a point was a single token, but
  1771. now each coordinate can be produced separately.
  1772.  
  1773. The same applies to transformation matrices and things, of course.
  1774.  
  1775. As I’ve already mentioned, a similar change may befall colours in a later
  1776. version of mkdrawf.
  1777.  
  1778.  
  1779. Strings have quotation marks
  1780. ----------------------------
  1781.  
  1782. In the older version, a text item might have contained a line like
  1783.   Text This` is` a` zog
  1784. where the backquotes indicated that the spaces following them were to be
  1785. part of the string. On reflection, I decided that this was a dreadful idea,
  1786. especially as I didn’t want to have to make the textual form of each token
  1787. part of the token. (Suppose you wanted a text item whose text was “$foo” or
  1788. something.) So now that would be replaced by
  1789.   Text "This is a zog"
  1790. which, to my mind, is cleaner.
  1791.  
  1792. The same difference affects other strings, such as group names and font names.
  1793.  
  1794.  
  1795. No implicit hexadecimal
  1796. -----------------------
  1797.  
  1798. In the older version, the OtherData in a tagged object were assumed to be given
  1799. in hexadecimal. Now if you want hex you must explicitly mark it as such with 0x.
  1800.  
  1801.  
  1802. ----------------------------------------------------------------------------
  1803.  
  1804.  
  1805. Revision history
  1806. ================
  1807.  
  1808. mkdrawf has been changed a number of times, and will doubtless change more
  1809. in the future. In case you’re curious about what has happened to it (or
  1810. want to see what’s changed since the last version you saw), here is a
  1811. brief account of the changes introduced with each new version. Not all
  1812. of these versions actually correspond to public releases of mkdrawf.
  1813.  
  1814. 2.00    First “new” version of mkdrawf; many incompatible changes in
  1815.     input format; programming features added; manual written.
  1816. 2.10    Sprites and transformed sprites added.
  1817. 2.20    Sprites and transformed sprites can be loaded from sprite files;
  1818.     Include feature; much improved error handling; several minor code
  1819.     changes.
  1820. 2.30    Bounding boxes of paths computed using Draw_ProcessPath instead of
  1821.     by computing bbox of points on path; optional tagfile features;
  1822.     Append, GSTrans features; almost all objects can have explicit
  1823.     BoundingBoxes; numerous bugfixes; code made rather cleaner;
  1824.     decdrawf -s and -v.
  1825. 2.34    Font, Str2Num, Num2Str, HCentreIn, CentreIn, Random features; implicit
  1826.     font tables; colours as triples of integers; JPEG objects; several
  1827.     minor bugfixes and code changes; tutorial written; !Drawf written,
  1828.     and some minor changes made to mkdrawf to support it.
  1829.  
  1830. ----------------------------------------------------------------------------
  1831.  
  1832.  
  1833. Decoding drawfiles
  1834. ==================
  1835.  
  1836. With mkdrawf comes another program, called decdrawf, which turns drawfiles
  1837. into descriptions of the sort understood by mkdrawf. This is useful if
  1838. you’ve lost the mkdrawf source code for a drawfile, or if you want to sketch
  1839. something roughly and then tweak it so that all the points are in just the
  1840. right places.
  1841.  
  1842.  
  1843. Using decdrawf
  1844. --------------
  1845.  
  1846. ... is trivial, even easier than using mkdrawf. Just type, say,
  1847.   decdrawf foo
  1848. to get the contents of the drawfile named foo displayed to the screen.
  1849. If you want the output sent to a file, type
  1850.   decdrawf foo > bar
  1851. and the output will be put in a file called bar.
  1852.  
  1853. As with mkdrawf, you can say
  1854.   decdrawf -v
  1855. to get a version number (which will keep in step with the version number of
  1856. mkdrawf, even though one program may change without any change in the other).
  1857. More importantly, you can also request that decdrawf put sprites in a separate
  1858. sprite file rather than “inline” in hexadecimal, by putting -s <filename>
  1859. on the command line. If there are no sprites in the drawfile, the sprite file
  1860. will not be created.
  1861.  
  1862. Warning: A drawfile may contain several copies of one sprite, or (worse)
  1863. several different sprites with the same name. decdrawf will not output
  1864. multiple copies of duplicated sprites to a sprite file; where different
  1865. sprites have the same name, decdrawf will write them all to the sprite file
  1866. as they occur, but will emit warning messages indicating that this is
  1867. happening.
  1868.  
  1869.  
  1870. The output from decdrawf
  1871. ------------------------
  1872.  
  1873. is a file suitable for feeding into mkdrawf. It doesn’t use any macros,
  1874. variables etc, of course. Here and there in the output are comments, which
  1875. are intended to make clearer the correspondence between the data in the
  1876. drawfile and its textual description, or (in, for instance, the case of the
  1877. Options object) to remind you what alterations you could make.
  1878.  
  1879. If you give the -s <filename> option to decdrawf, you will (if there actually
  1880. are any sprites in the drawfile) get two output files. If you change the
  1881. name of the sprite file, you will need to change the relevant FromFiles
  1882. before feeding the result back to mkdrawf. Also, when you use -s you are
  1883. not actually guaranteed that feeding the output into mkdrawf will produce
  1884. the right results; see the warning above.
  1885.  
  1886. If there are JPEG image objects in a drawfile fed to decdrawf it will by
  1887. default include them (in hexadecimal) in the decoded drawfile. This is
  1888. inefficient, and JPEG images are usually rather large; so, instead, put
  1889. -j <prefix> on the command line; this will make decdrawf put JPEG images in
  1890. separate files named prefix01 and so on. decdrawf makes no attempt to avoid
  1891. owerwriting existing files; one consequence of this is that you should be
  1892. careful of truncation problems if a drawfile contains several JPEG images.
  1893.  
  1894. As with mkdrawf, you can get decdrawf not to tell you the filename it’s
  1895. working on in warnings and errors by giving it the option -e.