using it.stefanochizzolini.clown.documents;
using it.stefanochizzolini.clown.documents.contents;
using it.stefanochizzolini.clown.documents.contents.colorSpaces;
using it.stefanochizzolini.clown.documents.contents.composition;
using entitiesit.stefanochizzolini.clown.documents.contents.entities;
using it.stefanochizzolini.clown.documents.contents.fonts;
using it.stefanochizzolini.clown.documents.contents.objects;
using it.stefanochizzolini.clown.files;
using System;
using System.Collections.Generic;
using System.Drawing;
namespace it.stefanochizzolini.clown.samples{
/**
<summary>This sample demonstrates some of the graphics operations available
through the PrimitiveFilter and BlockFilter classes.</summary>
*/
public class GraphicsSample
: ISample
{
#region static
#region fields
private static readonly DeviceRGBColor SampleColor = new DeviceRGBColor(1,0,0);
private static readonly DeviceRGBColor BackColor = new DeviceRGBColor(210/256d,232/256d,245/256d);
#endregion
#endregion
#region dynamic
#region interface
#region public
#region ISample
public void Run(
SampleLoader loader
)
{
// 1. Instantiate a new PDF file!
/* NOTE: a File object is the low-level (syntactic) representation of a PDF file. */
File file = new File();
// 2. Get its corresponding document!
/* NOTE: a Document object is the high-level (semantic) representation of a PDF file. */
Document document = file.Document;
// 3. Insert the contents into the document!
BuildCurvesPage(document,loader);
BuildMiscellaneousPage(document,loader);
BuildSimpleTextPage(document,loader);
BuildTextBlockPage(document,loader);
// (boilerplate metadata insertion -- ignore it)
loader.BuildAccessories(document,this.GetType(),"Composition elements","applying the composition elements");
// 4. Serialize the PDF file (again, boilerplate code -- see the SampleLoader class source code)!
loader.Serialize(file,this.GetType().Name,false);
}
#endregion
#endregion
#region private
private void BuildCurvesPage(
Document document,
SampleLoader loader
)
{
// 1. Add the page to the document!
Page page = new Page(document); // Instantiates the page inside the document context.
document.Pages.Add(page); // Puts the page in the pages collection.
SizeF pageSize = page.Size.Value;
// 2. Create a content builder for the page!
PrimitiveFilter builder = new PrimitiveFilter(page);
// 3. Drawing the page contents...
builder.SetFont(
new StandardType1Font(
document,
StandardType1Font.FamilyNameEnum.Courier,
true,
false
),
32
);
{
BlockFilter blockFilter = new BlockFilter(builder);
blockFilter.Begin(new RectangleF(30,0,pageSize.Width-60,50),AlignmentXEnum.Center,AlignmentYEnum.Middle);
blockFilter.ShowText("Curves");
blockFilter.End();
}
// 3.1. Arcs.
{
double y = 100;
for(
int rowIndex = 0;
rowIndex < 4;
rowIndex++
)
{
int angleStep = 45;
int startAngle = 0;
int endAngle = angleStep;
double x = 100;
double diameterX;
double diameterY;
switch(rowIndex)
{
case 0: default:
diameterX = 40;
diameterY = 40;
break;
case 1:
diameterX = 40;
diameterY = 20;
break;
case 2:
diameterX = 20;
diameterY = 40;
break;
case 3:
diameterX = 40;
diameterY = 40;
break;
}
for(
int index = 0,
length = 360/angleStep;
index < length;
index++
)
{
RectangleF arcFrame = new RectangleF((float)x,(float)y,(float)diameterX,(float)diameterY);
// Drawing the arc frame...
builder.BeginLocalState();
builder.SetLineWidth(0.25);
builder.SetLineDash(3,5,5);
builder.DrawRectangle(arcFrame);
builder.Stroke();
builder.End();
// Draw the arc!
builder.DrawArc(arcFrame,startAngle,endAngle);
builder.Stroke();
endAngle += angleStep;
switch(rowIndex)
{
case 3:
startAngle += angleStep;
break;
}
x += 50;
}
y += diameterY + 10;
}
}
// 3.2. Circle.
{
RectangleF arcFrame = new RectangleF(
100,
300,
100,
100
);
// Drawing the circle frame...
builder.BeginLocalState();
builder.SetLineWidth(0.25);
builder.SetLineDash(3,5,5);
builder.DrawRectangle(arcFrame);
builder.Stroke();
builder.End();
// Drawing the circle...
builder.SetFillColor(new DeviceRGBColor(1,0,0));
builder.DrawEllipse(arcFrame);
builder.FillStroke();
}
// 3.3. Horizontal ellipse.
{
RectangleF arcFrame = new RectangleF(
210,
300,
100,
50
);
// Drawing the ellipse frame...
builder.BeginLocalState();
builder.SetLineWidth(0.25);
builder.SetLineDash(3,5,5);
builder.DrawRectangle(arcFrame);
builder.Stroke();
builder.End();
// Drawing the ellipse...
builder.SetFillColor(new DeviceRGBColor(0,1,0));
builder.DrawEllipse(arcFrame);
builder.FillStroke();
}
// 3.4. Vertical ellipse.
{
RectangleF arcFrame = new RectangleF(
320,
300,
50,
100
);
// Drawing the ellipse frame...
builder.BeginLocalState();
builder.SetLineWidth(0.25);
builder.SetLineDash(3,5,5);
builder.DrawRectangle(arcFrame);
builder.Stroke();
builder.End();
// Drawing the ellipse...
builder.SetFillColor(new DeviceRGBColor(0,0,1));
builder.DrawEllipse(arcFrame);
builder.FillStroke();
}
// 3.5. Spirals.
{
double y = 500;
double spiralWidth = 100;
builder.SetLineWidth(.5);
for(
int rowIndex = 0;
rowIndex < 3;
rowIndex++
)
{
double x = 150;
double branchWidth = .5;
double branchRatio = 1;
for(
int spiralIndex = 0;
spiralIndex < 4;
spiralIndex++
)
{
double spiralTurnsCount;
switch(rowIndex)
{
case 0: default:
spiralTurnsCount = spiralWidth/(branchWidth*8);
break;
case 1:
spiralTurnsCount = spiralWidth/(branchWidth*8*(spiralIndex*1.15+1));
break;
}
switch(rowIndex)
{
case 2:
builder.SetLineDash(0,10,5);
builder.SetLineCap(LineCapEnum.Round);
break;
default:
break;
}
builder.DrawSpiral(
new PointF((float)x,(float)y),
0,
360*spiralTurnsCount,
branchWidth,
branchRatio
);
builder.Stroke();
x += spiralWidth + 10;
switch(rowIndex)
{
case 0: default:
branchWidth += 1;
break;
case 1:
branchRatio += .035;
break;
}
switch(rowIndex)
{
case 2:
builder.SetLineWidth(builder.State.LineWidth+.5);
break;
}
}
y += spiralWidth + 10;
}
}
// 4. Flush the contents into the page!
builder.Flush();
}
private void BuildMiscellaneousPage(
Document document,
SampleLoader loader
)
{
// 1. Add the page to the document!
Page page = new Page(document); // Instantiates the page inside the document context.
document.Pages.Add(page); // Puts the page in the pages collection.
SizeF pageSize = page.Size.Value;
// 2. Create a content builder for the page!
PrimitiveFilter builder = new PrimitiveFilter(page);
// 3. Drawing the page contents...
builder.SetFont(
new StandardType1Font(
document,
StandardType1Font.FamilyNameEnum.Courier,
true,
false
),
32
);
{
BlockFilter blockFilter = new BlockFilter(builder);
blockFilter.Begin(new RectangleF(30,0,pageSize.Width-60,50),AlignmentXEnum.Center,AlignmentYEnum.Middle);
blockFilter.ShowText("Miscellaneous");
blockFilter.End();
}
builder.BeginLocalState();
builder.SetLineJoin(LineJoinEnum.Round);
builder.SetLineCap(LineCapEnum.Round);
// 3.1. Polygon.
builder.DrawPolygon(
new PointF[]
{
new PointF(100,200),
new PointF(150,150),
new PointF(200,150),
new PointF(250,200)
}
);
// 3.2. Polyline.
builder.DrawPolyline(
new PointF[]
{
new PointF(300,200),
new PointF(350,150),
new PointF(400,150),
new PointF(450,200)
}
);
builder.Stroke();
// 3.3. Rectangle (both squared and rounded).
int x = 50;
int radius = 0;
while(x < 500)
{
if(x > 300)
{
builder.SetLineDash(3,5,5);
}
builder.SetFillColor(new DeviceRGBColor(1,x / 500d, x / 500d));
builder.DrawRectangle(
new RectangleF(x,250,150,100),
radius // NOTE: radius parameter determines the rounded angle size.
);
builder.FillStroke();
x += 175;
radius += 10;
}
builder.End(); // End local state.
builder.BeginLocalState();
builder.SetFont(
builder.State.Font,
12
);
// 3.4. Line cap parameter.
int y = 400;
foreach(LineCapEnum lineCap
in (LineCapEnum[])Enum.GetValues(typeof(LineCapEnum)))
{
builder.ShowText(
lineCap + ":",
new PointF(50,y),
AlignmentXEnum.Left,
AlignmentYEnum.Middle,
0
);
builder.SetLineWidth(12);
builder.SetLineCap(lineCap);
builder.DrawLine(
new PointF(120,y),
new PointF(220,y)
);
builder.Stroke();
builder.BeginLocalState();
builder.SetLineWidth(1);
builder.SetStrokeColor(DeviceRGBColor.White);
builder.SetLineCap(LineCapEnum.Butt);
builder.DrawLine(
new PointF(120,y),
new PointF(220,y)
);
builder.Stroke();
builder.End(); // End local state.
y += 30;
}
// 3.5. Line join parameter.
y += 50;
foreach(LineJoinEnum lineJoin
in (LineJoinEnum[])Enum.GetValues(typeof(LineJoinEnum)))
{
builder.ShowText(
lineJoin + ":",
new PointF(50,y),
AlignmentXEnum.Left,
AlignmentYEnum.Middle,
0
);
builder.SetLineWidth(12);
builder.SetLineJoin(lineJoin);
PointF[] points = new PointF[]
{
new PointF(120,y+25),
new PointF(150,y-25),
new PointF(180,y+25)
};
builder.DrawPolyline(points);
builder.Stroke();
builder.BeginLocalState();
builder.SetLineWidth(1);
builder.SetStrokeColor(DeviceRGBColor.White);
builder.SetLineCap(LineCapEnum.Butt);
builder.DrawPolyline(points);
builder.Stroke();
builder.End(); // End local state.
y += 50;
}
builder.End(); // End local state.
// 3.6. Clipping.
/*
NOTE: Clipping should be conveniently enclosed within a local state
in order to easily resume the unaltered drawing area after the operation completes.
*/
builder.BeginLocalState();
builder.DrawPolygon(
new PointF[]
{
new PointF(220,410),
new PointF(300,490),
new PointF(450,360),
new PointF(430,520),
new PointF(590,565),
new PointF(420,595),
new PointF(460,730),
new PointF(380,650),
new PointF(330,765),
new PointF(310,640),
new PointF(220,710),
new PointF(275,570),
new PointF(170,500),
new PointF(275,510)
}
);
builder.Clip();
// Showing a clown image...
// Instantiate a jpeg image object!
entities::Image image = entities::Image.Get(loader.InputPath + System.IO.Path.DirectorySeparatorChar + "images" + System.IO.Path.DirectorySeparatorChar + "Clown.jpg"); // Abstract image (entity).
// Show the image!
builder.ShowXObject(
image.ToXObject(document),
new PointF(
170,
320
),
new Size(450,0)
);
builder.End(); // End local state.
// 4. Flush the contents into the page!
builder.Flush();
}
private void BuildSimpleTextPage(
Document document,
SampleLoader loader
)
{
// 1. Add the page to the document!
Page page = new Page(document); // Instantiates the page inside the document context.
document.Pages.Add(page); // Puts the page in the pages collection.
SizeF pageSize = page.Size.Value;
// 2. Create a content builder for the page!
PrimitiveFilter builder = new PrimitiveFilter(page);
// 3. Inserting contents...
// Set the font to use!
builder.SetFont(
new StandardType1Font(
document,
StandardType1Font.FamilyNameEnum.Courier,
true,
false
),
32
);
AlignmentXEnum[] xAlignments = (AlignmentXEnum[])Enum.GetValues(typeof(AlignmentXEnum));
AlignmentYEnum[] yAlignments = (AlignmentYEnum[])Enum.GetValues(typeof(AlignmentYEnum));
int step = (int)(pageSize.Height) / ((xAlignments.Length-1) * yAlignments.Length+1);
BlockFilter blockFilter = new BlockFilter(builder);
RectangleF frame = new RectangleF(
30,
0,
pageSize.Width-60,
step/2
);
blockFilter.Begin(frame,AlignmentXEnum.Center,AlignmentYEnum.Middle);
blockFilter.ShowText(
"Simple text alignment"
);
blockFilter.End();
frame = new RectangleF(
30,
pageSize.Height-step/2,
pageSize.Width-60,
step/2 -10
);
blockFilter.Begin(frame,AlignmentXEnum.Right,AlignmentYEnum.Bottom);
builder.SetFont(builder.State.Font,10);
blockFilter.ShowText(
"NOTE: showText(...) methods return the actual bounding box of the text shown.\n"
+ "NOTE: The rotation parameter can be freely defined as a double-precision value."
);
blockFilter.End();
builder.SetFont(builder.State.Font,12);
int x = 30;
int y = step;
int alignmentIndex = 0;
foreach(AlignmentXEnum alignmentX
in (AlignmentXEnum[])Enum.GetValues(typeof(AlignmentXEnum)))
{
/*
NOTE: As text shown through PrimitiveFilter has no bounding box constraining its extension,
applying the justified alignment has no effect (it degrades to center alignment);
in order to get such an effect, use BlockFilter instead.
*/
if(alignmentX.Equals(AlignmentXEnum.Justify))
continue;
foreach(AlignmentYEnum alignmentY
in (AlignmentYEnum[])Enum.GetValues(typeof(AlignmentYEnum)))
{
if(alignmentIndex % 2 == 0)
{
builder.BeginLocalState();
builder.SetFillColor(BackColor);
builder.DrawRectangle(
new RectangleF(
0,
y-step/2,
pageSize.Width,
step
)
);
builder.Fill();
builder.End();
}
builder.ShowText(
alignmentX + " " + alignmentY + ":",
new PointF(x,y),
AlignmentXEnum.Left,
AlignmentYEnum.Middle,
0
);
y+=step;
alignmentIndex++;
}
}
double rotationStep = 0;
double rotation = 0;
for(
int columnIndex = 0;
columnIndex < 2;
columnIndex++
)
{
switch(columnIndex)
{
case 0:
x = 200;
rotationStep = 0;
break;
case 1:
x = (int)pageSize.Width / 2 + 100;
rotationStep = 360 / ((xAlignments.Length-1) * yAlignments.Length-1);
break;
}
y = step;
rotation = 0;
foreach(AlignmentXEnum alignmentX
in (AlignmentXEnum[])Enum.GetValues(typeof(AlignmentXEnum)))
{
/*
NOTE: As text shown through PrimitiveFilter has no bounding box constraining its extension,
applying the justified alignment has no effect (it degrades to center alignment);
in order to get such an effect, use BlockFilter instead.
*/
if(alignmentX.Equals(AlignmentXEnum.Justify))
continue;
foreach(AlignmentYEnum alignmentY
in (AlignmentYEnum[])Enum.GetValues(typeof(AlignmentYEnum)))
{
double startArcAngle = 0;
switch(alignmentX)
{
case AlignmentXEnum.Left:
// OK -- NOOP.
break;
case AlignmentXEnum.Right:
case AlignmentXEnum.Center:
startArcAngle = 180;
break;
}
builder.DrawArc(
new RectangleF(
x-10,
y-10,
20,
20
),
startArcAngle,
startArcAngle+rotation
);
DrawText(
builder,
"PDF Clown",
new PointF(x,y),
alignmentX,
alignmentY,
rotation
);
y+=step;
rotation+=rotationStep;
}
}
}
// 4. Flush the contents into the page!
builder.Flush();
}
private void BuildTextBlockPage(
Document document,
SampleLoader loader
)
{
// 1. Add the page to the document!
Page page = new Page(document); // Instantiates the page inside the document context.
document.Pages.Add(page); // Puts the page in the pages collection.
SizeF pageSize = page.Size.Value;
// 2. Create a content builder for the page!
PrimitiveFilter builder = new PrimitiveFilter(page);
// 3. Drawing the page contents...
builder.SetFont(
new StandardType1Font(
document,
StandardType1Font.FamilyNameEnum.Courier,
true,
false
),
32
);
AlignmentXEnum[] xAlignments = (AlignmentXEnum[])Enum.GetValues(typeof(AlignmentXEnum));
AlignmentYEnum[] yAlignments = (AlignmentYEnum[])Enum.GetValues(typeof(AlignmentYEnum));
int step = (int)(pageSize.Height) / (xAlignments.Length * yAlignments.Length+1);
BlockFilter blockFilter = new BlockFilter(builder);
{
blockFilter.Begin(
new RectangleF(
30,
0,
pageSize.Width-60,
step*.8f
),
AlignmentXEnum.Center,
AlignmentYEnum.Middle
);
blockFilter.ShowText(
"Text block alignment"
);
blockFilter.End();
}
// Drawing the text blocks...
int x = 30;
int y = (int)(step*1.2);
foreach(AlignmentXEnum alignmentX
in (AlignmentXEnum[])Enum.GetValues(typeof(AlignmentXEnum)))
{
foreach(AlignmentYEnum alignmentY
in (AlignmentYEnum[])Enum.GetValues(typeof(AlignmentYEnum)))
{
builder.SetFont(
builder.State.Font,
12
);
builder.ShowText(
alignmentX + " " + alignmentY + ":",
new PointF(x,y),
AlignmentXEnum.Left,
AlignmentYEnum.Middle,
0
);
builder.SetFont(
builder.State.Font,
8
);
for(
int index = 0;
index < 2;
index++
)
{
int frameX;
switch(index)
{
case 0:
frameX = 150;
blockFilter.Hyphenation = false;
break;
case 1:
frameX = 360;
blockFilter.Hyphenation = true;
break;
default:
throw new Exception();
}
RectangleF frame = new RectangleF(
frameX,
y-step*.4f,
200,
step*.8f
);
blockFilter.Begin(frame,alignmentX,alignmentY);
blockFilter.ShowText(
"Demonstrating how to constrain text inside a page area using PDF Clown. See the other available code samples (such as TypesettingSample) to discover more functionality details."
);
blockFilter.End();
builder.BeginLocalState();
builder.SetLineWidth(0.2);
builder.SetLineDash(5,5,5);
builder.DrawRectangle(frame);
builder.Stroke();
builder.End();
}
y+=step;
}
}
// 4. Flush the contents into the page!
builder.Flush();
}
private void DrawCross(
PrimitiveFilter builder,
PointF center
)
{
builder.DrawLine(
new PointF(center.X-10,center.Y),
new PointF(center.X+10,center.Y)
);
builder.DrawLine(
new PointF(center.X,center.Y-10),
new PointF(center.X,center.Y+10)
);
builder.Stroke();
}
private void DrawFrame(
PrimitiveFilter builder,
PointF[] frameVertices
)
{
builder.BeginLocalState();
builder.SetLineWidth(0.2);
builder.SetLineDash(5,5,5);
builder.DrawPolygon(frameVertices);
builder.Stroke();
builder.End();
}
private void DrawText(
PrimitiveFilter builder,
String value,
PointF location,
AlignmentXEnum alignmentX,
AlignmentYEnum alignmentY,
double rotation
)
{
// Show the anchor point!
DrawCross(builder,location);
builder.BeginLocalState();
builder.SetFillColor(SampleColor);
// Show the text onto the page!
PointF[] textFrame = builder.ShowText(
value,
location,
alignmentX,
alignmentY,
rotation
);
builder.End();
// Draw the frame binding the shown text!
DrawFrame(
builder,
textFrame
);
builder.BeginLocalState();
builder.SetFont(builder.State.Font,8);
// Draw the rotation degrees!
builder.ShowText(
"(" + ((int)rotation) + " degrees)",
new PointF(
location.X+70,
location.Y
),
AlignmentXEnum.Left,
AlignmentYEnum.Middle,
0
);
builder.End();
}
#endregion
#endregion
#endregion
}
}
|