Skip to content

Commit e892b5b

Browse files
committed
Prepare structure for QuestPdf renderer
1 parent 42b03e2 commit e892b5b

File tree

5 files changed

+480
-31
lines changed

5 files changed

+480
-31
lines changed

src/DocSharp.Common/Primitives/Unit.cs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,39 @@ internal static long CalculateTwips(UnitMetric type, double value)
168168
}
169169
}
170170

171+
/// <summary>
172+
/// Gets the value expressed in twips / DXA.
173+
/// </summary>
174+
internal static double CalculateMillimeters(UnitMetric type, double value)
175+
{
176+
switch (type)
177+
{
178+
case UnitMetric.Auto:
179+
case UnitMetric.Unitless:
180+
case UnitMetric.Percent: return 0.0; // not applicable
181+
182+
case UnitMetric.Millimeter: return value;
183+
case UnitMetric.Centimeter: return value * 10;
184+
case UnitMetric.Himetric: return value / 100; // 1 himetric = 1/100 mm
185+
186+
case UnitMetric.Inch: return value / 25.4 ; // 1 inch = 25.4 mm
187+
case UnitMetric.Point: return value * 72 / 25.4; // 1 point = 1/72 inch
188+
case UnitMetric.Twip: return value * 1440 / 25.4; // 1 twip = 1/1440 inch
189+
case UnitMetric.HundrethsOfInch: return value * 100 / 25.4; // 1/100 inch
190+
case UnitMetric.Pica: return value * 6 / 25.4; // 1 pica = 1/6 inch
191+
192+
case UnitMetric.Emus: return value / 36000; // 1 mm = 36,000 EMUs
193+
194+
case UnitMetric.EM: return value * 12 * 72 / 25.4; // Considering 1 em = 12 pt
195+
case UnitMetric.Ex: return value * 6 * 72 / 25.4; // Considering half of em
196+
197+
case UnitMetric.Diu: return value * 96 / 25.4; // 1 DIU = 1/96 inch
198+
case UnitMetric.Pixel: goto case UnitMetric.Diu; // Considering 96 DPI
199+
200+
default: goto case UnitMetric.Pixel;
201+
}
202+
}
203+
171204
//____________________________________________________________________
172205
//
173206

src/DocSharp.Common/Primitives/UnitMetric.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,14 @@ public static long ConvertToTwips(double value, UnitMetric unitType)
6161
return Unit.CalculateTwips(unitType, value);
6262
}
6363

64+
/// <summary>
65+
/// Converts value of the specified UnitMetric to millimeters.
66+
/// </summary>
67+
public static double ConvertToMillimeters(double value, UnitMetric unitType)
68+
{
69+
return Unit.CalculateMillimeters(unitType, value);
70+
}
71+
6472
internal static UnitMetric ToUnitMetric(string? type)
6573
{
6674
if (type == null) return UnitMetric.Unitless;

src/DocSharp.Renderer/DocxRenderer.cs

Lines changed: 142 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,12 @@
77
using DocumentFormat.OpenXml;
88
using DocumentFormat.OpenXml.Packaging;
99
using DocumentFormat.OpenXml.Wordprocessing;
10+
using W = DocumentFormat.OpenXml.Wordprocessing;
1011
using QuestPDF.Fluent;
11-
using QuestPDF.Infrastructure;
12-
using Document = QuestPDF.Fluent.Document;
1312

1413
namespace DocSharp.Renderer;
1514

16-
internal class DocxRenderer : DocxEnumerator<QuestPDF.Fluent.Document>, IDocumentRenderer<QuestPDF.Fluent.Document>
15+
internal class DocxRenderer : DocxEnumerator<QuestPdfModel>, IDocumentRenderer<QuestPDF.Fluent.Document>
1716
{
1817
/// <summary>
1918
/// Render a DOCX document to a QuestPDF document.
@@ -22,13 +21,24 @@ internal class DocxRenderer : DocxEnumerator<QuestPDF.Fluent.Document>, IDocumen
2221
/// <returns></returns>
2322
public QuestPDF.Fluent.Document Render(WordprocessingDocument inputDocument)
2423
{
25-
var outputDoc = QuestPDF.Fluent.Document.Create((_) =>
24+
var doc = inputDocument.MainDocumentPart?.Document;
25+
if (doc != null && doc.Body is Body body)
2626
{
27-
28-
});
29-
throw new NotImplementedException();
27+
var model = new QuestPdfModel();
28+
ProcessDocument(doc, model);
29+
return model.ToQuestPdfDocument();
30+
}
31+
else
32+
{
33+
// Return empty PDF document.
34+
return QuestPDF.Fluent.Document.Create(container => {
35+
container.Page(page => {
36+
page.Size(QuestPDF.Helpers.PageSizes.A4);
37+
});
38+
});
39+
}
3040
}
31-
41+
3242
/// <summary>
3343
/// Render a DOCX document to a QuestPDF document.
3444
/// </summary>
@@ -49,75 +59,181 @@ public QuestPDF.Fluent.Document Render(XDocument flatOpc)
4959
return Render(docx);
5060
}
5161

