Cdl

Document, Pages, Layers, Figures

<Cdl>
<Document Name="String" XType="String" ...>
<Background Id="DocumentId"><Brush/></Background>
<Pages>
<Page Name="String" XType="String" ...>
<Layers>
<Layer Name="String" XType="String" ...>
<Figures>
<TextBlock/>
<Shape/>
<Raster/>
<Group/>
<ProxyGroup/>
...

Figure

There are 5 figure types: <TextBlock>, <Shape>, <Raster>, <Group> and <ProxyGroup>.
Common properties of all figure types:

<Figure Name="String" XType="String"
Locked="Boolean" Hidden="Boolean" ...>
<Brush/>
<Pen/>
<PreTransform Matrix22="1,0,0,1"/>
<Anchor X="mm" Y="mm" -or- RelX="Number" RelY="Number"/>
<Transform Matrix22="1,0,0,1"/>
<Pin X="mm" Y="mm"/>
<PowerClipContents>
<PowerClipContent Id="String">
<Figures>...</Figures>
</PowerClipContent>
...
</PowerClipContents>
<Figure>

Text

<TextBlock LineDirection="Angle" CharDirection="Angle"
ExtraCharSpacing="Magnitude"
ExtraWordSpacing="Magnitude"
ExtraLineSpacing="Magnitude"
ColumnSpacing="Magnitude"
ColumnCount="Integer" LinesPerColumn="Integer"
LinesAlign="Left|Center|Right"
PowerClipId="String"
VerticalStyle="String" ... />
<Line>String</Line>
<Font Size="Number" AutoSize="Boolean"
Guid="String" Name="String"
FamilyName="String" FullName="String" PostscriptName="String"
Weight="Number" IsBold="Boolean"
IsItalic="Boolean" IsStrikeout="Boolean" IsUnderline="Boolean"/>
<TextPart TextRange="" ...same as TextBlock... >
<Font/>
</TextPart>
...
</TextBlock>

Shape

<Shape ...>
<!-- Unstructured polyregion -->
<Polyregion FillMode="Alternate|Winding" PowerClipId="String"
RenderFrame="0 0, 100 0, 100 100, 0 100"
RenderMatrix="1,0,0,1">
<Region Type="Bezier3" IsClosed="Boolean" Points="0 0,10 0,15 5|20 10,20|..."/>
<Region Type="Polyline" IsClosed="Boolean" Points="0 0,10 0,10 10,15 10..."/>
...
</Polyregion>
<!-- Boolean polyregion -->
<Polyregion FillMode="CadX" ...>
<Region ...>
<Hole Type="Bezier3" IsClosed="True" Points="..."/>
<Hole Type="Polyline" IsClosed="True" Points="..."/>
...
</Region>
...
</Polyregion>
...
</Shape>

Raster

<Raster ImageLink="Id" Width="px" Height="px" DPI="Number">
<MonochromeColors><Color/><Color/></MonochromeColors>
</Raster>

Group

<Group ...>
<Figures>...</Figures>
</Group>

ProxyGroup

<ProxyGroup Link="Id" ...>
<Colors>
<Color/>
<Color/>
...
</Colors>
...
</ProxyGroup>

Style

Solid Brush

<Brush>
<Color/>
</Brush>

Texture Brush

<TextureBrush ImageLink="Id"
TextureOffset="0.5 0.5" TargetOffset="0.5 0.5"
Matrix22="1,0,0,1"
TransformMode="Fixed|Clamp|RotateOnly|Full|StretchX|StretchY"
ClippingRect="lx ly hx hy">
<MonochromeColors><Color/><Color/></MonochromeColors>
</TextureBrush>

Linear Gradient Brush

<LinearGradientBrush Positions="[Points]"
From="Number" To="Number"
GammaCorrection="Boolean">
<Colors>
<Color/>
<Color/>
...
</Colors>
</LinearGradientBrush>

Radial Gradient Brush

<RadialGradientBrush Center="Point" Positions="[Numbers]">
<Colors>
<Color/>
<Color/>
...
</Colors>
</RadialGradientBrush>

Pen

<Pen Width="Number"
DashStyle="Solid|Dash|Dot|DashDot|DashDotDot"
StartCap="Flat|Square|Round|Triangle" EndCap="..."
DashCap="Flat|Round|Triangle"
LineJoin="Miter|Bevel|Round|MiterClipped|AdaptiveMiter"
MiterLimit="Number"
BehindFill="Boolean">
<Color/>
</Pen>

Color

<Color Alpha="0...1" RGB="RRGGBB" CMYK="CCMMYYKK"
Name="String" Tag="String" Label="String"
ShowThrough="Boolean"/>

Processes

Capital

<Capital ScaleX="Number" ScaleY="Number"
Pattern="First|Last|First Last"
HAlignment : "Left|Center|Right"
VAlignment : "Baseline|Top|Middle|Bottom"/>

BookEnd

<BookEnd HeadSX="Number" HeadSY="Number"
TailSX="Number" TailSY="Number"
HAlignment : "Left|Center|Right"
VAlignment : "Baseline|Top|Middle|Bottom"/>

Split

<Split Overlap="Number"
Pos="Number"
Turn="Number"
Gap="Number"/>

Border

<Border DX="Number" DY="Number"
Gap="Number"
Separate="Number"/>

Contour

<Contour Offset="Number"
Steps="Integer"
Inside="Boolean" Outside="Boolean"
IncludeHoles="Boolean"
Combine="Boolean"
Chamfer_D="Number" Chamfer_L="Number">
<Brush/>
<Pen/>
</Contour>

PenContour

<PenContour>
<Pens>
<Pen/>
<Pen/>
...
</Pens>
</PenContour>

Shadow

<Shadow OffsetX="Number" OffsetY="Number"
Gap="Number"
Simplify="Boolean">
<Brush/>
<Pen/>
</Shadow>

RasterShadow

<RasterShadow OffsetX="Number" OffsetY="Number">
<Pen/>
<Gap>
<Pen/>
</Gap>
</RasterShadow>

Effect3d

<Effect3d BorderIntensity="Number" BorderSize="Number"
ContourOffset="Number"
LightGap="Number" LightIntensity="Number"
LightSize="Number" LightSource="Up|Right|Down|Left"
ShadowIntensity="Number" ShadowSizePercentage="Number"
SlopeIntensity="Number" SlopeSize="Number"/>

Extrude3D

<Extrude3D Depth="Number" VanishingPoint="Point"
RotationX="Angle" RotationY="Angle" RotationZ="Angle">
<Brush/>
<Pen/>
</Extrude3D>

VerticalArch

<VerticalArch Height="Number" Width="Number" From="Angle" To="Angle"/>

Perspective

<Perspective HPoint="Point" VPoint="Point"/>

FitEnvelope

<FitEnvelope Mode="Freeform|Mixed|Uniform|Boxed"
HPos="Left|Center|Right|Stretched|Expanded"
VPos="Top|Center|Bottom|Stretched|Expanded"
HighResolution="Boolean"
KeepLines="Boolean"
AddBearingX="Boolean">
<Envelope>
<Curve Type="Bezier3" IsClosed="False" Points="..."/>
<Curve Type="Bezier3" IsClosed="False" Points="..."/>
<Curve Type="Bezier3" IsClosed="False" Points="..."/>
<Curve Type="Bezier3" IsClosed="False" Points="..."/>
</Envelope>
</FitEnvelope>

FitEllipse

<FitEllipse Height="Number" Width="Number"
Rotation="Angle"
Placement="Number"
Mirror="Boolean"
Inside="Boolean"
DontRotate="Boolean"
Fit="None|Scaled|Contained|Stretched|Expanded"/>

FitOnPath

<FitOnPath VPos="Above|Over|Below"
HPos="Fixed_Left|Fixed_CenterTop|Fixed_CenterBottom|
Fixed_Right|Stretched|Scaled|Expanded"
Offset="Number" DistanceFromPath="Number"
PlaceOnOtherSide="Boolean"
Fwd="Boolean"
DontRotate="Boolean"
Overhang="Boolean">
<Path Type="Bezier3" IsClosed="Boolean" Points="..."/>
</FitOnPath>

Distress

<Distress ScratchesLevel="Number"
RustLevel="Number"
FoldsLevel="Number"
OnOffThreshold="Number"/>

Primitives

Point

The documentation assumes the following variable is defined, it is recommended to use the same convention on user code:

