Skip to content

Commit 6f90494

Browse files
FEAT: Horizontal and vertical alignment within XRect
1 parent 49db540 commit 6f90494

File tree

1 file changed

+88
-17
lines changed

1 file changed

+88
-17
lines changed

PdfSharpCore/Drawing.Layout/XTextFormatter.cs

Lines changed: 88 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -150,17 +150,16 @@ public void DrawString(string text, XFont font, XBrush brush, XRect layoutRectan
150150
/// <param name="font">The font.</param>
151151
/// <param name="brush">The text brush.</param>
152152
/// <param name="layoutRectangle">The layout rectangle.</param>
153-
/// <param name="format">The format. Must be <c>XStringFormat.TopLeft</c></param>
154-
public void DrawString(string text, XFont font, XBrush brush, XRect layoutRectangle, XStringFormat format, XUnit? lineHeight = null)
153+
/// <param name="lineHeight">The height of each line</param>
154+
public XRect GetLayout(string text, XFont font, XBrush brush, XRect layoutRectangle,
155+
XUnit? lineHeight = null)
155156
{
156157
if (text == null)
157158
throw new ArgumentNullException("text");
158159
if (font == null)
159160
throw new ArgumentNullException("font");
160161
if (brush == null)
161162
throw new ArgumentNullException("brush");
162-
if (format.Alignment != XStringAlignment.Near || format.LineAlignment != XLineAlignment.Near)
163-
throw new ArgumentException("Only TopLeft alignment is currently implemented.");
164163

165164
Text = text;
166165
Font = font;
@@ -169,36 +168,78 @@ public void DrawString(string text, XFont font, XBrush brush, XRect layoutRectan
169168
_lineHeight = lineHeight?.Point ?? _lineSpace;
170169

171170
if (text.Length == 0)
172-
return;
171+
return new XRect(layoutRectangle.Location.X, layoutRectangle.Location.Y, 0, 0);
173172

174173
CreateBlocks();
175174

176175
CreateLayout();
177176

177+
return _layoutRectangle;
178+
}
179+
180+
/// <summary>
181+
/// Draws the text.
182+
/// </summary>
183+
/// <param name="text">The text to be drawn.</param>
184+
/// <param name="font">The font.</param>
185+
/// <param name="brush">The text brush.</param>
186+
/// <param name="layoutRectangle">The layout rectangle.</param>
187+
/// <param name="format">The format. Must be <c>XStringFormat.TopLeft</c></param>
188+
/// <param name="lineHeight">The height of each line</param>
189+
public void DrawString(string text, XFont font, XBrush brush, XRect layoutRectangle, XStringFormat format,
190+
XUnit? lineHeight = null)
191+
{
192+
if (format == null)
193+
throw new ArgumentNullException(nameof(format));
194+
195+
if (text.Length == 0)
196+
return;
197+
198+
GetLayout(text, font, brush, layoutRectangle, lineHeight);
199+
200+
SetAlignment(new TextFormatAlignment()
201+
{
202+
Horizontal = GetHorizontalAlignmentFromFormat(format),
203+
Vertical = GetVerticalAlignmentFromFormat(format)
204+
});
205+
178206
double dx = layoutRectangle.Location.X;
179-
double dy = layoutRectangle.Location.Y + _cyAscent;
180-
207+
double dy = layoutRectangle.Location.Y;
208+
209+
var lines = GetLines(_blocks).ToArray();
210+
181211
if (VerticalAlignment == XVerticalAlignment.Middle)
182212
{
183-
dy += layoutRectangle.Height / 2 - _layoutRectangle.Height / 2 - _cyDescent;
213+
dy += (layoutRectangle.Height - _layoutRectangle.Height + _lineHeight) / 2;
184214
}
185215
else if (VerticalAlignment == XVerticalAlignment.Bottom)
186216
{
187-
dy = layoutRectangle.Location.Y + layoutRectangle.Height - _layoutRectangle.Height + _lineHeight - _cyDescent;
217+
dy = layoutRectangle.Location.Y + layoutRectangle.Height - _layoutRectangle.Height + _lineHeight -
218+
_cyDescent;
188219
}
189-
220+
190221
int count = _blocks.Count;
191-
for (int idx = 0; idx < count; idx++)
222+
foreach (var line in lines)
192223
{
193-
Block block = _blocks[idx];
194-
if (block.Stop)
195-
break;
196-
if (block.Type == BlockType.LineBreak)
197-
continue;
198-
_gfx.DrawString(block.Text, font, brush, dx + block.Location.X, dy + block.Location.Y);
224+
if (Alignment != XParagraphAlignment.Justify)
225+
{
226+
var enumerable = line as Block[] ?? line.ToArray();
227+
var lineText = string.Join(" ", enumerable.Select(l => l.Text));
228+
var locationX = dx;
229+
if (format.Alignment == XStringAlignment.Center)
230+
locationX = dx + layoutRectangle.Width / 2;
231+
if (format.Alignment == XStringAlignment.Far)
232+
locationX += layoutRectangle.Width;
233+
_gfx.DrawString(lineText, font, brush, locationX, dy + enumerable.First().Location.Y, format);
234+
}
199235
}
200236
}
201237

238+
private static IEnumerable<IEnumerable<Block>> GetLines(List<Block> blocks)
239+
{
240+
return blocks.GroupBy(b => b.Location.Y);
241+
}
242+
202243
void CreateBlocks()
203244
{
204245
_blocks.Clear();
@@ -378,6 +419,36 @@ void HorizontalAlignLine(int firstIndex, int lastIndex, double layoutWidth)
378419
// - underline and strike-out variation
379420
// - super- and sub-script
380421
// - ...
422+
423+
private static XParagraphAlignment GetHorizontalAlignmentFromFormat(XStringFormat format)
424+
{
425+
switch (format.Alignment)
426+
{
427+
case XStringAlignment.Center:
428+
return XParagraphAlignment.Center;
429+
case XStringAlignment.Near:
430+
return XParagraphAlignment.Left;
431+
case XStringAlignment.Far:
432+
return XParagraphAlignment.Right;
433+
}
434+
435+
return XParagraphAlignment.Justify;
436+
}
437+
438+
private static XVerticalAlignment GetVerticalAlignmentFromFormat(XStringFormat format)
439+
{
440+
switch (format.LineAlignment)
441+
{
442+
case XLineAlignment.Center:
443+
return XVerticalAlignment.Middle;
444+
case XLineAlignment.BaseLine:
445+
case XLineAlignment.Far:
446+
return XVerticalAlignment.Bottom;
447+
case XLineAlignment.Near:
448+
default:
449+
return XVerticalAlignment.Top;
450+
}
451+
}
381452
}
382453

383454
public class TextFormatAlignment

0 commit comments

Comments
 (0)