52-
internal override void ProcessAnnotationReference(AnnotationReferenceMark annotationRef, Document sb)
62+
internal override void ProcessDocument(W.Document document, QuestPdfModel output)
63+
{
64+
// Process body and document background
65+
base.ProcessDocument(document, output);
66+
}
67+
68+
internal override void ProcessBody(W.Body body, QuestPdfModel output)
69+
{
70+
Sections = body.GetSections(); // Split content in sections (implemented in the base class)
71+
72+
foreach(var sect in Sections)
73+
{
74+
ProcessSection(sect, body.GetMainDocumentPart(), output);
75+
}
76+
}
77+
78+
internal override void ProcessSection((List<OpenXmlElement> content, SectionProperties properties) section, MainDocumentPart? mainPart, QuestPdfModel output)
79+
{
80+
// Process section properties here and add them to a new QuestPdfPageSet object
81+
var sectionProperties = section.properties;
82+
float w = (float)DocSharp.Primitives.PageSize.Default.WidthMm;
83+
float h = (float)DocSharp.Primitives.PageSize.Default.HeightMm;
84+
float l = (float)DocSharp.Primitives.PageMargins.Default.LeftMm;
85+
float t = (float)DocSharp.Primitives.PageMargins.Default.TopMm;
86+
float r = (float)DocSharp.Primitives.PageMargins.Default.RightMm;
87+
float b = (float)DocSharp.Primitives.PageMargins.Default.BottomMm;
88+
89+
if (sectionProperties.GetFirstChild<PageSize>() is PageSize size)
90+
{
91+
if (size.Width != null)
92+
w = (float)UnitMetricHelper.ConvertToMillimeters(size.Width.Value, UnitMetric.Twip);
93+
if (size.Height != null)
94+
h = (float)UnitMetricHelper.ConvertToMillimeters(size.Height.Value, UnitMetric.Twip);
95+
// if (size.Orient != null && size.Orient.Value == PageOrientationValues.Landscape)
96+
}
97+
if (sectionProperties.GetFirstChild<PageMargin>() is PageMargin margins)
98+
{
99+
if (margins.Top != null)
100+
t = (float)UnitMetricHelper.ConvertToMillimeters(margins.Top.Value, UnitMetric.Twip);
101+
if (margins.Bottom != null)
102+
{
103+
b = (float)UnitMetricHelper.ConvertToMillimeters(margins.Bottom.Value, UnitMetric.Twip);
104+
}
105+
if (margins.Left != null)
106+
{
107+
l = (float)UnitMetricHelper.ConvertToMillimeters(margins.Left.Value, UnitMetric.Twip);
108+
}
109+
if (margins.Right != null)
110+
{
111+
r = (float)UnitMetricHelper.ConvertToMillimeters(margins.Right.Value, UnitMetric.Twip);
112+
}
113+
}
114+
var pageSet = new QuestPdfPageSet(w, h, l, t, r, b, QuestPDF.Infrastructure.Unit.Millimetre);
115+
output.PageSets.Add(pageSet);
116+
117+
// Then, enumerate elements in the section (paragraphs, tables, ...)
118+
base.ProcessSection(section, mainPart, output);
119+
}
120+
121+
internal override void ProcessParagraph(Paragraph paragraph, QuestPdfModel output)
122+
{
123+
// Paragraph properties can be processed here.
124+
var alignment = paragraph.GetEffectiveProperty<TextAlignment>();
125+
126+
// Then, enumerate elements in the paragraph (runs, hyperlinks, math formulas).
127+
base.ProcessParagraph(paragraph, output);
128+
}
129+
130+
internal override void ProcessHyperlink(Hyperlink hyperlink, QuestPdfModel output)
131+
{
132+
// The hyperlink URL/anchor can be processed here.
133+
134+
// Then, enumerate runs in the hyperlink
135+
base.ProcessHyperlink(hyperlink, output);
136+
}
137+
138+
internal override void ProcessRun(Run run, QuestPdfModel output)
139+
{
140+
// Run properties can be processed here.
141+
bool bold = run.GetEffectiveProperty<Bold>() is Bold b && (b.Val == null || b.Val);
142+
bool italic = run.GetEffectiveProperty<Italic>() is Italic i && (i.Val == null || i.Val);
143+
144+
// Then, enumerate run elements (text, picture, break, page number, footnote reference...)
145+
base.ProcessRun(run, output);
146+
}
147+
148+
internal override void ProcessText(Text text, QuestPdfModel output)
149+
{
150+
var textString = text.Text;
151+
}
152+
153+
internal override void ProcessTable(Table table, QuestPdfModel output)
154+
{
155+
// Enumerate rows and cells
156+
base.ProcessTable(table, output);
157+
}
158+
159+
internal override void ProcessTableRow(TableRow tableRow, QuestPdfModel output)
160+
{
161+
// Enumerate cells
162+
base.ProcessTableRow(tableRow, output);
163+
}
164+
165+
internal override void ProcessTableCell(TableCell tableCell, QuestPdfModel output)
53166
{
167+
// Enumerate paragraphs (or nested tables) in the cell
168+
base.ProcessTableCell(tableCell, output);
54169
}
55170