var Px = Cx.Point;
var p = Px(x,y);
p.x p.y
p.set(x,y); // Modify inplace
p.set(point); // p := point
p.clone(); // return Px(p)
p.isEqual(point); // return p == point
p.isNear(point,eps); // return p ~= point
p.isZero(); // return x == 0 && y == 0
p.add(point); // p += point
p.substract(point); // p -= point
p.scalarMultiply(alpha); // p *= alpha
p.sm(alpha); // Shortcut for scalarMultiply
p.translate(offset); // p += offset, same as add
p.translate(dx,dy); // x += dx, y += dy
p.translated(offset);
p.translated(dx,dy);
p.transform(transform); // p := transform.apply(p)
p.transformed(transform); // return transform.apply(p)
p.toSVG(); // return 'x y'
p.toXmlString(); // return 'x y'
p.textualize(); // return 'x y'
p.toCore(); // return { X: x, Y: y }
p.norm2(); // return x2 + y2
p.norm(); // return sqrt( norm2 )
p.normalize(); // p := p.normalized()
p.normalized(); // return p / norm
p.perpendicular(); // return orthogonal vector
p.confined(bounds);
p.confined(lx,ly,hx,hy);
p.confine(bounds);
p.confine(lx,ly,hx,hy);
p.angle(); // return angle with respect to the x axis
p.angle_rad(); // return angle in radians
Px.areEqual(pa,pb); // return pa == pb
Px.fromXmlString(cdlPoint); // 'x y' => Px
Px.fromCore(pointModel); // {X,Y} => Px
Px.distance(pa,pb); // return euclidean distance between points
Px.distance2(pa,pb); // return squared euclidean distance
Px.minus(p); // return -p
Px.add(pa,pb); // return pa + pb
Px.substract(pa,pb); // return pa - pb
Px.scalarMultiply(p,alpha); // return p * alpha
Px.sm(p,alpha); // Shortcut for Px.scalarMultiply
Px.dotProduct(pa,pb); // return pa * pb
Px.crossProductZ(pa,pb); // return pa ^ pb
Px.interpolate(pa,pb,t); // return pa * t + pb * (1-t)
Px.isInsidePolygon(point,polygon);

Matrix

The documentation assumes the following variable is defined, it is recommended to use the same convention on user code:

var Mx = Cx.Matrix;
var m = Mx(s00,s01,s10,s11, dx,dy);
m.s00 m.s01 m.dx
m.s10 m.s11 m.dy
m.apply(point); // return m * point
m.apply(x,y); // return m * Px(x,y)
m.clone(); // return Mx(m);
m.isEqual(matrix); // return m == matrix
m.isNear(matrix,eps); // return m ~= matrix
m.isIdentity();
m.isAlmostIsotropic(); // Only rotation and isometric scaling
m.appended(matrix); // return m * matrix
m.determinant(); // return s00 * s11 - s01 * s10
m.scaleFactor(); // return sqrt(abs(determinant))
m.angle(); // return rotation angle
m.invert();
m.inverted();
m.toCssString(unit); // return 'matrix(s00,s01,s10,s11,dx unit,-dy unit)'
m.toMatrix22String(); // return 's00 s01 s10 s11'
m.toMatrixString(); // return 's00 s01 s10 s11 dx dy'
m.textualize(); // return 's00 s01 s10 s11 dx dy'
m.toCore(); // return { S00, S01, S10, S11, DX, DY }
// Only for matrix22
Mx.add(m1,m2); // return m1 + m2
Mx.substract(m1,m2); // return m1 - m2
Mx.scalarMultiply(matrix,alpha); // return matrix * alpha
Mx.sm(matrix,alpha); // scalarMultiply shortcut
Mx.multiply(ml,mr); // return ml * mr
Mx.concat(m1,m2,m3,...); // return m1 * m2 * m3 * ...
Mx.invert(matrix); // return matrix ^ -1
Mx.translate(offset); // return translation matrix
Mx.translate(dx, dy); // return translation matrix
Mx.scale(sx, sy, deg); // return scaling matrix
Mx.scaleFrom(point, sx, sy, deg); // return scaling matrix
Mx.rotate(deg); // return rotation matrix
Mx.rotateAround(point, deg); // retrun rotation matrix
Mx.shear(sx, sy, deg); // return shear matrix
Mx.shearAround(point, sx, sy, deg); // return shear matrix
Mx.transformAround(point, matrix); // return general matrix
Mx.stringToMatrix22(string); // 's00 s01 s10 s11' => Matrix
Mx.fromCore(m); return { S00, S01, S10, S11, DX, DY } => Matrix

Bounds

var b = Cx.Bounds(lx, ly, hx, hy);
b.lx b.ly b.hx b.hy
b.clone();
b.isEqual(bounds); // return b == bounds
b.lx_ly();
b.lx_hy();
b.hx_ly();
b.hx_hy();
b.center();
b.area();
b.width();
b.height();
b.translated(offset);
b.translated(x,y);
b.translate(offset);
b.translate(x,y);
b.scaled(sx,sy);
b.scale(sx,sy);
b.inflated(dw,dh);
b.inflate(dw,dh);
b.contains(point); return ( point inside b )
b.contains(x,y);
b.interpolate(x,y); // return Px( lx + x width, ly + y height )
b.deinterpolate(point); // return {x,y} such that point.x == lx + x width
// point.y == ly + y height
b.toXmlString();
b.textualize();
Cx.Bounds.fromBox(box); // { x, y, width, height } => Cx.Bounds
Cx.Bounds.fromXmlString(s); // 'lx ly hx hy' => Cx.Bounds
Cx.Bounds.fromCore(m); // { LX, LY, HX, HY } => Cx.Bounds
Cx.Bounds.ofPoints(points); // return points bounds
Cx.Bounds.ofPointsAfter(points,transform);
Cx.Bounds.ofThings(things); // return things bounds
Cx.Bounds.ofThingsAfter(things,transform);
Cx.Bounds.overlapPercentage(ba, bb)
Cx.Bounds.horizontalOverlapPercentage(ba, bb)
Cx.Bounds.areOverlapping(ba,bb)
Cx.Bounds.intersection(ba, bb)
Cx.Bounds.union(boundsArray)

Frame

var f = Cx.Frame(p0,p1,p2,p3);
f.p0 f.p1 f.p2 f.p3
f.clone();
f.isEqual(frame); // return f == frame
f.bounds();
f.center();
f.width(); // return distance(p0,p1)
f.height(); // return distance(p0,p3)
f.width2(); // return distance2(p0,p1)
f.height2(); // return distance2(p0,p3)
f.minSideLength2();
f.translate(dx,dy);
f.translated(dx,dy);
f.transform(t);
f.transformed(t);
f.interpolate(ax,ay);
f.toXmlString();
f.contains(point);
f.extend(olx,oly,ohx,ohy);
f.extended(olx,oly,ohx,ohy);
f.angle(); // p0 p1 angle
Cx.Frame.fromRect(x,y,width,height);
Cx.Frame.fromBounds(bounds)
Cx.Frame.around(center,width,height);
Cx.Frame.fromXmlString(s); // 'p0x p0y ... ' => Cx.Frame
Cx.Frame.areOverlapping(fa,fb);
Cx.Frame.overlapPercentage(fa,fb);

Objects

Canvas API exposes an imperative view of CDL (CadWorX Declarative Language), format used through all our software stack. It is designed to serve both simple (replacing a figure in a template) and complex manipulation of CDL document and templates.

The API follows JavaScipt semantics and naming conventions as much as possible, and fills the gaps borrowing the style of other popular frameworks like JQuery and Lo-dash, libraries that are used internally and encourage to interact with the API.

CDL tag names are CamelCase. For the most part, they are translated to Canvas using the same CamelCase tag name for type names and backCase for properties.

// <Contour OffsetX="10"></Contour>
var c = Cx.Contour({ offsetX: 10 });

Creation of elements

CDL elements are translated to typed objects in Canvas:

CDL Element Canvas Object
<FigureType> Cx.FigureType
<BrushType> Cx.BrushType
<PenType> Cx.PenType
<ProcessType> Cx.ProcessType
<Color> Cx.Color
Matrix22=" " Cx.Matrix ( Mx in the docs )
<Point X=" " Y=" "> Cx.Point ( Px in the docs )

Objects are initialized using JSON notation:

var contour = Cx.Contour({ offset: 10
, brush: { color: { rgb: 'FF0000', alpha: 0.5 } } });

You can mix JSON and Canvas objects if you already have the objects available:

var contour = Cx.Contour({ offset: 10
, brush: figure.brush() });

Properties

Following JQuery properties semantics, CIL properties exposes both get and set functionality directly using the property name to define a public function (with or with out parameters).

// Getter
var ox = shadow.offsetX();
// Setter
shadow.offsetX( ox+10 );

Setters return the modified object and can be chained to update several properties in a single line:

// Setters chaining
shadow.offsetX(10)
.offsetY(10)
.gap(3);

The values returned from properties are typed. You will get a number, a string or a brush when you query the for them. Property setters expect the same courtesy from the user, and passing a string when a number is required is undefined behavior.

