using System;
using System.Text;
using System.Collections;
using System.util;
using iTextSharp.text.pdf;
using iTextSharp.text.html;
using iTextSharp.text.factories;
using iTextSharp.text.pdf.draw;
/*
* $Id: Chunk.cs,v 1.20 2008/05/13 11:25:09 psoares33 Exp $
*
*
* Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
*
* The contents of this file are subject to the Mozilla Public License Version 1.1
* (the "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the License.
*
* The Original Code is 'iText, a free JAVA-PDF library'.
*
* The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
* the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
* All Rights Reserved.
* Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
* are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
*
* Contributor(s): all the names of the contributors are added in the source code
* where applicable.
*
* Alternatively, the contents of this file may be used under the terms of the
* LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
* provisions of LGPL are applicable instead of those above. If you wish to
* allow use of your version of this file only under the terms of the LGPL
* License and not to allow others to use your version of this file under
* the MPL, indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by the LGPL.
* If you do not delete the provisions above, a recipient may use your version
* of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the MPL as stated above or under the terms of the GNU
* Library General Public License as published by the Free Software Foundation;
* either version 2 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
* details.
*
* If you didn't download this code from the following link, you should check if
* you aren't using an obsolete version:
* http://www.lowagie.com/iText/
*/
namespace iTextSharp.text {
///
/// This is the smallest significant part of text that can be added to a document.
///
///
/// Most elements can be divided in one or more Chunks.
/// A chunk is a string with a certain Font.
/// all other layoutparameters should be defined in the object to which
/// this chunk of text is added.
///
///
///
/// Chunk chunk = new Chunk("Hello world", FontFactory.GetFont(FontFactory.COURIER, 20, Font.ITALIC, new Color(255, 0, 0)));
/// document.Add(chunk);
///
///
public class Chunk : IElement {
// public static membervariables
/** The character stand in for an image or a separator. */
public const string OBJECT_REPLACEMENT_CHARACTER = "\ufffc";
/// This is a Chunk containing a newline.
public static readonly Chunk NEWLINE = new Chunk("\n");
/** This is a Chunk containing a newpage. */
public static readonly Chunk NEXTPAGE = new Chunk("");
static Chunk() {
NEXTPAGE.SetNewPage();
}
// member variables
/// This is the content of this chunk of text.
protected StringBuilder content = null;
/// This is the Font of this chunk of text.
protected Font font = null;
/// Contains some of the attributes for this Chunk.
protected Hashtable attributes = null;
// constructors
///
/// Empty constructor.
///
///
/// Has six overloads.
///
public Chunk() {
this.content = new StringBuilder();
this.font = new Font();
}
/**
* A Chunk
copy constructor.
* @param ck the Chunk
to be copied
*/
public Chunk(Chunk ck) {
if (ck.content != null) {
content = new StringBuilder(ck.content.ToString());
}
if (ck.font != null) {
font = new Font(ck.font);
}
}
///
/// Constructs a chunk of text with a certain content and a certain Font.
///
/// the content
/// the font
public Chunk(string content, Font font) {
this.content = new StringBuilder(content);
this.font = font;
}
///
/// Constructs a chunk of text with a certain content, without specifying a Font.
///
/// the content
public Chunk(string content) : this(content, new Font()) {}
/**
* Constructs a chunk of text with a char and a certain Font
.
*
* @param c the content
* @param font the font
*/
public Chunk(char c, Font font) {
this.content = new StringBuilder();
this.content.Append(c);
this.font = font;
}
/**
* Constructs a chunk of text with a char, without specifying a Font
.
*
* @param c the content
*/
public Chunk(char c) : this(c, new Font()) {
}
///
/// Constructs a chunk containing an Image.
///
/// the image
/// the image offset in the x direction
/// the image offset in the y direction
public Chunk(Image image, float offsetX, float offsetY) : this(OBJECT_REPLACEMENT_CHARACTER, new Font()) {
Image copyImage = Image.GetInstance(image);
copyImage.SetAbsolutePosition(float.NaN, float.NaN);
SetAttribute(IMAGE, new Object[]{copyImage, offsetX, offsetY, false});
}
/**
* Key for drawInterface of the Separator.
* @since 2.1.2
*/
public const String SEPARATOR = "SEPARATOR";
/**
* Creates a separator Chunk.
* Note that separator chunks can't be used in combination with tab chunks!
* @param separator the drawInterface to use to draw the separator.
* @since 2.1.2
*/
public Chunk(IDrawInterface separator) : this(separator, false) {
}
/**
* Creates a separator Chunk.
* Note that separator chunks can't be used in combination with tab chunks!
* @param separator the drawInterface to use to draw the separator.
* @param vertical true if this is a vertical separator
* @since 2.1.2
*/
public Chunk(IDrawInterface separator, bool vertical) : this(OBJECT_REPLACEMENT_CHARACTER, new Font()) {
SetAttribute(SEPARATOR, new Object[] {separator, vertical});
}
/**
* Key for drawInterface of the tab.
* @since 2.1.2
*/
public const String TAB = "TAB";
/**
* Creates a tab Chunk.
* Note that separator chunks can't be used in combination with tab chunks!
* @param separator the drawInterface to use to draw the tab.
* @param tabPosition an X coordinate that will be used as start position for the next Chunk.
* @since 2.1.2
*/
public Chunk(IDrawInterface separator, float tabPosition) : this(separator, tabPosition, false) {
}
/**
* Creates a tab Chunk.
* Note that separator chunks can't be used in combination with tab chunks!
* @param separator the drawInterface to use to draw the tab.
* @param tabPosition an X coordinate that will be used as start position for the next Chunk.
* @param newline if true, a newline will be added if the tabPosition has already been reached.
* @since 2.1.2
*/
public Chunk(IDrawInterface separator, float tabPosition, bool newline) : this(OBJECT_REPLACEMENT_CHARACTER, new Font()) {
if (tabPosition < 0) {
throw new ArgumentException("A tab position may not be lower than 0; yours is " + tabPosition);
}
SetAttribute(TAB, new Object[] {separator, tabPosition, newline, 0});
}
///
/// Constructs a chunk containing an Image.
///
/// the image
/// the image offset in the x direction
/// the image offset in the y direction
/// true if the leading has to be adapted to the image
public Chunk(Image image, float offsetX, float offsetY, bool changeLeading) : this(OBJECT_REPLACEMENT_CHARACTER, new Font()) {
SetAttribute(IMAGE, new Object[]{image, offsetX, offsetY, changeLeading});
}
// implementation of the Element-methods
///
/// Processes the element by adding it (or the different parts) to an
/// IElementListener.
///
/// an IElementListener
/// true if the element was processed successfully
public bool Process(IElementListener listener) {
try {
return listener.Add(this);
}
catch (DocumentException) {
return false;
}
}
///
/// Gets the type of the text element.
///
/// a type
public int Type {
get {
return Element.CHUNK;
}
}
///
/// Gets all the chunks in this element.
///
/// an ArrayList
public ArrayList Chunks {
get {
ArrayList tmp = new ArrayList();
tmp.Add(this);
return tmp;
}
}
// methods
///
/// appends some text to this Chunk.
///
/// a string
/// a StringBuilder
public StringBuilder Append(string str) {
return content.Append(str);
}
// methods to retrieve information
///
/// Get/set the font of this Chunk.
///
/// a Font
public virtual Font Font {
get {
return font;
}
set {
this.font = value;
}
}
///
/// Returns the content of this Chunk.
///
/// a string
public virtual string Content {
get {
return content.ToString();
}
}
public override string ToString() {
return content.ToString();
}
///
/// Checks is this Chunk is empty.
///
/// false if the Chunk contains other characters than space.
public virtual bool IsEmpty() {
return (content.ToString().Trim().Length == 0) && (content.ToString().IndexOf("\n") == -1) && (attributes == null);
}
/**
* Gets the width of the Chunk in points.
* @return a width in points
*/
public float GetWidthPoint() {
if (GetImage() != null) {
return GetImage().ScaledWidth;
}
return font.GetCalculatedBaseFont(true).GetWidthPoint(Content, font.CalculatedSize) * HorizontalScaling;
}
///
/// Checks the attributes of this Chunk.
///
/// false if there aren't any.
public bool HasAttributes() {
return attributes != null;
}
///
/// Gets the attributes for this Chunk.
///
///
/// It may be null.
///
/// a Hashtable
public Hashtable Attributes {
get {
return attributes;
}
set {
attributes = value;
}
}
///
/// Sets an arbitrary attribute.
///
/// the key for the attribute
/// the value of the attribute
/// this Chunk
private Chunk SetAttribute(string name, Object obj) {
if (attributes == null)
attributes = new Hashtable();
attributes[name] = obj;
return this;
}
/** Key for text horizontal scaling. */
public const string HSCALE = "HSCALE";
/**
* Sets the text horizontal scaling. A value of 1 is normal and a value of 0.5f
* shrinks the text to half it's width.
* @param scale the horizontal scaling factor
* @return this Chunk
*/
public Chunk SetHorizontalScaling(float scale) {
return SetAttribute(HSCALE, scale);
}
/**
* Gets the horizontal scaling.
* @return a percentage in float
*/
public float HorizontalScaling {
get {
if (attributes == null) return 1f;
Object f = attributes[HSCALE];
if (f == null) return 1f;
return (float)f;
}
}
/// Key for underline.
public const string UNDERLINE = "UNDERLINE";
/**
* Sets an horizontal line that can be an underline or a strikethrough.
* Actually, the line can be anywhere vertically and has always the
* Chunk
width. Multiple call to this method will
* produce multiple lines.
* @param thickness the absolute thickness of the line
* @param yPosition the absolute y position relative to the baseline
* @return this Chunk
*/
public Chunk SetUnderline(float thickness, float yPosition) {
return SetUnderline(null, thickness, 0f, yPosition, 0f, PdfContentByte.LINE_CAP_BUTT);
}
/**
* Sets an horizontal line that can be an underline or a strikethrough.
* Actually, the line can be anywhere vertically and has always the
* Chunk
width. Multiple call to this method will
* produce multiple lines.
* @param color the color of the line or null
to follow
* the text color
* @param thickness the absolute thickness of the line
* @param thicknessMul the thickness multiplication factor with the font size
* @param yPosition the absolute y position relative to the baseline
* @param yPositionMul the position multiplication factor with the font size
* @param cap the end line cap. Allowed values are
* PdfContentByte.LINE_CAP_BUTT, PdfContentByte.LINE_CAP_ROUND and
* PdfContentByte.LINE_CAP_PROJECTING_SQUARE
* @return this Chunk
*/
public Chunk SetUnderline(Color color, float thickness, float thicknessMul, float yPosition, float yPositionMul, int cap) {
if (attributes == null)
attributes = new Hashtable();
Object[] obj = {color, new float[]{thickness, thicknessMul, yPosition, yPositionMul, (float)cap}};
Object[][] unders = Utilities.AddToArray((Object[][])attributes[UNDERLINE], obj);
return SetAttribute(UNDERLINE, unders);
}
/// Key for sub/basescript.
public const string SUBSUPSCRIPT = "SUBSUPSCRIPT";
///
/// Sets the text displacement relative to the baseline. Positive values rise the text,
/// negative values lower the text.
///
///
/// It can be used to implement sub/basescript.
///
/// the displacement in points
/// this Chunk
public Chunk SetTextRise(float rise) {
return SetAttribute(SUBSUPSCRIPT, rise);
}
public float GetTextRise() {
if (attributes != null && attributes.ContainsKey(SUBSUPSCRIPT)) {
return (float)attributes[SUBSUPSCRIPT];
}
return 0.0f;
}
/// Key for text skewing.
public const string SKEW = "SKEW";
/**
* Skews the text to simulate italic and other effects.
* Try alpha=0
and beta=12
.
* @param alpha the first angle in degrees
* @param beta the second angle in degrees
* @return this Chunk
*/
public Chunk SetSkew(float alpha, float beta) {
alpha = (float)Math.Tan(alpha * Math.PI / 180);
beta = (float)Math.Tan(beta * Math.PI / 180);
return SetAttribute(SKEW, new float[]{alpha, beta});
}
/// Key for background.
public const string BACKGROUND = "BACKGROUND";
///
/// Sets the color of the background Chunk.
///
/// the color of the background
/// this Chunk
public Chunk SetBackground(Color color) {
return SetBackground(color, 0, 0, 0, 0);
}
/** Sets the color and the size of the background Chunk
.
* @param color the color of the background
* @param extraLeft increase the size of the rectangle in the left
* @param extraBottom increase the size of the rectangle in the bottom
* @param extraRight increase the size of the rectangle in the right
* @param extraTop increase the size of the rectangle in the top
* @return this Chunk
*/
public Chunk SetBackground(Color color, float extraLeft, float extraBottom, float extraRight, float extraTop) {
return SetAttribute(BACKGROUND, new Object[]{color, new float[]{extraLeft, extraBottom, extraRight, extraTop}});
}
/// Key for text rendering mode.
public const string TEXTRENDERMODE = "TEXTRENDERMODE";
/** Sets the text rendering mode. It can outline text, simulate bold and make
* text invisible.
* @param mode the text rendering mode. It can be PdfContentByte.TEXT_RENDER_MODE_FILL
,
* PdfContentByte.TEXT_RENDER_MODE_STROKE
, PdfContentByte.TEXT_RENDER_MODE_FILL_STROKE
* and PdfContentByte.TEXT_RENDER_MODE_INVISIBLE
.
* @param strokeWidth the stroke line width for the modes PdfContentByte.TEXT_RENDER_MODE_STROKE
and
* PdfContentByte.TEXT_RENDER_MODE_FILL_STROKE
.
* @param strokeColor the stroke color or null
to follow the text color
* @return this Chunk
*/
public Chunk SetTextRenderMode(int mode, float strokeWidth, Color strokeColor) {
return SetAttribute(TEXTRENDERMODE, new Object[]{mode, strokeWidth, strokeColor});
}
/// Key for split character.
public const string SPLITCHARACTER = "SPLITCHARACTER";
///
/// Sets the split characters.
///
/// the SplitCharacter interface
/// this Chunk
public Chunk SetSplitCharacter(ISplitCharacter splitCharacter) {
return SetAttribute(SPLITCHARACTER, splitCharacter);
}
/// Key for hyphenation.
public const string HYPHENATION = "HYPHENATION";
///
/// sets the hyphenation engine to this Chunk.
///
/// the hyphenation engine
/// this Chunk
public Chunk SetHyphenation(IHyphenationEvent hyphenation) {
return SetAttribute(HYPHENATION, hyphenation);
}
/// Key for remote goto.
public const string REMOTEGOTO = "REMOTEGOTO";
///
/// Sets a goto for a remote destination for this Chunk.
///
/// the file name of the destination document
/// the name of the destination to go to
/// this Chunk
public Chunk SetRemoteGoto(string filename, string name) {
return SetAttribute(REMOTEGOTO, new Object[]{filename, name});
}
///
/// Sets a goto for a remote destination for this Chunk.
///
/// the file name of the destination document
/// the page of the destination to go to. First page is 1
/// this Chunk
public Chunk SetRemoteGoto(string filename, int page) {
return SetAttribute(REMOTEGOTO, new Object[]{filename, page});
}
/// Key for local goto.
public const string LOCALGOTO = "LOCALGOTO";
///
/// Sets a local goto for this Chunk.
///
///
/// There must be a local destination matching the name.
///
/// the name of the destination to go to
/// this Chunk
public Chunk SetLocalGoto(string name) {
return SetAttribute(LOCALGOTO, name);
}
/// Key for local destination.
public const string LOCALDESTINATION = "LOCALDESTINATION";
///
/// Sets a local destination for this Chunk.
///
/// the name for this destination
/// this Chunk
public Chunk SetLocalDestination(string name) {
return SetAttribute(LOCALDESTINATION, name);
}
/// Key for generic tag.
public const string GENERICTAG = "GENERICTAG";
///
/// Sets the generic tag Chunk.
///
///
/// The text for this tag can be retrieved with PdfPageEvent.
///
/// the text for the tag
/// this Chunk
public Chunk SetGenericTag(string text) {
return SetAttribute(GENERICTAG, text);
}
/// Key for image.
public const string IMAGE = "IMAGE";
///
/// Returns the image.
///
/// an Image
public Image GetImage() {
if (attributes == null) return null;
Object[] obj = (Object[])attributes[Chunk.IMAGE];
if (obj == null)
return null;
else {
return (Image)obj[0];
}
}
///
/// Checks if a given tag corresponds with this object.
///
/// the given tag
/// true if the tag corresponds
public static bool IsTag(string tag) {
return ElementTags.CHUNK.Equals(tag);
}
/// Key for Action.
public const string ACTION = "ACTION";
///
/// Sets an action for this Chunk.
///
/// the action
/// this Chunk
public Chunk SetAction(PdfAction action) {
return SetAttribute(ACTION, action);
}
///
/// Sets an anchor for this Chunk.
///
/// the Uri to link to
/// this Chunk
public Chunk SetAnchor(Uri url) {
return SetAttribute(ACTION, new PdfAction(url));
}
///
/// Sets an anchor for this Chunk.
///
/// the url to link to
/// this Chunk
public Chunk SetAnchor(string url) {
return SetAttribute(ACTION, new PdfAction(url));
}
/// Key for newpage.
public const string NEWPAGE = "NEWPAGE";
///
/// Sets a new page tag.
///
/// this Chunk
public Chunk SetNewPage() {
return SetAttribute(NEWPAGE, null);
}
/// Key for annotation.
public const string PDFANNOTATION = "PDFANNOTATION";
///
/// Sets a generic annotation to this Chunk.
///
/// the annotation
/// this Chunk
public Chunk SetAnnotation(PdfAnnotation annotation) {
return SetAttribute(PDFANNOTATION, annotation);
}
/**
* @see com.lowagie.text.Element#isContent()
* @since iText 2.0.8
*/
public bool IsContent() {
return true;
}
/**
* @see com.lowagie.text.Element#isNestable()
* @since iText 2.0.8
*/
public bool IsNestable() {
return true;
}
/**
* Returns the hyphenation (if present).
* @param hyphenation a HyphenationEvent instance
* @since 2.1.2
*/
public IHyphenationEvent GetHyphenation() {
if (attributes == null) return null;
return (IHyphenationEvent) attributes[Chunk.HYPHENATION];
}
// keys used in PdfChunk
/// Key for color.
public const string COLOR = "COLOR";
/// Key for encoding.
public const string ENCODING = "ENCODING";
}
}