56-
internal override void ProcessBookmarkEnd(BookmarkEnd bookmarkEnd, Document sb)
171+
internal override void ProcessBreak(Break @break, QuestPdfModel output)
57172
{
173+
// Process line/page/column break
58174
}
59175

60-
internal override void ProcessBookmarkStart(BookmarkStart bookmarkStart, Document sb)
176+
internal override void ProcessBookmarkStart(BookmarkStart bookmarkStart, QuestPdfModel output)
61177
{
62178
}
63179

64-
internal override void ProcessBreak(Break @break, Document sb)
180+
internal override void ProcessBookmarkEnd(BookmarkEnd bookmarkEnd, QuestPdfModel output)
65181
{
66182
}
67183

68-
internal override void ProcessCommentEnd(CommentRangeEnd commentEnd, Document sb)
184+
internal override void ProcessAnnotationReference(AnnotationReferenceMark annotationRef, QuestPdfModel output)
69185
{
70186
}
71187

72-
internal override void ProcessCommentReference(CommentReference commentRef, Document sb)
188+
internal override void ProcessCommentReference(CommentReference commentRef, QuestPdfModel output)
73189
{
74190
}
75191

76-
internal override void ProcessCommentStart(CommentRangeStart commentStart, Document sb)
192+
internal override void ProcessCommentStart(CommentRangeStart commentStart, QuestPdfModel output)
77193
{
78194
}
79195

80-
internal override void ProcessDocumentBackground(DocumentBackground background, Document sb)
196+
internal override void ProcessCommentEnd(CommentRangeEnd commentEnd, QuestPdfModel output)
81197
{
82198
}
83199

84-
internal override void ProcessDrawing(Drawing picture, Document sb)
200+
internal override void ProcessDocumentBackground(DocumentBackground background, QuestPdfModel output)
85201
{
86202
}
87203

88-
internal override void ProcessFieldChar(FieldChar field, Document sb)
204+
internal override void ProcessDrawing(Drawing picture, QuestPdfModel output)
89205
{
90206
}
91207

92-
internal override void ProcessFieldCode(FieldCode field, Document sb)
208+
internal override void ProcessVml(OpenXmlElement picture, QuestPdfModel output)
93209
{
94210
}
95211

96-
internal override void ProcessMathElement(OpenXmlElement element, Document sb)
212+
internal override void ProcessFieldChar(FieldChar field, QuestPdfModel output)
97213
{
98214
}
99215

100-
internal override void ProcessPageNumber(PageNumber pageNumber, Document sb)
216+
internal override void ProcessFieldCode(FieldCode field, QuestPdfModel output)
101217
{
102218
}
103219

104-
internal override void ProcessPositionalTab(PositionalTab posTab, Document sb)
220+
internal override void ProcessMathElement(OpenXmlElement element, QuestPdfModel output)
105221
{
106222
}
107223

108-
internal override void ProcessSymbolChar(SymbolChar symbolChar, Document sb)
224+
internal override void ProcessPageNumber(PageNumber pageNumber, QuestPdfModel output)
109225
{
110226
}
111227

112-
internal override void ProcessText(Text text, Document sb)
228+
internal override void ProcessPositionalTab(PositionalTab posTab, QuestPdfModel output)
113229
{
114230
}
115231

116-
internal override void ProcessVml(OpenXmlElement picture, Document sb)
232+
internal override void ProcessSymbolChar(SymbolChar symbolChar, QuestPdfModel output)
117233
{
118234
}
119235

120-
internal override void EnsureSpace(Document sb)
236+
internal override void EnsureSpace(QuestPdfModel output)
121237
{
122238
}
123239
}

0 commit comments

Comments
 (0)