This is a sample library that use Irony.Net to define a grammar to print PDF using PdfSharpCore
var parser = new Irony.Parsing.Parser(new PdfGrammar());
var parsingResult = parser.Parse(File.ReadAllText("pdfsharp.ipdf"));
if (parsingResult.HasErrors())
{
//show Error
foreach (var error in parsingResult.ParserMessages)
{
Console.Write(error.Location.ToString());
Console.Write("=>");
Console.WriteLine(error);
}
}
else
{
//PdfSharpCore cclasses
var document = new PdfDocument();
//draw parsing result
using var drawer = new PdfDocumentDrawer(document);
new PdfDrawerVisitor().Draw(drawer, parsingResult);
document.Save("helloworld.pdf");
}
or download source code, then goto PdfSharpDslConsole and run it
dotnet run
sequenceDiagram
participant yourprogram
participant PdfSharpDslCore
participant Irony
participant PdfSharp
yourprogram->>Irony: Parse file or text.
Irony -->> PdfSharpDslCore: use PdfGrammar.
Irony-->>yourprogram: Parsing result.
yourprogram->>PdfSharpDslCore: Define callback for Formula functions.
yourprogram->>PdfSharpDslCore: Draw()
PdfSharpDslCore -->>PdfSharp: use Document to draw.
PdfSharpDslCore->>yourprogram: call registered formula functions.
yourprogram-->>PdfSharpDslCore: function result.
PdfSharpDslCore->>PdfSharpDslCore: execute all instructions from source file.
PdfSharpDslCore-->>yourprogram: end of draw
It's a list of drawing "orders" follow by ';'
All coordinates are specified in 'points'
- 1 inch = 72.0 points
- 1 millimeter = 72.0 points / 25.4 ~=> 2.84 points
- 1 centimeter = 72.0 points / 2.54 ~=> 28.34 points
- a formula result can be string or double
- aritmetic/boolean operations are : +, -, /, *, %, >, <, >=, <=,==, <>, and, or
- variable reference : $VarName, and must be declared before with SET VAR VarName=Formula
- a formula is a string or a boudle value
- Boolean comparison are resolved using double, 0.0 => false, other value => true
- string comparison accept only <>, == operators
SET VAR A=2
SET VAR B=3
SET VAR CSquare=$A*$A+$B*$B
Formula can be used in :
- each number in [PointLocation, RectLocation, Width, FontSize, startAngle, sweepAngle]
- in UserDefineFunction (UDF)
- in IF condition
Formula support also customFunction
- Register a formula function in your code
var visitor = new PdfDrawerVisitor();
visitor.RegisterFormulaFunction("SUM", (args) => args.Sum(x => Convert.ToDouble(x)));
- then use it in formulas
SET VAR CSquare=Sum($A*$A, $B*$B+Sum(1,2,3))
# SET PEN Color Width [Style]
SET PEN black 1;
SET PEN black 1 solid;
SET PEN black 1 dot;
SET PEN black 1 dashdot;
SET PEN black 1 dashdotdot;
**Width** is one of
- number
- Formula
# SET BRUSH Color
SET BRUSH black;
**Color** is one of
- NamedColor : [color list](./README.md#named-color-list)
- HexColor : 0xRGB
- sample: 0xFFEEBB
# SET FONT FontName FontSize [FontStyle]
SET FONT Name="Arial" Size=20 bold;
FontName is one of
- string
- Formula
[FontStyle] is one of
- regular (if not specified)
- bold
- italic
- bolditalic
- underline
- strikeout
Draw text with a specified margin from top or bottom if negative.
# TITLE HAlign=HorizontalAlignment Text="text to draw"
TITLE HAlign=hcenter Text="TITLE TEST";
# TITLE [MarginTop] HorizontalAlignment "text to draw"
TITLE Margin=50 HAlign=hcenter Text="My title with margin 50";
HorizontalAlignment : left, hcenter, right [MarginTop] : margin from top if positive, margin from bottom if negative
# ELLIPSE RectLocation
ELLIPSE 5, 5, -5, -5;
# RECT RectLocation
RECT 5, 5, -5, -5;
SET BRUSH orange;
# FILLRECT RectLocation
FILLRECT 250, 100, 50,50;
SET BRUSH green;
# FILLELLIPSE RectLocation
FILLELLIPSE 250, 200, 50,50;
# LINE RectLocation
LINE 100,100, 200, 100;
here Width and Height of RectLocation is X1 and Y1
LINE, ELLIPSE, RECT use PEN (outline)
FILLRECT, FILLELLIPSE use PEN (outline) and BRUSH (fill)
RectLocation is one of
- positive number : number of point from left
- negative number : number of point from right
- formula : supports only "+ - * / ( )"
# PIE RectLocation startAngle sweepAngle
PIE 10,10,120,120 Start=0 Angle=90;
FILLPIE 10,10,120,120 Start=0 Angle=90;
# POLYGON PointLocation PointLocation PointLocation [PointLocation PointLocation PointLocation ...]
POLYGON 300,300, 350,320, 330,350, 240,240;
FILLPOLYGON 100,100, 150,120, 130,150, 240,40;
# MOVETO PointLocation
# LINETO PointLocation
MOVETO 300, 200;
LINETO 400, 200;
LINETO 400, 220;
LINETO 300, 200;
# NEWPAGE [PageSize] [PageOrientation];
NEWPAGE ;
NEWPAGE A4 portrait;
[PageSize] is one of
- A0, A1, A2, A3, A4, A5, A6, B0, B1, B2, B3, B4, B5, Crown, Demy, DoubleDemy, Elephant, Executive, Folio, Foolscap, GovernmentLetter, LargePost, Ledger, Legal, Letter, Medium, Post, QuadDemy, Quarto, RA0, RA1, RA2, RA3, RA4, RA5, Royal, Size10x14, Statement, STMT, Tabloid, Undefined
[PageSize] is one of
- portrait, landscape
# IMAGE PointLocation Source=ImageFilePath
IMAGE 100,100 Source="./imageTest.jpg";
# IMAGE PointLocation Data=Base64 encoded image
IMAGE 100,100 Source="data:image/...";
# IMAGE PointLocation,width,height width_height_unit ImageFilePath
IMAGE 320,100,34,34 point Source="./imageTest.jpg";
# IMAGE PointLocation,width,height width_height_unit [cropping] ImageFilePath
IMAGE 100,320,50,50 pixel crop Source="C:\\Samples\\imageTest.jpg";
IMAGE 100,320,50,50 pixel crop Source="C:/Samples/imageTest.jpg";
ImageFilePath : path can be relative or absolute
width_height_unit : 'point' or 'pixel'
- when specified image is scale to provided rectangle
[cropping] : don't scale but crop image from provided rectangle
# LINETEXT PointOrRect [hAlign] [vAlign] [Orientation] Text="text"
LINETEXT 42,100 Text="Horizontal text"
LINETEXT 42,100 vertical Text="Horizontal text"
LINETEXT 42,100 left bottom vertical Text="Horizontal text";
[hAlign] is one of
- left, right, hcenter
[vAlign] is one of
- top, bottom, vcenter
[Orientation] is one of
- horizontal, vertical
# TEXT PointOrRect [MaxWidth=formula] Text="text"
TEXT 42,100 Text="Horizontal text"
TEXT 42,100 MaxWidth=50 Text="Horizontal text"
- specify MaxWidth to wrap text on multi-lines
- this 'TEXT' cannot be align
# ROWTEMPLATE Count=formula Y=formula [BorderSize=formula]
# ENDROWTEMPLATE
ROWTEMPLATE Count=3 Y=300 BorderSize=5
# top line under border
LINE 0,0,$PAGEWIDTH-20, 0;
LINE 0,0,50, 50;
# bottom line under border
LINE 0,50,$PAGEWIDTH-20, 50;
ENDROWTEMPLATE
# rect include borders
RECT 0,300, $PAGEWIDTH-20, $LASTTEMPLATEHEIGHT
This statement is like a table, but only for row
- foreach loop the start point is 0,0
- you can access to variable '$ROWINDEX' inside template
- after template you can access to '$LASTTEMPLATEHEIGHT' to know the height(in point) of the previous template
[BorderSize]
- is to add space between each loop
- a space is added on top and at bottom when specified
Udf is like a method in C#, where you can group instructions and reuse multiple times
UDF MyUdf()
LINETEXT 100,100 Text="Horizontal text"
ENDUDF
UDF MyUdf1(X,Y)
LINETEXT $X,$Y Text="Horizontal text"
ENDUDF
udf with parameters
UDF HEXAGONE(X, Y, T)
SET VAR SQRT3=1.7320;
LINETEXT $X-$T/2, $Y-$T*$SQRT3/2 HAlign=left VAlign=bottom Text="MOVETO/LINETO";
MOVETO $X-$T/2, $Y-$T*$SQRT3/2;
LINETO $X+$T/2, $Y-$T*$SQRT3/2;
LINETEXT $X+$T/2,$Y-$T*$SQRT3/2 HAlign=left VAlign=bottom Orientation=60 Text="LINETO";
LINETO $X+$T, $Y+0;
LINETEXT $X+$T, $Y+0 HAlign=left VAlign=bottom Orientation=120 Text="LINETO";
LINETO $X+$T/2, $Y+$T*$SQRT3/2;
LINETEXT $X+$T/2, $Y+$T*$SQRT3/2 HAlign=left VAlign=bottom Orientation=$PI Text="LINETO";
LINETO $X-$T/2, $Y+$T*$SQRT3/2;
LINETEXT $X-$T/2, $Y+$T*$SQRT3/2 HAlign=left VAlign=bottom Orientation=240 Text="LINETO";
LINETO $X-$T, $Y+0;
LINETEXT $X-$T, $Y+0 HAlign=left VAlign=bottom Orientation=300 Text="LINETO";
LINETO $X-$T/2, $Y-$T*$SQRT3/2;
ENDUDF
introduce in 1.0.4
UDF __ONENEWPAGE()
# called on each new page
# add here your custom draw (example draw PageIndex)
LINETEXT ($PAGEWIDTH/2),$PAGEHEIGHT HAlign=hcenter VAlign=bottom Text=$PAGEINDEX;
ENDUDF
if you redefine 'MyUdf' in C# you can control
var visitor = new PdfDrawerVisitor();
visitor.RegisterCustomUdf("MyUdf", (drawer, argNames, argValues) => {
//....
//this udf is called before udf define in '.ipdf' file
drawer.DrawLineText("Horizontal Text", 100,100,null,null,
XStringAlignment.Near, XLineAlignment.Far,
new TextOrientation(){Orientation=TextOrientationEnum.Horizontal, Angle = 0});
//return true to override, false to execute also udf define un .ipdf
return true;
});
CALL MyUdf();
# udf with parameters
CALL MyUdf1(100,100);
each parameter can be a Formula
DEBUGOPTIONS Option1 [, Option2];
Available options
- DEBUG_TEXT : shows red rect around texts
- DEBUG_RULE : shows rule on each page
- DEBUG_ROWTEMPLATE : shows red rect around each iteration and index number of each at topleft rectangle
- text format is "{level}.{index}", where level is > 0 when ROWTEMPLATE is part of another ROWTEMPALTE
aliceblue antiquewhite aqua aquamarine azure beige bisque black blanchedalmond blue blueviolet brown burlywood cadetblue chartreuse chocolate coral cornflowerblue cornsilk crimson cyan darkblue darkcyan darkgoldenrod darkgray darkgreen darkkhaki darkmagenta darkolivegreen darkorange darkorchid darkred darksalmon darkseagreen darkslateblue darkslategray darkturquoise darkviolet deeppink deepskyblue dimgray dodgerblue firebrick floralwhite forestgreen fuchsia gainsboro ghostwhite gold goldenrod gray green greenyellow honeydew hotpink indianred indigo ivory khaki lavender lavenderblush lawngreen lemonchiffon lightblue lightcoral lightcyan lightgoldenrodyellow lightgray lightgreen lightpink lightsalmon lightseagreen lightskyblue lightslategray lightsteelblue lightyellow lime limegreen linen magenta maroon mediumaquamarine mediumblue mediumorchid mediumpurple mediumseagreen mediumslateblue mediumspringgreen mediumturquoise mediumvioletred midnightblue mintcream mistyrose moccasin navajowhite navy oldlace olive olivedrab orange orangered orchid palegoldenrod palegreen paleturquoise palevioletred papayawhip peachpuff peru pink plum powderblue purple red rosybrown royalblue saddlebrown salmon sandybrown seagreen seashell sienna silver skyblue slateblue slategray snow springgreen steelblue tan teal thistle tomato transparent turquoise violet wheat white whitesmoke yellow yellowgreen
this package is build on top of
-
PDF :
- pdfSharpCore : https://github.com/ststeiger/PdfSharpCore
-
Parsers :
You can generate C# from PDF DSL, in order to have "hard coded" PDF. You can generate C# code of UDF (user define function)
- is not yet available