Array properties

Working with lists of items is very common when dealing with CDL documents. A document is a list of figures, a figure has a list of processes, a linear gradient brush has a list of colors, Canvas has a list of selected figures. These lists are also exposed as normal properties:

// Getter
var figures = layer.figures();
// Setter
layer.figures( [text, shape, raster] );

The setter in this case will directly replace all figures in the document by the new given figure list.

Array properties can also be accessed using indexing:

// Get one figure
var figure = layer.figures(2);
// Replace one figure
layer.figures( 2, raster );

Array properties getters returns an extended version of a JavaScript Array. These arrays tries to mimic as much as possible the standard Array interface. All the functions in the standard are available. They work in the same way as normal arrays:

var figures = layer.figures();
for(var k=0, size=figures.length; k<size; ++k){
var figure = figures[k];
figure.translate(offset);
}

The new JavaScript standard iteration functions (and the extensions provided by lo-dash) are great tools for list handling, reading Underscore.js documentation is heavily recommended before using Canvas. The algorithm above can be writen as:

_.invoke( layer.figures(), 'translate', offset );

Cx Arrays extends the standard set of mutation functions to help in our domain. For example, following the example above, the user can remove the small figures using:

figures.remove(smallFigures);

The new mutation functions are:

Function Definition
.clear() Remove all elements
.add(a) Add elements
.set(a) Clear and add elements
.remove(e) Remove given elements
.erase(i,n) Remove a range (same as splice(i,n?n:1))
.insert(i,a) Insert element at a given position
.replace(e,a) Replace elements
.replaceAt(i,v) Replace element at given index
.moveForward(v,n) Relocates elements forward
.moveBackward(v,n) Relocates elements backward

For all functions, the parameters specs are:

  • a value or array of values to be added
  • e value or array of values to be removed
  • v value or array of values to be relocated
  • i array index
  • n count

Functions that remove values return these values so the user can use them or dispose them if needed.

Canvas

var canvas = Cx.Canvas({ renderTo: domId });

Properties

Properties Type Def Definition
zoom Number 1 View port transform zoom
center Point (0,0) View port transform center
wireframe Boolean false Show outline structure of figures
document Document Empty Document shown in the Canvas
selectedFigures Figures [] Current selection
background Document Empty Decoration background for the Canvas
backgroundColor Color White Background color, use null for transparency
maskColor Color Gray Mask color when using MaskPen outlines
maskAlpha Number 0.8 Mask alpha
locked Boolean false If true, tools and actions are not allowed to modify the document
showLoadingAnimation Boolean true Show loading feedback while waiting for the server
toolbar Toolbar null HUD Toolbar definition
hudClipboard Boolean false Show Clipboard button on the HUD
autoSelection Boolean true Newly added figures are auto selected

Events

Events Definition
'ready' Canvas is ready
'resize' Canvas size changed
'zoomupdated' zoom or center updated

Viewport management

canvas.zoomTo(zoom,center);
canvas.zoomBy(delta); // zoom += delta
canvas.zoomIn(factor); // zoom *= factor
canvas.zoomOut(factor); // zoom /= factor
canvas.zoomAround(bounds,margin);
canvas.zoomToFit$(figures,margin);
canvas.zoomToFitPages$(margin);
canvas.center(bounds);
canvas.center$(figures);
canvas.bounds();

Tools

canvas.tool(); // return current tool
canvas.tool(tool); // stack a new tool
canvas.popTool(); // commit current tool

Document forwarding interface

To make it easier to work with the canvas document, the following forwarding functions are provided:

canvas.pages(i,a);
canvas.activeLayerFigures(i,a);
canvas.activePageFigures(i,a);
canvas.layers(i,a);
canvas.figures(i,a);
canvas.allFigures();
canvas.commit$();
canvas.revert$();
canvas.update$();
canvas.add(figures);
canvas.remove(figures);
canvas.replace(old,new);
canvas.backOne(figures);
canvas.toBack(figures);
canvas.forwardOne(figures);
canvas.toFront(figures);
canvas.saveCopy$(attrs);
canvas.save$(attrs);
canvas.addClipart$(clipart);
canvas.replaceClipart$(old,clipart);
canvas.autoCreateMultiPartText$(figures);
canvas.breakMultiPartText(text);
canvas.group(figures);
canvas.ungroup(figures);
canvas.extractPowerClipContents(figure);
canvas.addPowerClipContents(figure,content);
canvas.reshape$(figures,action);

Selection helpers

canvas.selectAll(); // Shortcut for canvas.selectedFigures( doc.activeLayerFigures() )
canvas.clearSelection(); // Shortcut for canvas.selectedFigures().clear()
canvas.selectNext(); // Select next figure in z-order
canvas.keepSelection(); // Auto selection will not kick in for current transaction

Misc

// Returns a copy of the current zoom, offset, wireframe that can be stored to set back later
var s = canvas.state();
// Later...
canvas.state(s);
canvas.fill(context);
canvas.updateSize();
canvas.dispose();
canvas.render$();
canvas.contextFigures(i,a); // selection ? selectedFigures(i,a)
// : doc.figures(i,a)
canvas.action(id,config);
canvas.showPagesSelector$();
canvas.figureAtPoint( docPoint );

Tools aware history

if( canvas.canUndo() ) canvas.undo();
if( canvas.canRedo() ) canvas.redo();

Figure Annotations

canvas.annotate( figure, { message: 'Message', pen: ... } );
canvas.annotate( figures, { grouped: true, message: ... } );
canvas.annotate( function(figure){ }, { message: function(figure){}, ... });
canvas.annotate( function(figure){ }, function(figure){} );
canvas.annotate( function(figure){ }, function(figure){} );
canvas.unannotate( annotation );
canvas.clearAnnotations();

Conditions

Canvas conditions are part of the figures conditions API. Read the Conditions tutorial for more information.

canvas.condition(name,function(figure){ return boolean; });
canvas.arrayCondition(name,function(figures){ return boolean; });
canvas.is(figure,condition...);
canvas.is$(figure,conditions...);
canvas.are(figures,conditions...);
canvas.are$(figures,conditions...);
canvas.only(figures,conditions...);
canvas.only$(figures,conditions...);
canvas.saveConditions();
canvas.restoreConditions();

Canvas background

The canvas background is used to show decorations or app specific guides.

var backgrondDocument = canvas.background();
// ... modify and commit$ like a normal document

The background document is independent from the document the Canvas is displaying. You can have a document (the design you will transfer to a shirt) and display it with different kind of backgrounds: a realistic t-shirt for a final preview, a simplified version that is just a bounding box to aid in edition mode, etc.

If you want a background that will be persisted with the document, then use a background layer in your documents. The Canvas background is only for the apps to be able to add things like a page box for reference.

Canvas 3D

Document 3D, Model 3D and Model Data 3D.

Document 3D

A Document 3D extend Cx.Document with 3D helpers. Given an id in the server of a Document 3D the load function is the same as with normal documents:

