1# Pikchr User Manual 2 3# Introduction 4 5This is a guide to generating diagrams using Pikchr 6(pronounced "Picture"). This guide is 7designed to teach you to use Pikchr. It is not a reference for the 8Pikchr language (that is a [separate document][gram]) nor is it an explanation 9of why you might want to use Pikchr. The goal here is to provide 10a practical and accessible tutorial on using Pikchr. 11 12[gram]: ./grammar.md 13 14# Running Pikchr Scripts <a id="running"></a> 15 16The design goal of Pikchr is to enable embedded line diagrams in Markdown or other 17simple markup languages. The details on how to embedded Pikchr in Markdown is 18[covered separately][embed]. For the purpose of this tutorial, we will only write 19pure Pikchr scripts without the surrounding markup. To experiment 20with Pikchr, visit the [](/pikchrshow) page on the website hosting 21this document (preferably in a separate window). Type in the following 22script and press the Preview button: 23<a id="firstdemo"></a> 24 25~~~~~ pikchr source toggle indent 26 line; box "Hello," "World!"; arrow 27~~~~~ 28 29If you do this right, the output should appear as: 30 31~~~~~ pikchr toggle indent 32 line; box "Hello," "World!"; arrow 33~~~~~ 34 35So there you go: you've created and rendered your first diagram using 36Pikchr! You will do well to keep that /pikchrshow screen handy, in a 37separate browser window, so that you can try out scripts as you proceed 38through this tutorial. 39 40[embed]: ./usepikchr.md 41 42# Viewing Pikchr Script Source Code For This Document <a name="viewsrc"></a> 43 44For this particular document, you can click on any of the diagrams 45rendered by Pikchr and the display will convert to showing you the 46original Pikchr source text. Click again to go back to seeing the 47rendered diagram. 48 49The click-to-change-view behavior is a property of this one 50particular document and is not a general capability of Pikchr. On 51other documents containing Pikchr diagrams that are generated using Fossil 52you can use ctrl-click (alt-click on Macs) to toggle the view. 53That is, click on the diagram while holding down the Ctrl key or the Alt key. 54This is not possible if 55you are on a tablet or phone, since you don't have a Ctrl or Alt key to hold 56down there. Other systems might not implement the view-swapping behavior 57at all. This is a platform-depending feature that is one layer above 58Pikchr itself. 59 60# About Pikchr Scripts <a id="about"></a> 61 62Pikchr is designed to be simple. A Pikchr script is 63just a sequence of Pikchr statements, separated by either new-lines or 64semicolons. The "Hello, world!" example above used three statements, 65a "line", a "box", and an "arrow", each separated by semicolons. 66 67Whitespace (other than newlines) and comments are ignored. Comments in 68pikchr can be in the style of TCL, C, or C++. That is to say, comments 69consist of a "`#`" or "`//`" and include all characters up to but 70not including the next new-line, or all text 71in between "`/*`" and the first following "`*/`". 72The example script above could be rewritten with each statement on 73a separate line, and with comments describing what each statement is 74doing: 75 76~~~~~ pikchr source toggle indent 77 # The first component of the drawing is a line 78 line 79 // The second component is a box with text "Hello, World!" 80 box "Hello," "World!" 81 /* Finally an arrow */ 82 arrow 83~~~~~ 84 85Remember that new-lines separate statements. If you have a long statement 86that needs to be split into multiple lines, escape the newline with 87a backslash character and the new-line will be treated as any other space: 88 89~~~~~ pikchr source toggle indent 90 line 91 box \ 92 "Hello," \ 93 "World!" 94 arrow 95~~~~~ 96 97So, a Pikchr script is just a list of statements, but what is a statement? 98 99# Pikchr Statements <a id="statements"></a> 100 101*Most* statements are descriptions of a single graphic object that 102becomes part of the diagram. The first token of the statement is the 103object class-name. The following classes are currently supported: 104 105~~~~~ pikchr toggle indent 106box "box" 107circle "circle" at 1 right of previous 108ellipse "ellipse" at 1 right of previous 109oval "oval" at .8 below first box 110cylinder "cylinder" at 1 right of previous 111file "file" at 1 right of previous 112line "line" above from .8 below last oval.w 113arrow "arrow" above from 1 right of previous 114spline from previous+(1.8cm,-.2cm) \ 115 go right .15 then .3 heading 30 then .5 heading 160 then .4 heading 20 \ 116 then right .15 117"spline" at 3rd vertex of previous 118dot at .6 below last line 119text "dot" with .s at .2cm above previous.n 120arc from 1 right of previous dot 121text "arc" at (previous.start, previous.end) 122text "text" at 1.3 right of start of previous arc 123~~~~~ 124 125A statement can be only the class-name and nothing else, but the class-name 126is usually followed by one or more "attributes". Attributes are used 127to modify the appearance of the object, or to position the object relative 128to prior objects. 129 130So to revisit the ["Hello, World" demonstration script above](#firstdemo), 131we see that that script contains three object descriptions: 132 133 1. A "line" object with no attributes (meaning that the line is shown 134 with no changes to its default appearance). 135 2. A "box" object with two string literal attributes. The string 136 literal attributes cause the corresponding strings to be drawn 137 inside the box. 138 3. An "arrow" object with no attributes. 139 140# Layout <a id="layout"></a> 141 142By default, objects are stacked beside each other from left to right. 143The Pikchr layout engine keeps track of the "layout direction", which 144can be one of "right", "down", "left", or "up". The layout direction 145defaults to "right", but you can change it using a statement which 146consists of just the name of the new direction. So, 147if we insert the "down" statement in front of our test script, like 148this: 149 150~~~~~ pikchr source toggle indent 151 down 152 line 153 box "Hello," "World!" 154 arrow 155~~~~~ 156 157Then the objects are stacked moving downward: 158 159~~~~~ pikchr toggle indent 160 down 161 line 162 box "Hello," "World!" 163 arrow 164~~~~~ 165 166Or, you can change the layout direction to "left": 167 168~~~~~ pikchr toggle indent 169 left 170 line 171 box "Hello," "World!" 172 arrow 173~~~~~ 174 175Or to "up": 176 177~~~~~ pikchr toggle indent 178 up 179 line 180 box "Hello," "World!" 181 arrow 182~~~~~ 183 184It is common to stack line objects (lines, arrows, splines) against 185block objects (boxes, circles, ovals, etc.), but this is not required. 186You can stack a bunch of block objects together. 187For example: 188 189~~~~~ pikchr source toggle indent 190 box; circle; cylinder 191~~~~~ 192 193Yields: 194 195~~~~~ pikchr toggle indent 196 box; circle; cylinder 197~~~~~ 198 199More often, you want to put space in between the block objects. 200The special "move" object exists for that purpose. Consider: 201 202~~~~~ pikchr source toggle indent 203 box; move; circle; move; cylinder 204~~~~~ 205 206This script creates the same three block objects but with 207whitespace in between them: 208 209~~~~~ pikchr toggle indent 210 box; move; circle; move; cylinder 211~~~~~ 212 213Implementation note: A "move" is really just an invisible "line". So 214the following script generates the same output as the previous. 215([Try it!](/pikchrshow?content=box;line%20invisible;circle;line%20invisible;cylinder)) 216 217~~~~~ pikchr source toggle indent 218 box; line invisible; circle; line invisible; cylinder 219~~~~~ 220 221# Controlling Layout Using Attributes <a id="attributes"></a> 222 223The automatic stacking of objects is convenient in many cases, but 224most diagrams will want some objects placed somewhere other than 225immediately adjacent to their predecessor. For that reason, layout 226attributes are provided that allow precise placement of objects. 227 228To see how this works, consider the previous example of a box, circle, 229and cylinder separated by some space. Suppose we want to draw an arrow 230that goes downward out of the box, then right, then up into the 231cylinder. The complete script might look something like this: 232 233~~~~~ pikchr source toggle indent 234 box; move; circle; move; cylinder 235 arrow from first box.s \ 236 down 1cm \ 237 then right until even with first cylinder \ 238 then to first cylinder.s 239~~~~~ 240 241This script results in the following diagram: 242 243 244~~~~~ pikchr toggle indent 245 box; move; circle; move; cylinder 246 arrow from first box.s \ 247 down 1cm \ 248 then right until even with first cylinder \ 249 then to first cylinder.s 250~~~~~ 251 252That is indeed the image we want, but there are a lot of words on 253that "arrow" statement! Don't panic, though. It's actually pretty 254simple. We'll take it apart and explain it piece by piece. 255 256First note that the "arrow" statement is broken up into four separate 257lines of text, with a "`\`" at the end of the first three lines to 258prevent the subsequent new-line from prematurely closing the statement. 259Splitting up the arrow into separate lines this way is purely for 260human readability. If you are more comfortable putting the whole 261statement on one line, that is fine too. Pikchr doesn't care. Just 262be sure to remember the backslashes if you do split lines! 263 264The attributes on the "arrow" statement describe the path taken by 265the arrow. The first attribute is "`from first box.s`". This "from" 266attribute specifies where the arrow starts. In this case, it starts 267at the "s" (or "south") anchor point of the "first box". The "first box" 268part is probably self explanatory. (You can also write it as 269"1st box" instead of "first box", and in fact legacy-PIC requires 270the use of "1st" instead of "first".) But what is the ".s" part? 271 272Every block object has eight anchor points on its perimeter that are named 273for compass points, like this: 274 275~~~~~ pikchr toggle indent 276A: box 277dot color red at A.nw ".nw " rjust above 278dot same at A.w ".w " rjust 279dot same at A.sw ".sw " rjust below 280dot same at A.s ".s" below 281dot same at A.se " .se" ljust below 282dot same at A.e " .e" ljust 283dot same at A.ne " .ne" ljust above 284dot same at A.n ".n" above 285dot same at A.c " .c" ljust 286A: circle at 1.5 right of A 287dot color red at A.nw ".nw " rjust above 288dot same at A.w ".w " rjust 289dot same at A.sw ".sw " rjust below 290dot same at A.s ".s" below 291dot same at A.se " .se" ljust below 292dot same at A.e " .e" ljust 293dot same at A.ne " .ne" ljust above 294dot same at A.n ".n" above 295dot same at A.c " .c" ljust 296A: cylinder at 1.5 right of A 297dot color red at A.nw ".nw " rjust above 298dot same at A.w ".w " rjust 299dot same at A.sw ".sw " rjust below 300dot same at A.s ".s" below 301dot same at A.se " .se" ljust below 302dot same at A.e " .e" ljust 303dot same at A.ne " .ne" ljust above 304dot same at A.n ".n" above 305dot same at A.c " .c" ljust 306~~~~~ 307 308As you can see, there is also a ninth point in the middle called ".c". 309Every block object has these anchor points; you can refer to them 310when positioning the object itself, or when positioning other objects 311relative to the block object. In this case, we are starting the 312arrow at the ".s" anchor of the box. 313 314The next phrase on the "arrow" statement is "`down 1cm`". As you 315might guess, this phrase causes the arrow to move downward from its 316previous position (its starting point) by 1 centimeter. This phrase 317highlights a key enhancement of Pikchr over PIC, which did 318everything in inches only. No units were allowed. Pikchr allows 319you to attach units to measurements, as in this case where it is 320"1cm". Internally, Pikchr still keeps track of everything in inches 321for compatibility with PIC, so the "1cm" token is really just an 322alternative spelling for the numeric constant "0.39370078740157480316", 323which is the inch-equivalent of 1 centimeter. Surely you agree that 324"1cm" is much easier to read and write! Other units recognized by Pikchr 325are "px" for pixels, "pt" for points, "pc" for picas, "mm" for millimeters, 326and of course "in" for inches. Inches are assumed if no units are 327specified. 328 329Back to our arrow: we have now established a path for the arrow 330down 1 centimeter from the ".s" anchor of the box. The next phrase 331is: "`then right until even with first cylinder`". 332You can perhaps guess that this means that the arrow should continue 333to the right until it is lined up below the first cylinder. You, 334the diagram designer, don't know (and don't really want to know) 335how far apart the box and the cylinder are, so you can't tell it 336exactly how far to go. This phrase is a convenient way of telling 337Pikchr to "make the line long enough". 338 339Note that the "`first cylinder`" part of the "until even with" 340phrase is actually an abbreviation for "`first cylinder.c`" - the 341center of the cylinder. This is what we want. You could also 342write "`first cylinder.s`" if you want. 343 344The "until even with" phrase is not found in the original version of PIC. In that 345system, you would have to do some extra math to figure out the 346distance for yourself, something like 347"`then right (1st cylinder.s.x - 1st box.s.x)`". We think the 348"until even with" phrase is easier to use and understand. 349 350The final phrase in the "arrow" statement is 351"`then to first cylinder.s`". This phrase tells the arrow to go 352from wherever it is at the moment directly to the ".s" anchor 353of the cylinder. 354 355# The Advantage Of Relative Layout <a id="relative"></a> 356 357Notice that our sample diagram contains no coordinates and only 358one hard-coded distance, the "down 1cm" bit in the "arrow" statement. The script 359is written in such a way that the script-writer does not have 360to do a lot of distance calculation. The layout compensates 361automatically. 362 363For example, suppose you come back to this script later and 364decide you need to insert an ellipse in between the circle and 365the cylinder. This is easily accomplished: 366 367~~~~~ pikchr source toggle indent 368 box; move; circle; move; ellipse; move; cylinder 369 arrow from first box.s \ 370 down 1cm \ 371 then right until even with first cylinder \ 372 then to first cylinder.s 373~~~~~ 374 375We simply add the ellipse (and an extra "move") on the first line. 376Even though the coordinate positions of the objects have adjusted, 377the description of the arrow that connects the box to the 378cylinder is not based on coordinates or absolute distances, 379so it does not have to change at all. Pikchr 380compensates automatically: 381 382~~~~~ pikchr toggle indent 383 box; move; circle; move; ellipse; move; cylinder 384 arrow from first box.s \ 385 down 1cm \ 386 then right until even with first cylinder \ 387 then to first cylinder.s 388~~~~~ 389 390Both PIC and Pikchr allow you to specify hard-coded coordinates 391and distances when laying out your diagram, but you are encouraged 392to avoid that approach. Instead, place each new object you create 393relative to the position of prior objects. 394Pikchr provides many mechanisms for specifying the location 395of each object in terms of the locations of its predecessors. With 396a little study of the syntax options available to you (and discussed 397further below) you will be generating complex diagrams using Pikchr 398in no time. 399 400# Single-Pass Design <a id="single-pass"></a> 401 402Both Pikchr and PIC operate on a single-pass design. Objects 403can refer to other objects that occur before them in the script, but not 404to objects that occur later in the script. Any computations that go 405into placing an object occur as the object definition is parsed. As soon 406as the newline or semicolon that terminates the object definition is 407reached, the size, location, and characteristics of the object are 408fixed and cannot subsequently be altered. (One exception: sub-objects that 409are part of a `[]`-container (discussed later) are placed relative to the 410origin of the container. Their shape and locations relative to each 411other are fixed, but their final absolute position is not fixed until 412the `[]`-container itself is fixed.) 413 414The single-pass approach contributes to the conceptual simplicity of 415Pikchr (and PIC). There is no "solver" that has to work through 416forward and backward layout constraints to find a solution. This 417simplicity of design helps to keep Pikchr scripts easy to write and 418easy to understand. 419 420# Labeling Objects <a id="labeling"></a> 421 422The previous example used the phrases like "`first box`" and "`first cylinder`" 423to refer to particular objects. There are many variations on this naming 424scheme: 425 426 * "`previous`" ← the previous object regardless of its class 427 * "`last circle`" ← the most recently created circle object 428 * "`3rd last oval`" ← the antipenultimate oval object 429 * "`17th ellipse`" ← the seventeenth ellipse object 430 * ... and so forth 431 432These relative and ordinal references work, but they can be fragile. 433If you go back later and insert a new 434object in the stream, you can mess up the counting. Or, for that matter, 435you might just miscount. 436 437In a complex diagram, it often works better to assign symbolic names to 438objects, which we call “labels” in Pikchr. A label begins with a capital 439letter followed by some number of regular ASCII letters, digits or 440underscores, followed by a colon. This must come immediately before 441an object, without an intervening newline. 442Afterwards, the object can be referred to 443by that label. 444 445Consider how this simplifies our previous example: 446 447~~~~~ pikchr source toggle indent 448 B1: box; move; 449 circle; move; 450 ellipse; move; 451 C1: cylinder 452 arrow from B1.s \ 453 down 1cm \ 454 then right until even with C1 \ 455 then to C1.s 456~~~~~ 457 458By giving symbolic names to the box (B1) and cylinder (C1), the arrow path 459description is simplified. Furthermore, if the ellipse gets changed 460into another cylinder, the arrow still refers to the correct cylinder. 461 462The indentation of the lines following each symbolic name 463above is syntactically unimportant: it serves only to improve human 464readability. Nevertheless, this is typical coding style for Pikchr 465and PIC before it. 466 467# Layout Of Block Objects <a id="block-objects"></a> 468 469For lines (and arrows and splines), you have to specify a path that the line 470follows, a path that might involve multiple bends and turns. Defining the location 471of block objects is easier: you just provide a single location to place 472the object. Ideally, you should place the object relative to some other 473object, of course. 474 475Let's say you have box, and you want to position a circle 2 centimeters to the 476right of that box. You simply use an "`at`" attribute on the circle to tell it 477to position itself 2 cm to the right of the box: 478 479~~~~~ pikchr source toggle indent 480 B1: box 481 circle at 2cm right of B1 482~~~~~ 483 484The resulting diagram is: 485 486~~~~~ pikchr toggle indent 487 B1: box 488 circle at 2cm right of B1 489 490 X1: line thin color gray down 50% from 2mm south of B1.s 491 X2: line same from (last circle.s,X1.start) 492 arrow <-> thin from 3/4<X1.start,X1.end> right until even with X2 \ 493 "2cm" above color gray 494 assert( last arrow.width == 2cm ) 495~~~~~ 496 497(We’ve added gray dimension lines purely for illustration. Click the 498diagram [per the instructions above](#viewsrc) to see that they do not 499change the example, only add to it.) 500 501[fossil]: https://fossil-scm.org/ 502 503The circle is positioned so that its *center* is 2 centimeters to the 504right of the *center* of the box. If what you really wanted is that the 505left (or west) side of the circle is 2 cm to the right (or east) 506of the box, then just say so: 507 508~~~~~ pikchr source toggle indent 509 B1: box 510 C1: circle with .w at 2cm right of B1.e 511~~~~~ 512 513Normally an "`at`" clause will set the center of an object, but if 514you add a "`with`" prefix you can specify any other anchor 515point of the object to be the reference for positioning. The Pikchr 516script above is saying "make the C1.w point be 2 cm right of B1.e". 517And we have: 518 519~~~~~ pikchr toggle indent 520 B1: box 521 C1: circle with .w at 2cm right of B1.e 522 523 X1: line thin color gray down 50% from 2mm south of B1.se 524 X2: line same from (C1.w,X1.start) 525 arrow <-> thin from 3/4<X1.start,X1.end> right until even with X2 \ 526 "2cm" above color gray 527 assert( last arrow.width == 2cm ) 528~~~~~ 529 530That's the whole story behind positioning block objects on a diagram. 531You just add an attribute of the form: 532 533> **with** *reference-point* **at** *position* 534 535And Pikchr will place the specified reference-point of the object at 536*position*. If you omit the "`with`" clause, the center of the 537object ("`.c`") is used as the *reference-point*. The power of Pikchr 538comes from the fact that "*position*" can be a rather complex expression. 539The previous example used a relatively simple *position* 540of "`2cm right of B1.e`". That was sufficient for our simple diagram. 541More complex diagrams can have more complex *position* phrases. 542 543## Automatic Layout Of Block Objects <a id="auto-layout-block"></a> 544 545If you omit the "`at`" attribute from a block object, the object is positioned 546as if you had used the following: 547 548> `with .start at previous.end` 549 550Except, the very first object in the script has no "previous" and so it 551is positioned using: 552 553> `with .c at (0,0)` 554 555Let's talk little more about the usual case: 556"`with .start at previous.end`". The "`previous`" keyword means the 557previous object in the script. (You can also use the keyword "`last`" 558for this purpose.) So we are positioning the current object relative 559to the previous object. But what about the ".start" and ".end"? 560 561Remember that every object has 8 anchor points whose names correspond 562to compass directions: ".n", ".ne", ".e", ".se", ".s", ".sw", ".w", 563and ".nw", plus the ninth anchor, the center point ".c". Every object 564also has ".start" and ".end" anchor 565points, but their position varies depending on the 566layout direction that is current when the object is created. 567 568<blockquote> 569<table border="1" cellpadding="10px" cellspacing="0"> 570<tr><th>Layout Direction<th>.start<th>.end 571<tr><td>right<td>.w<td>.e 572<tr><td>down<td>.n<td>.s 573<tr><td>left<td>.e<td>.w 574<tr><td>up<td>.s<td>.n 575</table></blockquote> 576 577Recall the earlier example that consisted of three objects stacked 578together: 579 580~~~~~ pikchr source toggle indent 581 right; box; circle; cylinder 582~~~~~ 583 584(I added a "`right`" at the beginning to make the layout direction 585clear, but as "right" is the default layout direction, so it doesn't change 586anything.) 587 588Armed with our new knowledge of how "`at`"-less block objects are 589positioned, we can better understand what is going on. The box is 590the first object. It gets positioned with its center at (0,0), which 591we can show by putting a red dot at (0,0): 592 593~~~~~ pikchr source toggle indent 594 right; box; circle; cylinder 595 dot color red at (0,0) 596~~~~~ 597 598~~~~~ pikchr toggle indent 599 right; box; circle; cylinder 600 dot color red at (0,0) 601~~~~~ 602 603Because the layout direction is "right", the start and end of the box 604are the .w and .e anchor points. Prove this by putting more colored dots 605at those points and rendering the result: 606 607~~~~~ pikchr source toggle indent 608 right; box; circle; cylinder 609 dot color green at 1st box.start 610 dot color blue at 1st box.end 611~~~~~ 612 613~~~~~ pikchr toggle indent 614 right; box; circle; cylinder 615 dot color green at 1st box.start 616 dot color blue at 1st box.end 617~~~~~ 618 619Similarly, we can show that the .start and .end of the circle are its 620.w and .e anchor points. (Add new color dots to prove this to yourself, 621if you like.) And clearly, the .start of the circle is directly on top 622of the .end of the box. 623 624Now consider what happens if we change the layout direction after the 625circle is created but before the cylinder is created: 626 627~~~~~ pikchr source toggle indent 628 right; box; circle; down; cylinder 629~~~~~ 630 631This script works a little differently on Pikchr than it does on PIC. 632The change in behavior is deliberate, because we feel that the Pikchr 633approach is better. On PIC, the diagram above would be rendered 634like this: 635 636~~~~~ pikchr toggle indent 637 right; box; circle; cylinder with .n at previous.e 638~~~~~ 639 640But on Pikchr the placement of the cylinder is different: 641 642~~~~~ pikchr toggle indent 643 right; box; circle; cylinder with .n at previous.s 644~~~~~ 645 646Let's take apart what is happening here. In both systems, after 647the "circle" object has been parsed and positioned, the .end of 648the circle is the same as .e, because the layout direction is "right". 649If we omit the "down" and "cylinder" and draw a dot at the ".end" of 650circle to show where it is, we can see this: 651 652~~~~~ pikchr toggle indent 653 right; box; circle 654 dot color red at last circle.end 655~~~~~ 656 657The next statement is "down". The "down" statement changes the layout 658direction to "down" in both systems. In legacy PIC the .end of the circle 659remains at the .e anchor. Then when the "cylinder" is positioned, 660its ".start" is at .n because the layout direction is now "down", 661so the .n point of the cylinder is aligned to the .e point of 662the circle. 663 664Pikchr works like PIC with one important change: when the "down" statement 665is evaluated, Pikchr also moves the ".end" of the previous object 666to a new location that is appropriate for the new direction. In other 667words, the down command moves the .end of the circle from .e to .s. 668You can see this by setting a red dot at the .end of 669the circle *after* the "down" command: 670 671~~~~~ pikchr toggle indent 672 right; box; circle; down 673 dot color red at first circle.end 674~~~~~ 675 676Or, we can "`print`" the coordinates of the .end of the circle before 677and after the "down" command to see that they shift: 678 679~~~~~ pikchr toggle indent 680 right; box; C1: circle 681 print "before: ", C1.end.x, ", ", C1.end.y 682 down 683 print "after: ", C1.end.x, ", ", C1.end.y 684~~~~~ 685 686## Adjusting The Size Of Block Objects <a id="block-obj-size"></a> 687 688The size of every block object is controlled by three parameters: 689 690 * `width` (often abbreviated as `wid`) 691 * `height` (or `ht`) 692 * `radius` (or `rad`) 693 694There is also a fourth convenience parameter: 695 696 * `diameter` 697 698The `diameter` is always twice the radius. Setting the `diameter` automatically 699changes the `radius` and setting the `radius` automatically changes the 700`diameter`. 701 702Usually the meanings of these parameters are obvious. 703 704~~~~ pikchr toggle indent 705A: box thick 706line thin color gray left 70% from 2mm left of A.nw 707line same from 2mm left of A.sw 708text "height" at (7/8<previous.start,previous.end>,1/2<1st line,2ndline>) 709line thin color gray from previous text.n up until even with 1st line -> 710line thin color gray from previous text.s down until even with 2nd line -> 711X1: line thin color gray down 50% from 2mm below A.sw 712X2: line thin color gray down 50% from 2mm below A.se 713text "width" at (1/2<X1,X2>,6/8<X1.start,X1.end>) 714line thin color gray from previous text.w left until even with X1 -> 715line thin color gray from previous text.e right until even with X2 -> 716~~~~ 717 718The `radius` parameter, however, sometimes has non-obvious meanings. 719For example, on a box, the `radius` determines the rounding of corners: 720 721~~~~ pikchr toggle indent 722A: box thick rad 0.3*boxht 723line thin color gray left 70% from 2mm left of (A.w,A.n) 724line same from 2mm left of (A.w,A.s) 725text "height" at (7/8<previous.start,previous.end>,1/2<1st line,2ndline>) 726line thin color gray from previous text.n up until even with 1st line -> 727line thin color gray from previous text.s down until even with 2nd line -> 728X1: line thin color gray down 50% from 2mm below (A.w,A.s) 729X2: line thin color gray down 50% from 2mm below (A.e,A.s) 730text "width" at (1/2<X1,X2>,6/8<X1.start,X1.end>) 731line thin color gray from previous text.w left until even with X1 -> 732line thin color gray from previous text.e right until even with X2 -> 733X3: line thin color gray right 70% from 2mm right of (A.e,A.s) 734X4: line thin color gray right 70% from A.rad above start of X3 735text "radius" at (6/8<X4.start,X4.end>,1/2<X3,X4>) 736line thin color gray from (previous,X3) down 30% <- 737line thin color gray from (previous text,X4) up 30% <- 738~~~~ 739 740For a [cylinder object](./cylinderobj.md) the `radius` determines the 741thickness of the end caps: 742 743~~~~ pikchr toggle indent 744A: cylinder thick rad 150% 745line thin color gray left 70% from 2mm left of (A.w,A.n) 746line same from 2mm left of (A.w,A.s) 747text "height" at (7/8<previous.start,previous.end>,1/2<1st line,2ndline>) 748line thin color gray from previous text.n up until even with 1st line -> 749line thin color gray from previous text.s down until even with 2nd line -> 750X1: line thin color gray down 50% from 2mm below (A.w,A.s) 751X2: line thin color gray down 50% from 2mm below (A.e,A.s) 752text "width" at (1/2<X1,X2>,6/8<X1.start,X1.end>) 753line thin color gray from previous text.w left until even with X1 -> 754line thin color gray from previous text.e right until even with X2 -> 755X3: line thin color gray right 70% from 2mm right of (A.e,A.ne) 756X4: line thin color gray right 70% from A.rad below start of X3 757text "radius" at (6/8<X4.start,X4.end>,1/2<X3,X4>) 758line thin color gray from (previous,X4) down 30% <- 759line thin color gray from (previous text,X3) up 30% <- 760~~~~ 761 762For a [file object](./fileobj.md) the `radius` determines the size of 763the page fold-over in the upper-right corner: 764 765~~~~ pikchr toggle indent 766A: file thick rad 100% 767line thin color gray left 70% from 2mm left of (A.w,A.n) 768line same from 2mm left of (A.w,A.s) 769text "height" at (7/8<previous.start,previous.end>,1/2<1st line,2ndline>) 770line thin color gray from previous text.n up until even with 1st line -> 771line thin color gray from previous text.s down until even with 2nd line -> 772X1: line thin color gray down 50% from 2mm below (A.w,A.s) 773X2: line thin color gray down 50% from 2mm below (A.e,A.s) 774text "width" at (1/2<X1,X2>,6/8<X1.start,X1.end>) 775line thin color gray from previous text.w left until even with X1 -> 776line thin color gray from previous text.e right until even with X2 -> 777X3: line thin color gray right 70% from 2mm right of (A.e,A.n) 778X4: line thin color gray right 70% from A.rad below start of X3 779text "radius" at (6/8<X4.start,X4.end>,1/2<X3,X4>) 780line thin color gray from (previous,X4) down 30% <- 781line thin color gray from (previous text,X3) up 30% <- 782~~~~ 783 784For a [circle object](./circleobj.md), the width, height, and diameter 785are always the same, and the radius is always half the diameter. Changing 786any parameter automatically adjusts the other three. 787 788~~~~ pikchr toggle indent 789A: circle thick rad 120% 790line thin color gray left 70% from 2mm left of (A.w,A.n) 791line same from 2mm left of (A.w,A.s) 792text "height" at (7/8<previous.start,previous.end>,1/2<1st line,2ndline>) 793line thin color gray from previous text.n up until even with 1st line -> 794line thin color gray from previous text.s down until even with 2nd line -> 795X1: line thin color gray down 50% from 2mm below (A.w,A.s) 796X2: line thin color gray down 50% from 2mm below (A.e,A.s) 797text "width" at (1/2<X1,X2>,6/8<X1.start,X1.end>) 798line thin color gray from previous text.w left until even with X1 -> 799line thin color gray from previous text.e right until even with X2 -> 800X3: line thin color gray right 70% from 2mm right of (A.e,A.s) 801X4: line thin color gray right 70% from A.rad above start of X3 802text "radius" at (6/8<X4.start,X4.end>,1/2<X3,X4>) 803line thin color gray from (previous,X3) down 30% <- 804line thin color gray from (previous text,X4) up 30% <- 805line thin color gray <-> from A.sw to A.ne 806line thin color gray from A.ne go 0.5*A.rad ne then 0.25*A.rad east 807text " diameter" ljust at end of previous line 808~~~~ 809 810Even though they are curvy objects, the `radius` (and hence `diameter`) 811has no effect on [ellipse](./ellipseobj.md) and [oval](./ovalobj.md) objects. 812The size of those objects is determined purely by their width and height: 813 814~~~~ pikchr toggle indent 815A: ellipse thick 816line thin color gray left 70% from 2mm left of (A.w,A.n) 817line same from 2mm left of (A.w,A.s) 818text "height" at (7/8<previous.start,previous.end>,1/2<1st line,2ndline>) 819line thin color gray from previous text.n up until even with 1st line -> 820line thin color gray from previous text.s down until even with 2nd line -> 821X1: line thin color gray down 50% from 2mm below (A.w,A.s) 822X2: line thin color gray down 50% from 2mm below (A.e,A.s) 823text "width" at (1/2<X1,X2>,6/8<X1.start,X1.end>) 824line thin color gray from previous text.w left until even with X1 -> 825line thin color gray from previous text.e right until even with X2 -> 826~~~~ 827 828~~~~ pikchr toggle indent 829A: oval thick 830X0: line thin color gray left 70% from 2mm left of (A.w,A.n) 831X1: line same from 2mm left of (A.w,A.s) 832text "height" at (7/8<previous.start,previous.end>,1/2<X0,X1>) 833line thin color gray from previous text.n up until even with X0 -> 834line thin color gray from previous text.s down until even with X1 -> 835X2: line thin color gray down 50% from 2mm below (A.w,A.s) 836X3: line thin color gray down 50% from 2mm below (A.e,A.s) 837text "width" at (1/2<X2,X3>,6/8<X2.start,X2.end>) 838line thin color gray from previous text.w left until even with X2 -> 839line thin color gray from previous text.e right until even with X3 -> 840 841A: oval thick wid A.ht ht A.wid at 2.0*A.wid right of A 842X0: line thin color gray left 70% from 2mm left of (A.w,A.n) 843X1: line same from 2mm left of (A.w,A.s) 844text "height" at (7/8<previous.start,previous.end>,1/2<X0,X1>) 845line thin color gray from previous text.n up until even with X0 -> 846line thin color gray from previous text.s down until even with X1 -> 847X2: line thin color gray down 50% from 2mm below (A.w,A.s) 848X3: line thin color gray down 50% from 2mm below (A.e,A.s) 849text "width" small at (1/2<X2,X3>,6/8<X2.start,X2.end>) 850line thin color gray from previous text.w left until even with X2 -> 851line thin color gray from previous text.e right until even with X3 -> 852~~~~ 853 854Notice that with an oval object, the semicircular end-cap is always 855on the narrow end of the object. In the default configuration where 856the height is less than the width, the semicircular end-caps are on the 857left and right, but if the width and height are modified so that the 858width is less than the height, then semicircles appear on the top and 859bottom instead. 860 861 862### Default Sizes <a id="def-size"></a> 863 864Block objects have default sizes, which are determined by variables. 865For example, the width of a box is initialized with the value of the `boxwid` 866variable, which defaults to `0.75in`. 867 868It is common for Pikchr scripts 869to change these default at or near the beginning of a script in order to adjust 870the default sizes of objects defined within that script. 871 872### Setting Sizes Using Attributes <a id="size-attr"></a> 873 874Use the "`width`" (or "`wid`") attribute to change the width of an object. 875The argument to this attribute can be an expression — such as "`1cm`" or 876"`0.75*boxwid`" — or it can be a percentage of the prior value, 877such as "`75%`". This also works for "`height`", 878"`radius`", and "`diameter`". 879 880### Automatic Sizing To Fit Text Annotations <a id="text-ann-size"></a> 881 882If a block object contains text annotations, the "`fit`" attribute causes 883the width and height to be adjusted so that the object neatly encloses that 884text. The "`fit`" attribute only considers text that is previously defined 885for the object, or in other words text annotations that occur to the left 886of the "`fit`" keyword. The width and height can be adjusted further after 887the "`fit`" keyword, for example to provide a larger margin around the 888text. Click on the following script to see the difference that the 889"`width 125%`" at the end of the second box definition makes. 890 891~~~~ pikchr source toggle indent 892 down 893 box "Auto-fit text annotation" "as is" fit 894 move 50% 895 box "Auto-fix text annotation" "with 125% width" fit width 125% 896~~~~ 897 898If at the end of a block object definition, either the width or height of the 899object is less than or equal to zero, then that dimension is increased so as to 900enclose all text annotations on the object. Thus, for example, 901you can make all of the 902boxes in your diagram auto-fit around their text annotations by prefacing 903your script with something like: 904 905~~~~ pikchr source toggle indent 906 boxwid = 0; boxht = 0; 907 box "Hello"; 908 move 909 box "A longer label" "with multiple lines" "of label text" 910~~~~ 911 912For all of these auto-fit features, Pikchr needs to know the dimensions of the 913text annotations after rendering. Unfortunately, that information is not 914readily available, as Pikchr runs long before the generated SVG reaches the 915web-browser in which it will be displayed. Hence, Pikchr has to guess at the 916text size. Usually it does a good job of this, but it can be a little off, 917especially for unusual (read: "non-ASCII") characters or if the CSS for 918the rendering environment sets a non-standard font face or font size. To 919compensate, the "`charwid`" and "`charht`" variables can be adjusted or 920extra spaces can be added at the beginning or end of text strings. 921 922These auto-fit features are a new innovation for Pikchr and are not available 923in other PIC family interpreters, as far as we are aware. 924 925## Attributes For Stroke Width And Drawing Colors <a id="stroke-attr"></a> 926 927Various attributes can be added to both block and line objects to influence 928how the objects are drawn. 929 930 * `thickness` *dimension* 931 * `thick` 932 * `thin` 933 * `invisible` (or `invis`) 934 * `color` *color* 935 * `fill` *color* 936 937The "`thickness`", "`thick`", "`thin`", and "`invisible`" attributes control 938the stroke width of the lines that construct an object. The default stroke width 939for all objects is determined by the "`thickness`" variable, which defaults 940to "`0.015in`". The "`thick`" and "`thin`" attributes increase or decrease 941the stroke width by fixed percentages. These attributes can be repeated 942to make the stroke width ever thicker or thinner, up to the limit of the object’s 943dimensions where the stroke fills the entire object. The "`invisble`" attribute 944simply sets the stroke width to 0. 945 946~~~~ pikchr toggle indent 947 boxwid = 0 948 boxht = 0 949 right 950 box "normal" 951 move 952 box "thin" thin 953 move 954 box "thick" thick 955 move 956 box "thick thick thick" thick thick thick 957 move 958 box "invisible" invisible 959~~~~ 960 961Notice that “invisible” refers only to the object outline, not to the 962whole object. You therefore cancel the “invisible” attribute with 963“solid”, not “visible”: 964 965~~~~ pikchr toggle indent 966 boxwid = 0 967 boxht = 0 968 box "fully visible" 969 box invisible color gray "outline invisible" 970 box same solid "outline visible again" fit 971~~~~ 972 973The "`color`" and "`fill`" attributes change the foreground and background 974colors of an object. Colors can be expressed using any of [the 148 standard 975CSS color names][ccn] such as "Bisque" or "AliceBlue" or "LightGray". Color 976names are not case sensitive, so "bisque", "BISQUE", and "Bisque" all mean 977the same thing. Color names can also be expressed as an integer which is 978interpreted as a 24-bit RGB value. It is convenient to express numeric 979color values using hexadecimal notation. "Bisque" is the same as "0xffe4c4", 980which is the same as "16770244". 981 982~~~~ pikchr toggle indent 983 box "Color: CadetBlue" "Fill: Bisque" fill Bisque color CadetBlue fit 984 move 985 oval "Color: White" "Fill: RoyalBlue" color White fill ROYALBLUE fit 986~~~~ 987 988Setting the "`fill`" to a negative number, to "None", or to "Off" makes the 989background transparent. That is the default. 990 991The default foreground color is black. 992 993[ccn]: https://developer.mozilla.org/en-US/docs/Web/CSS/color_value 994 995### Filled Polygons <a id="filled-polys"></a> 996 997The "`fill`" attribute does not affect the rendering of lines unless the 998route of the line is terminated by the "`close`" attribute. The "`close`" 999keyword converts the line into a polygon: 1000 1001~~~~ pikchr toggle indent 1002 line go 3cm heading 150 then 3cm west close \ 1003 /* ^^^^^ nota bene! */ \ 1004 fill 0x006000 color White "green" below "triangle" below 1005~~~~ 1006 1007Polygons are not required to have a fill color. With the default fill of “none,” 1008you can use the "`close`" 1009keyword to convert a polygon into a line and leave the background transparent, 1010but using "`fill` *color*" together with "`close`" is a common idiom. 1011 1012## Text Annotations <a id="text-ann"></a> 1013 1014Every object can have up to five lines of text annotation. Each annotation 1015is a string literal attribute on the object definition. By default, the 1016annotations are displayed around the center of the object, from top to bottom, 1017in the order that they appear in the input script. 1018 1019~~~~ pikchr toggle indent 1020 box "box containing" "three lines" "of text" fit 1021 move 1022 arrow "Labeled" "line" wid 200% 1023~~~~ 1024 1025## Text Attributes <a id="text-attr"></a> 1026 1027The layout and font style of the annotations can be modified using keywords 1028that appear after each string literal. The following modifiers are supported: 1029 1030 * **above** 1031 * **aligned** 1032 * **below** 1033 * **big** 1034 * **bold** 1035 * **center** 1036 * **italic** 1037 * **ljust** 1038 * **rjust** 1039 * **small** 1040 1041### Position Text Above Or Below The Center Of The Object <a id="text-pos"></a> 1042 1043The "`above`" and "`below`" keywords control the location of the 1044text above or below the center point of the object with which 1045the text is associated. If there is just one text on the object 1046and the "`above`" and "`below`" keywords are omitted, the text is 1047placed directly over the center of the object. This causes 1048the text to appear in the middle of lines: 1049 1050~~~~ pikchr indent toggle 1051 line "on the line" wid 150% 1052~~~~ 1053 1054So, if there is just a single text label on a line, you probably 1055want to include either the "`above`" or "`below`" keyword. 1056 1057~~~~ pikchr indent toggle 1058 line "above" above; move; line "below" below 1059~~~~ 1060 1061If there are two texts on the object, they straddle the center point 1062above and below, even without the use of the "`above`" and "`below`" 1063keywords: 1064 1065~~~~ pikchr indent toggle 1066 line wid 300% "text without \"above\"" "text without \"below\"" 1067~~~~ 1068 1069The "`above`" and "`below`" attributes do not stack or accumulate. Each "`above`" 1070or "`below`" overrides any previous "`above`" or "`below`" for the same text. 1071 1072If there are multiple texts and all are marked "`above`" or "`below`", then 1073all are placed above or below the center point, in order of appearance. 1074 1075~~~~ pikchr indent toggle 1076 line width 200% "first above" above "second above" above 1077 move 1078 line same "first below" below "second below" below 1079~~~~ 1080 1081### Justify Text Left Or Right <a id="text-just"></a> 1082 1083As the "`above`" and "`below`" keywords control up and down positioning of 1084the text, so the "`ljust`" and "`rjust`" keywords control left and right 1085positioning. 1086 1087For a line, the "`ljust`" means that the left side of the text is flush 1088against the center point of the line, and "`rjust`" means that the right 1089side of the text is flush against the center point of the line. 1090(In the following diagram, the red dot is at the center of the line.) 1091 1092~~~~ pikchr indent toggle 1093 line wid 200% "ljust" ljust above "rjust" rjust below 1094 dot color red at previous.c 1095~~~~ 1096 1097For a block object, "`ljust`" shifts the text to be left justified 1098against the left edge of the block (with a small margin) and 1099"`rjust`" puts the text against the right side of the object (with 1100the same margin). 1101 1102~~~~ pikchr indent toggle 1103 box "ljust" ljust "longer line" ljust "even longer line" ljust fit 1104 move 1105 box "rjust" rjust "longer line" rjust "even longer line" rjust fit 1106~~~~ 1107 1108The behavior of "`ljust`" and "`rjust`" for block objects in Pikchr differs 1109from legacy PIC. 1110In PIC, text is always justified around the center point, as in lines, 1111but this means there is no easy way to left justify multiple lines of 1112text within a "box" or "file", so the behavior was changed for 1113Pikchr. 1114 1115Pikchr allows three separate text objects inside another object by combining 1116"`ljust`", "`rjust`", and the default text centering: 1117 1118~~~~ pikchr indent toggle 1119 box wid 300% \ 1120 "above-ljust" above ljust \ 1121 "above-rjust" above rjust \ 1122 "centered" center \ 1123 "below-ljust" below ljust \ 1124 "below-rjust" below rjust 1125~~~~ 1126 1127### Text Attribute "center" <a id="text-center"></a> 1128 1129The "`center`" attribute cancels all prior "`above`", "`below`", "`ljust`", and 1130"`rjust`" attributes for the current text object. 1131 1132### Bold And Italic Font Styles <a id="font-style"></a> 1133 1134The "`bold`" and "`italic`" attributes cause the text object to use a bold or 1135italic font. Fonts can be both bold and italic at the same time: 1136 1137~~~~ pikchr indent toggle 1138 box "bold" bold "italic" italic "bold-italic" bold italic fit 1139~~~~ 1140 1141### Aligned Text <a id="text-align"></a> 1142 1143The "`aligned`" attribute causes text associated with a straight line 1144to be rotated to align with that line: 1145 1146~~~~ pikchr indent toggle 1147 arrow go 150% heading 30 "aligned" aligned above 1148 move to 1cm east of previous.end 1149 arrow go 150% heading 170 "aligned" aligned above 1150 move to 1cm east of previous.end 1151 arrow go 150% north "aligned" aligned above 1152~~~~ 1153 1154To display rotated text not associated with a line, attach the 1155text to a line that is marked "`invisible`" 1156 1157~~~~ pikchr indent toggle 1158 box ht 200% wid 50% 1159 line invis from previous.s to previous.n "rotated text" aligned 1160~~~~ 1161 1162Note that the direction of aligned text is the same as the direction of 1163the line itself, so if you draw a line from right to left, the aligned 1164text will appear upside down: 1165 1166~~~~ pikchr indent toggle 1167 circle "C1" fit 1168 circle "C0" at C1+(2.5cm,-0.3cm) fit 1169 arrow from C0 to C1 "aligned" aligned above chop 1170~~~~ 1171 1172If you need aligned text on an arrow that goes from right to left, 1173and you do not want the text to be rendered upside-down, draw 1174the arrow from left to right and include the "`<-`" attribute 1175so that the arrowhead is at the beginning rather than at the end: 1176 1177~~~~ pikchr indent toggle 1178 circle "C1" fit 1179 circle "C0" at C1+(2.5cm,-0.3cm) fit 1180 arrow from C1 to C0 "aligned" aligned above <- chop 1181~~~~ 1182 1183### Adjusting The Font Size <a id="font-size"></a> 1184 1185The "`big`" and "`small`" attributes cause the text to be a little larger 1186or a little smaller, respectively. Two "`big`" attributes cause the 1187text to be larger still, as do two "`small`" attributes. Text 1188size does not increase or decrease beyond two "`big`" or "`small`" keywords. 1189 1190~~~~ pikchr indent toggle 1191 box "small small" small small "small" small \ 1192 "(normal)" italic \ 1193 "big" big "big big" big big ht 200% 1194~~~~ 1195 1196A "`big`" keyword cancels any prior "`small`" keywords on the same text, 1197and a "`small`" keyword cancels any prior "`big`" keywords. 1198 1199 1200## Text Is Positioned Around The Center Of The Object <a id="text-center"></a> 1201 1202The anchor point for text annotations is usually the center of the bounding box for 1203the whole object. This is intuitive for block objects and straight lines. 1204But for multi-segment lines, the text might not be near 1205the line itself. For example, in the following four-segment arrow, 1206the red box is the bounding box and the red dot shows the center of the 1207bounding box. The text label is aligned relative to the center of the 1208bounding box, which is not close to any part of the actual line. 1209 1210~~~~ pikchr toggle indent 1211arrow up 1.5cm right 1.5cm then down .5cm right 1cm then up .5cm right .3cm \ 1212 then down 2.5cm right 1cm "text" 1213box color red thin thin width previous.wid height previous.ht \ 1214 with .c at previous.c 1215dot at last arrow.c color red behind last arrow 1216~~~~ 1217 1218If you need to position text beside one specific segment of a multi-segment 1219line, consider creating a separate "`invis`" line over top of that line 1220segment and attaching the text to the "invis" line instead. Here is the 1221same arrow as before, but with the text attached to a separate "invis" line 1222that overlays the second segment of the arrow: 1223 1224~~~~ pikchr toggle indent 1225arrow up 1.5cm right 1.5cm then down .5cm right 1cm then up .5cm right .3cm \ 1226 then down 2.5cm right 1cm 1227box color red thin thin width previous.wid height previous.ht \ 1228 with .c at previous.c 1229dot at last arrow.c color red behind last arrow 1230line invis from 2nd vertex of last arrow to 3rd vertex of last arrow \ 1231 "text" below aligned 1232~~~~ 1233 1234The anchor point for text is *usually* the center of the object, but 1235in some cases, the anchor point might be fudged a little. This happens, 1236for example for cylinder objects: 1237 1238~~~ pikchr toggle indent 1239C1: cylinder "text in a" "cylinder" rad 120% 1240 dot color red at C1.c 1241 dot color blue at 0.75*C1.rad below C1.c 1242~~~ 1243 1244The red dot is on the center of the cylinder and the blue dot shows the 1245anchor point for the text. The text is a little lower for cylinders because 1246that looks better. With out this adjustment of the text center point, the 1247cylinder text would look goofy: 1248 1249~~~ pikchr toggle indent 1250C1: cylinder rad 120% 1251 text "text in a" "cylinder" at C1.c 1252~~~ 1253 1254# Containers 1255 1256A "container" is a list of one or more objects contained within "`[`...`]`". 1257A container is a collection of one or more objects that looks like a single 1258object to the remainder of the script. 1259 1260For example: 1261 1262~~~ pikchr toggle source indent 1263 A: [ 1264 oval "Hello" 1265 arrow 1266 box "World" radius 4px 1267 ] 1268 Border: box thin width A.width+0.5in height A.height+0.5in at A.center 1269~~~ 1270 1271The "A" container is composed of an oval, and arrow, and a box with rounded 1272corners. But to the subsequent "Border" box, the "A" container appears to 1273be a single object. The Border box can reference the overall width and height 1274and the center point of the A container in order to size and position itself to 1275enclose the container with a 0.25in border: 1276 1277~~~ pikchr toggle indent 1278 A: [ 1279 oval "Hello" 1280 arrow 1281 box "World" radius 4px 1282 ] 1283 Border: box thin width A.width+0.5in height A.height+0.5in at A.center 1284~~~ 1285 1286A container is mostly useful for adding a border around a collection of 1287objects, as shown above, or adding a caption to a diagram. The following 1288diagram shows what a caption might look like. 1289(Click to see the Pikchr source text.) 1290 1291~~~ pikchr toggle indent 1292 A: [ 1293 oval "Hello" 1294 arrow 1295 box "World" radius 4px 1296 ] 1297 Caption: text "Diagram Caption" italic with .n at 0.1in below A.s 1298~~~ 1299 1300 1301In legacy PIC, layout direction changes (the "up", "down", "left", and "right" 1302commands) and variable definitions within a container only affect subsequent 1303statements within the same container. Once the container closes, the prior direction 1304and variable values are restored. Pikchr does not work this way. In 1305Pikchr, layout direction changes and variable definitions that occur within 1306a container continue to be in effect after the container. 1307 1308# Summary And Conclusion 1309 1310Though based on the decades-old PIC language, Pikchr itself is a relatively 1311new system. However it has already proven itself to be amazingly useful for 1312helping to illustrate concepts in technical documentation written using Markdown. 1313 1314This document has provided an overview of how Pikchr works. For more 1315details and other perspectives, see the following resources: 1316 1317 * [The original Kernighan paper on PIC](/uv/pic.pdf) 1318 * [DPIC documentation](/uv/dpic-doc.pdf) 1319 * [ESR's documentation on GnuPIC](/uv/gpic.pdf) 1320 * [Pikchr Language Spec](./grammar.md) 1321 * [Differences between PIC and Pikchr](./differences.md) 1322 * [The scope and purpose of Pikchr](./purpose.md) 1323 * [Step-by-step example of writing a Pikchr document](./teardown01.md) 1324