summaryrefslogtreecommitdiffstats
path: root/DHTMLX.Export.PDF
diff options
context:
space:
mode:
Diffstat (limited to 'DHTMLX.Export.PDF')
-rw-r--r--DHTMLX.Export.PDF/DHTMLX.Export.PDF.csproj76
-rw-r--r--DHTMLX.Export.PDF/MonthRow.cs13
-rw-r--r--DHTMLX.Export.PDF/PDFImages.cs33
-rw-r--r--DHTMLX.Export.PDF/PDFPage.cs27
-rw-r--r--DHTMLX.Export.PDF/PDFWriter.cs2141
-rw-r--r--DHTMLX.Export.PDF/Properties/AssemblyInfo.cs36
-rw-r--r--DHTMLX.Export.PDF/RGBColor.cs75
-rw-r--r--DHTMLX.Export.PDF/Resizer.cs68
-rw-r--r--DHTMLX.Export.PDF/SchedulerEvent.cs161
-rw-r--r--DHTMLX.Export.PDF/SchedulerMonth.cs60
-rw-r--r--DHTMLX.Export.PDF/TreeTimelineParser.cs61
-rw-r--r--DHTMLX.Export.PDF/XMLParser.cs344
-rw-r--r--DHTMLX.Export.PDF/lib/ExtendLib.cs489
-rw-r--r--DHTMLX.Export.PDF/packages.config5
14 files changed, 3589 insertions, 0 deletions
diff --git a/DHTMLX.Export.PDF/DHTMLX.Export.PDF.csproj b/DHTMLX.Export.PDF/DHTMLX.Export.PDF.csproj
new file mode 100644
index 0000000..b3ef1d8
--- /dev/null
+++ b/DHTMLX.Export.PDF/DHTMLX.Export.PDF.csproj
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProductVersion>8.0.30703</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{11B5A6CD-281E-4BC3-BC54-425BD7B467EA}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>DHTMLX.Export.PDF</RootNamespace>
+ <AssemblyName>DHTMLX.Export.PDF.Scheduler</AssemblyName>
+ <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <TargetFrameworkProfile />
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>bin\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <Prefer32Bit>false</Prefer32Bit>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ <Prefer32Bit>false</Prefer32Bit>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="HtmlAgilityPack">
+ <HintPath>..\packages\HtmlAgilityPack.1.4.9.5\lib\Net45\HtmlAgilityPack.dll</HintPath>
+ </Reference>
+ <Reference Include="PdfSharp">
+ <HintPath>..\packages\PDFsharp.1.32.3057.0\lib\net20\PdfSharp.dll</HintPath>
+ </Reference>
+ <Reference Include="PdfSharp.Charting">
+ <HintPath>..\packages\PDFsharp.1.32.3057.0\lib\net20\PdfSharp.Charting.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Drawing" />
+ <Reference Include="System.Web" />
+ <Reference Include="System.Xml" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="lib\ExtendLib.cs" />
+ <Compile Include="MonthRow.cs" />
+ <Compile Include="PDFImages.cs" />
+ <Compile Include="PDFPage.cs" />
+ <Compile Include="PDFWriter.cs" />
+ <Compile Include="Resizer.cs" />
+ <Compile Include="SchedulerEvent.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="RGBColor.cs" />
+ <Compile Include="SchedulerMonth.cs" />
+ <Compile Include="TreeTimelineParser.cs" />
+ <Compile Include="XMLParser.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="packages.config" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+ Other similar extension points exist, see Microsoft.Common.targets.
+ <Target Name="BeforeBuild">
+ </Target>
+ <Target Name="AfterBuild">
+ </Target>
+ -->
+</Project> \ No newline at end of file
diff --git a/DHTMLX.Export.PDF/MonthRow.cs b/DHTMLX.Export.PDF/MonthRow.cs
new file mode 100644
index 0000000..0b5d60e
--- /dev/null
+++ b/DHTMLX.Export.PDF/MonthRow.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace DHTMLX.Export.PDF
+{
+ public class MonthRow
+ {
+ public double Height { get; set; }
+ public string[] Cells { get; set; }
+ }
+}
diff --git a/DHTMLX.Export.PDF/PDFImages.cs b/DHTMLX.Export.PDF/PDFImages.cs
new file mode 100644
index 0000000..8411f37
--- /dev/null
+++ b/DHTMLX.Export.PDF/PDFImages.cs
@@ -0,0 +1,33 @@
+using System.Collections.Generic;
+using System.IO;
+using PdfSharp.Drawing;
+using System.Drawing;
+
+using DHTMLX.Export.PDF.Scheduler;
+namespace DHTMLX.Export.PDF.Scheduler
+{
+ public class PDFImages
+ {
+
+ private Dictionary<string, XImage> _cache = new Dictionary<string, XImage>();
+ public XImage Get(string path)
+ {
+ if (_cache.ContainsKey(path))
+ {
+ return _cache[path];
+ }
+
+ if (File.Exists(path))
+ {
+ FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read);
+ var img = new Bitmap(fileStream, false);
+ _cache.Add(path, (XImage)img);
+
+ return _cache[path];
+ }
+
+ return null;
+ }
+
+ }
+}
diff --git a/DHTMLX.Export.PDF/PDFPage.cs b/DHTMLX.Export.PDF/PDFPage.cs
new file mode 100644
index 0000000..ad2a91e
--- /dev/null
+++ b/DHTMLX.Export.PDF/PDFPage.cs
@@ -0,0 +1,27 @@
+using System.Collections.Generic;
+using DHTMLX.Export.PDF.Scheduler;
+using System.Xml;
+
+namespace DHTMLX.Export.PDF
+{
+ public class PDFPage
+ {
+ public List<SchedulerEvent> Multiday { get; set; }
+ public List<SchedulerEvent> Events { get; set; }
+ public PDFPage()
+ {
+ Multiday = new List<SchedulerEvent>();
+ Events = new List<SchedulerEvent>();
+ }
+ public ColorProfile Profile { get; set; }
+ public bool Header { get; set; }
+ public bool Footer { get; set; }
+ public string Mode { get; set; }
+ public string TodayLabel { get; set; }
+ public XmlNode Node { get; set; }
+ public string[][] Cols { get; set; }
+ public string[,] Rows { get; set; }
+ public List<MonthRow> RowObs { get; set; }
+
+ }
+}
diff --git a/DHTMLX.Export.PDF/PDFWriter.cs b/DHTMLX.Export.PDF/PDFWriter.cs
new file mode 100644
index 0000000..f4ce115
--- /dev/null
+++ b/DHTMLX.Export.PDF/PDFWriter.cs
@@ -0,0 +1,2141 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using PdfSharp;
+using System.IO;
+using PdfSharp.Drawing;
+using System.Web;
+using PdfSharp.Pdf;
+
+using PdfSharp.Drawing.Layout;
+using DHTMLX.Export.PDF.Formatter;
+using DHTMLX.Export.PDF.Scheduler;
+
+using HtmlAgilityPack;
+
+namespace DHTMLX.Export.PDF
+{
+ public enum Orientation
+ {
+ Default,
+ Landscape,
+ Portrait
+ }
+ public class SchedulerPDFWriter
+ {
+
+ public Orientation Orientation = Orientation.Default;
+ public string HeaderImgPath = "header.png";
+ public string FooterImgPath = "footer.png";
+ public double HeaderImgHeight = 100;
+ public double FooterImgHeight = 100;
+ public double BaseFontSize = 7.0;
+ public double WeekAgendarDayFont = 9.4;
+
+ public bool TrimContentStrings = true;
+ public bool TrimLayoutStrings = true;
+ public bool MultipageMonthLayout = false;
+ public double HeaderFontSize = 7.0;
+ public double TimelineRowMinHeight = 50;
+ public double BorderWidth = 0.5;
+
+ protected XMLParser Parser;
+ protected PdfDocument Pdf;
+ protected PdfPage Page;
+ protected List<PdfPage> Pages;
+ protected List<XGraphics> Graphics;
+ protected XGraphics Gfx;
+ protected XFont F1;
+ protected PDFImages Images = new PDFImages();
+ protected bool NeedPagesNums;
+
+ private Resizer _resizer;
+ private double _pageWidth;
+ private double _pageHeight;
+
+ private double _initialOffsetTop = 30;
+ private double _initialOffsetBottom = 30;
+ private double _initialOffsetLeft = 30;
+ private double _initialOffsetRight = 30;
+
+ private double _offsetTop = 30;
+ private double _offsetBottom = 30;
+ private double _offsetLeft = 30;
+ private double _offsetRight = 30;
+ private double _headHeight = 20;
+ private double _monthDayHeaderHeight = 20;
+ private double _monthEventHeight = 12;
+ private double _leftScaleWidth = 80;
+ private double _timelineLeft = 80;
+ private double _monthEventOffsetLeft = 2;
+ private double _monthEventOffsetTop = 2;
+ private double _yearMonthOffsetLeft = 10;
+ private double _yearMonthOffsetTop = 10;
+ private double _yearMonthLabelHeight = 20;
+ private double _weekEventHeaderHeight = 10;
+ private double _agendaColOneWidth = 150;
+ private double _multidayLineHeight = 14;
+ private double _weekAgendaEventHeight = 20;
+
+ private string _pageNumTemplate = "Page {pageNum}/{allNum}";
+
+ private double _monthDayWidth;
+ private double _monthDayHeight;
+ private double _contHeight;
+ private double _contWidth;
+
+ private double _weekDayWidth;
+ private double _weekDayHeight;
+ private double _headerHeight;
+ private double _multiHeight;
+
+ private ColorProfile _profile;
+
+ private double _cellOffset = 3;
+
+ private string _bgColor = "C2D5FC";
+ private string _lineColor = "586A7E";
+ private string _headerLineColor = "FFFFFF";
+
+ private string _dayHeaderColor = "EBEFF4";
+ private string _watermarkTextColor = "8b8b8b";
+ private string _dayBodyColor = "FFFFFF";
+ private string _dayHeaderColorInactive = "E2E3E6";
+ private string _dayBodyColorInactive = "ECECEC";
+ private string _eventColor = "FFE763";
+ private string _eventTextColor = "887A2E";
+ private string _scaleOneColor = "FCFEFC";
+ private string _scaleTwoColor = "DCE6F4";
+ private string _timelineTreeColor = "969394";
+ private string _eventBorderColor = "B7A543";
+ private string _textColor = "000000";
+ private string _yearDayActiveColor = "EBEFF4";
+ private string _yearDayInactiveColor = "D6D6D6";
+ private string _multidayColor = "E1E6FF";
+ private string _matrixEventColor = "FFFFFF";
+ private string _view;
+ private string _watermark;
+
+ public string ContentType { get { return "application/pdf"; } }
+ protected PDFPage CurrentPage { get; set; }
+
+ private double[] SelectColor(string fullColor, double[] def)
+ {
+ if ((fullColor != "transparent")
+ && ((_profile == ColorProfile.FullColor) || (_profile == ColorProfile.Color)))
+ {
+ return RGBColor.GetColor(fullColor);
+ }
+ return def;
+ }
+
+
+ private string StripHtml(string html)
+ {
+ return HtmlEntity.DeEntitize(html);
+ }
+ private string TextWrap(string text, double width, XFont f, bool actuallyDo)
+ {
+ text = StripHtml(text);
+
+ if (!actuallyDo)
+ return text;
+ return TextWrap(text, width, f);
+ }
+
+ private string TextWrap(string text, double width, XFont f)
+ {
+ text = StripHtml(text);
+
+ width = _resizer.ResizeX(width);
+ if ((Gfx.MeasureString(text, f).Width <= width) || (text.Length == 0))
+ {
+ return text;
+ }
+ while ((Gfx.MeasureString(text + "...", f).Width > width) && (text.Length > 0))
+ {
+ text = text.Substring(0, text.Length - 1);
+ }
+ return text + "...";
+ }
+ public double[] GetSizes(PageOrientation orientation, PageSize size)
+ {
+ var sizes = new double[2];
+ var siz = PageSizeConverter.ToSize(size);
+
+ if (orientation == PageOrientation.Landscape)
+ {
+
+ sizes[0] = siz.Height;
+ sizes[1] = siz.Width;
+ }
+ else
+ {
+ sizes[1] = siz.Height;
+ sizes[0] = siz.Width;
+ }
+
+ return sizes;
+
+ }
+ private void SetColorProfile(ColorProfile profile)
+ {
+ if ((profile == ColorProfile.Color) || (profile == ColorProfile.FullColor))
+ {
+ _bgColor = "C2D5FC";
+ _lineColor = "c1d4fc";
+ _headerLineColor = "FFFFFF";
+ _dayHeaderColor = "EBEFF4";
+ _dayBodyColor = "FFFFFF";
+ _dayHeaderColorInactive = "E2E3E6";
+ _dayBodyColorInactive = "ECECEC";
+ _eventColor = "FFE763";
+ _eventTextColor = "887A2E";
+ _scaleOneColor = "FCFEFC";
+ _scaleTwoColor = "DCE6F4";
+
+ _timelineTreeColor = "969394";
+
+ _eventBorderColor = "B7A543";
+ _textColor = "000000";
+ _yearDayActiveColor = "EBEFF4";
+ _yearDayInactiveColor = "D6D6D6";
+ _multidayColor = "E1E6FF";
+ _matrixEventColor = "FFFFFF";
+ _watermarkTextColor = "8b8b8b";
+ }
+ else
+ {
+ if (profile == ColorProfile.Gray)
+ {
+ _bgColor = "D3D3D3";
+ _lineColor = "666666";
+ _headerLineColor = "FFFFFF";
+ _dayHeaderColor = "EEEEEE";
+ _dayBodyColor = "FFFFFF";
+ _dayHeaderColorInactive = "E3E3E3";
+ _dayBodyColorInactive = "ECECEC";
+ _eventColor = "DFDFDF";
+ _eventTextColor = "000000";
+ _scaleOneColor = "FFFFFF";
+
+ _timelineTreeColor = "BBBBBB";
+
+ _scaleTwoColor = "E4E4E4";
+ _eventBorderColor = "9F9F9F";
+ _textColor = "000000";
+ _yearDayActiveColor = "EBEFF4";
+ _yearDayInactiveColor = "E2E3E6";
+ _multidayColor = "E7E7E7";
+ _matrixEventColor = "FFFFFF";
+ _watermarkTextColor = "8b8b8b";
+ }
+ else
+ {
+ _bgColor = "FFFFFF";
+ _lineColor = "000000";
+ _headerLineColor = "000000";
+ _dayHeaderColor = "FFFFFF";
+ _dayBodyColor = "FFFFFF";
+ _dayHeaderColorInactive = "FFFFFF";
+ _dayBodyColorInactive = "FFFFFF";
+ _eventColor = "FFFFFF";
+ _eventTextColor = "000000";
+
+ _timelineTreeColor = "FFFFFF";
+
+ _scaleOneColor = "FFFFFF";
+ _scaleTwoColor = "FFFFFF";
+ _eventBorderColor = "000000";
+ _textColor = "000000";
+ _yearDayActiveColor = "FFFFFF";
+ _yearDayInactiveColor = "FFFFFF";
+ _multidayColor = "FFFFFF";
+ _matrixEventColor = "FFFFFF";
+ _watermarkTextColor = "000000";
+ }
+ }
+ }
+ private void CreatePdf(PageOrientation orientation, PageSize size)
+ {
+ _resizer = new Resizer(orientation, Orientation);
+
+ if (Pdf == default(PdfDocument))
+ {
+ Pdf = new PdfDocument();
+ F1 = CreateFont("Helvetica", 10);
+ Pdf.Version = 14;
+ Pages = new List<PdfPage>();
+ }
+ NewPage(_resizer.Orient, size);
+ }
+
+ protected PdfPage NewPage(PageOrientation orient, PageSize size)
+ {
+ Page = new PdfPage(Pdf);
+ Pdf.AddPage(Page);
+
+ Gfx = XGraphics.FromPdfPage(Page, XGraphicsPdfPageOptions.Replace);
+ if (Graphics == null)
+ Graphics = new List<XGraphics>();
+ Graphics.Add(Gfx);
+ Pages.Add(Page);
+
+ Page.Size = size;
+ Page.Orientation = orient;
+
+ TodayLabelDraw(Gfx);
+
+ _headerHeight = _headHeight;
+ _offsetTop = _initialOffsetTop;
+ _offsetBottom = _initialOffsetBottom;
+ _offsetLeft = _initialOffsetLeft;
+ _offsetRight = _initialOffsetRight;
+
+ var sizes = GetSizes(_resizer.Orient, size);
+ _pageWidth = sizes[0] - _offsetLeft - _offsetRight;
+ _pageHeight = sizes[1] - _offsetTop - _offsetBottom;
+
+ PrintHeader();
+ PrintFooter();
+ return Page;
+ }
+ protected XFont CreateFont(string name, double size)
+ {
+ var fontSettings = new XPdfFontOptions(PdfFontEncoding.Unicode);
+ return new XFont(name, size, new XFontStyle(), fontSettings);
+ }
+
+
+ public MemoryStream Generate(string xml)
+ {
+ var data = new MemoryStream();
+
+ Generate(xml, data);
+ return data;
+ }
+ public void Generate(string xml, HttpResponse resp)
+ {
+ if (resp == default(HttpResponse))
+ {
+ throw new ArgumentNullException("resp", "HttpResponse is null");
+ }
+ var data = new MemoryStream();
+
+ resp.ContentType = ContentType;
+ resp.HeaderEncoding = Encoding.UTF8;
+
+ resp.AppendHeader("Cache-Control", "max-age=0");
+ Generate(xml, data);
+
+ try
+ {
+ data.WriteTo(resp.OutputStream);
+ }
+ catch (Exception e)
+ {
+ throw new Exception("Can't write to the output stream:" + e.Message);
+ }
+
+ }
+ public void PrintPage(PDFPage page)
+ {
+ _view = page.Mode;
+ _profile = page.Profile;
+ SetColorProfile(_profile);
+
+
+ CurrentPage = page;
+ switch (_view)
+ {
+ case "month":
+ PrintMonth(page);
+ break;
+ case "year":
+ PrintYear(page);
+ break;
+ case "agenda":
+ case "map":
+ PrintAgenda(page);
+ break;
+ case "treetimeline":
+ case "timeline":
+ PrintTimeline(page);
+ break;
+ case "matrix":
+ PrintMatrix(page);
+ break;
+ case "week_agenda":
+ PrintWeekAgenda(page);
+ break;
+ default:
+ PrintWeek(page);
+ break;
+ }
+
+ PrintWatermark();
+ }
+
+ public void PrintPages()
+ {
+ foreach (var i in Parser.Pages)
+ {
+ PrintPage(i);
+ }
+ }
+
+ public void Generate(string xml, Stream resp)
+ {
+ if (string.IsNullOrEmpty(xml))
+ {
+ throw new ArgumentException("Input string is null or empty!", "xml");
+ }
+ Parser = new XMLParser();
+
+ try
+ {
+
+ var pages = Parser.GetPages(xml);
+ foreach (var page in pages)
+ {
+ Parser.SetXML(page);
+ PrintPages();
+ }
+ if (NeedPagesNums)
+ {
+ AgendaPagesDraw();
+ }
+ OutputPdf(resp);
+ }
+ catch (Exception e)
+ {
+ throw;
+ }
+ }
+
+ private void OutputPdf(Stream resp)
+ {
+ Pdf.Save(resp, false);
+ }
+
+ private void PrintMonth(PDFPage page)
+ {
+ CreatePdf(PageOrientation.Landscape, PageSize.A4);
+ MonthHeaderDraw();
+ MonthContainerDraw();
+ MonthEventsDraw(page);
+
+ }
+
+ private void PrintYear(PDFPage page)
+ {
+ CreatePdf(PageOrientation.Landscape, PageSize.A4);
+ YearDraw(page);
+ }
+
+ private void PrintAgenda(PDFPage page)
+ {
+ CreatePdf(PageOrientation.Portrait, PageSize.A4);
+ AgendaHeaderDraw();
+ AgendaEventDraw(page);
+ NeedPagesNums = true;
+ }
+
+ private void PrintTimeline(PDFPage page)
+ {
+ _leftScaleWidth = _timelineLeft;
+ var size = PageSize.A4;
+ CreatePdf(PageOrientation.Landscape, size);
+
+ var rows = Parser.WeekRowsParsing(CurrentPage);
+ var blocksNumber = (int)((_pageHeight - _headerHeight) / TimelineRowMinHeight);
+
+ var pages = (int)Math.Ceiling((double)rows.Length / (double)blocksNumber);
+ NeedPagesNums = true;
+ for (var i = 0; i < pages; i++)
+ {
+ var currentPageRows = rows.Skip(i * blocksNumber).Take(blocksNumber).ToArray();
+ WeekHeaderDraw();
+ TimelineContainerDraw(currentPageRows);
+ TimelineEventsDraw(page, i + 1, blocksNumber);
+ if (i != pages - 1)
+ {
+ NewPage(_resizer.Orient, size);
+ }
+ }
+ }
+
+ private void PrintMatrix(PDFPage page)
+ {
+ _leftScaleWidth = _timelineLeft;
+ CreatePdf(PageOrientation.Landscape, PageSize.A4);
+ WeekHeaderDraw();
+ MatrixContainerDraw(page);
+ }
+
+ private void PrintWeek(PDFPage page)
+ {
+ CreatePdf(PageOrientation.Portrait, PageSize.A4);
+ WeekHeaderDraw();
+ WeekMultidayDraw(page);
+ WeekContainerDraw();
+ WeekEventsDraw(page);
+ if (_profile == ColorProfile.BW)
+ WeekBwBordersDraw();
+ }
+
+ private void PrintWeekAgenda(PDFPage page)
+ {
+
+ CreatePdf(PageOrientation.Portrait, PageSize.A4);
+ var events = page.Events.ToArray();
+ WeekAgendaContainerDraw();
+ while (events.Length > 0)
+ {
+
+ events = WeekAgendaEventsDraw(events);
+ if (events.Length > 0)
+ {
+ Page = NewPage(PageOrientation.Portrait, PageSize.A4);
+ WeekAgendaContainerDraw();
+ }
+ }
+ }
+
+ private void PrintWatermark()
+ {
+ if (_watermark == null) return;
+
+ F1 = CreateFont(F1.FontFamily.Name, 10);
+
+ for (var i = 1; i <= Pages.Count; i++)
+ {
+ var graph = Graphics[i - 1];
+
+ var text = new XTextFormatter(graph);
+ var x = _offsetLeft;
+ var y = _pageHeight + _offsetTop + F1.Size;
+ text.DrawString(_watermark, F1, new XSolidBrush(RGBColor.GetXColor(_watermarkTextColor)), _resizer.Rect(x, y, graph.MeasureString(_watermark, F1).Width, F1.Size));
+ }
+ }
+
+ private void MonthHeaderDraw()
+ {
+ var bgColor = RGBColor.GetColor(_bgColor);
+ var borderColor = RGBColor.GetColor(_headerLineColor);
+ var cols = Parser.MonthColsParsing(CurrentPage);
+ var width = _pageWidth / cols[0].Length;
+ var height = _headerHeight;
+ var x = _offsetLeft;
+ var y = _offsetTop;
+
+ var font = new XFont(F1.FontFamily.Name, F1.Size);
+
+ for (var i = 0; i < cols[0].Length; i++)
+ {
+ XRect cell = _resizer.Rect(x, y, width, height);
+
+ Gfx.DrawRectangle(new XSolidBrush(RGBColor.GetXColor(bgColor)), cell);
+
+ if (i > 0)
+ {
+ var points = new XPoint[4];
+ points[0] = _resizer.Point(x, y);
+ points[1] = _resizer.Point(x, y + height);
+ Gfx.DrawLine(new XPen(RGBColor.GetXColor(borderColor), 1), points[0], points[1]);
+ }
+
+ var text = new XTextFormatter(Gfx);
+ var content = TextWrap(cols[0][i], width - 2 * _cellOffset, font, TrimLayoutStrings);
+ var textX = x + (width - Gfx.MeasureString(content, F1).Width) / 2;
+ var textY = y + (height - F1.Size) / 2;
+
+ text.DrawString(content, font, new XSolidBrush(RGBColor.GetXColor(RGBColor.GetColor(_textColor))), _resizer.Rect(textX, textY, Gfx.MeasureString(content, F1).Width, font.Size));
+
+ x += width;
+ }
+ }
+
+ private void MonthContainerDraw()
+ {
+ var borderColor = RGBColor.GetColor(_lineColor);
+ var dayHeaderColor = RGBColor.GetColor(_dayHeaderColor);
+ var dayBodyColor = RGBColor.GetColor(_dayBodyColor);
+ var dayHeaderColorInactive = RGBColor
+ .GetColor(_dayHeaderColorInactive);
+ var dayBodyColorInactive = RGBColor
+ .GetColor(_dayBodyColorInactive);
+ var rows = Parser.MonthRowsParsing(CurrentPage);
+ var width = _pageWidth / 7;
+ var height = (_pageHeight - _headerHeight) / rows.GetLength(0);
+ _monthDayWidth = width;
+ _monthDayHeight = height;
+ var x = _offsetLeft;
+ var y = _offsetTop + _headerHeight;
+ for (var i = 0; i < rows.GetLength(0); i++)
+ {
+
+ for (var j = 0; j < rows.GetLength(1); j++)
+ {
+ var activeDay = GetActiveDay(rows, i, j);
+
+ var cell = _resizer.Rect(x, y, width, height);
+ var cellIn = _resizer.Rect(x, y, width, _monthDayHeaderHeight);
+ XBrush cellInBrush, cellBrush;
+ if (activeDay)
+ {
+ cellBrush = new XSolidBrush(RGBColor.GetXColor(dayBodyColor));
+ cellInBrush = new XSolidBrush(RGBColor.GetXColor(dayHeaderColor));
+ }
+ else
+ {
+ cellBrush = new XSolidBrush(RGBColor.GetXColor(dayBodyColorInactive));
+ cellInBrush = new XSolidBrush(RGBColor.GetXColor(dayHeaderColorInactive));
+ }
+
+
+ Gfx.DrawRectangle(cellBrush, cell);
+ Gfx.DrawRectangle(cellInBrush, cellIn);
+
+ var points = new XPoint[3];
+ points[0] = _resizer.Point(x, y);
+ points[1] = _resizer.Point(x + width, y);
+ points[2] = _resizer.Point(x, y + height);
+ Gfx.DrawLine(new XPen(RGBColor.GetXColor(borderColor), BorderWidth), points[0], points[2]);
+ Gfx.DrawLine(new XPen(RGBColor.GetXColor(borderColor), BorderWidth), points[0], points[1]);
+
+
+
+ var label = rows[i, j];
+ var textX = x + width - Gfx.MeasureString(label, F1).Width - _cellOffset;
+
+ var textY = y + (_monthDayHeaderHeight + F1.Size) / 2;
+
+ Gfx.DrawString(label, F1, new XSolidBrush(RGBColor.GetXColor(_textColor)), _resizer.Point(textX, textY));
+ x += width;
+ }
+ x = _offsetLeft;
+
+ y += height;
+ }
+
+
+ var points2 = new XPoint[3];
+ points2[0] = _resizer.Point(_offsetLeft + _pageWidth, _offsetTop);
+ points2[1] = _resizer.Point(_offsetLeft + _pageWidth, _offsetTop + _pageHeight);
+ points2[2] = _resizer.Point(_offsetLeft, _offsetTop + _pageHeight);
+
+ Gfx.DrawLine(new XPen(RGBColor.GetXColor(borderColor), BorderWidth), points2[0], points2[1]);
+ Gfx.DrawLine(new XPen(RGBColor.GetXColor(borderColor), BorderWidth), points2[1], points2[2]);
+
+
+ }
+
+ private void MonthEventsDraw(PDFPage page)
+ {
+ var rowObjects = Parser.GetRowsObjects(page);
+
+ var eventColor = RGBColor.GetColor(_eventColor);
+ var eventBorderColor = RGBColor.GetColor(_eventBorderColor);
+ var textColor = RGBColor.GetColor(_eventTextColor);
+ var events = page.Events;
+ var minHeight = events.Count != 0 ? events.Min(e => e.Y) : 0;
+ var footenote = 1;
+ var eventsGrid = new int[6][];
+
+ for (var i = 0; i < 6; i++)
+ {
+ eventsGrid[i] = new int[7];
+ for (var j = 0; j < 7; j++)
+ {
+ eventsGrid[i][j] = 0;
+ }
+ }
+
+ var evHeight = events.Sum(e => e.Height) / (double)events.Count + 3;
+
+ for (var i = 0; i < events.Count; i++)
+ {
+ var eventText = events[i].Text;
+ var day = events[i].Day;
+ var week = events[i].Week - 1;
+
+ eventsGrid[week][day] = (int)Math.Floor((events[i].Y - rowObjects.Where((r, ind) => ind < week).Sum(r => r.Height)) / (evHeight));//todo: remove magic with event indexes
+
+ var width = (events[i].Width * _monthDayWidth) / 100;
+ var type = events[i].Type;
+ var bgColor = events[i].BackgroundColor;
+ var color = events[i].Color;
+ if (type == "event_line")
+ {
+
+ var cellX = _offsetLeft + day * _monthDayWidth
+ + _monthEventOffsetLeft;
+ var cellY = _offsetTop;
+ cellY += _headerHeight;
+ cellY += week * _monthDayHeight;
+ cellY += _monthDayHeaderHeight;
+ cellY += eventsGrid[week][day]
+ * (_monthEventHeight + _monthEventOffsetTop);
+ cellY += _monthEventOffsetTop;
+
+
+ var height = _monthEventHeight;
+ var cellPen = new XPen(RGBColor.GetXColor(eventBorderColor), BorderWidth);
+
+ var borders = new XPoint[4];
+ borders[0] = _resizer.Point(cellX, cellY);
+ borders[1] = _resizer.Point(cellX + width, cellY);
+ borders[2] = _resizer.Point(cellX + width, cellY + height);
+ borders[3] = _resizer.Point(cellX, cellY + height);
+
+
+ var cellIn = _resizer.Rect(cellX, cellY, width, height);
+ var cellInBrush = new XSolidBrush(RGBColor.GetXColor(SelectColor(bgColor, eventColor)));
+
+ F1 = CreateFont(F1.FontFamily.Name, 8);
+
+ var label = TextWrap(eventText, width - 2 * _cellOffset, F1, TrimContentStrings);
+ var textX = cellX + _cellOffset;
+
+ var textY = cellY + (height + F1.Size) / 2;
+ var textBrush = new XSolidBrush(RGBColor.GetXColor(SelectColor(color, textColor)));
+
+ if ((cellY + height) >= (_offsetTop + _headerHeight + (week + 1)
+ * _monthDayHeight))
+ {
+ var eventFootenote = GetFootenoteExists(events, week, day);
+ if (eventFootenote > 0)
+ {
+ events[i].Footenote = eventFootenote;
+ }
+ else
+ {
+ events[i].Footenote = footenote;
+ footenote++;
+ }
+ }
+ else
+ {
+
+ Gfx.DrawRectangle(cellInBrush, cellIn);
+ Gfx.DrawLine(cellPen, borders[0], borders[1]);
+ Gfx.DrawLine(cellPen, borders[1], borders[2]);
+ Gfx.DrawLine(cellPen, borders[2], borders[3]);
+ Gfx.DrawLine(cellPen, borders[3], borders[0]);
+
+ Gfx.DrawString(label, F1, textBrush, _resizer.Point(textX, textY));
+ }
+ }
+ else
+ {
+ var cellX = _offsetLeft + day * _monthDayWidth
+ + _monthEventOffsetLeft;
+ var cellY = _offsetTop;
+ cellY += _headerHeight;
+ cellY += week * _monthDayHeight;
+ cellY += _monthDayHeaderHeight;
+ cellY += eventsGrid[week][day]
+ * (_monthEventHeight + _monthEventOffsetTop);
+ cellY += _monthEventOffsetTop;
+ var height = _monthEventHeight;
+ F1 = CreateFont(F1.FontFamily.Name, 8);
+
+ var text = TextWrap(eventText, width - 2 * _cellOffset, F1, TrimContentStrings);
+
+ XSolidBrush textBrush = new XSolidBrush(RGBColor.GetXColor(SelectColor(color, textColor)));
+
+ var textX = cellX + _cellOffset;
+ var textY = cellY + (height + F1.Size) / 2;
+
+ if (cellY + height >= _offsetTop + _headerHeight + (week + 1)
+ * _monthDayHeight)
+ {
+ var eventFootenote = GetFootenoteExists(events, week, day);
+ if (eventFootenote > 0)
+ {
+ events[i].Footenote = eventFootenote;
+ }
+ else
+ {
+ events[i].Footenote = footenote;
+ footenote++;
+ }
+ }
+ else
+ {
+ Gfx.DrawString(text, F1, textBrush, _resizer.Point(textX, textY));
+
+ }
+ }
+ }
+ if (_profile == ColorProfile.BW)
+ MonthBwBordersDraw();
+ MonthFootenotesDraw(events, footenote, page, minHeight);
+ }
+
+ private int GetFootenoteExists(IList<SchedulerEvent> events, int week, int day)
+ {
+ var result = -1;
+ for (var i = 0; i < events.Count; i++)
+ {
+ var ev = events[i];
+ var eventWeek = ev.Week - 1;
+ var eventDay = ev.Day;
+ if (eventWeek == week && eventDay == day)
+ {
+ var foote = ev.Footenote;
+ if (foote > 0)
+ {
+ result = ev.Footenote;
+ }
+ }
+ }
+ return result;
+ }
+
+ private void MonthFootenotesDraw(IList<SchedulerEvent> events, int footenotes, PDFPage exportPage, double minHeight)
+ {
+ if (footenotes > 1)
+ {
+ NeedPagesNums = true;
+ Page = NewPage(PageOrientation.Landscape, PageSize.A4);
+ }
+ else
+ {
+ return;
+ }
+
+ if (MultipageMonthLayout)
+ {
+
+ var evs = new List<SchedulerEvent>();
+ for (var i = 1; i < footenotes; i++)
+ {
+ var block = getFootenoteEvents(events, i).ToList();
+ var offset = block.Min(e => e.Y) - minHeight;
+ foreach (var ev in block)
+ {
+ ev.Y -= offset;
+ }
+ evs.AddRange(block);
+ }
+ evs.ForEach(e => e.Footenote = 0);
+
+ CurrentPage.Events = evs;
+
+ MonthHeaderDraw();
+ MonthContainerDraw();
+ MonthEventsDraw(exportPage);
+ }
+ else
+ {
+
+ var rows = Parser.MonthRowsParsing(CurrentPage);
+ var borderColor = RGBColor.GetColor(_lineColor);
+ var eventColor = RGBColor.GetColor(_eventColor);
+ var eventTextColor = RGBColor.GetColor(_eventTextColor);
+
+ var labelHeight = 20;
+ var height = 20;
+ var width = 160;
+ var offsetLeft = 20;
+ var x = _offsetLeft;
+ var y = _offsetTop;
+ for (var i = 1; i < footenotes; i++)
+ {
+ var footEvents = getFootenoteEvents(events, i);
+
+
+ var day = footEvents[0].Day;
+ var week = footEvents[0].Week - 1;
+ if (y + labelHeight + height > _offsetTop + _pageHeight)
+ {
+ x += width + offsetLeft;
+ if (x + width > _offsetLeft + _pageWidth)
+ {
+ Page = NewPage(PageOrientation.Landscape, PageSize.A4);
+
+ x = _offsetLeft;
+ }
+ y = _offsetTop;
+ }
+ var label = rows[week, day] + "[" + i.ToString() + "]";
+
+
+ var labelX = x + (width - Gfx.MeasureString(label, F1).Width) / 2;
+ var labelY = y + labelHeight - _cellOffset;
+ Gfx.DrawString(label, F1, new XSolidBrush(RGBColor.GetXColor(_textColor)), _resizer.Point(labelX, labelY));
+
+ y += labelHeight;
+ for (var j = 0; j < footEvents.Count; j++)
+ {
+ if (y + height > _offsetTop + _pageHeight)
+ {
+ x += width + offsetLeft;
+ if (x + width > _offsetLeft + _pageWidth)
+ {
+ Page = NewPage(PageOrientation.Landscape, PageSize.A4);
+ x = _offsetLeft;
+ }
+ y = _offsetTop;
+ labelX = x + (width - Gfx.MeasureString(label, F1).Width) / 2;
+ labelY = y + labelHeight - _cellOffset;
+
+ Gfx.DrawString(label, F1, new XSolidBrush(RGBColor.GetXColor(_textColor)), _resizer.Point(labelX, labelY));
+
+ y += labelHeight;
+ }
+
+ var borders = new XPoint[4];
+ borders[0] = _resizer.Point(x, y);
+ borders[1] = _resizer.Point(x + width, y);
+ borders[2] = _resizer.Point(x + width, y + height);
+ borders[3] = _resizer.Point(x, y + height);
+ var contBg = _resizer.Rect(x, y, width, height);
+
+ var evBrush = new XSolidBrush(RGBColor.GetXColor(SelectColor(footEvents[j].BackgroundColor, eventColor)));
+
+ Gfx.DrawRectangle(evBrush, contBg);
+ Gfx.DrawLine(new XPen(RGBColor.GetXColor(borderColor), BorderWidth), borders[0], borders[1]);
+ Gfx.DrawLine(new XPen(RGBColor.GetXColor(borderColor), BorderWidth), borders[1], borders[2]);
+ Gfx.DrawLine(new XPen(RGBColor.GetXColor(borderColor), BorderWidth), borders[2], borders[3]);
+ Gfx.DrawLine(new XPen(RGBColor.GetXColor(borderColor), BorderWidth), borders[3], borders[0]);
+
+ var text = TextWrap(footEvents[j].Text, width - 2 * _cellOffset, F1, TrimContentStrings);
+
+ var textX = x + _cellOffset;
+ var textY = y + (height + F1.Size) / 2;
+
+ Gfx.DrawString(text, F1, new XSolidBrush(RGBColor.GetXColor(SelectColor(footEvents[j].Color, eventTextColor))), _resizer.Point(textX, textY));
+
+ y += height;
+ }
+ }
+ }
+ }
+
+ private IList<SchedulerEvent> getFootenoteEvents(IList<SchedulerEvent> events,
+ int footenote)
+ {
+ var nums = 0;
+ for (var i = 0; i < events.Count; i++)
+ {
+ if (events[i].Footenote == footenote)
+ {
+ nums++;
+ }
+ }
+ var footEvents = new List<SchedulerEvent>(nums);
+ for (var i = 0; i < events.Count; i++)
+ {
+ if (events[i].Footenote == footenote)
+ {
+ footEvents.Add(events[i]);
+ }
+ }
+ return footEvents;
+ }
+
+ private void MonthBwBordersDraw()
+ {
+ var borderColor = RGBColor.GetColor(_lineColor);
+ var x = _offsetLeft;
+ var y = _offsetTop;
+ Line(borderColor, x, y, x + _pageWidth, y);
+ Line(borderColor, x, y, x, y + _headerHeight);
+
+ x = _offsetLeft + _pageWidth;
+ Line(borderColor, x, y, x, y + _headerHeight);
+ }
+
+ private void WeekHeaderDraw()
+ {
+ var bgColor = RGBColor.GetColor(_bgColor);
+ var borderColor = RGBColor.GetColor(_headerLineColor);
+ var cols = Parser.WeekColsParsing(CurrentPage);
+
+ _weekDayWidth = (_pageWidth - _leftScaleWidth) / cols[0].Length;
+ var defHeight = _headerHeight;
+ _headerHeight = defHeight * cols.Length;
+
+ var ratios = Parser.ScaleRatios(CurrentPage).Select(r => (double)r).ToList();
+
+
+ for (var scale = 0; scale < cols.Length && scale < 2; scale++)
+ {
+ var x = _offsetLeft + _leftScaleWidth;
+ var height = defHeight;
+
+ var y = _offsetTop + defHeight * scale;
+
+
+ var width = (_pageWidth - _leftScaleWidth) / cols[scale].Length;
+
+
+ if (_weekDayWidth > width)
+ _weekDayWidth = width;
+ for (var col = 0; col < cols[scale].Length; col++)
+ {
+ if (scale == 0 && ratios.Count > 0 && cols[1].Length > 0 && col < ratios.Count)
+ {
+ width = (_pageWidth - _leftScaleWidth) / cols[1].Length * ratios[col];
+ }
+ else
+ {
+ width = (_pageWidth - _leftScaleWidth) / cols[scale].Length;
+ }
+
+ var cell = _resizer.Rect(x, y, width, height);
+
+ var cellBrush = new XSolidBrush(RGBColor.GetXColor(bgColor));
+ Gfx.DrawRectangle(cellBrush, cell);
+
+ var points = new XPoint[3];
+ points[0] = _resizer.Point(x, y);
+ points[1] = _resizer.Point(x + width, y);
+ points[2] = _resizer.Point(x, y + height);
+
+ Gfx.DrawLine(new XPen(RGBColor.GetXColor(borderColor), BorderWidth), points[0], points[2]);
+ Gfx.DrawLine(new XPen(RGBColor.GetXColor(borderColor), BorderWidth), points[0], points[1]);
+
+
+ F1 = new XFont(F1.FontFamily.Name, HeaderFontSize);
+
+ var text = TextWrap(cols[scale][col], width
+ - 2 * _cellOffset, F1, TrimLayoutStrings);
+
+ var textX = x + (width - Gfx.MeasureString(text, F1).Width) / 2;
+ var textY = y + (height + F1.Size) / 2;
+ Gfx.DrawString(text, F1, new XSolidBrush(RGBColor.GetXColor(_textColor)), _resizer.Point(textX, textY));
+
+ x += width;
+ }
+
+ }
+ }
+
+ private void WeekMultidayDraw(PDFPage page)
+ {
+ var bgColor = RGBColor.GetColor(_multidayColor);
+ var borderColor = RGBColor.GetColor(_headerLineColor);
+
+ _multiHeight = GetMultidayHeight(page);
+ var x = _offsetLeft;
+ var y = _offsetTop + _headerHeight;
+ var cell = _resizer.Rect(x, y, _pageWidth, _multiHeight);
+
+ var cellBrush = new XSolidBrush(RGBColor.GetXColor(bgColor));
+ Gfx.DrawRectangle(cellBrush, cell);
+
+ var points = new XPoint[4];
+ points[0] = _resizer.Point(x + _leftScaleWidth, y + 0);
+ points[1] = _resizer.Point(x + _leftScaleWidth, y + _multiHeight);
+ points[2] = _resizer.Point(x + 0, y + 0);
+ points[3] = _resizer.Point(x + _pageWidth, y + 0);
+
+ Gfx.DrawLine(new XPen(RGBColor.GetXColor(borderColor), BorderWidth), points[0], points[1]);
+ Gfx.DrawLine(new XPen(RGBColor.GetXColor(borderColor), BorderWidth), points[2], points[3]);
+
+ _headerHeight += _multiHeight;
+ }
+
+ private double GetMultidayHeight(PDFPage page)
+ {
+ var cols = Parser.WeekColsParsing(page);
+ var events = page.Multiday;
+ var scheme = new int[cols[0].Length];
+ for (var i = 0; i < scheme.Length; i++)
+ scheme[i] = 0;
+ for (var i = 0; i < events.Count; i++)
+ {
+ var day = events[i].Day;
+ var len = events[i].Len;
+ for (var j = day; j < day + len; j++)
+ scheme[j]++;
+ }
+ var max = scheme[0];
+ for (var i = 1; i < scheme.Length; i++)
+ {
+ if (scheme[i] > max)
+ max = scheme[i];
+ }
+ return max * _multidayLineHeight;
+ }
+
+ private void WeekContainerDraw()
+ {
+ var bgColor = RGBColor.GetColor(_bgColor);
+ var borderColor = RGBColor.GetColor(_lineColor);
+ var headerLineColor = RGBColor.GetColor(_headerLineColor);
+ var scaleOneColor = RGBColor.GetColor(_scaleOneColor);
+ var scaleTwoColor = RGBColor.GetColor(_scaleTwoColor);
+ var rows = Parser.WeekRowsParsing(CurrentPage);
+ var width = _leftScaleWidth;
+ var height = (_pageHeight - _headerHeight) / rows.Length;
+ _weekDayHeight = height;
+ var x = _offsetLeft;
+ var y = _offsetTop + _headerHeight;
+ for (var i = 0; i < rows.Length; i++)
+ {
+
+ var cell = _resizer.Rect(x, y, width, height);
+ var cellBrush = new XSolidBrush(RGBColor.GetXColor(bgColor));
+
+ var scaleOne = _resizer.Rect(x + width, y, _pageWidth - width, height / 2);
+ var scaleOneBrush = new XSolidBrush(RGBColor.GetXColor(scaleOneColor));
+
+ var scaleTwo = _resizer.Rect(x + width, y + height / 2, _pageWidth - width, height / 2);
+ var scaleTwoBrush = new XSolidBrush(RGBColor.GetXColor(scaleTwoColor));
+
+ Gfx.DrawRectangle(cellBrush, cell);
+ Gfx.DrawRectangle(scaleOneBrush, scaleOne);
+ Gfx.DrawRectangle(scaleTwoBrush, scaleTwo);
+
+ Gfx.DrawLine(new XPen(RGBColor.GetXColor(headerLineColor), BorderWidth), _resizer.Point(x, y), _resizer.Point(x + width, y));
+
+ var text = TextWrap(rows[i], width - 2 * _cellOffset, F1, TrimLayoutStrings);
+ var textX = x + (width - Gfx.MeasureString(text, F1).Width) / 2;
+ var textY = y + (height + F1.Size) / 2;
+
+ Gfx.DrawString(text, F1, new XSolidBrush(RGBColor.GetXColor(_textColor)), _resizer.Point(textX, textY));
+
+ y += height;
+ }
+
+ var cols = Parser.WeekColsParsing(CurrentPage);
+ width = (_pageWidth - _leftScaleWidth) / cols[0].Length;
+ x = _offsetLeft + _leftScaleWidth;
+ y = _offsetTop + _headerHeight;
+ for (var scale = 0; scale < cols.Length; scale++)
+ {
+ for (var col = 0; col < cols[scale].Length; col++)
+ {
+ var points = new XPoint[2];
+ points[0] = _resizer.Point(x, y);
+ points[1] = _resizer.Point(x, _pageHeight + _offsetTop);
+
+ Gfx.DrawLine(new XPen(RGBColor.GetXColor(borderColor), BorderWidth), points[0], points[1]);
+
+ x += width;
+ }
+ y += _headerHeight;
+ }
+
+ var points2 = new XPoint[2];
+ points2[0] = _resizer.Point(x, y - _multiHeight);
+ points2[1] = _resizer.Point(x, _offsetTop + _pageHeight);
+
+ Gfx.DrawLine(new XPen(RGBColor.GetXColor(borderColor), BorderWidth), points2[0], points2[1]);
+ }
+
+ private void WeekEventsDraw(PDFPage page)
+ {
+ var eventBorderColor = RGBColor.GetColor(_eventBorderColor);
+ var eventColor = RGBColor.GetColor(_eventColor);
+
+ var textColor = RGBColor.GetColor(_eventTextColor);
+ var textFormatter = new DHXTextFormatter(Gfx);
+ var events = page.Events;
+ var defAlign = textFormatter.Alignment;
+
+ for (var i = 0; i < events.Count; i++)
+ {
+ var x = _offsetLeft + _leftScaleWidth + events[i].X
+ * _weekDayWidth / 100;
+ var y = _offsetTop + _headerHeight + events[i].Y
+ * _weekDayHeight / 100;
+ var width = events[i].Width * _weekDayWidth / 100;
+ var height = events[i].Height * _weekDayHeight / 100;
+ var text = events[i].Text;
+ var headerText = events[i].HeaderText;
+ var bgColor = events[i].BackgroundColor;
+ var color = events[i].Color;
+
+
+ var borders = new XPoint[4];
+ borders[0] = _resizer.Point(x, y);
+ borders[1] = _resizer.Point(x + width, y);
+ borders[2] = _resizer.Point(x + width, y + height);
+ borders[3] = _resizer.Point(x, y + height);
+
+
+ var eventBg = _resizer.Rect(x, y, width, height);
+ var evBrush = new XSolidBrush(RGBColor.GetXColor(SelectColor(bgColor, eventColor)));
+
+ F1 = new XFont(F1.FontFamily.Name, BaseFontSize);
+
+ var textY = y + (_weekEventHeaderHeight - F1.Size) / 2;
+ var headTxtBrush = new XSolidBrush(RGBColor.GetXColor(SelectColor(color, textColor)));
+
+ var bodyTxt = text;
+ var bodyTextX = x;
+ var bodyTextWidth = width;
+ if (width > 3 * _cellOffset)
+ {
+ bodyTextX = x + _cellOffset;
+ bodyTextWidth = width - 2 * _cellOffset;
+ }
+ var bodyTextY = y;
+ var bodyTextHeight = height;
+ if (height > 3 * _cellOffset)
+ {
+ bodyTextY = y + _cellOffset + _weekEventHeaderHeight;
+ bodyTextHeight = height - 2 * _cellOffset;
+ }
+
+
+
+ var bodyTxtBrush = new XSolidBrush(RGBColor.GetXColor(SelectColor(color, textColor)));
+
+ Gfx.DrawRectangle(evBrush, eventBg);
+ var borderPen = new XPen(RGBColor.GetXColor(eventBorderColor), BorderWidth);
+ Gfx.DrawLine(borderPen, borders[0], borders[1]);
+ Gfx.DrawLine(borderPen, borders[1], borders[2]);
+ Gfx.DrawLine(borderPen, borders[2], borders[3]);
+ Gfx.DrawLine(borderPen, borders[3], borders[0]);
+
+ Gfx.DrawLine(borderPen, _resizer.Point(x, y + _weekEventHeaderHeight), _resizer.Point(x + width, y + _weekEventHeaderHeight));
+
+ textFormatter.Alignment = XParagraphAlignment.Center;
+ textFormatter.DrawString(headerText, F1, headTxtBrush, _resizer.Rect(x, textY, width, _weekEventHeaderHeight));
+
+ textFormatter.Alignment = defAlign;
+
+ textFormatter.DrawString(bodyTxt, F1, bodyTxtBrush, _resizer.Rect(bodyTextX, bodyTextY, bodyTextWidth, bodyTextHeight));
+
+ }
+
+ // preparing scheme to calculate multiday position
+ var cols = Parser.WeekColsParsing(CurrentPage);
+ var scheme = new int[cols[0].Length];
+ for (var i = 0; i < scheme.Length; i++)
+ scheme[i] = 0;
+
+ events = page.Multiday;
+ var offset = 1;
+ for (var i = 0; i < events.Count; i++)
+ {
+ var ev = events[i];
+ var day = ev.Day;
+ var len = ev.Len;
+ var text = ev.Text;
+ var bgColor = ev.BackgroundColor;
+ var color = ev.Color;
+
+ var width = len * _weekDayWidth - 2 * offset;
+ var height = _monthEventHeight;
+ var x = _offsetLeft + _leftScaleWidth + day
+ * _weekDayWidth + offset;
+ var y = _offsetTop + _headHeight + scheme[day]
+ * _multidayLineHeight;
+
+ var cont = _resizer.Rect(x, y, width, height);
+ var evBrush = new XSolidBrush(RGBColor.GetXColor(SelectColor(bgColor, eventColor)));
+
+ F1 = new XFont(F1.FontFamily.Name, BaseFontSize);
+ var txtX = x + _cellOffset;
+ var txtY = y + (_weekEventHeaderHeight - F1.Size) / 2;
+ var textBrush = new XSolidBrush(RGBColor.GetXColor(SelectColor(color, textColor)));
+
+ Gfx.DrawRectangle(evBrush, cont);
+ var borders = new XPoint[4];
+ borders[0] = _resizer.Point(x, y);
+ borders[1] = _resizer.Point(x + width, y);
+ borders[2] = _resizer.Point(x + width, y + height);
+ borders[3] = _resizer.Point(x, y + height);
+ Gfx.DrawLine(new XPen(RGBColor.GetXColor(eventBorderColor), BorderWidth), borders[0], borders[1]);
+ Gfx.DrawLine(new XPen(RGBColor.GetXColor(eventBorderColor), BorderWidth), borders[1], borders[2]);
+ Gfx.DrawLine(new XPen(RGBColor.GetXColor(eventBorderColor), BorderWidth), borders[2], borders[3]);
+ Gfx.DrawLine(new XPen(RGBColor.GetXColor(eventBorderColor), BorderWidth), borders[3], borders[0]);
+ textFormatter.DrawString(text, F1, textBrush, _resizer.Rect(txtX, txtY, width, height));
+ for (var j = day; j < day + len; j++)
+ scheme[j]++;
+ }
+ }
+
+ private void WeekBwBordersDraw()
+ {
+ var borderColor = RGBColor.GetColor(_lineColor);
+
+ var x = _offsetLeft;
+ var y = _offsetTop;
+ Line(borderColor, x + _leftScaleWidth, y, x + _pageWidth,
+ y);
+
+ if (_multiHeight > 0)
+ {
+ y = _offsetTop + _headerHeight - _multiHeight;
+ Line(borderColor, x + _leftScaleWidth, y, x
+ + _pageWidth, y);
+ Line(borderColor, x, y, x, y + _pageHeight
+ - (_headerHeight - _multiHeight));
+ }
+
+ y = _offsetTop + _headerHeight;
+ Line(borderColor, x, y, x + _pageWidth, y);
+
+ y = _offsetTop + _pageHeight;
+ Line(borderColor, x, y, x + _pageWidth, y);
+
+ x = _offsetLeft + _leftScaleWidth;
+ Line(borderColor, x, y, x, y + _headerHeight);
+
+ x = _offsetLeft + _pageWidth;
+ Line(borderColor, x, y, x, y + _headerHeight);
+
+ }
+
+ private void Line(double[] color, double x1, double y1, double x2, double y2)
+ {
+ Gfx.DrawLine(new XPen(RGBColor.GetXColor(color), BorderWidth), _resizer.Point(x1, y1), _resizer.Point(x2, y2));
+ }
+ private void Line(double[] color, double x1, double y1, double x2, double y2, XRect cell)
+ {
+ Gfx.DrawLine(new XPen(RGBColor.GetXColor(color), BorderWidth), _resizer.Point(cell.Location.X + x1, cell.Location.Y + y1), _resizer.Point(cell.Location.X + x2, cell.Location.Y + y2));
+ }
+
+ private void _drawTimelineContainerPart(string[] rows)
+ {
+ var headerLineColor = RGBColor.GetColor(_headerLineColor);
+ var x = _offsetLeft;
+ var y = _offsetTop + _headerHeight;
+ var width = _leftScaleWidth;
+ var height = TimelineRowMinHeight;
+ for (var i = 0; i < rows.Length; i++)
+ {
+ var cell = _resizer.Rect(x, y, width, height);
+ var cellBrush = new XSolidBrush(RGBColor.GetXColor(_bgColor));
+
+ var scaleOne = _resizer.Rect(x + width, y, _pageWidth - width, height);
+ var scaleOneBrush = new XSolidBrush(RGBColor.GetXColor(_scaleOneColor));
+
+ Gfx.DrawRectangle(cellBrush, cell);
+ Gfx.DrawRectangle(scaleOneBrush, scaleOne);
+
+ Line(headerLineColor, x, y, x + width, y);
+
+ var text = TextWrap(rows[i], width - 2 * _cellOffset, F1, TrimLayoutStrings);
+ var textX = x + (width - Gfx.MeasureString(text, F1).Width) / 2;
+ var textY = y + (height + F1.Size) / 2;
+ Gfx.DrawString(text, F1, new XSolidBrush(RGBColor.GetXColor(_textColor)), _resizer.Point(textX, textY));
+
+ y += height;
+ }
+ }
+
+
+ private double _getPadding(TreeTimelineCategory row)
+ {
+ double levelPadding = 0.0;
+ for (var lev = 0; lev < row.Level; lev++)
+ {
+ levelPadding += Gfx.MeasureString("ww", F1).Width;
+ }
+ if (row.IsExpandable)
+ levelPadding -= Gfx.MeasureString("+ ", F1).Width;
+ if (levelPadding < 0)
+ levelPadding = 0.0;
+ return levelPadding;
+ }
+ private void _drawTreeLevelScales(string[] rows)
+ {
+ var x = _offsetLeft;
+ var y = _offsetTop + _headerHeight;
+ var width = _leftScaleWidth;
+ var height = (_pageHeight - _headerHeight) / rows.Length;
+ var pars = new TreeTimelineParser();
+ F1 = new XFont(F1.FontFamily.Name, F1.Size, XFontStyle.Bold);
+ for (var i = 0; i < rows.Length; i++)
+ {
+
+ var row = pars.Parse(rows[i]);
+ if (row.IsExpandable)
+ {
+ var levelPadding = _getPadding(row);
+ var scaleOne = _resizer.Rect(x + width, y, _pageWidth - width, height);
+ var scaleOneBrush = new XSolidBrush(RGBColor.GetXColor(_timelineTreeColor));
+
+
+ Gfx.DrawRectangle(scaleOneBrush, scaleOne);
+
+
+ var textX = levelPadding + x;
+ var textY = y + (height + F1.Size) / 2;
+ var text = (row.Expanded ? " - " : " + ") + row.Text;
+ text = TextWrap(text, _pageWidth, F1, TrimLayoutStrings);
+ Gfx.DrawString(text, F1, new XSolidBrush(RGBColor.GetXColor(_textColor)), _resizer.Point(textX, textY));
+ }
+ y += height;
+ }
+ F1 = new XFont(F1.FontFamily.Name, F1.Size, XFontStyle.Regular);
+ }
+ private void _drawTreeTimelineContainerPart(string[] rows)
+ {
+ var headerLineColor = RGBColor.GetColor(_headerLineColor);
+ var y = _offsetTop + _headerHeight;
+ var width = _leftScaleWidth;
+ var height = (_pageHeight - _headerHeight) / rows.Length;
+
+ var pars = new TreeTimelineParser();
+
+ for (var i = 0; i < rows.Length; i++)
+ {
+ var x = _offsetLeft;
+ var row = pars.Parse(rows[i]);
+
+ var levelPadding = _getPadding(row);
+
+ XRect cell;
+ XBrush cellBrush;
+
+ if (row.IsExpandable)
+ {
+ F1 = new XFont(F1.FontFamily.Name, F1.Size, XFontStyle.Bold);
+ cell = _resizer.Rect(x, y, width, height);
+ cellBrush = new XSolidBrush(RGBColor.GetXColor(_timelineTreeColor));
+ Gfx.DrawRectangle(cellBrush, cell);
+ }
+ else
+ {
+ F1 = new XFont(F1.FontFamily.Name, F1.Size, XFontStyle.Regular);
+
+ cell = _resizer.Rect(x, y, width, height);
+ cellBrush = new XSolidBrush(RGBColor.GetXColor(_bgColor));
+
+ var scaleOne = _resizer.Rect(x + width, y, _pageWidth - width, height);
+ var scaleOneBrush = new XSolidBrush(RGBColor.GetXColor(_scaleOneColor));
+
+ var text = TextWrap(row.Text, width - 2 * _cellOffset - levelPadding, F1, TrimLayoutStrings);
+ var textX = levelPadding + x;
+ var textY = y + (height + F1.Size) / 2;
+ Gfx.DrawRectangle(cellBrush, cell);
+ Gfx.DrawRectangle(scaleOneBrush, scaleOne);
+ Gfx.DrawString(text, F1, new XSolidBrush(RGBColor.GetXColor(_textColor)), _resizer.Point(textX, textY));
+ }
+
+ Line(headerLineColor, x, y, x + width, y);
+
+ y += height;
+ }
+
+ }
+
+ private void TimelineContainerDraw(string[] rows)
+ {
+ var borderColor = RGBColor.GetColor(_lineColor);
+
+ var isTree = false;
+ if (rows.Length > 0)
+ {
+ isTree = TreeTimelineParser.IsTreeRow(rows[0]);
+ }
+
+ if (isTree)
+ {
+ _drawTreeTimelineContainerPart(rows);
+ }
+ else
+ {
+ _drawTimelineContainerPart(rows);
+ }
+
+ var cols = Parser.WeekColsParsing(CurrentPage);
+ var width = double.MaxValue;
+ var height = TimelineRowMinHeight;
+ _weekDayHeight = height;
+ var colCount = -1;
+ for (var i = 0; i < cols.Length; i++)
+ {
+ var scale = (_pageWidth - _leftScaleWidth) / cols[i].Length;
+ if (width > scale)
+ width = scale;
+ if (colCount < cols[i].Length)
+ colCount = cols[i].Length;
+ }
+
+ var x = _offsetLeft + _leftScaleWidth;
+ var y = _offsetTop + _headerHeight;
+
+ var colHeight = height * rows.Length + _offsetTop + _headerHeight;
+ for (var i = 0; i < colCount; i++)
+ {
+ Gfx.DrawLine(new XPen(RGBColor.GetXColor(borderColor), BorderWidth),
+ _resizer.Point(x, y), _resizer.Point(x, colHeight));
+
+ x += width;
+ }
+
+ if (isTree)
+ _drawTreeLevelScales(rows);
+
+ Gfx.DrawLine(new XPen(RGBColor.GetXColor(borderColor), BorderWidth),
+ _resizer.Point(_offsetLeft + _leftScaleWidth, y), _resizer.Point(_offsetLeft + _leftScaleWidth + width, y));
+
+ y = _offsetTop + _headerHeight + height;
+ for (var i = 0; i < rows.Length; i++)
+ {
+ Gfx.DrawLine(new XPen(RGBColor.GetXColor(borderColor), BorderWidth),
+ _resizer.Point(_offsetLeft + _leftScaleWidth, y), _resizer.Point(_offsetLeft + _pageWidth, y));
+ y += height;
+ }
+
+ Gfx.DrawLine(new XPen(RGBColor.GetXColor(borderColor), BorderWidth),
+ _resizer.Point(_offsetLeft + _leftScaleWidth, _offsetTop + _headerHeight),
+ _resizer.Point(_offsetLeft + _pageWidth, _offsetTop + _headerHeight));
+
+ Gfx.DrawLine(new XPen(RGBColor.GetXColor(borderColor), BorderWidth),
+ _resizer.Point(x, _offsetTop),
+ _resizer.Point(x, colHeight));
+ }
+
+ private void MatrixContainerDraw(PDFPage page)
+ {
+ var bgColor = RGBColor.GetColor(_bgColor);
+ var borderColor = RGBColor.GetColor(_lineColor);
+ var headerLineColor = RGBColor.GetColor(_headerLineColor);
+ var matrixEventColor = RGBColor.GetColor(_matrixEventColor);
+ var textColor = RGBColor.GetColor(_textColor);
+ var rows = Parser.WeekRowsParsing(CurrentPage);
+ var height = (_pageHeight - _headerHeight) / rows.Length;
+ var cols = Parser.WeekColsParsing(CurrentPage);
+ var events = page.Events;
+ var columns = cols[0];
+ for (var i = 0; i < rows.Length; i++)
+ {
+ for (var j = 0; j <= columns.Length; j++)
+ {
+ var ev = events[i * (columns.Length + 1) + j];
+ var evBgColor = ev.BackgroundColor;
+ var evTextColor = ev.Color;
+ var text = ev.Text;
+ var x = _offsetLeft + Math.Max(j - 1, 0)
+ * _weekDayWidth + (j != 0 ? 1 : 0)
+ * _leftScaleWidth;
+ var y = _offsetTop + _headerHeight + i * height;
+
+ var width = (j == 0) ? _leftScaleWidth : _weekDayWidth;
+
+
+ var cell = _resizer.Rect(x, y, width, height);
+ var cellBrush = new XSolidBrush(RGBColor.GetXColor(SelectColor(evBgColor, matrixEventColor)));
+
+
+
+ if (j == 0)
+ cellBrush = new XSolidBrush(RGBColor.GetXColor(bgColor));
+ Gfx.DrawRectangle(cellBrush, cell);
+
+
+ // draw cell text
+ F1 = new XFont(F1.FontFamily.Name, (j == 0) ? BaseFontSize : 8.4);
+ var txt = TextWrap(text, width - 2 * _cellOffset, F1, TrimContentStrings);
+ var textX = x + (width - Gfx.MeasureString(txt, F1).Width) / 2;
+ var textY = y + (height - F1.Size) / 2;
+ var txtBrush = new XSolidBrush(RGBColor.GetXColor(SelectColor(evTextColor, textColor)));
+
+ Gfx.DrawString(txt, F1, txtBrush, _resizer.Point(textX, textY));
+
+ // draw borders
+ if (j == 0)
+ {
+ Line(headerLineColor, x, y, x + width, y);
+ }
+ else
+ {
+ Line(borderColor, x, y, x + width, y);
+ Line(borderColor, x, y, x, y + height);
+ }
+ }
+ }
+
+ // border right
+ Line(borderColor, _offsetLeft + _pageWidth, _offsetTop, _offsetLeft + _pageWidth, _offsetTop
+ + _pageHeight);
+
+ Line(borderColor, _offsetLeft, _offsetTop + _pageHeight, _offsetLeft + _pageWidth, _offsetTop
+ + _pageHeight);
+ }
+
+ private void TimelineEventsDraw(PDFPage page, int pageNumber, int blocksNumber)
+ {
+ var eventBorderColor = RGBColor.GetColor(_eventBorderColor);
+ var eventColor = RGBColor.GetColor(_eventColor);
+ var textColor = RGBColor.GetColor(_eventTextColor);
+ var events = page.Events;
+
+ var offset = 1;
+ for (var i = 0; i < events.Count; i++)
+ {
+ var ev = events[i];
+ var text = ev.Text;
+ var bgColor = ev.BackgroundColor;
+ var color = ev.Color;
+
+ if (ev.Week >= pageNumber * blocksNumber) continue;
+ if (ev.Week < (pageNumber - 1) * blocksNumber) continue;
+
+ var x = _offsetLeft + _leftScaleWidth + ev.X
+ * _weekDayWidth / 100 + offset;
+ var y = _offsetTop + _headerHeight + ev.Y
+ * _weekDayHeight / 100 + ((ev.Week - (pageNumber - 1) * blocksNumber)
+ * _weekDayHeight);
+
+ var width = ev.Width * _weekDayWidth / 100;
+ var height = _monthEventHeight;
+
+ var cell = _resizer.Rect(x, y, width, height);
+
+ var cellBrush = new XSolidBrush(RGBColor.GetXColor(SelectColor(bgColor, eventColor)));
+
+ F1 = new XFont(F1.FontFamily.Name, BaseFontSize);
+ var txt = TextWrap(text, width, F1, TrimContentStrings);
+ var txtX = x + _cellOffset;
+ var txtY = y + (_weekEventHeaderHeight + F1.Size) / 2;
+ var txtBrush = new XSolidBrush(RGBColor.GetXColor(SelectColor(color, textColor)));
+
+
+ Gfx.DrawRectangle(cellBrush, cell);
+
+ var borders = new XPoint[4];
+ borders[0] = _resizer.Point(x, y);
+ borders[1] = _resizer.Point(x + width, y);
+ borders[2] = _resizer.Point(x + width, y + height);
+ borders[3] = _resizer.Point(x, y + height);
+ Gfx.DrawLine(new XPen(RGBColor.GetXColor(eventBorderColor), BorderWidth), borders[0], borders[1]);
+ Gfx.DrawLine(new XPen(RGBColor.GetXColor(eventBorderColor), BorderWidth), borders[1], borders[2]);
+ Gfx.DrawLine(new XPen(RGBColor.GetXColor(eventBorderColor), BorderWidth), borders[2], borders[3]);
+ Gfx.DrawLine(new XPen(RGBColor.GetXColor(eventBorderColor), BorderWidth), borders[3], borders[0]);
+
+ Gfx.DrawString(txt, F1, txtBrush, _resizer.Point(txtX, txtY));
+ }
+ }
+
+ private void YearDraw(PDFPage page)
+ {
+ var bgColor = RGBColor.GetColor(_bgColor);
+ var borderColor = RGBColor.GetColor(_lineColor);
+ var headerLineColor = RGBColor.GetColor(_headerLineColor);
+ var textColor = RGBColor.GetColor(_textColor);
+ var eventColor = RGBColor.GetColor(_eventColor);
+ var yearDayActiveColor = RGBColor.GetColor(_yearDayActiveColor);
+ var yearDayInactiveColor = RGBColor.GetColor(_yearDayInactiveColor);
+ var monthes = Parser.YearParsing(CurrentPage);
+ var events = page.Events;
+ var width = (_pageWidth - _yearMonthOffsetLeft * 3) / 4;
+ var height = (_pageHeight - _yearMonthOffsetTop * 2) / 3;
+ var monthX = _offsetLeft;
+ var monthY = _offsetTop;
+ for (var i = 0; i < 3; i++)
+ {
+ for (var j = 0; j < 4; j++)
+ {
+ var mon = monthes[i * 4 + j];
+ var label = mon.GetLabel();
+ var rows = mon.GetRows();
+ var onlyDays = mon.GetOnlyDays();
+
+ var monthCont = _resizer.Rect(monthX, monthY, width, height);
+ var monthContBrush = new XSolidBrush(RGBColor.GetXColor(bgColor));
+
+
+ var labelText = TextWrap(label, width, F1, TrimLayoutStrings);
+ var labelTextX = monthX + (width - Gfx.MeasureString(label, F1).Width) / 2;
+ var labelTextY = monthY + (_yearMonthLabelHeight + F1.Size) / 2;
+ var labelTextBrush = new XSolidBrush(RGBColor.GetXColor(textColor));
+
+ Gfx.DrawRectangle(monthContBrush, monthCont);
+ Gfx.DrawString(labelText, F1, labelTextBrush, _resizer.Point(labelTextX, labelTextY));
+
+
+ var cellWidth = width / 7;
+ var cellHeight = (height - _yearMonthLabelHeight)
+ / rows.GetLength(0);
+ var cellX = monthX;
+ var cellY = monthY + _yearMonthLabelHeight;
+ for (var k = 0; k < rows.GetLength(0); k++)
+ {
+ for (var l = 0; l < 7; l++)
+ {
+
+ var cell = _resizer.Rect(cellX, cellY, cellWidth, cellHeight);
+ XBrush cellBrush;
+
+ var ind = GetEventIndex(events, l, k - 1, i * 4 + j);
+ if (k == 0)
+ {
+ cellBrush = new XSolidBrush(RGBColor.GetXColor(bgColor));
+ }
+ else
+ {
+ if (GetActiveDay(onlyDays, k - 1, l))
+ {
+ if (ind == -1)
+ {
+ cellBrush = new XSolidBrush(RGBColor.GetXColor(yearDayActiveColor));
+ }
+ else
+ {
+ var ev = events[ind];
+ var color = ev.BackgroundColor;
+ cellBrush = new XSolidBrush(RGBColor.GetXColor(SelectColor(color, eventColor)));
+
+ }
+ }
+ else
+ {
+ cellBrush = new XSolidBrush(RGBColor.GetXColor(yearDayInactiveColor));
+
+ }
+ }
+ Gfx.DrawRectangle(cellBrush, cell);
+
+ if (k == 0)
+ Line(headerLineColor, 0, 0, cellWidth, 0,
+ cell);
+ else
+ Line(borderColor, 0, 0, cellWidth, 0, cell);
+ if (l > 0)
+ if (k == 0)
+ Line(headerLineColor, 0, 0, 0,
+ cellHeight, cell);
+ else
+ Line(borderColor, 0, 0, 0, cellHeight,
+ cell);
+
+ var cellText = rows[k, l];
+ var cellTextX = cellX + (cellWidth - Gfx.MeasureString(cellText, F1).Width) / 2;
+ var cellTextY = cellY + (cellHeight + F1.Size) / 2;
+ XSolidBrush evBrush;
+
+ if (ind > -1)
+ {
+ var ev = events[ind];
+ var color = ev.Color;
+ evBrush = new XSolidBrush(RGBColor.GetXColor(SelectColor(color, textColor)));
+
+ }
+ else
+ evBrush = new XSolidBrush(RGBColor.GetXColor(textColor));
+ Gfx.DrawString(cellText, F1, evBrush, _resizer.Point(cellTextX, cellTextY));
+ cellX += cellWidth;
+ }
+ cellX = monthX;
+ cellY += cellHeight;
+ }
+ if (_profile == ColorProfile.BW)
+ {
+ Line(headerLineColor, 0, 0, 0, height, monthCont);
+ Line(headerLineColor, 0, 0, width, 0, monthCont);
+ Line(headerLineColor, 0, height, width, height,
+ monthCont);
+ Line(headerLineColor, width, 0, width, height,
+ monthCont);
+ }
+ monthX += _yearMonthOffsetLeft + width;
+ }
+ monthX = _offsetLeft;
+ monthY += _yearMonthOffsetTop + height;
+ }
+ }
+
+ private void AgendaHeaderDraw()
+ {
+ var bgColor = RGBColor.GetColor(_bgColor);
+ var borderColor = RGBColor.GetColor(_headerLineColor);
+ var textColor = RGBColor.GetColor(_textColor);
+ var cols = Parser.AgendaColsParsing(CurrentPage);
+
+ var width = _pageWidth;
+ var height = _headerHeight;
+ var x = _offsetLeft;
+ var y = _offsetTop;
+
+ var headerBg = _resizer.Rect(x, y, width, height);
+
+ var monthContBrush = new XSolidBrush(RGBColor.GetXColor(bgColor));
+ Gfx.DrawRectangle(monthContBrush, headerBg);
+
+ var dateWidth = _agendaColOneWidth;
+ var nameWidth = width - _agendaColOneWidth;
+
+ var sep = new[] { _resizer.Point(x + dateWidth, y), _resizer.Point(x + dateWidth, y + _headerHeight) };
+ Gfx.DrawLine(new XPen(RGBColor.GetXColor(borderColor), 0.3), sep[0], sep[1]);
+
+
+ F1 = new XFont(F1.FontFamily.Name, BaseFontSize);
+ var dateText = cols[0];
+
+ var textBrush = new XSolidBrush(RGBColor.GetXColor(textColor));
+ var dateTextX = x + (dateWidth - Gfx.MeasureString(dateText, F1).Width) / 2;
+ var dateTextY = y + (height + F1.Size) / 2;
+ Gfx.DrawString(dateText, F1, textBrush, _resizer.Point(dateTextX, dateTextY));
+
+
+
+ var nameText = cols[1];
+ var nameTextX = x + dateWidth + (nameWidth - Gfx.MeasureString(nameText, F1).Width) / 2;
+ var nameTextY = y + (height + F1.Size) / 2;
+ Gfx.DrawString(nameText, F1, textBrush, _resizer.Point(nameTextX, nameTextY));
+
+
+ var borders = new[]{
+ _resizer.Point(x, y),
+ _resizer.Point(x + width, y),
+ _resizer.Point(x + width, y + height),
+ _resizer.Point(x, y + height)};
+ Gfx.DrawLine(new XPen(RGBColor.GetXColor(_lineColor), 0.3), borders[0], borders[1]);
+ Gfx.DrawLine(new XPen(RGBColor.GetXColor(_lineColor), 0.3), borders[1], borders[2]);
+ Gfx.DrawLine(new XPen(RGBColor.GetXColor(_lineColor), 0.3), borders[2], borders[3]);
+ Gfx.DrawLine(new XPen(RGBColor.GetXColor(_lineColor), 0.3), borders[3], borders[0]);
+
+ }
+
+ private void AgendaEventDraw(PDFPage page)
+ {
+ var scaleOneColor = RGBColor.GetColor(_scaleOneColor);
+ var scaleTwoColor = RGBColor.GetColor(_scaleTwoColor);
+ var borderColor = RGBColor.GetColor(_lineColor);
+ var textColor = RGBColor.GetColor(_textColor);
+ var events = page.Events;
+ var width = _pageWidth;
+ var height = _headerHeight;
+ var x = _offsetLeft;
+ var y = _offsetTop + _headerHeight;
+
+ var linePen = new XPen(RGBColor.GetXColor(_eventBorderColor), BorderWidth);
+
+ F1 = new XFont(F1.FontFamily.Name, BaseFontSize);
+ for (var i = 0; i < events.Count; i++)
+ {
+ if (y + height > _offsetTop + _pageHeight)
+ {
+
+ Gfx.DrawLine(linePen, _resizer.Point(x, y), _resizer.Point(x + width, y));
+
+
+ Page = NewPage(PageOrientation.Portrait, PageSize.A4);
+
+ AgendaHeaderDraw();
+ y = _offsetTop + _headerHeight;
+ }
+
+
+
+ var headerCont = _resizer.Rect(x, y, width, height);
+ XBrush headerBrush;
+ if (i % 2 == 0)
+ {
+ headerBrush = new XSolidBrush(RGBColor.GetXColor(scaleOneColor));
+ }
+ else
+ {
+ headerBrush = new XSolidBrush(RGBColor.GetXColor(scaleTwoColor));
+ }
+
+ var dateWidth = _agendaColOneWidth;
+
+ Gfx.DrawRectangle(headerBrush, headerCont);
+
+ var borders = new[]{
+ _resizer.Point(x, y),
+ _resizer.Point(x + dateWidth, y),
+ _resizer.Point(x + dateWidth, y + height),
+ _resizer.Point(x, y + height)};
+ Gfx.DrawLine(new XPen(RGBColor.GetXColor(borderColor), BorderWidth), borders[0], borders[1]);
+ Gfx.DrawLine(new XPen(RGBColor.GetXColor(borderColor), BorderWidth), borders[1], borders[2]);
+ Gfx.DrawLine(new XPen(RGBColor.GetXColor(borderColor), BorderWidth), borders[2], borders[3]);
+ Gfx.DrawLine(new XPen(RGBColor.GetXColor(borderColor), BorderWidth), borders[3], borders[0]);
+
+ var headerText = events[i].HeaderAgendaText;
+ var text = events[i].Text;
+
+ var textBrush = new XSolidBrush(RGBColor.GetXColor(textColor));
+
+ var dateTextX = x + (dateWidth - Gfx.MeasureString(headerText, F1).Width) / 2;
+ var dateTextY = y + (height + F1.Size) / 2;
+ Gfx.DrawString(headerText, F1, textBrush, _resizer.Point(dateTextX, dateTextY));
+
+
+
+ var nameTextX = x + dateWidth + _cellOffset;
+ var nameTextY = y + (height + F1.Size) / 2;
+ Gfx.DrawString(text, F1, textBrush, _resizer.Point(nameTextX, nameTextY));
+
+ Gfx.DrawLine(new XPen(RGBColor.GetXColor(borderColor), BorderWidth), _resizer.Point(x, y), _resizer.Point(x, y + height));
+ Gfx.DrawLine(new XPen(RGBColor.GetXColor(borderColor), BorderWidth), _resizer.Point(x, y), _resizer.Point(x + width, y));
+ Gfx.DrawLine(new XPen(RGBColor.GetXColor(borderColor), BorderWidth), _resizer.Point(x + width, y), _resizer.Point(x + width, y + height));
+ Gfx.DrawLine(new XPen(RGBColor.GetXColor(borderColor), BorderWidth), _resizer.Point(x + dateWidth, y), _resizer.Point(x + dateWidth, y + height));
+
+
+ y += height;
+ }
+
+ Gfx.DrawLine(new XPen(RGBColor.GetXColor(borderColor), BorderWidth), _resizer.Point(x, y), _resizer.Point(x + width, y));
+
+
+ }
+
+ private void PrintFooter()
+ {
+ if (CurrentPage.Footer)
+ {
+ var im = Images.Get(FooterImgPath);
+ if (im != null)
+ {
+ Gfx.DrawImage(im, _resizer.Point(_offsetLeft, _pageHeight + _offsetTop - FooterImgHeight));
+ _pageHeight -= FooterImgHeight;
+ _offsetBottom += FooterImgHeight;
+ }
+ }
+ }
+
+ private void AgendaPagesDraw()
+ {
+ for (var i = 1; i <= Pages.Count; i++)
+ {
+ var graph = Graphics[i - 1];
+ if (_profile == ColorProfile.BW
+ && CurrentPage.Mode != "month")
+ MonthBwBordersDraw();
+ var str = _pageNumTemplate;
+ str = str.Replace("{pageNum}", i.ToString());
+ str = str.Replace("{allNum}", Pages.Count.ToString());
+
+ var text = new XTextFormatter(graph);
+ var x = _pageWidth + _offsetLeft - graph.MeasureString(str, F1).Width;
+
+ var y = _pageHeight + _offsetTop + F1.Size;
+ if (CurrentPage.Footer && Images.Get(FooterImgPath) != null)
+ y += FooterImgHeight;
+
+ text.DrawString(str, F1, new XSolidBrush(RGBColor.GetXColor(_textColor)), _resizer.Rect(x, y, graph.MeasureString(str, F1).Width, F1.Size));
+ }
+
+ }
+
+
+ private void WeekAgendaContainerDraw()
+ {
+ var cols = Parser.AgendaColsParsing(CurrentPage);
+ var x = _offsetLeft;
+ var contWidth = (_pageWidth) / 2;
+ var contHeight = (_pageHeight) / 3;
+ _contWidth = contWidth;
+ _contHeight = contHeight;
+
+
+ for (var i = 0; i < 3; i++)
+ {
+ var y = _offsetTop + contHeight * i;
+ WeekAgendarDayDraw(cols[i], contWidth, contHeight, x, y);
+ }
+ x += contWidth;
+ for (var i = 0; i < 2; i++)
+ {
+ var y = _offsetTop + contHeight * i;
+ WeekAgendarDayDraw(cols[i + 3], contWidth, contHeight, x, y);
+ }
+
+ var tallContHeight = contHeight / 2;
+ for (var i = 0; i < 2; i++)
+ {
+ var y = _offsetTop + contHeight * 2 + tallContHeight * i;
+ WeekAgendarDayDraw(cols[i + 5], contWidth, tallContHeight, x, y);
+ }
+ var headerLineColor = RGBColor.GetColor(_headerLineColor);
+ for (var i = 0; i < 3; i++)
+ {
+ var y = _offsetTop + contHeight * i;
+ Line(headerLineColor, x, y, x, y + _monthDayHeaderHeight);
+ }
+ }
+
+ private void WeekAgendarDayDraw(string name, double width, double height, double x, double y)
+ {
+ var bgColor = RGBColor.GetColor(_bgColor);
+ var borderColor = RGBColor.GetColor(_lineColor);
+ var textColor = RGBColor.GetColor(_textColor);
+ F1 = new XFont(F1.FontFamily.Name, WeekAgendarDayFont);
+ var dayCont = _resizer.Rect(x, y, width, height);
+
+ var borders = new[]{
+ _resizer.Point(x, y),
+ _resizer.Point(x + width, y),
+ _resizer.Point(x + width, y + height),
+ _resizer.Point(x, y + height)};
+ Gfx.DrawLine(new XPen(RGBColor.GetXColor(bgColor), BorderWidth), borders[0], borders[1]);
+ Gfx.DrawLine(new XPen(RGBColor.GetXColor(bgColor), BorderWidth), borders[1], borders[2]);
+ Gfx.DrawLine(new XPen(RGBColor.GetXColor(bgColor), BorderWidth), borders[2], borders[3]);
+ Gfx.DrawLine(new XPen(RGBColor.GetXColor(bgColor), BorderWidth), borders[3], borders[0]);
+
+ Line(borderColor, 0, 0, width, 0, dayCont);
+ Line(borderColor, 0, 0, 0, height, dayCont);
+ Line(borderColor, width, 0, width, height, dayCont);
+ Line(borderColor, 0, height, width, height, dayCont);
+
+ var labelCont = _resizer.Rect(x, y, width, _monthDayHeaderHeight);
+ Gfx.DrawRectangle(new XSolidBrush(RGBColor.GetXColor(bgColor)), labelCont);
+
+ var txt = name;
+ x = x + _cellOffset + (width - _cellOffset - Gfx.MeasureString(name, F1).Width) / 2;
+ y = y + (_monthDayHeaderHeight + F1.Size) / 2;
+ Gfx.DrawString(txt, F1, new XSolidBrush(RGBColor.GetXColor(textColor)), _resizer.Point(x, y));
+ }
+
+ private SchedulerEvent[] WeekAgendaEventsDraw(SchedulerEvent[] events)
+ {
+ var borderColor = RGBColor.GetColor(_lineColor);
+ var textColor = RGBColor.GetColor(_textColor);
+ var offsets = new int[7];
+ for (var i = 0; i < offsets.Length; i++)
+ offsets[i] = 0;
+ var rest = new List<SchedulerEvent>();
+
+ for (var i = 0; i < events.Length; i++)
+ {
+ var ev = events[i];
+ var day = ev.Day;
+ var contHeight = (day < 5) ? _contHeight : _contHeight / 2;
+ var contWidth = _contWidth;
+ double x;
+ switch (day)
+ {
+ case 0:
+ case 2:
+ case 4:
+ x = _offsetLeft;
+ break;
+ default:
+ x = _offsetLeft + contWidth;
+ break;
+ }
+ var contStartY = _offsetTop + Math.Floor(day / 2.0) * _contHeight - (day > 5 ? contHeight : 0);
+ var offset = offsets[day] * _weekAgendaEventHeight;
+ var y = contStartY + _monthDayHeaderHeight + offset;
+
+ if (contStartY + contHeight < y + _weekAgendaEventHeight)
+ {
+ rest.Add(ev);
+ continue;
+ }
+
+
+ var borders = new[]{
+ _resizer.Point(x, y),
+ _resizer.Point(x + _contWidth, y),
+ _resizer.Point(x + _contWidth, y + _weekAgendaEventHeight),
+ _resizer.Point(x, y + _weekAgendaEventHeight)};
+ Gfx.DrawLine(new XPen(RGBColor.GetXColor(borderColor), BorderWidth), borders[0], borders[1]);
+ Gfx.DrawLine(new XPen(RGBColor.GetXColor(borderColor), BorderWidth), borders[1], borders[2]);
+ Gfx.DrawLine(new XPen(RGBColor.GetXColor(borderColor), BorderWidth), borders[2], borders[3]);
+ Gfx.DrawLine(new XPen(RGBColor.GetXColor(borderColor), BorderWidth), borders[3], borders[0]);
+
+ F1 = new XFont(F1.FontFamily.Name, 9);
+
+ x = x + _cellOffset;
+ y = y + (_weekAgendaEventHeight + F1.Size) / 2;
+ Gfx.DrawString(ev.Text, F1, new XSolidBrush(RGBColor.GetXColor(textColor)), _resizer.Point(x, y));
+
+ offsets[day]++;
+ }
+ var eventsList = new SchedulerEvent[rest.Count];
+ for (var i = 0; i < rest.Count; i++)
+ eventsList[i] = rest[i];
+ return eventsList;
+ }
+
+ private void TodayLabelDraw()
+ {
+ var g1 = Graphics[0];
+ TodayLabelDraw(g1);
+ }
+
+ private void TodayLabelDraw(XGraphics p1)
+ {
+ F1 = new XFont(F1.FontFamily.Name, 10);
+
+ var today = CurrentPage.TodayLabel;
+ var todayText = today;
+ var todayX = _offsetLeft;
+ var todayY = _offsetTop - _cellOffset;
+ p1.DrawString(todayText, F1, new XSolidBrush(RGBColor.GetXColor(_textColor)), _resizer.Point(todayX, todayY));
+ }
+
+ private int GetEventIndex(IList<SchedulerEvent> events, int day, int week, int month)
+ {
+ for (var i = 0; i < events.Count; i++)
+ {
+ var evDay = events[i].Day;
+ var evWeek = events[i].Week;
+ var evMonth = events[i].Month;
+ if ((evDay == day) && (evWeek == week) && (evMonth == month))
+ {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ private bool GetActiveDay(string[,] rows, int row, int col)
+ {
+ bool flag;
+ var flagCount = 0;
+ if (int.Parse(rows[0, 0]) == 1)
+ {
+ flag = true;
+ flagCount = 1;
+ }
+ else
+ {
+ flag = false;
+ }
+
+ var prevDay = int.Parse(rows[0, 0]);
+ for (var i = 0; i < rows.Length; i++)
+ {
+ for (var j = 0; j < rows.GetLength(1); j++)
+ {
+ if (int.Parse(rows[i, j]) < prevDay && flagCount < 2)
+ {
+ flag = !flag;
+ flagCount++;
+ }
+ if (i == row && j == col)
+ {
+ return flag;
+ }
+ prevDay = int.Parse(rows[i, j]);
+ }
+ }
+ return flag;
+ }
+
+ public string GetView()
+ {
+ return _view;
+ }
+
+
+
+ private void PrintHeader()
+ {
+ if (CurrentPage.Header)
+ {
+ var im = Images.Get(HeaderImgPath);
+ if (im != null)
+ {
+ Gfx.DrawImage(im, _resizer.Point(_offsetLeft, _offsetTop));
+ _pageHeight -= HeaderImgHeight;
+ _offsetTop += HeaderImgHeight;
+ }
+ }
+ }
+
+ public void SetWatermark(string mark)
+ {
+ _watermark = mark;
+ }
+ }
+} \ No newline at end of file
diff --git a/DHTMLX.Export.PDF/Properties/AssemblyInfo.cs b/DHTMLX.Export.PDF/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..7ad7f96
--- /dev/null
+++ b/DHTMLX.Export.PDF/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("scheduler-pdf-net")]
+[assembly: AssemblyDescription("Tool for exporting dhtmlxScheduler v4.x to pdf")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Dinamenta, UAB")]
+[assembly: AssemblyProduct("scheduler-pdf-net")]
+[assembly: AssemblyCopyright("Copyright © 2017 Dinamenta, UAB")]
+[assembly: AssemblyTrademark("DHTMLX")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("e8777cf2-7f63-4dc4-81e6-6dbc788e5af6")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.2.0.0")]
+[assembly: AssemblyFileVersion("1.2.0.0")]
diff --git a/DHTMLX.Export.PDF/RGBColor.cs b/DHTMLX.Export.PDF/RGBColor.cs
new file mode 100644
index 0000000..58e1a43
--- /dev/null
+++ b/DHTMLX.Export.PDF/RGBColor.cs
@@ -0,0 +1,75 @@
+using System;
+using System.Collections.Generic;
+using System.Text.RegularExpressions;
+using PdfSharp.Drawing;
+namespace DHTMLX.Export.PDF.Scheduler
+{
+ public class RGBColor
+ {
+ private static Dictionary<string, double[]> _parsedColors = new Dictionary<string, double[]>();
+
+ public static double[] GetColor(string color)
+ {
+ if (_parsedColors.ContainsKey(color))
+ return (double[])_parsedColors[color];
+ var original = color;
+ color = RGBColor.ProcessColorForm(color);
+ var result = new double[3];
+ var r = color.Substring(0, 2);
+ var g = color.Substring(2, 2);
+ var b = color.Substring(4, 2);
+
+ result[0] = int.Parse(r, System.Globalization.NumberStyles.HexNumber) / 255.0;
+ result[1] = int.Parse(g, System.Globalization.NumberStyles.HexNumber) / 255.0;
+ result[2] = int.Parse(b, System.Globalization.NumberStyles.HexNumber) / 255.0;
+ _parsedColors.Add(original, result);
+ return result;
+ }
+
+ public static XColor GetXColor(string color)
+ {
+ var dblColor = GetColor(color);
+ return XColor.FromArgb((int)Math.Floor(dblColor[0] * 255), (int)Math.Floor(dblColor[1] * 255), (int)Math.Floor(dblColor[2] * 255));
+ }
+
+ public static XColor GetXColor(double[] dblColor)
+ {
+ return XColor.FromArgb((int)Math.Floor(dblColor[0] * 255), (int)Math.Floor(dblColor[1] * 255), (int)Math.Floor(dblColor[2] * 255));
+ }
+
+ public static string ProcessColorForm(string color)
+ {
+ if (color.Equals("transparent"))
+ {
+ return "";
+ }
+ if (Regex.IsMatch(color, "#[0-9A-Fa-f]{6}"))
+ {
+ return color.Substring(1);
+ }
+
+ if (Regex.IsMatch(color, "[0-9A-Fa-f]{6}"))
+ {
+ return color;
+ }
+
+ var m3 = Regex.Match(color, "rgb\\s?\\(\\s?(\\d{1,3})\\s?,\\s?(\\d{1,3})\\s?,\\s?(\\d{1,3})\\s?\\)");
+
+ if (m3.Length > 0)
+ {
+ var r = m3.Groups[1].Value;
+ var g = m3.Groups[2].Value;
+ var b = m3.Groups[3].Value;
+ r = int.Parse(r).ToString("x");
+ r = (r.Length == 1) ? "0" + r : r;
+ g = int.Parse(g).ToString("x");
+ g = (g.Length == 1) ? "0" + g : g;
+ b = int.Parse(b).ToString("x");
+ b = (b.Length == 1) ? "0" + b : b;
+ color = r + g + b;
+ return color;
+ }
+ return "";
+ }
+ }
+} \ No newline at end of file
diff --git a/DHTMLX.Export.PDF/Resizer.cs b/DHTMLX.Export.PDF/Resizer.cs
new file mode 100644
index 0000000..4f9ef0e
--- /dev/null
+++ b/DHTMLX.Export.PDF/Resizer.cs
@@ -0,0 +1,68 @@
+using PdfSharp.Drawing;
+using PdfSharp;
+
+
+namespace DHTMLX.Export.PDF
+{
+ internal class Resizer
+ {
+ private double _xRatio = 1;
+ private double _yRatio = 1;
+ public PageOrientation Orient { get; set; }
+ private bool _keep = true;
+ private void _CalcRatio(Orientation actual, Orientation desired)
+ {
+ if (desired == Orientation.Default || actual == desired)
+ return;
+
+ _keep = false;
+
+ _yRatio = 1.0 / _xRatio;
+ }
+
+ public Resizer(PageOrientation from, Orientation to)
+ {
+ _CalcRatio(ToDHXOrient(from), to);
+ if (_keep)
+ Orient = from;
+ else
+ Orient = ToPDFOrient(to);
+ }
+
+ public PageOrientation ToPDFOrient(Orientation orient)
+ {
+ return orient == Orientation.Landscape ? PageOrientation.Landscape : PageOrientation.Portrait;
+ }
+
+ public Orientation ToDHXOrient(PageOrientation orient)
+ {
+ return orient == PageOrientation.Landscape ? Orientation.Landscape : Orientation.Portrait;
+ }
+
+ public XPoint Point(double x, double y)
+ {
+ return new XPoint(ResizeX(x), ResizeY(y));
+ }
+
+ public double ResizeX(double x)
+ {
+ if (_keep)
+ return x;
+
+ return x * _xRatio;
+ }
+
+ public double ResizeY(double y)
+ {
+ if (_keep)
+ return y;
+
+ return y * _yRatio;
+ }
+
+ public XRect Rect(double x, double y, double width, double height)
+ {
+ return new XRect(ResizeX(x), ResizeY(y), ResizeX(width), ResizeY(height));
+ }
+ }
+} \ No newline at end of file
diff --git a/DHTMLX.Export.PDF/SchedulerEvent.cs b/DHTMLX.Export.PDF/SchedulerEvent.cs
new file mode 100644
index 0000000..45b5b6d
--- /dev/null
+++ b/DHTMLX.Export.PDF/SchedulerEvent.cs
@@ -0,0 +1,161 @@
+using System;
+using System.Xml;
+using System.Text.RegularExpressions;
+
+namespace DHTMLX.Export.PDF.Scheduler
+{
+ public class SchedulerEvent
+ {
+ private string _backgroundColor;
+ private string _text = "";
+ private string _color;
+
+ public SchedulerEvent(){
+ Footenote = -1;
+ }
+
+ public string Text
+ {
+ get { return _text ?? (_text = ""); }
+ protected set { _text = value; }
+ }
+ public int Day { get; protected set; }
+ public int Week { get; protected set; }
+ public int Month { get; protected set; }
+ public int Len { get; protected set; }
+ public double X { get; protected set; }
+ public double Y { get; set; }
+ public string Type { get; protected set; }
+ public double Width { get; protected set; }
+ public double Height { get; protected set; }
+ public string HeaderText { get; protected set; }
+ public string HeaderAgendaText { get; protected set; }
+
+ public string BackgroundColor
+ {
+ get
+ {
+ _backgroundColor = ProcessColor(_backgroundColor);
+ return _backgroundColor;
+ }
+ protected set { _backgroundColor = value; }
+ }
+
+ public string Color
+ {
+ get
+ {
+ _color = ProcessColor(_color);
+ return _color;
+ }
+ protected set { _color = value; }
+ }
+
+ public int Footenote { get; set; }
+
+ private string GetNodeValue(XmlNode node)
+ {
+ var txt = node.FirstChild != null ? node.FirstChild.Value : "";
+ if (string.IsNullOrEmpty(txt))
+ txt = node.InnerText;
+
+ if (string.IsNullOrEmpty(txt))
+ txt = "";
+ return txt;
+ }
+ private int GetNumAttributeValue(XmlNode node, string attr)
+ {
+ string val = node.Attributes[attr] != null ? node.Attributes[attr].Value : "0";
+ int result = 0;
+ if (!string.IsNullOrEmpty(val) && val != "undefined")
+ int.TryParse(val, out result);
+ return result;
+ }
+ private string GetAttributeValue(XmlNode node, string attr)
+ {
+ return node.Attributes[attr] != null ? node.Attributes[attr].Value : "0";
+
+ }
+ private double GetDoublAttributeValue(XmlNode node, string attr)
+ {
+ string val = node.Attributes[attr] != null ? node.Attributes[attr].Value : "0";
+ double result = 0;
+
+ if (!string.IsNullOrEmpty(val) && val != "undefined")
+ double.TryParse(val, System.Globalization.NumberStyles.Any, System.Globalization.NumberFormatInfo.InvariantInfo, out result);
+ return result;
+ }
+ public void Parse(XmlNode parent)
+ {
+ var children = parent.ChildNodes;
+ var bgProcessed = false;
+ for (var i = 0; i < children.Count; i++)
+ {
+ switch (children[i].LocalName)
+ {
+ case "body":
+ Text = GetNodeValue(children[i]);
+ BackgroundColor = GetAttributeValue(children[i], "backgroundColor");
+ Color = GetAttributeValue(children[i], "color");
+ bgProcessed = true;
+ break;
+ case "header":
+ HeaderText = GetNodeValue(children[i]);
+ break;
+ case "head":
+ HeaderAgendaText = GetNodeValue(children[i]);
+ break;
+ }
+ }
+ if (!bgProcessed)
+ {
+ BackgroundColor = GetAttributeValue(parent, "backgroundColor");
+ Color = GetAttributeValue(parent, "color");
+ }
+
+ Day = GetNumAttributeValue(parent, "day");
+ Week = GetNumAttributeValue(parent, "week");
+ Len = GetNumAttributeValue(parent, "len");
+ Month = GetNumAttributeValue(parent, "month");
+
+ X = GetDoublAttributeValue(parent, "x");
+ Y = GetDoublAttributeValue(parent, "y");
+ Width = GetDoublAttributeValue(parent, "width");
+ Height = GetDoublAttributeValue(parent, "height");
+
+ Type = GetAttributeValue(parent, "type");
+ }
+
+ private string ProcessColor(string color)
+ {
+
+ if (Regex.IsMatch(color, "#[0-9A-Fa-f]{6}"))
+ {
+ return color.Substring(1);
+ }
+
+ if (Regex.IsMatch(color, "[0-9A-Fa-f]{6}"))
+ {
+ return color;
+ }
+
+ var m3 = Regex.Match(color, "rgb\\s?\\(\\s?(\\d{1,3})\\s?,\\s?(\\d{1,3})\\s?,\\s?(\\d{1,3})\\s?\\)");
+
+ if (m3.Length > 0)
+ {
+ var r = m3.Groups[1].Value;
+ var g = m3.Groups[2].Value;
+ var b = m3.Groups[3].Value;
+ r = int.Parse(r).ToString("x");
+ r = (r.Length == 1) ? "0" + r : r;
+ g = int.Parse(g).ToString("x");
+ g = (g.Length == 1) ? "0" + g : g;
+ b = int.Parse(b).ToString("x");
+ b = (b.Length == 1) ? "0" + b : b;
+ color = r + g + b;
+ return color;
+ }
+ return "transparent";
+ }
+ }
+} \ No newline at end of file
diff --git a/DHTMLX.Export.PDF/SchedulerMonth.cs b/DHTMLX.Export.PDF/SchedulerMonth.cs
new file mode 100644
index 0000000..e23bc88
--- /dev/null
+++ b/DHTMLX.Export.PDF/SchedulerMonth.cs
@@ -0,0 +1,60 @@
+using System;
+using System.Xml;
+
+namespace DHTMLX.Export.PDF.Scheduler
+{
+ public class SchedulerMonth
+ {
+ private string _monthName;
+ private string[,] _rows;
+
+ public void Parse(XmlNode parent)
+ {
+ _monthName = parent.Attributes["label"].Value;
+ var parsRows = XMLParser.GetElementsByTagName(parent, "row");
+ var cols = XMLParser.GetElementsByTagName(parent, "column");
+
+ if ((parsRows.Count != 0) && (cols.Count != 0))
+ {
+ _rows = new string[parsRows.Count + 1, 7];
+ for (var i = 0; i < cols.Count; i++)
+ {
+ _rows[0, i] = cols[i].FirstChild.Value;
+ }
+ for (var i = 1; i <= parsRows.Count; i++)
+ {
+ var values = parsRows[i - 1].FirstChild.Value.Split(new[] { "|" }, StringSplitOptions.None);
+ for (var j = 0; j < values.Length; j++)
+ {
+ _rows[i, j] = values[j];
+ }
+ }
+ }
+ }
+
+ public string GetLabel()
+ {
+ return _monthName;
+ }
+
+ public string[,] GetRows()
+ {
+ return _rows;
+ }
+
+ public string[,] GetOnlyDays()
+ {
+ var days = new string[_rows.GetLength(0) - 1, 7];
+
+
+ for (var i = 1; i < _rows.GetLength(0); i++)
+ {
+ for (var j = 0; j < 7; j++)
+ {
+ days[i - 1, j] = _rows[i, j];
+ }
+ }
+ return days;
+ }
+ }
+} \ No newline at end of file
diff --git a/DHTMLX.Export.PDF/TreeTimelineParser.cs b/DHTMLX.Export.PDF/TreeTimelineParser.cs
new file mode 100644
index 0000000..70d97b6
--- /dev/null
+++ b/DHTMLX.Export.PDF/TreeTimelineParser.cs
@@ -0,0 +1,61 @@
+using System.Text.RegularExpressions;
+
+namespace DHTMLX.Export.PDF
+{
+ public class TreeTimelineCategory
+ {
+ public bool Expanded { get; set; }
+ public int Level { get; set; }
+ public bool IsExpandable { get; set; }
+ public string Text { get; set; }
+ public TreeTimelineCategory(string text, int level, bool allowchild, bool expanded)
+ {
+ Level = level;
+ Expanded = expanded;
+ IsExpandable = allowchild;
+ Text = text;
+ }
+ public TreeTimelineCategory() : this("", 0, false, false)
+ {
+
+ }
+ }
+
+
+ public class TreeTimelineParser
+ {
+
+ /*
+ * Html tree timeline rows, e.g.:
+ <div class=\"dhx_scell_level0\">
+ <div class=\"dhx_scell_expand\">-</div><div class=\"dhx_scell_name\">Web Testing Dep.</div>
+ </div>
+ <div class=\"dhx_scell_level1\">
+ <div class=\"dhx_scell_expand\"> </div><div class=\"dhx_scell_name\">Managers</div>
+ </div>
+ <div class=\"dhx_scell_level1\">
+ <div class=\"dhx_scell_name\">Elizabeth Taylor</div>
+ </div>"
+ */
+ public static bool IsTreeRow(string item)
+ {
+ var treeRowRegex = "^<div.*dhx_scell_level.*>.*(dhx_scell_expand|dhx_scell_name).*<\\/div>$";
+ return (Regex.IsMatch(item.Trim(), treeRowRegex));
+ }
+ public TreeTimelineCategory Parse(string item)
+ {
+ var levelReg = "dhx_scell_level([0-9]+)";
+ var isExpandable = "dhx_scell_expand";
+ var state = "dhx_scell_expand.*?>(-| )<\\/div";
+ var text = "dhx_scell_name.*?>(.+?)<\\/div";
+ var expandable = Regex.IsMatch(item, isExpandable);
+ var level = 0;
+ int.TryParse(Regex.Match(item, levelReg).Groups[1].Value, out level);
+ var expanded = Regex.Match(item, state).Groups[1].Value == "-";
+ var value = Regex.Match(item, text).Groups[1].Value;
+ return new TreeTimelineCategory(value, level, expandable, expanded);
+
+
+ }
+ }
+}
diff --git a/DHTMLX.Export.PDF/XMLParser.cs b/DHTMLX.Export.PDF/XMLParser.cs
new file mode 100644
index 0000000..fff6a7b
--- /dev/null
+++ b/DHTMLX.Export.PDF/XMLParser.cs
@@ -0,0 +1,344 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Xml;
+
+namespace DHTMLX.Export.PDF.Scheduler
+{
+ public enum ColorProfile
+ {
+ Color,
+ FullColor,
+ Gray,
+ BW,
+ Custom
+ }
+
+ public class XMLParser
+ {
+ public List<PDFPage> Pages { get; set; }
+
+ public ColorProfile StringToColorProfile(string profile)
+ {
+ if (profile == null)
+ return ColorProfile.Color;
+ switch (profile.ToLower())
+ {
+ case "gray":
+ return ColorProfile.Gray;
+ case "full_color":
+ return ColorProfile.FullColor;
+ case "color":
+ return ColorProfile.Color;
+ case "bw":
+ return ColorProfile.BW;
+ case "custom":
+ return ColorProfile.Custom;
+ default:
+ return ColorProfile.Color;
+ }
+ }
+
+ public static List<XmlNode> GetElementsByTagName(XmlNode parent, string name)
+ {
+ var list = new List<XmlNode>();
+ foreach (XmlNode node in parent.ChildNodes)
+ {
+ if (node.LocalName == name)
+ {
+ list.Add(node);
+ }
+ else
+ {
+ list.AddRange(GetElementsByTagName(node, name));
+ }
+ }
+ return list;
+ }
+
+ public void ParsePages(XmlNode root)
+ {
+
+ if (root.Name == "pages")
+ {
+ var n1 = GetElementsByTagName(root, "page");
+ if (n1 != null && n1.Count > 0)
+ {
+
+ for (var i = 0; i < n1.Count; i++)
+ {
+ var page = new PDFPage { Node = n1[i] };
+ Pages.Add(page);
+ ParseConfig(page);
+ EventsParsing(page);
+ }
+ }
+ }
+ else
+ {
+ var page = new PDFPage { Node = root };
+ Pages.Add(page);
+ ParseConfig(page);
+ EventsParsing(page);
+ }
+
+ }
+ public void ParseConfig(PDFPage page)
+ {
+ XmlNode scale = null;
+ var root = page.Node;
+ foreach (XmlNode nod in root.ChildNodes)
+ {
+ if (nod.LocalName == "scale")
+ {
+ scale = nod;
+ break;
+ }
+ }
+
+ var toCheck = new List<XmlNode> { root };
+ if (scale != null)
+ toCheck.Add(scale);
+ if (root.ParentNode != null && root.ParentNode.NodeType != XmlNodeType.Document && root.ParentNode.Name != "data")
+ {
+ toCheck.Add(root.ParentNode);
+ }
+
+ for (var i = 0; i < toCheck.Count; i++)
+ {
+ if (toCheck[i].Attributes["profile"] != null && page.Profile == default(ColorProfile))
+ {
+ page.Profile = StringToColorProfile(toCheck[i].Attributes["profile"].Value);
+ }
+ if (toCheck[i].Attributes["header"] != null && page.Header == default(bool))
+ {
+ page.Header = (toCheck[i].Attributes["header"].Value == "true");
+ }
+ if (toCheck[i].Attributes["footer"] != null && page.Footer == default(bool))
+ {
+ page.Footer = (toCheck[i].Attributes["footer"].Value == "true");
+ }
+
+ if (toCheck[i].Attributes["mode"] != null && page.Mode == default(string))
+ page.Mode = toCheck[i].Attributes["mode"] != null ? toCheck[i].Attributes["mode"].Value : "";
+
+ if (toCheck[i].Attributes["today"] != null && page.TodayLabel == default(string))
+ page.TodayLabel = toCheck[i].Attributes["today"] != null ? toCheck[i].Attributes["today"].Value : "";
+
+ }
+
+
+ }
+
+ public IEnumerable<XmlNode> GetPages(string xml)
+ {
+ var dom = new XmlDocument();
+ dom.LoadXml(xml);
+ var root = dom.DocumentElement;
+ var res = new List<XmlNode>();
+
+ if (root.FirstChild.Name != "data")
+ {
+ res.Add(root);
+ }
+ else
+ {
+ foreach (var nod in root.ChildNodes)
+ res.Add(nod as XmlNode);
+ }
+ return res;
+ }
+
+
+ public void SetXML(XmlNode root)
+ {
+ Pages = new List<PDFPage>();
+ ParsePages(root);
+ }
+
+ public string[][] MonthColsParsing(PDFPage page)
+ {
+
+ var n1 = GetElementsByTagName(page.Node, "column");
+ if (n1 != null && n1.Count > 0)
+ {
+ page.Cols = new[] { new string[n1.Count] };
+
+ for (var i = 0; i < n1.Count; i++)
+ {
+ var col = n1[i];
+ page.Cols[0][i] = col.FirstChild.Value;
+ }
+ }
+ return page.Cols;
+ }
+
+ public IList<MonthRow> GetRowsObjects(PDFPage page)
+ {
+ if (page.RowObs == null)
+ {
+ var n1 = GetElementsByTagName(page.Node, "row");
+ if (n1 != null && n1.Count > 0)
+ {
+ page.RowObs = new List<MonthRow>(7);
+ for (var i = 0; i < n1.Count; i++)
+ {
+ var r = new MonthRow();
+ page.RowObs.Add(r);
+
+ var node = n1[i];
+
+ double height;
+ var hght = node.Attributes["height"].Value;
+
+ if (double.TryParse(hght, out height))
+ r.Height = height;
+ else
+ r.Height = default(double);
+
+ var week = node.FirstChild.Value;
+ r.Cells = week.Split(new[] { "|" }, StringSplitOptions.None);
+
+ }
+ }
+ }
+ return page.RowObs;
+ }
+
+ public string[,] MonthRowsParsing(PDFPage page)
+ {
+ var n1 = GetElementsByTagName(page.Node, "row");
+ if (n1 != null && n1.Count > 0)
+ {
+ page.Rows = new string[n1.Count, 7];
+ for (var i = 0; i < n1.Count; i++)
+ {
+ var row = n1[i];
+ var week = row.FirstChild.Value;
+ var days = week.Split(new[] { "|" }, StringSplitOptions.None);
+ for (var j = 0; j < days.Length; j++)
+ page.Rows[i, j] = days[j];
+ }
+ }
+ return page.Rows;
+ }
+
+ public void EventsParsing(PDFPage page)
+ {
+ var n1 = GetElementsByTagName(page.Node, "event");
+ if (n1 != null && n1.Count > 0)
+ {
+ for (var i = 0; i < n1.Count; i++)
+ {
+ var ev = n1[i];
+ SchedulerEvent oEv = new SchedulerEvent();
+ oEv.Parse(ev);
+ if ((oEv.Type == "event_line") && (page.Mode != "month") && (page.Mode != "timeline") && (page.Mode != "treetimeline"))
+ {
+ page.Multiday.Add(oEv);
+ }
+ else
+ {
+ page.Events.Add(oEv);
+ }
+ }
+ }
+ }
+
+ public int[] ScaleRatios(PDFPage page)
+ {
+ var n1 = GetElementsByTagName(page.Node, "column");
+ return n1.Where(n => n.Attributes["second_scale"] != null).GroupBy(n => n.Attributes["second_scale"].Value).Select(g => g.Count()).ToArray();
+ }
+
+ public string[][] WeekColsParsing(PDFPage page)
+ {
+ if (page.Cols != null)
+ return page.Cols;
+ var n1 = GetElementsByTagName(page.Node, "column");
+
+ if (n1 != null && n1.Count > 0)
+ {
+
+ var scale1 = n1.Where(n => n.Attributes["second_scale"] == null).ToList();
+ var scale2 = n1.Where(n => n.Attributes["second_scale"] != null).ToList();
+
+ string[][] scales;
+ if (scale2.Count > 0)
+ {
+ scales = new string[2][];
+ scales[0] = new string[scale1.Count];
+ scales[1] = new string[scale2.Count];
+ }
+ else
+ {
+ scales = new string[1][];
+ scales[0] = new string[scale1.Count];
+ }
+
+ for (var i = 0; i < scale1.Count; i++)
+ {
+ scales[0][i] = scale1[i].FirstChild.Value;
+ }
+
+ for (var i = 0; i < scale2.Count; i++)
+ {
+ scales[1][i] = scale2[i].FirstChild.Value;
+ }
+ page.Cols = scales;
+
+ }
+ return page.Cols;
+ }
+
+ public string[] WeekRowsParsing(PDFPage page)
+ {
+ string[] rows = null;
+ var n1 = GetElementsByTagName(page.Node, "row");
+ if (n1 != null && n1.Count > 0)
+ {
+ rows = new string[n1.Count];
+ for (var i = 0; i < n1.Count; i++)
+ {
+ var row = n1[i];
+ rows[i] = row.FirstChild.Value;
+ }
+ }
+ return rows;
+ }
+
+ public SchedulerMonth[] YearParsing(PDFPage page)
+ {
+ SchedulerMonth[] monthes = null;
+ var n1 = GetElementsByTagName(page.Node, "month");
+ if (n1 != null && n1.Count > 0)
+ {
+ monthes = new SchedulerMonth[n1.Count];
+ for (var i = 0; i < n1.Count; i++)
+ {
+ monthes[i] = new SchedulerMonth();
+ var mon = n1[i];
+ monthes[i].Parse(mon);
+ }
+ }
+ return monthes;
+ }
+
+ public string[] AgendaColsParsing(PDFPage page)
+ {
+ string[] cols = null;
+ var n1 = GetElementsByTagName(page.Node, "column");
+ if (n1 != null && n1.Count > 0)
+ {
+ cols = new string[n1.Count];
+ for (var i = 0; i < n1.Count; i++)
+ {
+ var col = n1[i];
+ cols[i] = col.FirstChild.Value;
+ }
+ }
+ return cols;
+ }
+
+ }
+} \ No newline at end of file
diff --git a/DHTMLX.Export.PDF/lib/ExtendLib.cs b/DHTMLX.Export.PDF/lib/ExtendLib.cs
new file mode 100644
index 0000000..98832b8
--- /dev/null
+++ b/DHTMLX.Export.PDF/lib/ExtendLib.cs
@@ -0,0 +1,489 @@
+#region PDFsharp - A .NET library for processing PDF
+//
+// Authors:
+// Stefan Lange (mailto:Stefan.Lange@pdfsharp.com)
+//
+// Copyright (c) 2005-2009 empira Software GmbH, Cologne (Germany)
+//
+// http://www.pdfsharp.com
+// http://sourceforge.net/projects/pdfsharp
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the "Software"),
+// to deal in the Software without restriction, including without limitation
+// the rights to use, copy, modify, merge, publish, distribute, sublicense,
+// and/or sell copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Collections;
+using System.Text;
+using PdfSharp.Drawing;
+using PdfSharp.Pdf.IO;
+using PdfSharp.Drawing.Layout;
+namespace DHTMLX.Export.PDF.Formatter
+{
+ /// <summary>
+ /// Represents a very simple text formatter.
+ /// If this class does not satisfy your needs on formatting paragraphs I recommend to take a look
+ /// at MigraDoc Foundation. Alternatively you should copy this class in your own source code and modify it.
+ /// </summary>
+ public class DHXTextFormatter
+ {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="XTextFormatter"/> class.
+ /// </summary>
+ public DHXTextFormatter(XGraphics gfx)
+ {
+ if (gfx == null)
+ throw new ArgumentNullException("gfx");
+ this.gfx = gfx;
+ }
+ XGraphics gfx;
+
+ /// <summary>
+ /// Gets or sets the text.
+ /// </summary>
+ /// <value>The text.</value>
+ public string Text
+ {
+ get { return this.text; }
+ set { this.text = value; }
+ }
+ string text;
+
+ /// <summary>
+ /// Gets or sets the font.
+ /// </summary>
+ public XFont Font
+ {
+ get { return this.font; }
+ set
+ {
+ if (value == null)
+ throw new ArgumentNullException("font");
+ this.font = value;
+
+ this.lineSpace = font.GetHeight(this.gfx);
+
+ var family = this.Font.FontFamily;
+
+ var cellSpace = family.GetLineSpacing(font.Style);
+ var cellAscent = family.GetCellAscent(font.Style);
+ var cellDescent = family.GetCellDescent(font.Style);
+
+ this.cyAscent = lineSpace * cellAscent / cellSpace;
+ this.cyDescent = lineSpace * cellDescent / cellSpace;
+
+ // HACK in XTextFormatter
+ this.spaceWidth = gfx.MeasureString("x x", value).Width;
+ this.spaceWidth -= gfx.MeasureString("xx", value).Width;
+ }
+ }
+ XFont font;
+ double lineSpace;
+ double cyAscent;
+ double cyDescent;
+ double spaceWidth;
+
+ /// <summary>
+ /// Gets or sets the bounding box of the layout.
+ /// </summary>
+ public XRect LayoutRectangle
+ {
+ get { return this.layoutRectangle; }
+ set { this.layoutRectangle = value; }
+ }
+ XRect layoutRectangle;
+
+ /// <summary>
+ /// Gets or sets the alignment of the text.
+ /// </summary>
+ public XParagraphAlignment Alignment
+ {
+ get { return this.alignment; }
+ set { this.alignment = value; }
+ }
+ XParagraphAlignment alignment = XParagraphAlignment.Left;
+
+ /// <summary>
+ /// Draws the text.
+ /// </summary>
+ /// <param name="text">The text to be drawn.</param>
+ /// <param name="font">The font.</param>
+ /// <param name="brush">The text brush.</param>
+ /// <param name="layoutRectangle">The layout rectangle.</param>
+ public void DrawString(string text, XFont font, XBrush brush, XRect layoutRectangle)
+ {
+ DrawString(text, font, brush, layoutRectangle, XStringFormats.TopLeft);
+ }
+
+ /// <summary>
+ /// Draws the text.
+ /// </summary>
+ /// <param name="text">The text to be drawn.</param>
+ /// <param name="font">The font.</param>
+ /// <param name="brush">The text brush.</param>
+ /// <param name="layoutRectangle">The layout rectangle.</param>
+ /// <param name="format">The format. Must be <c>XStringFormat.TopLeft</c></param>
+ public void DrawString(string text, XFont font, XBrush brush, XRect layoutRectangle, XStringFormat format)
+ {
+ if (text == null)
+ throw new ArgumentNullException("text");
+ if (font == null)
+ throw new ArgumentNullException("font");
+ if (brush == null)
+ throw new ArgumentNullException("brush");
+ if (format.Alignment != XStringAlignment.Near || format.LineAlignment!= XLineAlignment.Near)
+ throw new ArgumentException("Only TopLeft alignment is currently implemented.");
+
+ Text = text;
+ Font = font;
+ LayoutRectangle = layoutRectangle;
+
+ if (text.Length == 0)
+ return;
+
+ CreateBlocks(layoutRectangle.Width);
+
+ CreateLayout();
+
+ double dx = layoutRectangle.Location.X;
+ double mWidth = layoutRectangle.Size.Width;
+ double dy = layoutRectangle.Location.Y + cyAscent;
+ int count = this.blocks.Count;
+ for (int idx = 0; idx < count; idx++)
+ {
+ Block block = (Block)this.blocks[idx];
+ if (block.Stop)
+ break;
+ if (block.Type == BlockType.LineBreak)
+ continue;
+
+
+ if (idx +1 < count)
+ {
+ if (this.blocks[idx + 1].Stop)
+ {
+ if (block.Text.Length > 3)
+ {
+ block.Text = block.Text.Substring(0, block.Text.Length - 3) + "...";
+ }
+ else
+ {
+ int dots = 0;
+ while (dots < 3 && gfx.MeasureString(block.Text, font).Width < mWidth)
+ {
+ block.Text += ".";
+ dots++;
+ }
+ }
+ }
+ }
+ gfx.DrawString(block.Text, font, brush, dx + block.Location.X, dy + block.Location.Y);
+ }
+ }
+
+ void CreateBlocks(double maxWidth)
+ {
+ this.blocks.Clear();
+ int length = this.text.Length;
+ bool inNonWhiteSpace = false;
+ int startIndex = 0, blockLength = 0;
+ for (int idx = 0; idx < length; idx++)
+ {
+ char ch = text[idx];
+
+ // Treat CR and CRLF as LF
+ if (ch == Chars.CR)
+ {
+ if (idx < length - 1 && text[idx + 1] == Chars.LF)
+ idx++;
+ ch = Chars.LF;
+ }
+ if (ch == Chars.LF)
+ {
+ if (blockLength != 0)
+ {
+ string token = text.Substring(startIndex, blockLength);
+ this.blocks.Add(new Block(token, BlockType.Text,
+ this.gfx.MeasureString(token, this.font).Width));
+ }
+ startIndex = idx + 1;
+ blockLength = 0;
+ this.blocks.Add(new Block(BlockType.LineBreak));
+ }
+ else if (Char.IsWhiteSpace(ch))
+ {
+ if (inNonWhiteSpace)
+ {
+ string token = text.Substring(startIndex, blockLength);
+ this.blocks.Add(new Block(token, BlockType.Text,
+ this.gfx.MeasureString(token, this.font).Width));
+ startIndex = idx + 1;
+ blockLength = 0;
+ }
+ else
+ {
+ blockLength++;
+ }
+ }
+ else
+ {
+ inNonWhiteSpace = true;
+ blockLength++;
+ if (startIndex + blockLength < length)
+ {
+ if (this.gfx.MeasureString(text.Substring(startIndex, blockLength + 1), this.font).Width >= maxWidth)
+ {
+ string token = text.Substring(startIndex, blockLength);
+ this.blocks.Add(new Block(token, BlockType.Text,
+ this.gfx.MeasureString(token, this.font).Width));
+ startIndex = startIndex + blockLength;
+ blockLength = 0;
+ inNonWhiteSpace = false;
+ }
+ }
+
+ }
+ }
+ if (blockLength != 0)
+ {
+ string token = text.Substring(startIndex, blockLength);
+ this.blocks.Add(new Block(token, BlockType.Text,
+ this.gfx.MeasureString(token, this.font).Width));
+ }
+ }
+
+ void CreateLayout()
+ {
+ double rectWidth = this.layoutRectangle.Width;
+ double rectHeight = this.layoutRectangle.Height - this.cyAscent - this.cyDescent;
+ int firstIndex = 0;
+ double x = 0, y = 0;
+ int count = this.blocks.Count;
+ for (int idx = 0; idx < count; idx++)
+ {
+ Block block = (Block)this.blocks[idx];
+ if (block.Type == BlockType.LineBreak)
+ {
+ if (Alignment == XParagraphAlignment.Justify)
+ ((Block)this.blocks[firstIndex]).Alignment = XParagraphAlignment.Left;
+ AlignLine(firstIndex, idx - 1, rectWidth);
+ firstIndex = idx + 1;
+ x = 0;
+ y += this.lineSpace;
+ }
+ else
+ {
+ double width = block.Width; //!!!modTHHO 19.11.09 don't add this.spaceWidth here
+ if ((x + width <= rectWidth || x == 0) && block.Type != BlockType.LineBreak)
+ {
+ block.Location = new XPoint(x, y);
+ x += width + spaceWidth; //!!!modTHHO 19.11.09 add this.spaceWidth here
+ }
+ else
+ {
+ AlignLine(firstIndex, idx - 1, rectWidth);
+ firstIndex = idx;
+ y += lineSpace;
+ if (y > rectHeight)
+ {
+ block.Stop = true;
+ break;
+ }
+ block.Location = new XPoint(0, y);
+ x = width + spaceWidth; //!!!modTHHO 19.11.09 add this.spaceWidth here
+ }
+ }
+ }
+ if (firstIndex < count && Alignment != XParagraphAlignment.Justify)
+ AlignLine(firstIndex, count - 1, rectWidth);
+ }
+
+ /// <summary>
+ /// Align center, right or justify.
+ /// </summary>
+ void AlignLine(int firstIndex, int lastIndex, double layoutWidth)
+ {
+ XParagraphAlignment blockAlignment = ((Block)(this.blocks[firstIndex])).Alignment;
+ if (this.alignment == XParagraphAlignment.Left || blockAlignment == XParagraphAlignment.Left)
+ return;
+
+ int count = lastIndex - firstIndex + 1;
+ if (count == 0)
+ return;
+
+ double totalWidth = -this.spaceWidth;
+ for (int idx = firstIndex; idx <= lastIndex; idx++)
+ totalWidth += ((Block)(this.blocks[idx])).Width + this.spaceWidth;
+
+ double dx = Math.Max(layoutWidth - totalWidth, 0);
+ //Debug.Assert(dx >= 0);
+ if (this.alignment != XParagraphAlignment.Justify)
+ {
+ if (this.alignment == XParagraphAlignment.Center)
+ dx /= 2;
+ for (int idx = firstIndex; idx <= lastIndex; idx++)
+ {
+ Block block = (Block)this.blocks[idx];
+ block.Location += new XSize(dx, 0);
+ }
+ }
+ else if (count > 1) // case: justify
+ {
+ dx /= count - 1;
+ for (int idx = firstIndex + 1, i = 1; idx <= lastIndex; idx++, i++)
+ {
+ Block block = (Block)this.blocks[idx];
+ block.Location += new XSize(dx * i, 0);
+ }
+ }
+ }
+
+ readonly List<Block> blocks = new List<Block>();
+
+ enum BlockType
+ {
+ Text, Space, Hyphen, LineBreak,
+ }
+
+ /// <summary>
+ /// Represents a single word.
+ /// </summary>
+ class Block
+ {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="Block"/> class.
+ /// </summary>
+ /// <param name="text">The text of the block.</param>
+ /// <param name="type">The type of the block.</param>
+ /// <param name="width">The width of the text.</param>
+ public Block(string text, BlockType type, double width)
+ {
+ Text = text;
+ Type = type;
+ Width = width;
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="Block"/> class.
+ /// </summary>
+ /// <param name="type">The type.</param>
+ public Block(BlockType type)
+ {
+ Type = type;
+ }
+
+ /// <summary>
+ /// The text represented by this block.
+ /// </summary>
+ public string Text;
+
+ /// <summary>
+ /// The type of the block.
+ /// </summary>
+ public BlockType Type;
+
+ /// <summary>
+ /// The width of the text.
+ /// </summary>
+ public double Width;
+
+ /// <summary>
+ /// The location relative to the upper left corner of the layout rectangle.
+ /// </summary>
+ public XPoint Location;
+
+ /// <summary>
+ /// The alignment of this line.
+ /// </summary>
+ public XParagraphAlignment Alignment;
+
+ /// <summary>
+ /// A flag indicating that this is the last bock that fits in the layout rectangle.
+ /// </summary>
+ public bool Stop;
+ }
+ // TODO:
+ // - more XStringFormat variations
+ // - calculate bounding box
+ // - left and right indent
+ // - first line indent
+ // - margins and paddings
+ // - background color
+ // - text background color
+ // - border style
+ // - hyphens, soft hyphens, hyphenation
+ // - kerning
+ // - change font, size, text color etc.
+ // - line spacing
+ // - underine and strike-out variation
+ // - super- and sub-script
+ // - ...
+ }
+
+
+
+ /// <summary>
+ /// Character table by name.
+ /// </summary>
+ internal sealed class Chars
+ {
+ // ReSharper disable InconsistentNaming
+ public const char EOF = (char)65535; //unchecked((char)(-1));
+ public const char NUL = '\0'; // EOF
+ public const char CR = '\x0D'; // ignored by lexer
+ public const char LF = '\x0A'; // Line feed
+ public const char BEL = '\a'; // Bell
+ public const char BS = '\b'; // Backspace
+ public const char FF = '\f'; // Form feed
+ public const char HT = '\t'; // Horizontal tab
+ public const char VT = '\v'; // Vertical tab
+ public const char NonBreakableSpace = (char)160; // char(160)
+
+ // The following names come from "PDF Reference Third Edition"
+ // Appendix D.1, Latin Character Set and Encoding
+ public const char SP = ' ';
+ public const char QuoteDbl = '"';
+ public const char QuoteSingle = '\'';
+ public const char ParenLeft = '(';
+ public const char ParenRight = ')';
+ public const char BraceLeft = '{';
+ public const char BraceRight = '}';
+ public const char BracketLeft = '[';
+ public const char BracketRight = ']';
+ public const char Less = '<';
+ public const char Greater = '>';
+ public const char Equal = '=';
+ public const char Period = '.';
+ public const char Semicolon = ';';
+ public const char Colon = ':';
+ public const char Slash = '/';
+ public const char Bar = '|';
+ public const char BackSlash = '\\';
+ public const char Percent = '%';
+ public const char Dollar = '$';
+ public const char At = '@';
+ public const char NumberSign = '#';
+ public const char Question = '?';
+ public const char Hyphen = '-'; // char(45)
+ public const char SoftHyphen = '­'; // char(173)
+ public const char Currency = '¤';
+ // ReSharper restore InconsistentNaming
+ }
+}
diff --git a/DHTMLX.Export.PDF/packages.config b/DHTMLX.Export.PDF/packages.config
new file mode 100644
index 0000000..4a69c7b
--- /dev/null
+++ b/DHTMLX.Export.PDF/packages.config
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="HtmlAgilityPack" version="1.4.9.5" targetFramework="net461" />
+ <package id="PDFsharp" version="1.32.3057.0" targetFramework="net461" />
+</packages> \ No newline at end of file