1) First Step - Learn the original CFDG
First thing you need to do is learn the original CFDG language, which ContextFree1, implements. You can learn all the basic concepts at http://www.contextfreeart.org/mediawiki/index.php/CFDG_HOWTO.
2) What CInk doesn't support?
CInk implements almost everything of CFDG1, but fews bolts are still missing due to technical limitations.
include
statements are ignored. Since CInk runs in a browser so it doesn't have the notion of files, but URLs instead. This is technically possible to implement but that would require some code to make AJAX calls to fecth these included files. In fact, I need to think a little more about this. You can consider this in future scope. I won't give any time frame for this.size
in CInk behaves very differently from ContextFree. Whereas in ContextFree, it defines the dimension of the canvas, in CInk canvas size is constant and has no special meaning except that all transforms are applied globally. So this is the best place put code to scale the whole design. Usually any ContextFree code needs to be scaled down by a factor of 50 - 100 times if it is to be rendered by CInk.- Support for
tile
is broken. Technically it cannot be supported in CInk. To support proper tiling as ContexFree does, CInk will need to retain the primitive informations till the very end of the rendering process. This is not possible since CInk renders all primitives on HTML5canvas
, andcanvas
remembers only the bitmap information. All primitive information are lost. Had CInk used SVG then it might have been possible, but SVG was not used since it might have had huge performance penalty. - Path command
ARCTO
allows two parameterscw
andlarge
. ContexFree (tested on version 2) seems to behave wierdly when both these parameters are used. If you have ContextFree then try running the following code:-
You will notice that ContexFree still renders the small arc. I believe that is incorrect. CInk will render it correctly.startshape wrongArc
#size {s 0.4}
path wrongArc {
ARCTO {x 2 y 0 r 0 rx 2 ry 1 p large p cw }
STROKE {}
}
3) CInk extensions - CFDG2
This section enlists the language extensions added to CFDG. These statements and features are not available in original CFDG and ContextFree.
New transforms
CInk has thrown in some new transforms that can be used like any other existing transforms, like -
hue
,x
,skew
, etc.You can draw shadows! So, now anything which is drawn can have shadow and you do not need to fake it in some way. It is immensly useful and is used by Neon Letters (in gallery). You can learn how to use them here.
shx
- Shadow's x-offset.shy
- Shadow's y-offset.shblur
- Set shadow blur.shh
- Set shadow color's hue.shb
- Set shadow color's brightness (actually value).shsat
- Set shadow color's staturation.sha
- Set shadow color's alpha, i.e. transperency.
Some miscellenious transforms
sw
- This sets the stroke width. This doesn't affect path's stroke width.gx
- Global x. This is a totally different kind of transformation. Allow me to explain it using the below example:-
In the above code we can see that since in the current transform x is 0 sostartshape A
rule A {
B {x 1}
C {x 2}
}
rule B {
CIRCLE {}
}
rule C {
CIRCLE {}
}
B
will be displayed at (1,0) andC
will be displayed at (2,0). Now if we modifiy the code as:-startshape A
rule A {
B {gx 1} //...(1)
C {gx 2} //...(2)
}
rule B {
CIRCLE {}
}
rule C {
CIRCLE {}
}
Then
B
will still be displayed at (1,0), butC
will be displayed at (3,0). You might ask how? Well the answer isgx
, as its name suggest is a global transform. All other transforms in CFDG are local, so they have limited scope where they can have effect. In this case what exactly happend was that the expression marked by (1) incremented the global x by 1. The initial value of gloabal x is zero. When a primitive (here it isCIRCLE
) is displayed then it adds the current value ofgx
to its local value ofx
. In this code we never changed the local x so it was always 0. So, the evaluation of steps were:When in B -> x=0, gx=0+1=1, so B draws at x=0 + 1 -> Now we goto C -> x=0, gx=1+2=3, so C is drawn at x=0 + 3 ->Now finally gx is 3
.Unfortunately, this transform bends the rules of CFDG. It doesn't gel well but is needed in some scenarios i.e. all this global funda is not for regular use but is nonetheless sometimes required. Check out Neon Letters for example.
-
gy
- Global y. Similar togx
, but this affectsy
transform.
Predefined Event Rules
First concocted by Aza for Algorithm Ink2, the Predefined Event Rules are a beatiful addition to CFDG. I have added a few more from my end. They can be used like any other rule but will automatically be triggered when their events occur.
MOUSECLICK
- As it sounds, whenever a user clicks on the canvas this rule will be fired. There is one twist though. The (x,y) location of the click will be applied as local transforms to this rule.MOUSEMOVE
- This is similar toMOUSECLICK
but is triggered when the mouse moves over the canvas.TIME
- This is a time event. Unlike the other event rules this is not triggered automatically, instead the designer needs to call this rule from another rule. The difference being, unlike normal rules, this won't be executed immediately, instead it will lie idle till the "right time". Once it is executed this won't recurr. If you need to created a recurring timer then you can call this rule recursively. The "right time" I spoke of is the weight of this rule. This rule has one caveat - it can be defined only once. So it is illegal to define more than oneTIME
rule. If at anytime you want to cancel a 'scheduled' call, you can call theSTOPTIME
primtive.TYPE
- This is triggered on keypress, but requires that the canvas has the focus. This will capture the character typed-in and apply that as local text transform (discussed later).
-
New primitives
Primitives are atomic tasks (explained in section 4). They render a basic shape after applying all the current transforms on it. So a
CIRCLE
alyways renders a circle of unit radius and at the origin of the coordinate system. The coordinate system decides the shape, size, location and color of the shape, based on the current applicable transforms. Note the phrase, 'applicable transforms', which means that some transforms could be ignored. Sosw
(stroke width) transform will have no impact onCIRCLE
, since it is drawn filled and not stroked, however it will have its impact onLINE
, since it is stroked.LINE
- It draws a line of unit length.ECHO
- Draws some texts. Discussed next.
-
Text transforms
This is the single most important extension to CFDG, the ability to print texts. ContextFree comes bundled with a CFDG program with paths that draw many alphabets. We can avoid this using CInk as
canvas
already provides first class support for characters. CInk doesn't twist the original grammar to force this. Infact, it introduces a new primitive -ECHO
, which behaves exactly like any other primitives.New text transforms:-
fn
- Sets the font name.fs
- Sets the font size. This is additive. So when multiplefs
transforms are encountered then their values will be added up as we progress. This allows us to print texts which progressively vary in size.fu
- Sets the unit for the font size, i.e. 'em', 'px' or 'pt'.fstyle
- Sets the font stlye. Possible values -italic
,bold
,cap
andnormal
.normal
is default.t
- Aah! The prized transform. This is the one which allows you to set the text that needs to be shown. This too is additive, so if your expression ist A t B t C
, then the net output will be the stringABC
.t
accepts single character or a string of characters as argument. If the supplied string contains anything other than digits or english alphabets then it must be enclosed in double quotes.bkspc
- This removes the last character, if any. So, if we modify the above example to –t A t B t C bkspc
, the output then changes toAB
.e
- This is likebkspc
but instead of removing the last character it empties out the full text. So, whenever this is used the the final output will always be an empty string.|t
- This one is a genius! I can't help myself from putting so many exclamations and smileys. There goes one more. This command should be followed by an integer. This value is then added to the last character's unicode (decimal) value. So when the current string isABC
then the expression|t 1
will output the stringABCD
. This is because on adding 1 to unicode (in this case the ASCII) value ofC
, we getD
. ThisD
then gets concatenated with the last string.This little buddy has one more trick up its sleeve. What do you expect will be the output of
t ABC e |t 1
? Well, it won't be an empty string. It will beD
! This is becausee
andbkspc
are, what I call, past-influential transforms. Past-influential transforms are not supposed to influence the output of the future transforms. In this exampleC
's ASCII code is passed-on to|t
even whenC
perishes. Had it not done that then|t
would output different strings, based on if it was preceeded or not preceeded bye
andbkspc
. That is against the nature of past-influential transforms, and would have made it hard to predict the output. So,e
orbkspc
do not influence the output of|t
.base
- This is better explained here.align
- This is better explained here.st
- Strokes the text, i.e. draws the text's outlines. Value ofsw
is used here to set the thickness of the stroke lines.ft
- Fills the text. This is the default behavior for drawing texts. We cannot stroke and fill the same text sost
andft
should not be used together.
Unicode Support:-Text transforms support Unicode3 characters. This allows you to print non-english characters. Its format is
{ux}
, where the 'x' should be replaced by the decimal Unicode value of the character. So,{u65}
will printA
. You might wonder; how will you print the character '{'? Well the only way is to use{u123}
to print{
and{u125}
for}
. This applies for double and single quotes too. For them use{u34}
and{u39}
respectively.Check out the example code with live demo on my blog here.
4) CInk caveats
This enlists some gotchas you need to be aware of.
ARCTO
gotcha - CInk uses a complex and non-optimal method to draw theARCTO
arcs. This becausecanvas
doesn't provide any API to draw elliptical arcs. It does provide some APIs to draw circular arcs but they need different set of information. To keep the code maintainable I didn't optimise this part.- Paths gotcha - Javascript engines are single threaded so if any JS code takes too long to respond then the browser will lockup (in case of Chrome only that tab will lock up). CInk being processor intensive, it uses a trick to tackle this. It mimics the behavior of a time sharing OS running on a single core processor. In such a scenario when you have two or more simultaneously running processes then the OS makes sure that each process gets access to the processor for a breif period of time. This is called time-slicing and these time slices are so small that the user gets the impression that all of them are using the processor simultaneously. Similarly, CInk too divides all its tasks into chunks of atomic tasks and collection tasks. Each atomic task needs to be complete in one cycle.
While a collection task is, ofcourse, a collection of many atomic or collection tasks. Atomic works cannot be sub-divided like a collection. A
rule
is a collection task as it might be divided into a number of more tasks.path
on the other hand is by nature atomic and cannot be subdivded. So, I will advise you against defining complex paths as they might lockup the browser when drawn in hordes. z-index rendering - HTML
canvas
doesn't support z-index and there is no way to handel the different layers. CInk uses a workaround to implement this very much needed feature. The workaround is to create a bunch ofcanvas
DOMs, stacked over each other. Theirz-index
are set toz
transform's values (accurately speaking, the value is not equal to thez
value but calculated from it).When CInk renderer is instantiated then it checks for a
hasZ
flag in the compiled code, if found then it switches to a z-mode. This flag is set by the compiler, if it finds that the code usesz
transform. When in z-mode, CInk wraps the passedcanvas
inside adiv
with CSS class - CInkWrapper. CInk also changes thecanvas
'postion
property toabsolute
. It takes care of positioning thecanvas
such that it stays at the original spot. Since thecanvas
is now absolutely positioned, it may mess up your layout. I suggest you to setup your layout withcanvas
absolutely positioned. At the end of the rendering process, all the different pieces of the design will be copied to the originalcanvas
and the clone canvases will be deleted. The wrapperdiv
will be gone too and the original canvas' CSS styles will be reverted. This scheme works but seems to take a heavy toll on Firfox. Chrome easily handels this pressure.As I mentioned, CInk creates layers of canvases, and fortunately we can 'see-through' them. Ofcourse, unless you fill it with some color, but CInk needs to fill it with the background color. So it creates an extra canvas to fill with only the background color. CInk makes sure that this canvas is the bottom of the stack. While rendering, whenever it finds that it doesn't have a canvas at the required
z
, it creates one. CInk makes sure that all clone canvases are of exact same dimension and positioned at exactly the same spot and are within the wrapperdiv
. During rendering you might end up with loads of such clones. You might wonder how can you create an UI element (e.g.div
) which is guaranteed to stay on top of CInk. For this you need to create a positioned element and set itsz-index
value to more than 200. CInk will never create any layer overz-index
of 200.- z-index rendering for code that uses Predefined Event Rules - Everything stated above applies here too, except that at the end of rendering the wrapper
div
won't be removed. The backgroundcanvas
too will retained, but clone canvases will be deleted after copying the bitmaps from them. This is done so, because, after the main rendering process, the events may still fire some rules. Those rules may also try to usez
transform. The wrapper and backgroundcanvas
will be removed only whenshutAndDispose()
4 is called.
- http://www.contextfreeart.org/mediawiki/index.php/Context_Free_Art:About (Context Free Art)
- http://azarask.in/projects/algorithm-ink (Algorithm Ink)
- What is Unicode? (Wikipedia article)
- Download and API Reference (Look inside API reference section)