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"; } }