PDFsharp & MigraDoc Foundation

PDFsharp - A .NET library for processing PDF & MigraDoc Foundation - Creating documents on the fly
It is currently Fri Jul 05, 2024 11:27 pm

All times are UTC


Forum rules


Please read this before posting on this forum: Forum Rules



Post new topic Reply to topic  [ 2 posts ] 
Author Message
PostPosted: Wed Dec 15, 2010 7:17 pm 
Offline

Joined: Wed Dec 15, 2010 7:11 pm
Posts: 1
Hi, i was having dificult to align the text into a retangle. i loked at the class and it was only implemented for aligment TopLeft, so i changed it to accept the center, right, etc... i don't know if it will be of any help, or if you alread corrected it, but i am posting the code, hope it helps. this is the code of the XtextFormatter.cs.


#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;

namespace PdfSharp.Drawing.Layout
{
/// <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 XTextFormatter
{
/// <summary>
/// Initializes a new instance of the <see cref="XTextFormatter"/> class.
/// </summary>
public XTextFormatter(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);
this.cyAscent = lineSpace * font.cellAscent / font.cellSpace;
this.cyDescent = lineSpace * font.cellDescent / font.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();

CreateLayout();





double dx = layoutRectangle.Location.x;
double dy = layoutRectangle.Location.y + cyAscent;



/* Alterado por Ângelo Cossa */
List<double> Larr_lineWidth = new List<double>();
List<double> Larr_lineStart = new List<double>();

//If the text fills all the retangle, there is no sense in alignment
bool ends_before_end = false;

//Se if the last block comes before the end,
for (int idx = 0; idx < this.blocks.Count; idx++)
{
Block block = (Block)this.blocks[idx];

if (block.Type == BlockType.LineBreak)
{
Larr_lineStart.Add(0);

if ((idx - 1) < 0)
{
Larr_lineWidth.Add(0);
}
else
{
Larr_lineWidth.Add(this.blocks[idx - 1].Location.X + this.blocks[idx - 1].Width);
}
}

if (block.Stop)
{
ends_before_end = true;
break;
}
}

//Add the last line
Larr_lineStart.Add(0);

if ((this.blocks.Count - 1) < 0)
{
Larr_lineWidth.Add(0);
}
else
{
Larr_lineWidth.Add(this.blocks[this.blocks.Count - 1].Location.X + this.blocks[this.blocks.Count - 1].Width);
}

//Adjust the linestart
if (format.Alignment != XStringAlignment.Near)
{

for (int n = 0; n < Larr_lineWidth.Count; n++)
{
//gets the diference between the width of the retangle and the width of the line
double rest = layoutRectangle.width - Larr_lineWidth[n];


if (format.Alignment == XStringAlignment.Center)
{

Larr_lineStart[n] = rest / 2D;
}
else if (format.Alignment == XStringAlignment.Far)
{
Larr_lineStart[n] = rest;
}
}

}


if (format.LineAlignment != XLineAlignment.Near && !ends_before_end) {

Block last_block = (Block)this.blocks[this.blocks.Count - 1];

//gets the height of the text
double text_height = (last_block.Location.y + last_block.Height);

//the diference between the size of the block and the size fo the text
double rest = layoutRectangle.Height - text_height;


if (format.LineAlignment == XLineAlignment.BaseLine)
{
//if the text is in the botton, the rest is in the top
dy += rest;
}
else if (format.LineAlignment == XLineAlignment.Center)
{
//If the text is in the middle half the rest in the top
dy += (rest / 2D);
}


}




int count = this.blocks.Count;
int lineCount = 0;

for (int idx = 0; idx < count; idx++)
{
Block block = (Block)this.blocks[idx];
if (block.Stop)
break;
if (block.Type == BlockType.LineBreak)
{
lineCount++;
continue;
}

//Now that the text is correctly aligned vertically align it horinzontally
gfx.DrawString(block.Text, font, brush, dx + Larr_lineStart[lineCount] + block.Location.x, dy + block.Location.y);
}
}

void CreateBlocks()
{
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, this.gfx.MeasureString(token, this.font).Height));
}
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, this.gfx.MeasureString(token, this.font).Height));
startIndex = idx + 1;
blockLength = 0;
}
else
{
blockLength++;
}
}
else
{
inNonWhiteSpace = true;
blockLength++;
}
}
if (blockLength != 0)
{
string token = text.Substring(startIndex, blockLength);
this.blocks.Add(new Block(token, BlockType.Text,
this.gfx.MeasureString(token, this.font).Width, this.gfx.MeasureString(token, this.font).Height));
}
}

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>
/// <param name="height">the height of the text</param>
public Block(string text, BlockType type, double width,double height)
{
Text = text;
Type = type;
Width = width;
Height = height;
}

/// <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 Heigth of the text.
/// </summary>
public double Height;


/// <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
// - ...
}
}


Top
 Profile  
Reply with quote  
PostPosted: Mon Jan 24, 2011 1:10 pm 
Offline

Joined: Mon Jan 24, 2011 1:04 pm
Posts: 1
I have updated the XTextFormatter.cs in the code folder of PDFSharp but i'm still gettin the "only TopLeft..." throw when I select XStringFormats.Center


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 2 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 70 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Privacy Policy, Data Protection Declaration, Impressum
Powered by phpBB® Forum Software © phpBB Group