Cx.Document.load$(id) .then(function(doc){
// doc is of type Cx3D.Document
Properties Type Def Definition
model3D String null Server Id of associated Model 3D
modelData3D String null Server Id of associated Model Data 3D

The 3D document overwrites the document add function. It can trigger an active layer change so islands don’t get mixed with the design.

doc.add(figures);

Helper methods to work with islands and design layers

doc.islandsLayer(); // return active page islands layer
doc.designLayers(); // return active page design layers
doc.islandsLayer(page); // return page islands layer
doc.designLayers(page); // return page design layers
doc.isTextureIsland(figure);

Texture islands with the same name across all pages should share the same brush to keep the system consistent. Use the following function when changing the brush of a texture island:

doc.textureIslandBrush(figure,brush);

One possible flow for a multi size 3D application is to ask the user to design one size to create a template that will be copied over all other sizes. The following function implements a scaled or non scaled copy, it is expected that the arrangements in both documents are similar.

doc.copyDesignTo$(doc,{scaled:false}) .then( ...

Model 3D

Given a Document 3D, the associated model can be accesed with:

doc.loadModel3D$() .then(function(model) { ...

In case of having the server id of the Model, or the Xml representation:

Cx3D.Model.load$(id) .then(function(model){ ...
var model = Cx3D.Model.fromXml(xml);
var model = Cx3D.Model.fromXmlString(s);
Properties Type Def Definition
modelData3D String null Server Id of associated Model Data 3D

An empty working space document associated with this model can be created with:

model.createDocument3D$() .then(function(doc3D){ ...

A new arrangement containing all islands in their original position can be create with:

var page = model.createCustomPage(name);

Model Data 3D

Given a Model 3D, the associated model data can be loaded with:

model.loadModelData3D$() .then(function(modelData){ ...

Or using its server id:

Cx3D.ModelData.load$(id) .then(function(modelData){ ...
Properties Type Def Definition
data json null 3D polygonal data
id String null Server Id

Production Texture

var texture = Cx3D.ProductionTexture({ renderTo: domId });
Properties Type Def Definition
document Document 3D null Working space document
model Model 3D null Model 3D
dpi Number 2 * 25.4 Resolution
showSelectedFigures Boolean true Show selection in 3D
texture.watch(canvas);
texture.dispose();
texture.updateSize();

Model View

var mv = Cx3D.ModelView({ renderTo: domId });
Properties Type Def Definition
backgroundColor Color Gray Background color, null for transparency
autoRotate Boolean false Auto rotate model
loadingAnimationMessage String 'Loading 3D Model' Message
mv.modelData(modelData);
mv.watch(texture);
mv.dispose();
mv.image();
mv.updateSize();
mv.zoomToFront();
mv.zoomToBack();
mv.zoomToRight();
mv.zoomToLeft();
mv.zoomIn(scale);
mv.zoomOut(scale);
mv.rotateCameraRight(angle);
mv.rotateCameraLeft(angle);
mv.rotateCameraDown(angle);
mv.rotateCameraUp(angle);
mv.rotateModelRight(angle);
mv.rotateModelLeft(angle);
mv.rotateModelDown(angle);
mv.rotateModelUp(angle);

Thumbail image

Cx3D.thumbnailImage$(config);

3D Preview

var preview = Cx3D.createPreview(domId,docId);

Document

Cx.Document

Properties

Properties Type Def Definition
id String null Id of the document in the Server
docType String 'Doc' Server side document type
xType String null Document type
undoLimit Integer 10 Maximun number of history points kept
name String null Name stored in the Server
notes String null Notes stored in the Server
owned Boolean true The current user owns this document
archived Boolean false The document is archived in the Server
tags Tag Array [] Core tags
metadata Metadata None Extra app data

Events

Events Definition
'saved' Fired after the document is saved in the Server
'lock' Fired when a transaction starts
'unlock' Document is able to process next transaction
'commitstarted' Commit started, hook to assure things like showThrough color
'commit' Transaction finished succesfully
'revert' Transaction failed, state reverted to previous history point
'undo' Fired after an undo operation
'redo' Fired after a redo operation
'pageschanged' Pages array changed
'activepagechanged' Active Page changed
'layerschanged' Layers array changed
'activelayerchanged' Active layer changed

Creation

var doc = Cx.Document();

Pages

doc.pages(i,a);
doc.activePage();
doc.activePageIndex();
doc.releasePages(pages);

Layers

doc.layers(i,a);
doc.activeLayer();
doc.activeLayerIndex();
doc.releaseLayers(layers);

Figures

doc.figures(i,a);
doc.allFigures();

The document offers helper functions to directly modify the figures in the active layer. The doc.group(figures) function will remove the figures from the document, and add them grouped.

doc.backOne(figures);
doc.toBack(figures);
doc.forwardOne(figures);
doc.toFront(figures);
doc.autoCreateMultiPartText$(figures);
doc.breakMultiPartText(text);
doc.group(figures);
doc.ungroup(figures);
doc.extractPowerClipContents(figure);
doc.addPowerClipContents(figure,content);
doc.reshape$(figures,action);

Transactions

doc.lock();
doc.unlock();
doc.commit$();
doc.revert$();
doc.update$();

Utilities

doc.background();
doc.clone();
doc.toXmlString();

Loading and Saving

Cx.Document.load$(id) .then(function(doc){ ...
Cx.Pages.load$(id) .then(function(pages){ ...
Cx.Layers.load$(id) .then(function(layers){ ...
Cx.Document.fromXmlString(string);
Cx.Document.fromXml(node);
doc.saveCopy$();
doc.save$();
doc.isSaved();

History

Each document keeps track of its history up to undoLimit states. History is used both as a way to let users undo and redo their work, and to allow transactions to be properly reverted.

if( doc.canUndo() )
doc.undo();
if( doc.canRedo() )
doc.redo();

When implementing undo and redo actions for your app, use the canvas.undo() machinery that uses tools history instead of plain document history. Read more about Canvas and tools history in the Canvas reference.

Templating

Adds a clipart centered in the template and with proper scaling (half the template size)

doc.addClipart$(clipart) .then(...

Replaces a clipart taking care of keeping the user transform, placing and size.

doc.replaceClipart$(old, clipart) .then(...

Figures

There are five figure types: Cx.Text, Cx.Shape, Cx.Raster, Cx.Group and Cx.ProxyGroup. They all share the same base: Cx.Figure. These are the common properties and functions.

Properties

Properties Type Def Definition
name String null Figure name
xType String 'CadX.Figure' Figure type
pen Pen empty Figure outline
brush Brush empty Figure fill
alpha 0…1 1 Global alpha
locked Boolean false If true, the figure can not be selected
hidden Boolean false If true, the figure is not visible
visible Boolean true Opposite of hidden
anchor Anchor Relative (0.5,0.5) Figure anchor generator
preMatrix22 Matrix22 Identity Transformation applied before processes
processes Process Array [] Figure effects
matrix22 Matrix22 Identity Figure transformation
pin Point (0, 0) Figure position
powerClipContents PowerClipContent Array [] Power clipped figures
metadata Metadata empty App metadata

Read only properties

Properties Type Def Definition
localId Integer unique Client based unique id, not serialized
canBeSelected Boolean true Is visible and is not locked
outputFigure Figure null Processed figure output
grouped Boolean false The figure is inside a group
isEmpty Boolean false Text with no lines, shape with not polyregions, group with no figures
layer Layer - Layer the figure is part of
topFigure Figure - Top input figure, i.e. main group

Functions

f.clone();
f.toXml();
f.toXmlString();
f.lock();
f.commit$();
f.revert$();
f.update$();
f.invalidate();
f.invalidated();
f.processed();
f.currentlyProcessing();

Transformations

f.translate(offset);
f.translate(dx,dy);
f.scaleFrom(point,sx,sy,deg);
f.rotateAround(point,angle);
f.shearAround(point,sx,sy,deg);
f.transform(matrix);
f.angle();
f.angle(angle,pivot);
f.rotate$(angle);
f.scale$(sx,sy);
f.mirrorX$();
f.mirrorY$();
f.align$(alignment,to,margin);
f.fit$(bounds,config);
f.setSize$({ width, height, locked, pin });
// Options 'nothing', 'bounds', 'center', 'width', 'frame', 'frameCenter', 'frameWidth':
f.modifyKeeping$(what,func);

Color interface

f.setTaggedColors(tag,color);
f.setLabeledColors(label,color);
f.getColors();
f.replaceColor(oldColor,newColor,config);
f.uniqueColorZones(options);
f.changeColorZone(zone,value);
f.getBrushes();
f.replaceBrush(oldBrush,newBrush);
f.uniqueBrushZones(options,zones);
f.changeBrushZone(zone,value);

Power Clip

f.extractPowerClipContents();

Xml CDL

Cx.Figure.fromXml(node);
Cx.Figure.fromXmlString(string);

Conditions

Cx.Figure.condition(name,function(figure){ return boolean });
Cx.Figure.arrayCondition(name,function(figures){ return boolean });
Cx.Figure.saveConditions();
Cx.Figure.restoreConditions();

Text

var text = Cx.Text({
text: 'Hello world!',
fontSize: 50
});
Properties Type Def Definition
text String 'Text' Figure text as a single string (with \n for multiline)
lines String Array ['Text'] Figure text lines
font Font Arial Font
fontSize Number 54.2 Font size
fontAutoSize Boolean true Size is adjusted using the M height
lineDirection Angle 0 Direction of the text line
charDirection Angle 90 Direction of each chararacters
verticalStyle *String’ SingleLine Options: SingleLine, MultiLine
extraCharSpacing Magnitude '0' Extra space between characters
extraWordSpacing Magnitude '0' Extra space between words
extraLineSpacing Magnitude '0' Extra space between lines
columnSpacing Magnitude '0' Column spacing
columnCount Integer 1 Number of columns
linesPerColumn Integer 0 Lines per column, 0 is disabled
linesAlign String 'Center' Options: 'Left', 'Center', 'Right'
fillMode String Winding Options: CadX, Winding, Alternate
powerClipId String null Power clip content link
textParts TextPart Array [] Text Part definition if mutli part

Member Functions

text.isEmpty(); // return text == ''
text.isMultiPart(); // return textParts.length > 0
text.breakIntoParts(); // return Text Array equivalent to the text parts
text.addPowerClipContents(figures); // Add figures to the powerclip content

Multi Part Text

var range = Cx.TextRange({ start: 1, end: 0 });
range.slice(text); // return text range
range.clone();
range.isEqual(other);
var part = Cx.TextPart({ textRange: range, ... text properties ... });
part.clone();
Cx.Figure.autoCreateMultiPartText$(figures) .then(function(multiPartText) { ...

Shape

var shape = Cx.Shape({
polyregions: [...],
brush:{ color:{ rgb: '000000' }}
});

Properties

Properties Type Def Definition
polyregions Polyregion Array [] Shape polyregions
shape.addPowerClipContents(figures);

Shape constructors

var rectangle = Cx.Shape.Rectangle({
bounds: Cx.Bounds(lx,ly,hx,hy)
, brush: brush, pen: pen
};
var rectangle = Cx.Shape.Rectangle({
center: Px(0,0), width: 200, height: 100
, brush: brush, pen: pen
};
var polyline = Cx.Shape.Polyline({
points: [...]
, brush: brush, pen: pen
});

Polyregion

Region

Curve

Polyline

Raster

var raster = Cx.Raster({ imageLink: '30305c17-ef10-4183-9c94-008f9a7c2d6b' });

Properties

Properties Type Def Definition
imageLink Id nul Image Id
width Magnitude null Linked image width
height Magnitude null Linked image height
dpi Number 25.4 Initial DPI
monochromeColors [Color,Color] [] For monochorme bitmaps, color for 0 and 1
raster.isMonochrome();
raster.globalDpi$();
raster.globalDpi_();

Group

var group = Cx.Group.create(figures);

Properties

Properties Type Def Definition
figures Figure Array [] Grouped figures

Member Functions

group.ungroupedFigures(); // return equivalent ungrouped figures
group.regroup(figures); // Add equivalent figures to the group
group.ungroup(figures); // return and remove figures ungrouping them
group.ungroup(); // return and remove all figures, leave the group empty

Helpers

Cx.Group.create(figures); // Create group with equivalent figures

ProxyGroup

var proxy = Cx.ProxyGroup({ link: '...' });

Properties

Properties Type Def Definition
link String null Linked Document Id
width Magnitude null Initial Width
height Magnitude null Initial Height
colors Color Array [] Colors of the linked figures

Metrics

Modifying the model is always a sync operation. Normally there is no need to care about the async nature of the interaction between Canvas and the server. For example:

figure.translate(10,0);
figure.rotateAround(figure.pin(),45);
figure.commit$();

On the other hand, if metrics are needed to define the values that you are going to change then we are in promises land. Getting metrics is an async operation in Canvas.
As every async operation in Canvas, metrics functions are marked with a trailing $ and will return a promise for the computed value:

figure.center$() .then(function(center){
figure.rotateAround(center,45);
figure.commit$();
});

Figure metrics

Name Type Definition
matrix$ Matrix Transformation applied to curve points
bounds$ Bounds Bounds of the rendered figure
center$ Point Center of the figure bounds
frame$ Frame Frame of the rendered figure
vectorBounds$ Bounds Curves Bounds, pens dropped
vectorFrame$ Frame Curves Frame, pens dropped

Pre metrics

The figure frame is computed transforming with the matrix the bounds of the untransformed figure. We call the metrics of the untransformed figure pre metrics. These metrics are needed for some operations like envelope equalization.

Name Type Definition
prePin$ Point Untransformed pin, figure anchor
preBounds$ Bounds Bounds of the untransformed rendered figure
preCenter$ Point Center of the figure pre bounds
preVectorBounds$ Bounds Untransformed Curves Bounds, pens dropped

Global metrics

Grouped figures are then transformed by their parents matrix. Global metrics provide an easy way to know the final bounds of a figure even if they are grouped. If the figure is not grouped, global metrics will be equal to the normal metrics. The global version of the metrics are: globalMatrix$, globalBounds$, globalCenter$, globalFrame$, globalVectorBounds$, globalVectorFrame$, globalPreBounds$ and globalPreVectorBounds$.

Examples

[TODO]

Why metrics are async operations?

Canvas JavaScript engine (Cx) is unable to reproduce every operation supported by the CadWorX CadXEngine server. Only a subset of CDL documents can be completely handled locally. For example, a Text will need the server to process the fonts, generate the vector representation of the characters and arrange them to get to its final output vector shape representation. We call updating to the act of computing the figure’s output representation (composed of only simple shapes and raster figures). Because Cx may need the help of CadXEngine server, updating a figure is an asynchronous operation. Measuring geometry figure properties like bounds and frame requires the output of the figure to be up-to-date.

When using metrics, Canvas takes care of updating the figure behind the scene. Figure updating can also be triggered manually using:

figure.update$() .then(function(figure){
// ...
});

If you already know the figure is up-to-date, you can use synchronous versions of the metrics. The set of functions that needs the figure to be updated are marked with a trailing underscore sign, underscore so developers can easily identify them: bounds, frame, center_:

figure.update$() .then(function(figure){
var b = figure.bounds_();
var f = figure.frame_();
// ...
});

These may be useful in some contexts, but always go for the async version of the metrics first. Calling any metric_ function when the figure is invalidated (its output has not been updated) will result in an exception. As reference, internally metrix$ is implemented like:

metrix$: function(){
return this.update$() .then(function(figure){
return figure.metrix_();
});
}

Transformations

Every transformation method returns the figure or figures that were transformed so you can chain them.

Basic transformation on figures, the deg parameter in scaleFrom and shearAround applies the transform in a rotated space.

figure.translate(x,y); // figure.translate(offset);
figure.scaleFrom(point,sx,sy [,deg]);
figure.rotateAround(point,angle);
figure.shearAround(point,sx,sy [,deg]);
figure.transform(matrix);
Cx.translate(figures, x,y); // Cx.translate(figures, offset);
Cx.scaleFrom(figures, point,sx,sy [,deg]);
Cx.rotateAround(figures, point,angle);
Cx.shearAround(figures, point,sx,sy [,deg]);
Cx.transform(figures, matrix);

Transformations using the center of the figures bounds as the pivot. We need to use metrics here so these operations are asynchronous.

figure.rotate$(angle);
figure.scale$(sx, sy);
figure.mirrorX$();
figure.mirrorY$();
Cx.rotate$(figures, angle);
Cx.scale$(figures, sx, sy);
Cx.mirrorX$(figures);
Cx.mirrorY$(figures);

Alignment

figure.center$( to );
Cx.center$( figures, to );

Center a figure or a figures list. to can be a point or anything that has a center (bounds, frame, other figures).

figure.align$( alignment, to [, margin] );

Align the figure against a given bounds.

  • alignment any combination of Left, Center, Right with Top, Middle, Bottom. Examples: “TopLeft”, “Center”, “Bottom”, “CenterMiddle”. It doesn’t matter the order or if you put a space or a comma between them (this is ok: “Top Right”).
  • to a bounds object of something we can get bounds from (canvas,frame,other figures).
  • margin optional margin for the alignment
Cx.align$( figures, alignment [, to, margin] );

Align a group of figures to a given bounds. If you call it without a to parameter it will align the figures against themselves.

Cx.groupedAlign$( figures, alignment, to [,margin] );

Align the figures without loosing their relative distances.

Examples:

// Center figures in Canvas
Cx.center$( figures, canvas );
// Align figures to the top of the Canvas (respecting relative distances)
Cx.groupedAlign$( figures, 'Top', canvas );
// Align figures baselines
Cx.align$( figures, 'bottom' );

Fitting

Cx.fit$(figures, to,{ locked:[bool], fit:['Max'/'Min'/'Mean'] });

Fits a group of figures to a bounds object or anything that has bounds.

Examples:

// Fit figures to cover the Canvas visible area
Cx.fit$(figures, canvas);
// Fit figures to cover all the figures in the document
Cx.fit$(figures, doc.activePageFigures());
Cx.setSize$(figures, { width:[n], height:[n], locked:[bool], fit:['Max'/'Min'/'Mean'], pin:[point] });

Examples:

// Set the width of the selected figures, preserving aspect ratio.
Cx.setSize$(canvas.selectedFigures(),{width:400})
// Set the width and height of the figures, preserving aspect ratio and area of the bounds.
Cx.setSize$(figures,{width:500,fit:'Mean'});
// Set width and height, do not preserve aspect ratio
Cx.setSize$(figures,{width:100,height:100,locked:false});

Boolean operations

Cx.reshape$(figures,action) .then(function( newFigures ) {
// ...

Performs a reshape action on a list of figures. The action can be any of Cx.E.ReshapeAction: ‘Combine’, ‘Weld’, ‘Condense’, ‘FrontMinusBack’, ‘BackMinusFront’, ‘BreakApart’, ‘BreakApartRegions’ and ‘BreakApartByColor’

Cx.combine$(figures) .then(function( newFigure ){ ...
Cx.weld$(figures) .then(function( newFigure ){ ...
Cx.condense$(figures) .then(function( newFigure ){ ...
Cx.frontMinusBack$(figures) .then(function( newFigure ){ ...
Cx.backMinusFront$(figures) .then(function( newFigure ){ ...

Direct functions for combine type operations. Get a list of figures and return one composed figure.

Working with colors

Cx.forEachColor(figures,function(color){ ... },context);

Iterate through every color of a list of figures.


var zones = Cx.uniqueColorZones(figures, { collapseTags:[bool] });

Returns a list of unique color zones composed of a solid color (both from pens and brushes) and with textures. Each zone has a value member that can be a Cx.Color or a Cx.TextureBrush.


Cx.changeColorZone(figures, zone, newValue);

Replaces a color zone with a new value.

var map = function(color) { return newColor -or- color; };
Cx.convertColors(figures, map);

Converts the colors in the figures using the function map.

Cx.colorAt$(figures, point).then( function(color) ) {
// ...

Gets the color at the given point for a list of figures.

Brushes and Pens

When reading the [[introduction]] you might have noticed among the parameters to initialize the figure that a brush is specified.

For each figure different kinds of brushes and pens can be specified and changed by changing the corresponding [[properties]].

Check the pens and brushes sample app ([[brushespens.html|https://github.com/Stahls/CadXDocumentation/blob/master/brushespens.html]] and [[brushespens.js|https://github.com/Stahls/CadXDocumentation/blob/master/brushespens.js]]) for some examples.

Brushes

figure.brush(brush);
doc.commit$();

Brush types: Brush, LinearGradientBrush, RadialGradientBrush, TextureBrush.

Brush

A regular solid color brush.

Brush Type Def Definition
color Color Black Sets the brush color
Cx.Brush({ color: { rgb: '000000' } });
<Brush><Color RGB="000000"></Color></Brush>

Linear Gradient Brush

Forms a linear gradient using the specified colors and points.

LinearGradientBrush Type Def Definition
colors Color Array [ White, Black ] Gradient Colors
positions Number Array [ 0,1 ] Range (between 0 and 1) of the figure that each color will cover
from Point (0.0,0.5) Relative point where the gradient begins
to Point (1.0,0.5) Relative point where the gradient ends
gammaCorrection Boolean true Gamma correction
Cx.LinearGradientBrush({ from: Px(0.0,0.5), to: Px(1.0,0.5)
, gammaCorrection: true
, positions: [ 0, 1 ]
, colors: [ { rgb: 'FFFFFF' }
, { rgb: '000000' } ] });
<LinearGradientBrush From="0.0 0.5" To="1.0 0.5"
GammaCorrection="True"
Positions="0 1">
<Color RGB="FFFFFF"></Color>
<Color RGB="000000"></Color>
</LinearGradientBrush>

Radial Gradient Brush

Forms a radial gradient using the specified colors and points

RadialGradientBrush Type Def Definition
centerColor Color White Center color
outerColors Color Array [Black] Outer colors
positions Number Array [0,1] Range (between 0.0 and 1.0) of the figure that each color will cover
center Point (0.5,0.5) Sets the relative point where the gradient begins
radiuses Number 1.0 Sets the relative radiuses of the outer colors
Cx.RadialGradientBrush({ centerColor: { rgb: 'FFFFFF' }
, outerColors: [ { rgb: '000000' } ]
, positions: [ 0, 1 ]
, center: 0.5,0.5, radiuses: [1] )});
<RadialGradient CenterColor="White" OuterColors="Black" Positions="0.0 1.0" Center="0.5 0.5" Radiuses="1.0"/>

Texture brush

Adds an image based texture to the figure.

TextureBrush Type Def Definition
imageLink String null Image Id on the server
textureOffset Point (0.0,0.0) Texture relative offset
targetOffset Point (0.0,0.0) Target relative offset
matrix22 Matrix Identity Transform to apply to the image
transformMode Enum Full Options: Fixed, Clamp, RotateOnly, Full, StretchX, StretchY
clippingRect Bounds (0,0,1,1) Relative bounds of the image
Cx.TextureBrush({ imageLink: '...',
, textureOffset: Px(0,0), targetOffset: Px(0,0)
, matrix22: Mx(), transformMode: `Full`
, clippingRect: Cx.Bounds(0,0,1,1) });
<TextureBrush ImageLink="..."
TextureOffset="0 0" TargetOffset="0 0"
Matrix22="1 0 0 1" TransformMode="Full"
ClippingRect="0 0 1 1"/>

Pens

Pen types: Pen, CutPen, EmptyPen, DisplayPen, MaskPen

var pen = Cx.Pen({ width: 2, color: { rgb: color } });
figure.pen(pen);
doc.commit$();

Pen

Pen Type Def Definition
color Color Transparent Pen color
width Number 5 Pen width
startCap Enum Flat Options: Flat, Square, Round, Triangle
endCap Enum Flat Options: Flat, Square, Round, Triangle
dashCap Enum Flat Options: Flat, Round, Triangle
dashStyle Enum Solid Options: Solid, Dash, Dot, DashDot, DashDotDot
lineJoin Enum Round Options: Round, Bevel, Miter, MiterClipped
miterLimit Number 10 Miter limit
behindFill Boolean true Draw the pen behind the fill
Cx.Pen({ color: { rgb: '000000' }, width: 5
, startCap: 'Flat', endCap: 'Flat'
, dashCap: 'Flat', dashStyle: 'Solid'
, lineJoin: 'Round', miterLimit: 10
, behindFill: true });
<Pen Width="5" StartCap="Flat" EndCap="Flat"
DashCap="Flat" DashStyle="Solid"
LineJoin="Round" MiterLimit="10.0"
BehindFill="True">
<Color RGB="000000"></Color>
</Pen>

Processes

Effects can be applied to a Canvas figure using the processes array property.

var processes = figure.processes();
processes.add( process );

Some processes are restricted to specific kinds of figures.

Text processes

Can be applied only to Text.

Changes the size of the first and last letter.

Cx.Capital Type Def Definition
scaleX Number 1 X axis scale to be applied to the letter
scaleY Number 1 Y axis scale to be applied to the letter
hAlignment Enum Center Options: Left, Center, Right
vAlignment Enum Baseline Options: Baseline, Top, Middle, Bottom
pattern Enum 'First Last' Options: 'First', 'Last', 'First Last'
var process = Cx.Capital({ scaleX: 1.5, scaleY: 1.5, vAlignment: 'Middle', pattern: 'First' });
<Capital ScaleX="2" ScaleY="2" HAlignment="Center" VAlignment="Baseline" Pattern="First Last"/>

Similar to Capital but offers better control of the resizing.

Cx.BookEnd Type Def Definition
headSX Number 1 X axis scale to be applied to the first letter
headSY Number 1 Y axis scale to be applied to the first letter
tailSX Number 1 X axis scale to be applied to the last letter
tailSY Number 1 Y axis scale to be applied to the last letter
hAlignment Enum Center Options: Left, Center, Right
vAlignment Enum Baseline Options: Baseline, Top, Middle, Bottom
var process = Cx.BookEnd({ headSX: 1.2, headSY: 1.5, tailSX: 1.2, tailSY: 1.5
, hAlignment: 'Center', vAlignment: 'Bottom' });
<BookEnd HeadSX="1.2" HeadSY="1.5" TailSX="1.2" TailSY="1.5"
HAlignment="Center" VAlignment="Baseline"/>

Fits the text to an arc.

Cx.ClassicArc Type Def Definition
width Number 500 Width of the arc
height Number 100 Height of the arc
from Angle 160 Angle of the arc where the text starts
to Angle 20 Angle of the arc where the text finishes
dontRotate Boolean false Whether to rotate or not the each letter
var process = Cx.ClassicArc({ width: 1000, height: 400, from: 135, to: 45, dontRotate: false });
<ClassicArc Width="1000" Height="400" From="135" To="45" DontRotate="false"/>

Fits the text to an ellipse.

Cx.FitEllipse Type Def Definition
height Number 100 Height of the ellipse
width Number 500 Widht of the ellipse
rotation Number 0 Angle to rotate the text with respect to its center after fitting
placement Number 90 Angle to place the center of the text in the ellipse
mirror Boolean False Whether to use a mirror effect on the text or not
inside Boolean True Whether to fit the text inside the ellipse or not
dontRotate Boolean False Whether to rotate or not the text
fit Enum None Options: None, Scaled, Contained, Stretched, Expanded
var process = Cx.FitEllipse({ height: 100, width: 500, rotation: 0, placement: 90
, mirror: false, inside: true, dontRotate: false, fit: 'None'});
<FitEllipse Height="100" Width="500" Rotation="0" Placement="90"
Mirror="False" Inside="True" DontRotate="False" Fit="None"/>

Fits the text in a defined path.

FitOnPath Type Def Definition
vPos Enum Over Options: Above, Over, Below
hPos Enum Fixed_CenterTop Options: Fixed_Left, Fixed_CenterTop, Fixed_CenterBottom, Fixed_Right, Stretched, Scaled, Expanded
offset Number 0 Offset of the text and the beginning of the path
distanceFromPath Number 0 Distance between the path and the text
placeOnOtherSide Boolean False Whether to place the text on the other side of the path or not
fwd Boolean True Whether place the text forwards or backwards in the path
dontRotate Boolean False Whether to rotate or not the text
overhang Boolean False Whether to use overhang or not
//path Path - The path the text will be fitting to
var process = Cx.FitOnPath({ path: Cx.Curve(points,false)
, vPos: 'Over', hPos: 'Fixed_CenterTop', offset: 0
, distanceFromPath: 0, placeOnOtherSide: false
, fwd: true, dontRotate: false, overhang: false });
<FitOnPath VPos="Over" HPos="Fixed_CenterTop" Offset="0" DistanceFromPath="0"
PlaceOnOtherSide="False" Fwd="True" DontRotate="False" Overhang="False">
<Path Type="Bezier3" IsClosed="False" Points="..."></Path>
</FitOnPath>

Deform processes

This processes deform the figure they’re applied to.

Fits the figure to an arch.

VerticalArch Type Def Definition
height Number 100 Height of the arch
width Number 500 Width of the arc
from Number 160 Angle of the arc where the figure starts
to Number 20 Angle of the arc where the figure starts
var process = Cx.VerticalArch({ height: 100, width: 500, from: 160, to: 20 });
<VerticalArch Height="100" Width="500" From="160" To="20"/>

Makes the figure to be shown as if it was beeing looked from a certain perspective.

Cx.Perspective Type Def Definition
hPoint Point (1000, 0) Horizontal vanishing point
vPoint Point (0, 300) Vertical vanishing point
var process = Cx.Perspective({ hPoint: Px(1000, 0), vPoint: Px(0, 300) });
<Perspective HPoint="1000, 0" VPoint="0, 300"/>

Fits the figure to the form of an envelope

FitEnvelope Type Def Definition
envelope Cx.Envelope Envelope to fit the figure
mode Enum Mixed Options: Mixed, Freeform, Uniform, Boxed
vPos Enum Stretched Options: Stretched, Top, Center, Bottom, Expanded
hPos Enum Stretched Options: Stretched, Left, Center, Right, Expanded
highResolution Boolean False Whether to use or not high resolution
keepLines Boolean False Whether to keep the lines or not
addBearingX Boolean False Whether to add or not bearing x
var process = Cx.FitEnvelope({ envelope: Cx.Envelope(curves)
, mode: 'Mixed'
, vPos: 'Stretched', hPos: 'Stretched'
, highResolution: false, keepLines: false
, addBearingX: false });
<FitEnvelope Mode="Mixed" VPos="Stretched",
HPos="Stretched" HighResolution="False" KeepLines="False"
AddBearingX="False" VPoint="0 300">
<Envelope>
<Curve Type="Bezier3" IsClosed="False" Points="..."></Curve>
<Curve Type="Bezier3" IsClosed="False" Points="..."></Curve>
<Curve Type="Bezier3" IsClosed="False" Points="..."></Curve>
<Curve Type="Bezier3" IsClosed="False" Points="..."></Curve>
</Envelope>
</FitEnvelope>

Decorate processes

This processes decorate the figure (i.e. add elements like shadows or contours).

Adds a border to the figure.

Cx.Border Type Def Definition
dX Number 20 The size of the border for the x axis
dY Number 30 The size of the border for the y axis
gap Number 10 The gap between the parts of the figure if separate
separate Boolean False Whether to separate the figure or not
var process = Cx.Border({ dX: 20, dY: 30, gap: 10, separate: false });
<Border DX="20" DY="30" Gap="10" Separate="False"/>

Add a contour to the figure.

Cx.Contour Type Def Definition
pen Cx.Pen - The pen to use
brush Cx.Brush - The brush to use
offset Number 5 The offset of each contour step
steps Number 1 Number of steps of the contour
inside Boolean false Contour towards the inside
outside Boolean true Contour towards the outside
includeHoles Boolean false Include holes of the input figure
combine Boolean false Combine all parts of the contour in a single shape
chamfer_D Number 0.1 Soften the edges of the contour
chamfer_L Number 0.1 Soften the edges of the contour
var process = Cx.Contour({ pen: Cx.Pen({ width: 2, color:{ rgb: '0000FF' } })
, brush: Cx.Brush({ color:{ rgb: 'FF0000' } })
, offset: 5, steps: 1, inside: false, outside: true
, includeHoles: false, combine: false
, chamfer_D: 0.1, chamfer_L: 0.1 });
<Contour Offset="5" Steps="1" Inside="False" Outside="True"
IncludeHoles="False" Combine="False"
Chamfer_D="0.1" Chamfer_L="0.1">
<Pen Width="2"><Color RGB="0000FF"></Pen>
<Brush><Color RGB="FF0000"></Color></Brush>
</Contour>

Add a contour to the figure made with a list of pens.

Cx.PenContour Type Definition
pens Pens Array Each pen defines a step with the given width
var process = Cx.PenContour({ pens: [
Cx.Pen({ width: 5, color:{ rgb: 'FF0000' } })
, Cx.Pen({ width: 3, color:{ rgb: '0000FF' } })
]});
<PenContour>
<Pens>
<Pen Width="5"><Color RGB="FF0000"></Color></Pen>
<Pen Width="3"><Color RGB="0000FF"></Color></Pen>
</Pens>
</PenContour>

Add a shadow to the figure.

Cx.Shadow Type Def Definition
pen Pen - The pen to use
brush Brush - The brush to use
offsetX Number 5 The X offset of the shadow
offsetY Number 5 The Y offset of the shadow
gap Number 10 The gap between the figure and the shadow
simplify Boolean false Simplified output
var process = Cx.Shadow({ pen: Cx.Pen({ width: 2, color:{ rgb: '0000FF' } })
, brush: Cx.Brush({ color:{ rgb: 'FF0000' } })
, offsetX: 5, offsetY: 5, gap: 10, simplify: false });
<Shadow OffsetX="5" OffsetY="5" Gap="5" Simplify="False">
<Pen Width="2"><Color RGB="0000FF"></Pen>
<Brush><Color RGB="FF0000"></Color></Brush>
</Shadow>

Same as shadow except that this process only uses raster pens.

Cx.RasterShadow Type Def Definition
pen Pen - The pen to use
brush Brush - The brush to use
offsetX Number 5 The X offset of the shadow
offsetY Number 5 The Y offset of the shadow
gap Gap - The gap between the figure and the shadow
var gap = Cx.RasterShadowGap({ pen: Cx.Pen({ width: 1, color:{ rgb: 'FFFFFF' } })} });
var process = Cx.RasterShadow({ pen: Cx.Pen({ width: 2, color:{ rgb: '0000FF' } })
, brush: Cx.Brush({ color:{ rgb: 'FF0000' } })
, offsetX: 5, offsetY: 5
, gap: gap };
<RasterShadow OffsetX="5" OffsetY="5">
<Pen Width="2"><Color RGB="0000FF"></Pen>
<Brush><Color RGB="FF0000"></Color></Brush>
<Gap>
<Pen Width="1"><Color RGB="FFFFFF"></Pen>
</Gap>
</RasterShadow>

Gives the figure a 3d effect.

Cx.Effect3d Type Def Definition
borderIntensity Number 0.7 The border intensity
borderSize Number 1.0 The border size
contourOffset Number 1.0 The contour offset
lightGap Number 2.0 The light gap
lightIntensity Number 0.7 The light intensity
lightSize Number 3.0 The light size
lightSource Enum Up Options: Up, Right, Down, Left
shadowIntensity Number 0.35 The shadow intensity
shadowSizePercentage Number 0.95 The percentage of the shadow size
slopeIntensity Number 0.3 The slope intensity
slopeSize Number 1.5 The slope size
var process = Cx.Effect3d({ borderIntensity: 0.7, borderSize: 1.0, contourOffset: 1.0
, lightGap: 2.0, lightIntensity: 0.7, lightSize: 3.0, lightSource: 'Up'
, shadowIntensity: 0.35, shadowSizePercentage: 0.95
, slopeIntensity: 0.3, slopeSize: 1.5});
<Effect3d BorderIntensity:"0.7" BorderSize="1.0" ContourOffset="1.0"
LightGap="2.0" LightIntensity="0.7" LightSize:"3.0" LightSource="Up"
ShadowIntensity="0.35" ShadowSizePercentage="0.95"
SlopeIntensity="0.3" SlopeSize="1.5"/>

Extrude3D

Gives the figure a 3d extrude effect.

Cx.Extrude3D Type Def Definition
pen Pen - The pen to use
brush Brush - The brush to use
depth Number 10 Depth of the extruding shape
vanishingPoint Point (0,0) Vanishing point
rotationX Number 0 Rotation with respect to x axis
rotationY Number 0 Rotation with respect to y axis
rotationZ Number 0 Rotation with respect to z axis
var process = Cx.Extrude3D({ pen: Cx.Pen({ width: 2, color:{ rgb: '0000FF' } })
, brush: Cx.Brush({ color:{ rgb: 'FF0000' } })
, depth: 10, vanishingPoint: Px(0,0)
, rotationX: 0, rotationY: 0, rotationZ: 0 });
<Extrude3D Depth="10" VanishingPoint="0 0" RotationX="0" RotationY:"0" RotationZ="0">
<Pen Width="2"><Color RGB="0000FF"/></Pen>
<Brush><Color RGB="FF0000"></Color></Brush>
</Extrude3D>

Split

Splits the figure.

Cx.Split Type Def Definition
overlap Number 0 The amount of the figure to overlap when splitting
pos Number 0.5 Position where the gap will be, 0.5 is the middle of the figure
turn Number 0 Angle to rotate the gap respect to the y axis
gap Number 10 The size of the gap
var process = Cx.Split({ overlap: 0, pos: 0.5, turn: 0, gap: 10 });
<Split Overlap:"0" Pos="0.5" Turn="0" Gap="10"/>

Utilities

Raster operations

Cx.rasterize$( figures, { dpi: 25.4 } )
.then( function( rasters ){
// ...
});

Converts figures to a raster representation. By default the dpi is 25.4 * 3, allowing for some looseless up scaling afterwards.

Cx.vectorize$( rasters, {
backColors : [ 'FFFFFF' ]
, foreColors : [ '000000', 'FF0000' ]
, regionResolution: 6
, fitToCurveResolution: 7
})
.then( function( vectorFigures ) {

Convert the raster figures in vector representations.

Cut Outline

Cx.cutOutline$( figures, { offset: 10 })
.then( function( cutOutlineFigures ) {
// ...

Create a cut outline around a list of figures.

General

var f = Cx.findByType(figures,type);
var fs = Cx.filterByType(figures,type);

find and filter versions to work with types directly.

Cx.forEachText(figures, function(text){ ... }, context);
Cx.forEachShape(figures, function(shape){ ... }, context);
Cx.forEachRaster(figures, function(raster){ ... }, context);
Cx.forEachGroup(figures, function(group){ ... }, context);
Cx.forEachProxyGroup(figures, function(proxyGroup){ ... }, context);

Iteration by figure type.

var cs = Cx.cloneDeep(figures);

Configuration

Canvas API offers extensions and global parameters to configure the user experience in a per client basis. To set up your configuration options is to include a Cx.Canvas.Config.js file after Canvas scripts has been loaded (this may improve later when Canvas starts offering head.js based loading tools).

<!-- Load Canvas Scripts -->
...
<!-- End Canvas Scripts section -->
<script type="text/javascript" src="Cx.Canvas.Config.js"></script>

In this file, you will define the configuration of Canvas just as you would do with a Web.Config file in ASP.Net.

User defined typed metadata for figures

It is very useful to be able to attach metadata to each figure in a document when implementing the client logic. Things like “Fabric”, “Material” or “HighQualityPrinting” may only have meaning in the particular context of a certain application. The approach that Canvas takes, it to give clients the basic properties that are common when building graphic application and offer an extension point for user defined properties.

In you Cx.Canvas.Config.js file you can call the function:

Cx.Figure.setupClientProperties({
fabricType : { type: 'string', def: 'Cotton' }
, highQualityPrinting : { type: 'boolean', def: false, dropDef:true }
// , ... other properties
});

Once this is inplace your client can use their own defined properties in the same way it uses the normal figures properties (like “pin, “layer”, etc).

// In the client code
// getter
var ft = figure.fabricType() ;
// setter
figure.fabricType('Linen');

For each property, the type config option let the system do automatic parsing into the real representation of your properties. You can select ‘string’, ‘number’, ‘integer’, ‘boolean’, ‘point’, ‘color’, ‘brush’, etc. For a complete list read this non existent documentation (?). This is very useful to avoid writing code like parseInt( figure.charLimit() ) in your code base that can lead to subtle bugs.

The def config set up a default value for figures where the property has not been yet defined and dropDef controls if the value is going to be dropped from the CDL in the case it is the default. This is useful for metadata that has a clear default that will not change in the future. For example, the Text columnCount property is dropped if its value is 1.

You can check a real configuration file used by Kiosk4 here: Cx.Canvas.Config.js

Properties defined by one client and stored in Cx servers are not going to be dropped, even if other clients will open these documents. All the metadata will be kept safe as an internal key-value dictionary in the figures.

Because other clients may later use the same names, it is convenient to use some kind of namespace when naming your client defined properties. For TX project we are using properties with names like “txName”.

Global parameters

Canvas exposed several global parameters that control optimizations, general user interface related strategies and debugging modes. To change a particular variable use:

Cx.Global.configurationVariableName = enabled; // true-or-false

This is a (probably) incomplete list of configuration variables. Look directly in the source code to check an up-to-date version of it.

Name Def What it does
enableDocumentHistory true Document history is an expensive feature that simple applications should be able to disable. If you only care for quick rendering like in a Kiosk application and the UI is not going to offer undo/redo functionality, set this variable to false.
useCurvesBasedSelection true If the shapes are big enough, the user will be able to select a figure behind other figures frame. Disable this option to get pure frame based selection.
useCharactersBBoxBasedSelection true If the figure is a Text, avoid using the internal curves and perform the hit testing using the character bounding boxes. This allows us to take into account the pen width and offer the user big enough hit surfaces for the letters.
renderLocallyWhenPossible true For simple cases, when there are not TextureBrush, PowerClips or other unsuppoted CDL properties, the figure will be drawn locally using SVG and Raphael instead of calling the server RenderCachedFigure (Core: Figure/Render).
avoidCacheWhenRenderLocally true If we can draw locally, then there is no need to cache the figure.
renderPenBehindFillLocally true SVG does not support pens behind fill directly, so we have to produce the same effect by doing one path with the pen and another copy of the path with fill over it. Disable this option if the browser is having problems copying with the extra curves.
renderAnisotropicTransformLocally true SVG applies transforms to the pen nib. In chrome and firefox this can be disabled using the vector-effect property setted to non-scaling-stroke and compensate for the scaling factor manually. This flag enables local rendering for both browsers and leaves IE with server rendering.
processLocallyWhenPossible true For simple shapes we can avoid the call to Figure/Render directly because there is no processing needed to be done. This option improves a lot the experience when dealing with cliparts. The only caveat is that this figures will not have a cache Id so some idioms that the Designer2 was using needs to be updated to always call the new async function CadX.Figures.cache first.
showLocalPreviewRepresentation true When a server image representation is requested for the first time to the server a preview grayed local SVG based representation will be showed to the user as visual feedback.
showServerRenderingLoadingAnimation true When a server image representation is requested for the first time to the server and it is not possible to do a local preview (because the figure is a Raster or showLocalPreviewRepresentation is false) a loading animation is showed in the place the figure will appear.
previewUsingRealRepresentation true Brushes and pens are applied to the preview to match as best as possible the real representation while waiting for the server.
replaceColorsLocallyWhenPossible true When the figure can be drawn locally we can avoid re-processing it in the server for color replacing operations and directly replace the colors in the output figure maintained locally. This will invalidate the relationship between the current cached figure in the server and the local representation so the cache Id of the figure is dropped in the process.
useSubpixelPinForServerRendering true When asking an image to the server we only use a subpixel version of the pin. When the figure is translated an integer number of pixels (given the current zoom) we can use fastTranslate because we know that the image returned by the server will be exactly the same (because the subpixel pin is equal). This happens when users move things dragging it on the screen. Disabling this option will avoid the use of fastTranslate and always ask the server to render using the real pin. This is not something you will like to disable often, since the experience you will get is a lot worse.
computeFigureGeometryLocally true The bounding box and final transformation of the figures will be updated using the local object model instead of calling the server MeasureRenderInfo.
alwaysRenderLocally false This option will force the system to render everything locally even when the result is not perfect because of unsupported CDL properties. It is a good idea to use it when testing some things because of the speed improvements. This option overrides the renderLocallyWhenPossible option.