[Mono-list] PDF creation library for Mono?
Willem J.W. Semmelink
willems@digicore.co.za
Tue, 5 Oct 2004 09:12:18 +0200
> -----Original Message-----
> From: Marek Habersack [mailto:grendel@caudium.net]=3D20
> Sent: Tuesday, 5 October 2004 10:31 AM
> To: mono-list@lists.ximian.com
> Subject: [Mono-list] PDF creation library for Mono?
>=3D20
> Hello,
>=3D20
> I was wondering whether anyone knows about a free, managed=3D20
> PDF creation library that works with Mono? I've googled for=3D20
Hi Marek
I attach a class below that I am currently working on. I give it away as =
GPL.=20
I have no project registered for it (yet), but feel free to send me bug =
reports and suggestions via email.
This is how you use the class:
PDFExport expt =3D new PDFExport();
String filename =3D "Test.pdf";
//Assign Info and other properties before beginning the export
expt.Information.Title =3D "Document Title";
expt.Information.Subject=3D"Document Subject";
expt.Information.AuthorName =3D "Willem";
expt.Information.Keywords =3D "Test Export";
expt.Information.Creator =3D "My Test Program";
expt.PageSize =3D SBReport.Export.PageSizes.pgA4;
if (Strm=3D=3Dnull)
expt.BeginExport(filename); //Illustrate export to file
else {
expt.BeginExport(Strm); //Illustrate export to stream (2nd HTML =
example)
}=20
expt.NewPage(); =09
expt.WriteText("Toets A",20,10,"Arial",10);
expt.WriteText("Toets B",40,20,"Times New Roman",10);
expt.WriteText("Toets C",60,40,"Courier New",10);
expt.WriteText("Willem Semmelink",120,80,"Script",20);
expt.DrawVLine(150,150,200);
SBReport.RptColour clr =3D new SBReport.RptColour(250,0,0);
System.Drawing.Color fillclr =3D System.Drawing.Color.Aquamarine;
expt.DrawHLine(155,150,200,LineStyles.Dash,2,clr);
expt.DrawRectangle(200,200,300,120,LineStyles.Solid,2,clr,fillclr,FillPat=
terns.DiagCrossLines);
expt.NewPage();
fillclr =3D System.Drawing.Color.DarkOrchid;
expt.WriteText("Sonya Semmelink",120,80,"Arial",20);
expt.DrawHLine(50,150,200);
expt.DrawVLine(50,150,200,LineStyles.Dots,1,clr);
expt.DrawRectangle(200,200,300,120,LineStyles.Solid,2,clr,fillclr,FillPat=
terns.HorizLines);
expt.EndExport();
System.Console.WriteLine(filename + " was created");
Regards
Willem Semmelink
//Below follows the PDF class:
using System;
//using System.FileStream;
using System.Collections;
using System.Collections.Specialized;
using System.IO;
namespace SBReport.Export
{
/// <summary>
/// Summary description for Class.
/// </summary>
public class PDFExport : IExportInterface
{
public PDFExport()
{
}
=09
#region Properties=20
=09
#endregion
#region Public methods
=09
//Code common to both public BeginExport methods
protected override void OnStartDoc()
{
//Initialize all data
xrefTable =3D new ArrayList(); // Table containing object offsets =
=09
//PDFWriter =3D new =
System.IO.StreamWriter(PDFOutStream,System.Text.Encoding.ASCII);
m_PageObjRefs=3D""; // Clear the page references =09
m_StartXOffs=3D0; // Reset startxref value
m_LastObjId=3D-1; // Reset object count
m_PagesCount=3D0; // Reset number of pages in doc
m_PageContents=3D""; // Clean curent page contents
m_Offset =3D 10; // PDF header contains 0...9 bytes, incl CRLF
// so the first object will write at position 10
m_PageProcSetPatterns=3D""; // Clear patterns for current page
m_IsFirstPage=3Dtrue; // Is the first page of the document
m_Patterns =3D new ArrayList(); // Table containing pattern IDs
foreach(int i in Enum.GetValues(typeof(FillPatterns))) =09
{ //Create an empty array item (i.e. value of 0) for each enumerated =
pattern
m_Patterns.Add(0); =20
} =09
m_Fonts=3Dnew Hashtable(); //Start with no fonts in document
m_PageFonts=3D""; //No fonts on current page
=09
//Start writing to the stream //PDF Spec Paragraph 5.13 =09
StreamWrite("%PDF-1.3" + CRLF); // Write the PDF header
xrefTable.Add(GetNewObjID()); // First Object has offset of 0 =09
=09
//Get Object reference for Pages object [it is written at end of doc]
m_PagesObjId =3D GetNewObjID();
}
//No XML comment - defined in parent
protected override void OnEndDoc()
{
int rootObjectId,outlineObjectId; =09
//Finish the curent page____________________________
FlushCurrentPage();
//Write Pages Object________________________ Adobe Spec 6.3
string text =3D "/Type /Pages" + CRLF + //Write object type
"/Count " + m_PagesCount.ToString(); //Number of pages in document
text +=3D CRLF + "/Kids [" + m_PageObjRefs + "]"; //Add references to =
all pages
=09
PDFWriteObj(m_PagesObjId,true, //This object ID; dictionary<<, >> =
text); //Contents of the pages object =09
//Write Outline Object_____________________ Adobe Spec 6.7
outlineObjectId =3D GetNewObjID(); //Save obj ID of Outline object=20
PDFWriteObj( //Write Outlines Object
outlineObjectId,true, //This object number; dictionary<<, >>=20
"/Type /Outlines" + CRLF + //Write object type
"/Count 0"); //Empty object for now =09
//Write the root object_____________________ Adobe Spec 6.2
rootObjectId =3D GetNewObjID(); //Save obj ID of catalog object as =
root =09
PDFWriteObj( //Write Catalog Object
rootObjectId,true, //This object number; dictionary<<, >>=20
"/Type /Catalog" + CRLF + //Write object type
"/Pages " + PDFObjRef(m_PagesObjId) + CRLF+ //Pages reference =3D 3 =
=09
"/Outlines " +PDFObjRef(outlineObjectId)+CRLF+ //Outlines reference =
=3D 2
"/Pagemode /UseOutlines"); //Start Acrobat Reader to view =
Outlines
// Write final stuff to end the file properly
int infoObjectID=3DWriteDocumentInfo(); //Write the document info =
object=09
WriteCrossRef(); //Write the Cross Reference Table =09
WriteTrailer(rootObjectId,infoObjectID); //Write the Trailer
//Clean up memory that was used
xrefTable.Clear();
}
//No XML comment - defined in parent
public override void NewPage()
{ =20
if (! m_IsFirstPage) { //If this is not the first page, write =
previous page to stream
FlushCurrentPage();
}
m_PageContents=3D""; //Start with a clean page contents object =
array
m_PageProcSetPatterns=3D""; //Start with no patterns in ProcSet
m_IsFirstPage=3Dfalse; //Next time we call this function, we will =
flush crrent page
m_PagesCount++; //Increment pages counter
m_PageFonts=3D""; //Start page with no fonts in resource list
}
=09
//No XML comment - defined in parent
public override void WriteText(string text,int left, int =
top,SBReport.Font font)
{ //Adobe Specification Chapter 11
string fontRef =3D PDFAddFont(font); //Returns something like "/F1"
int objId=3DGetNewObjID();
int pgHeight =3D PAGE_DIMENSIONS[(int)m_PageSize,1]; =09
PDFWriteStreamObj(objId,"",
"BT" + CRLF +
fontRef+" " + font.Size.ToString() + " Tf" + CRLF +=20
"-0.1940 Tc" + CRLF + //Character spacing
left.ToString() + " " +
(pgHeight - top).ToString() + " " + //PDF measures from bottom of =
pg
"Td ("+text+") Tj" + CRLF +
"ET" + CRLF =20
);//PDFWriteObj
if (m_PageContents.Length > 0) {
m_PageContents +=3D " ";
}
m_PageContents +=3D PDFObjRef(objId);
} =09
=09
public override void DrawHLine(int fromX, int fromY,int length,
LineStyles style,int thickness, RptColour clr )
{
DrawPDFLine(fromX,fromY,fromX+length,fromY,style,thickness,clr);
}
public override void DrawVLine(int fromX, int fromY,int length,
LineStyles style,int thickness,
RptColour clr
)
{
DrawPDFLine(fromX,fromY,fromX,fromY+length,style,thickness,clr);
} =09
=09
//No XML comment - defined in parent
public override void DrawRectangle(int left, int top,int width, int =
height,
LineStyles style,int thickness, RptColour lineClr, RptColour =
fillClr,
FillPatterns pattern)
{ //Adobe specification Paragraph 7.1, Chapter 12
int objId=3DGetNewObjID();
int pgHeight =3D PAGE_DIMENSIONS[(int)m_PageSize,1];
string widthstr =3D "";
string colorstr=3D PDFColour(lineClr,true);
string fillClrStr=3D"";
if (fillClr !=3Dnull) fillClrStr=3DPDFColour(fillClr,false);
if (thickness > 1) {widthstr =3D thickness.ToString() + " w" + CRLF;}
string stylestr=3DPDFLineStyle(style);
string patternStr =3D "";
string fillStr =3D ((fillClr=3D=3Dnull)? "S":"B") + CRLF;
if (pattern !=3D FillPatterns.Solid)=20
{
fillStr =3D "S" + CRLF;
PDFFillPattern(pattern); //Create a pattern object if it does =
not exist
patternStr =3D //"/Pattern cs /P" +
"/CS1 cs" + CRLF +
String.Format("{0,4} {1,4} {2,4}", =09
((double)fillClr.Red/255), //We do not use the PDFColour =
function
((double)fillClr.Green/255), //because we do not want the "rg" =
at the end
((double)fillClr.Blue/255)) +
" /P" +=09
((int) pattern).ToString() +
" scn" + CRLF + =09
left.ToString() + " " +
(pgHeight-top).ToString() + " " +
width.ToString() + " " +
( - height).ToString() + " re" + CRLF +
"f" + CRLF; =20
}
PDFWriteStreamObj(objId,"", =09
patternStr +
colorstr +=20
fillClrStr+
widthstr + stylestr + =20
left.ToString() + " " +
(pgHeight-top).ToString() + " " +
width.ToString() + " " +
( - height).ToString() + " re" + CRLF +
fillStr=09
);//PDFWriteObj
if (m_PageContents.Length > 0)=20
{
m_PageContents +=3D " ";
}
m_PageContents +=3D PDFObjRef(objId); =09
}
=09
#endregion Public Methods
//---------------------------------------------------
#region Private Functions/Methods
/// <summary>
/// Write an object to the PDF file and add it's offset to the
/// xref table.
/// </summary>
/// <param name=3D"objno">Object number</param>
/// <param name=3D"dictionary">Write <c><<</c> at start and <c>>></c> =
at end</param>
/// <param name=3D"dictionaryText">Object contents - printed in =
dictionary</param>
private void PDFWriteObj(int objno,bool dictionary,string =
dictionaryText)
{
string txt =3D objno.ToString() + " 0 obj" + CRLF;
if (dictionary) {=20
txt +=3D "<<" + CRLF;=20
}
txt +=3D dictionaryText + CRLF;
if (dictionary) {
txt +=3D ">>" + CRLF;=09
}
//if (writeEndObj)=20
//{
txt +=3D "endobj"+ CRLF+CRLF;=20
//} =09
xrefTable[objno] =3Dm_Offset; //Insert offset at object index
m_Offset +=3D txt.Length; //Calculate offset for next object =09
StreamWrite(txt);
}
/// <summary>
/// Write an object with an embedded stream
/// </summary>
/// <param name=3D"objno">Object ID</param>
/// <param name=3D"dictionaryText">Object text - printed in =
dictionary</param>
/// <param name=3D"streamText">Stream contents</param>
private void PDFWriteStreamObj(int objno, string dictionaryText, =
string streamText)
{ //Adobe Specification Paragraph 4.8
int streamLen =3D streamText.Length;
string fullText =3D "<< " +=20
(dictionaryText =3D=3D ""? "":(CRLF+dictionaryText + CRLF)) +=20
"/Length " + streamLen.ToString() +=20
(dictionaryText =3D=3D ""? " >>":CRLF+">>")+
CRLF +
"stream" + CRLF +
streamText +=20
"endstream"; =09
PDFWriteObj(objno,false,fullText);
}
=09
//returns something like /F1 - reference to font by internal name
private string PDFAddFont(SBReport.Font font)
{
/*const string widths =3D =09
"[278 278 355 556 556 889 667 190 333 333 389 "+
"584 278 333 278 278 556 556 556 556 556 556 556 "+
"556 556 556 278 278 584 584 584 556 1015 667 667 "+
"722 722 667 610 778 722 278 500 667 556 832 722 "+
"778 667 778 722 667 610 722 667 944 667 667 610 "+
"278 278 278 469 556 333 556 556 500 556 556 278 "+
"556 556 222 222 500 222 832 556 556 556 556 333 "+
"500 278 556 500 722 500 500 500 334 260 334 584 "+
"750 556 750 222 556 333 1000 556 556 333 1000 667 "+
"333 1000 750 610 750 750 222 222 333 333 350 556 "+
"1000 333 1000 500 333 944 750 500 667 278 333 556 "+
"556 556 556 260 556 333 736 370 556 584 333 736 552 "+
"400 549 333 333 333 576 537 278 333 333 365 556 834 "+
"834 834 610 667 667 667 667 667 667 1000 722 667 667 "+
"667 667 278 278 278 278 722 722 778 778 778 778 778 "+
"584 778 722 722 722 722 667 667 610 556 556 556 556 "+
"556 556 889 500 556 556 556 556 278 278 278 278 556 "+
"556 556 556 556 556 556 549 610 556 556 556 556 500 556 500]";
*/
string fontReference;
int fontObjectId;
if(m_Fonts.ContainsKey(font.Name))
{ //Font has been used before - return it's object ID
string s =3D (string)m_Fonts[font.Name];
fontReference=3Ds.Substring(0,s.IndexOf(","));
fontObjectId=3Dint.Parse(s.Substring(s.IndexOf(",")+1));
}=20
else
{ //Font not yet used, stream out its details=20
fontObjectId=3DGetNewObjID();
fontReference =3D "/F" + (m_Fonts.Count+1).ToString(); =09
m_Fonts.Add(font.Name,fontReference+","+fontObjectId.ToString()); =
//Remember which fonts we streamed out
SBReport.FontMetrics fontMetrics =3D font.CalcFontMetrics();
int FontFlags =3D 0 +
(fontMetrics.IsFixedWidth? 1:0) +
(fontMetrics.IsSerif? 2:0) +
(fontMetrics.IsSymbol? 4:0) +
(fontMetrics.IsScript? 8:0) +
(fontMetrics.IsSymbol? 0:32)+ //32 is on right: not symblic
(font.Italic? 64:0);
string widths =3D "";
for(int i =3D 32; i <=3D 255; i++)
{ //get the width of each character in the font
widths +=3D fontMetrics.CharWidths[i].ToString() + " ";
}
//Adobe Spec 7.7
int widthsObjID=3DGetNewObjID();
int fontdescrID=3DGetNewObjID();
PDFWriteObj(fontObjectId,true, //font object id; dictionary:<<, >> =
=09
/* _________ Type 1 Font Descriptor __________ =09
* "/Type /Font" + CRLF + //Object type
* "/Subtype /Type1" + CRLF + =09
*((font.Name=3D=3D"Arial")? "/BaseFont /Helvetica" : "/BaseFont =
/Times-Roman")
* */
=09
/* _________ TrueType Font Descriptor _________*/
"/Type /Font" + CRLF + //Object type
"/Subtype /TrueType" + CRLF +
"/Name " + fontReference + CRLF +
"/BaseFont /" + PDFFontName(font.Name) + =20
((font.Bold=3D=3Dtrue || font.Italic=3D=3Dtrue)?=20
//true: add font styles after font name
"," +=20
(font.Bold=3D=3Dtrue? "":"Bold") +=20
(font.Italic=3D=3Dtrue? "":"Italic") =09
//false: no font style added
:"")
+ CRLF +
"/Encoding /WinAnsiEncoding" + CRLF +=20
/* "WinAnsiEncoding", "MacRomanEncoding", "MacExpertEncoding",
* "StandardEncoding", "PDFDocEncoding"
* */
"/FirstChar 32" + CRLF + //Replace with variable
"/LastChar 255" + CRLF + //Replace with variable =09
//"/Widths " + PDFObjRef(widthsObjID) + CRLF+
"/Widths [" + widths + "]"+ CRLF+
"/FontDescriptor " + PDFObjRef(fontdescrID)
); =09
//PDFWriteObj(widthsObjID,true,widths);
PDFWriteObj(fontdescrID,true,
"/Type /FontDescriptor" + CRLF + =09
"/FontName /" + PDFFontName(font.Name) + CRLF + =20
"/Flags " + FontFlags.ToString() + CRLF +
"/FontBBox [" +
fontMetrics.FontBox.left + " " +
fontMetrics.FontBox.top + " " +
fontMetrics.FontBox.right+ " " +
fontMetrics.FontBox.bottom+ "]" + CRLF+
//[-250 -144 2664 864]" +CRLF+
"/Ascent "+ fontMetrics.Ascent + CRLF + //"/Ascent 864" + CRLF +
"/CapHeight "+ fontMetrics.Ascent + CRLF + //"/CapHeight 864" + =
CRLF +
"/Descent "+fontMetrics.Descent + CRLF + //"/Descent -144" + CRLF + =
=09
"/AvgWidth "+fontMetrics.AvgWidth + CRLF + //"/AvgWidth 432" + CRLF =
+
"/MaxWidth "+fontMetrics.MaxWidth + CRLF + //"/MaxWidth 2664" + =
CRLF +
"/StemV 0" + CRLF +
"/ItalicAngle 0"=09
);
}//if ContainsKey
=09
//Only add to page resources if it is not yet there
if (m_PageFonts.IndexOf(fontReference) < 0) {=20
m_PageFonts +=3D fontReference + " " + PDFObjRef(fontObjectId) + " =
";
}
return fontReference;
}
//PDF does not like spaces in names like "Times New Roman". Remove =
spaces
private string PDFFontName(string oldName)
{
return oldName.Replace(" ","");
}
private void FlushCurrentPage()
{ //Write the last (current) page to the stream,=20
=20
//ProcSet______________________________________ Adobe Spec 7.6
int procset=3DGetNewObjID();
string ProcSetText =3D"/Font << " + m_PageFonts + " >> " + CRLF+
"/ProcSet [/PDF /Text /ImageC]"; =09
=09
if (m_PageProcSetPatterns.Length >0) //Adobe Spec Example 7.32
{
ProcSetText +=3D CRLF + "/Pattern << " + m_PageProcSetPatterns + " =
>>" + CRLF +
"/ColorSpace << /CS1 [/Pattern /DeviceRGB] >>";
} =09
PDFWriteObj(procset,true,ProcSetText);=20
=09
//Page Object
double pgWidth =3D PAGE_DIMENSIONS[(int)m_PageSize,0];
double pgHeight =3D PAGE_DIMENSIONS[(int)m_PageSize,1];
string text =3D "/Type /Page" + CRLF + //Define object type
"/Parent " + PDFObjRef(m_PagesObjId) + CRLF +=20
"/MediaBox [0 0 " +=20
pgWidth.ToString() + " " + //Define page size
pgHeight.ToString() + "]" + CRLF +
"/Resources " + PDFObjRef(procset) + CRLF +=20
//"/Resources << " +
//"/Font << /" + fName + " " + PDFObjRef(fontid) + " >> " +
//"/ProcSet " + PDFObjRef(procset) + ">>" + CRLF +
"/Contents " +
( m_PageContents.Length <=3D 5? m_PageContents : "[" + =
m_PageContents + "]") =09
;
int newObjID =3D GetNewObjID();
PDFWriteObj(newObjID,true, //This object number
text);=09
if (m_PageObjRefs.Length > 0){
m_PageObjRefs +=3D " ";
}
m_PageObjRefs +=3D PDFObjRef(newObjID);
}
///<summary>PDF object reference</summary>
private string PDFObjRef(int o)
{ //Adobe Specification Paragraph 4.11
return o.ToString() + " 0 R";
}
/// <summary>Write the PDF cross-reference table</summary>
private void WriteCrossRef()
{ //Adobe speification Paragraph 5.15
m_StartXOffs =3D m_Offset; //Save offset of xref=20
StreamWrite("xref" + CRLF); //Intro to the xref table
//First number indicates we start at object 0 [first entry in this =
subsection]
//Second number is the number of cross reference entries
StreamWrite("0 " + xrefTable.Count.ToString() + CRLF);=20
int i =3D 0;
foreach (int offset in xrefTable)
{ //Each entry must be exactly 20 bytes, including end-of-line marker
//offset =3D number of bytes from the begining of the file to the=20
//beginning of the object: must be 10 bytes long, padded with =
leading zeroes
if (i=3D=3D0) StreamWrite("0000000000 65535 f"+CRLF);
else=20
{
StreamWrite(String.Format("{0:D10} 00000 n{1}",offset, CRLF));
}
++i;
}
}
/// <summary>Write the last part of the PDF file</summary>
private void WriteTrailer(int root,int info)
{ //Adobe Specificaton Paragraph 5.16
StreamWrite("trailer" + CRLF + "<<" + CRLF);
StreamWrite("/Size " + xrefTable.Count.ToString() + CRLF);
StreamWrite("/Root " + PDFObjRef(root) + CRLF);=09
if (info > 0)
{
StreamWrite("/Info " + PDFObjRef(info) + CRLF);=09
}
StreamWrite(">>"+CRLF+"startxref"+CRLF+m_StartXOffs+CRLF); //Save =
position of xref table
=09
//Specification says nothing about newline after %%EOF. Acrobat =
reader works without it
//Ghostview owever complains - since gv is used a lot on linux I =
added CRLF.
StreamWrite("%%EOF"+CRLF); //End-of-file marker
}
/// <summary>Write a Document Info object</summary>
/// <returns>Object ID of the object</returns>
private int WriteDocumentInfo() //returns Object ID of the info object
{ // Adobe Specification Paragraph 6.10
string text =3D "";
=09
//Title________________________________________________
if(Information.Title.Length > 0)
{
text +=3D "/Title (" + ConvertStrToPDF(Information.Title) + ")" + =
CRLF;
}
//Subject______________________________________________
if(Information.Subject.Length > 0)
{
text +=3D "/Subject (" +ConvertStrToPDF(Information.Subject) + ")" + =
CRLF;
}
//Author_______________________________________________
if (Information.AuthorName.Length > 0)
{ =09
text +=3D "/Author (" + ConvertStrToPDF(Information.AuthorName) + =
")" + CRLF;
}
//Creationdate_________________________________________
DateTime now =3D DateTime.Now;
TimeZone z =3D TimeZone.CurrentTimeZone;
TimeSpan t =3D z.GetUtcOffset(now);
text +=3D "/CreationDate (D:" +=20
now.ToString("yyyyMMddHHmmss") +
"+" + t.Hours.ToString("D2") + "'"+t.Minutes +"')" + CRLF;
=09
//Document Keywords____________________________________
if (Information.Keywords.Length > 0)
{ =09
text +=3D "/Keywords (" + ConvertStrToPDF(Information.Keywords) + =
")" + CRLF;
}
//Program that created the PDF document
if (Information.Creator.Length > 0)
{
text +=3D "/Creator (" + ConvertStrToPDF(Information.Creator) + ")" =
+ CRLF;
}
//Producer of the PDF document
text +=3D "/Producer (" + ConvertStrToPDF(ProductVersion) + ")";
//Write the info object________________________________
int newObjID =3D GetNewObjID();
PDFWriteObj(newObjID,true, //This object number; dictionary:<<, >> =
text); //document info
return newObjID;
}
/// <summary>Increment Object ID and return it</summary>
/// <returns>New Object ID number</returns>
private int GetNewObjID() =09
{
xrefTable.Add(0); //Increase xross reference table size [Insert ID =
in table when writing obj]
return ++m_LastObjId; //Return a new number to keep Object IDs unique
}
// /// <summary>Output the data to the file or stream</summary>
// /// <param name=3D"s">String of data to write</param>
// private void StreamWrite(string s)
// { //If we write a string, the length is first written - we DONT want =
that: make charArray
// PDFWriter.Write(s.ToCharArray());
// }
/// <summary>Normalize string so that special characters are handled =
appropriately</summary>
/// <param name=3D"s">String to normalize</param>
/// <returns>Strin after normalisation</returns>
private string ConvertStrToPDF(string s)
{ //convert "\", "(", and ")" to "\x".
string tmp=3Ds;
tmp.Replace(@"\", @"\\");
tmp.Replace(@"(", @"\(");
tmp.Replace(@")", @"\)");
tmp.Replace("\r", @"\r");
tmp.Replace("\n", @"\n");
return tmp;
}
=09
=09
/// <summary>Create colour</summary>
/// <param name=3D"c">colour to use</param>
/// <param name=3D"f">g or rg if false (fill); G or RG if true =
(stroke)</param>
/// <returns>PDF string representation</returns>
private string PDFColour(RptColour c,bool f)
{ //Adobe specification, Paragraph 8.5, 12.1
string colorstr;
if ((c.Red+c.Green+c.Blue)=3D=3D0)=20
{
if (m_IsBlack) {
colorstr =3D ""; //Conserve file size: need not repeat last color
} else {
m_IsBlack=3Dtrue;
colorstr =3D ((f)? "0 G":"0 g") + CRLF;
}
}
else=20
{
m_IsBlack=3Dfalse;
colorstr =3D String.Format("{0,4} {1,4} {2,4} {3}", =09
((double)c.Red/255),
((double)c.Green/255),
((double)c.Blue/255),
((f)? "RG":"rg") + CRLF
);
}
return (colorstr);
}
private void DrawPDFLine(int fromX, int fromY,int toX, int toY,
LineStyles style,int thickness,
RptColour clr
)
{ // Adobe Specification Paragrap 12.1
int objId=3DGetNewObjID();
int pgHeight =3D PAGE_DIMENSIONS[(int)m_PageSize,1];
string widthstr =3D "";
string colorstr=3D PDFColour(clr,true); =09
if (thickness > 1) {widthstr =3D thickness.ToString() + " w" + CRLF;}
string stylestr=3DPDFLineStyle(style); =09
PDFWriteStreamObj(objId,"",
colorstr+
widthstr + stylestr + =20
fromX.ToString() + " " +
(pgHeight-fromY).ToString() +" m" + CRLF +
toX.ToString() + " " +
(pgHeight-toY).ToString() + " l" + CRLF +
"s" + CRLF =20
);//PDFWriteObj
if (m_PageContents.Length > 0)=20
{
m_PageContents +=3D " ";
}
m_PageContents +=3D PDFObjRef(objId); =
=20
}
/// <summary>Sets line style</summary> =09
/// <returns>String to be written in PDF file</returns>
private string PDFLineStyle(LineStyles style)
{ //Adobe Specification, Paragraph 8.3
string stylestr=3D"";
switch(style)
{
case LineStyles.Dots:
m_IsSolid=3Dfalse;
stylestr=3D"[1 2] 0 d" + CRLF; //1 on 2 off=20
break;
case LineStyles.Dash:
m_IsSolid=3Dfalse;
//Adobe's spec has example of [3 3] as 3 on, 3 off, but that =
displays=20
//almost solid - had to make [3 5] or [3 6] to get decent spaces =
in-between.
stylestr=3D"[3 5] 0 d" + CRLF;
break;
//Adobe spec seems not to allow for dash-dot, etc
default:
if (m_IsSolid) {
stylestr=3D""; //save file size: need not repeat for each line
} else {
m_IsSolid=3Dtrue;
stylestr=3D"[4 0] 0 d" + CRLF;
}
break;
}
return stylestr;
}
/// <summary>Create a fill pattern object.</summary>
/// <param name=3D"pattern">Pattern to create. An Error is thrown if =
the Solid pattern is passed.</param>
/// <returns>Object ID of the pattern</returns>
private int PDFFillPattern(FillPatterns pattern)
{ //Adobe Specification Paragraph 7.17 - see example of star pattern =
(Example 7.33)
int objId =3D (int) m_Patterns[(int) pattern];
if (objId > 0) // If the pattern has been defined, we simply return =
it's Object ID
{
AddPatternToProcSet(objId,(int)pattern); //Ensure it is in current =
page's resources
return objId; //Re-use same pattern object
}=20
else //Add the pattern object to the file
{
objId=3DGetNewObjID();
//int procSetId =3D GetNewObjID();=09
//PDFWriteObj(procSetId,true,"/ProcSet [/PDF] "); //Create a ProcSet =
for the pattern
string ObjectText =3D=20
"/Type /Pattern" + CRLF + =09
"/PatternType 1" + CRLF + //Tiling pattern (smoothing not yet =
implemented)
"/Resources << >>" + CRLF + //+ PDFObjRef(procSetId) + CRLF +
"/PaintType 2" + CRLF + //Use external colour, i.e. colour not =
defined in pattern
"/TilingType 1" + CRLF ; //Pattern cells are spaced consistently
//Matrix not defined, accept default of identity matrix
=09
//Now we define the pattern in the stream part of the object
string PatternStr=3D"";
switch (pattern)
{
case FillPatterns.VertLines:
ObjectText +=3D=20
"/BBox [0 0 7 8]" + CRLF + //Pattern bounding box Spec Example =
7.33 =09
"/XStep 8" + CRLF + //Note This is differrent between Example=20
"/YStep 7"; //7.33 and 7.32 [Bitmap vs vector-drawn]
PatternStr =3D "0 0 m" + CRLF + "0 8 l" + CRLF + "s" + CRLF +
"2 0 m" + CRLF + "2 8 l" + CRLF + "s" + CRLF +
"4 0 m" + CRLF + "4 8 l" + CRLF + "s" + CRLF +
"6 0 m" + CRLF + "6 8 l" + CRLF + "s";
break;
case FillPatterns.HorizLines:
ObjectText +=3D=20
"/BBox [0 0 8 7]" + CRLF + //Pattern bounding box Spec Example =
7.33 =09
"/XStep 7" + CRLF + //Note This is differrent between Example=20
"/YStep 8"; //7.33 and 7.32 [Bitmap vs vector-drawn]
PatternStr=3D "0 0 m" + CRLF + "8 0 l" + CRLF + "s" + CRLF +
"0 2 m" + CRLF + "8 2 l" + CRLF + "s" + CRLF +
"0 4 m" + CRLF + "8 4 l" + CRLF + "s" + CRLF +
"0 6 m" + CRLF + "8 6 l" + CRLF + "s"; =09
break;
case FillPatterns.CrossLines:
ObjectText +=3D=20
"/BBox [0 0 8 8]" + CRLF + //Pattern bounding box Spec Example =
7.33 =09
"/XStep 6" + CRLF + //Note This is differrent between Example=20
"/YStep 6"; //7.33 and 7.32 [Bitmap vs vector-drawn]
PatternStr=3D "0 0 m" + CRLF + "8 0 l" + CRLF + "s" + CRLF +
"0 2 m" + CRLF + "8 2 l" + CRLF + "s" + CRLF +
"0 4 m" + CRLF + "8 4 l" + CRLF + "s" + CRLF +
"0 6 m" + CRLF + "8 6 l" + CRLF + "s" + CRLF +
//Vert
"0 0 m" + CRLF + "0 8 l" + CRLF + "s" + CRLF +
"2 0 m" + CRLF + "2 8 l" + CRLF + "s" + CRLF +
"4 0 m" + CRLF + "4 8 l" + CRLF + "s" + CRLF +
"6 0 m" + CRLF + "6 8 l" + CRLF + "s";
break;=09
case FillPatterns.DiagFwLines:
ObjectText +=3D=20
"/BBox [0 0 5 5]" + CRLF + //Pattern bounding box Spec Example =
7.33 =09
"/XStep 5" + CRLF + //Note This is differrent between Example=20
"/YStep 5"; //7.33 and 7.32 [Bitmap vs vector-drawn]
=09
PatternStr=3D "0 0 m" + CRLF + "5 5 l" + CRLF + "s" + CRLF +
"-3 3 m" + CRLF + "3 -3 l" + CRLF + "s";
break;=09
case FillPatterns.DiagBwLines:
ObjectText +=3D=20
"/BBox [0 0 5 5]" + CRLF + //Pattern bounding box Spec Example =
7.33 =09
"/XStep 5" + CRLF + //Note This is differrent between Example=20
"/YStep 5"; //7.33 and 7.32 [Bitmap vs vector-drawn]
=09
PatternStr=3D "0 5 m" + CRLF + "5 0 l" + CRLF + "s" + CRLF +
"3 -3 m" + CRLF + "-3 3 l" + CRLF + "s";
break;=09
case FillPatterns.DiagCrossLines:
ObjectText +=3D=20
"/BBox [0 0 5 5]" + CRLF + //Pattern bounding box Spec Example =
7.33 =09
"/XStep 5" + CRLF + //Note This is differrent between Example=20
"/YStep 5"; //7.33 and 7.32 [Bitmap vs vector-drawn]
=09
PatternStr=3D=20
"0 0 m" + CRLF + "5 5 l" + CRLF + "s" + CRLF +
"-3 3 m" + CRLF + "3 -3 l" + CRLF + "s"+CRLF+
"0 5 m" + CRLF + "5 0 l" + CRLF + "s" + CRLF +
"3 -3 m" + CRLF + "-3 3 l" + CRLF + "s";
break; =09
case FillPatterns.Solid:
throw new ArgumentOutOfRangeException("pattern");
}
string StreamText =3D PatternStr + CRLF; =09
PDFWriteStreamObj(objId,ObjectText,StreamText);=09
m_Patterns[(int) pattern] =3D objId;
AddPatternToProcSet(objId,(int)pattern); //Ensure it is in current =
page's resources
return objId;
}
}
private void AddPatternToProcSet(int objId,int pattern)
{ =09
string patternName =3D "/P" + pattern.ToString();
if (m_PageProcSetPatterns.IndexOf(patternName) < 0)
{
if (m_PageProcSetPatterns.Length > 0)
{
m_PageProcSetPatterns +=3D " ";
}
m_PageProcSetPatterns +=3D patternName + " " + PDFObjRef(objId);
}
}
#endregion Private functions/Methods
#region Private data members =09
private System.IO.Stream PDFOutStream; // Stream in which the PDF =
output is sent
private System.IO.StreamWriter PDFWriter;=20
private ArrayList xrefTable; =09
private string m_PageObjRefs=3D"";
private int m_StartXOffs =3D 0;
private int m_LastObjId =3D0;=09
private int m_PagesObjId=3D0;
private int m_Offset;
=09
private bool m_IsBlack=3Dtrue; //True if we do not need to repeat =
black colour
private bool m_IsSolid=3Dtrue; //True if Solid line - need not =
repeat for each line
private ArrayList m_Patterns; //List of ObjetID's, Array index =3D =
FillPatterns enum
private Hashtable m_Fonts=3Dnull; //List of all fonts used in the =
document
=09
//Create a separate Page class for te following?
private string m_PageContents=3D"";
private string m_PageProcSetPatterns=3D"";
private bool m_IsFirstPage=3Dtrue;=09
private int m_PagesCount=3D0; //Number of pages in document
private string m_PageFonts=3D""; //List of ObjectID's of fonts used =
on this page
#endregion
}
}
//END OF PDF CLASS
using System;
using System.Drawing;
using System.IO;
namespace SBReport.Export
{
public struct DocInfo
{ =09
/// <summary>
/// Title of the document. PDF files have an info object where the=20
/// document's title can be saved.=20
/// </summary>
public string Title
{
get {return m_Title; }
set {m_Title =3D value; }
}
private string m_Title;
/// <summary>
/// Subject of the document. PDF files have an info object where the=20
/// document's subject can be saved.=20
/// </summary>
public string Subject
{
get {return m_Subject; }
set {m_Subject =3D value; }
}
private string m_Subject;
/// <summary>
/// Name of document author. PDF files have an info object where the=20
/// name of the document's author can be saved.=20
/// </summary>
public string AuthorName
{
get {return m_AuthorName; }
set {m_AuthorName =3D value; }
}
private string m_AuthorName;
/// <summary>
/// Keywords for the document. PDF files have an info object where the =
/// keywords can be saved.=20
/// </summary>
public string Keywords
{
get {return m_Keywords; }
set {m_Keywords =3D value; }
}
private string m_Keywords;
/// <summary>
/// Creator of the document. PDF files have an info object where the=20
/// program name that created the document can be saved.=20
/// </summary>
public string Creator
{
get {return m_Creator; }
set {m_Creator =3D value; }
}
private string m_Creator;
}
=09
/// <summary>
/// Interface to export the report
/// </summary>
public abstract class IExportInterface
{ =09
#region properties
public DocInfo Information;
=09
///<summary>Determines the size of the page.</summary>
///<remarks>Changing this property in runtime affects all pages after
/// changing. The current page, and all new pages created after=20
/// changing this property will be in the new size,=20
/// whilst all pages that were created before changing this property, =
will
/// remain in the old size.</remarks>
public PageSizes PageSize
{
get{return m_PageSize; }
set{m_PageSize =3D value;}
}
protected PageSizes m_PageSize=3DPageSizes.pgA4;
=09
/// <summary>
/// File name to use when saving the document to a file
/// </summary>
public string FileName
{
get{return m_FileName; }
set{m_FileName=3Dvalue;}
}
protected string m_FileName=3D"";
#endregion properties
#region public methods
/// <summary>
/// Start the export, and write it to disk in the file given by the =
parameter.
/// If a file already exists with the specifiec name, the file will be =
overwritten
/// by the new exported file.
/// </summary>
/// <remarks>This function will be implemented to create a =
System.IO.FileStream=20
/// class. The remainder of the execution wil be as if BeginExport was
/// called with the stream as a parameter - see the stream version of =
this function.</remarks>
/// <param name=3D"filename">File to which we must export</param>
public void BeginExport(string filename)
{
m_FileName =3D filename;
System.IO.FileInfo fi =3D new FileInfo(filename); =09
m_fileFull=3Dfi.FullName.Substring(0,fi.FullName.LastIndexOf('.'));=20
m_fileBase=3Dfi.Name.Substring(0,fi.Name.LastIndexOf('.'));=20
m_fileExt =3Dfi.Extension; //extension part of file name
=09
CreateFileStream(filename);
OnStartDoc();
}
=09
/// <summary>
/// Start the export, and write it to a stream as given in the =
parameter.
/// </summary>
/// </summary>
/// <remarks>By exporting all output to a stream, we open up more =
possibilities
/// for exporting. To ensure compatibility, the file version of this =
function=20
/// also creates a stream for file output.
/// This function can be implemented to create a =
System.IO.BinaryWriter=20
/// with the stream as a parameter to it's constructor. All export is =
then done
/// via the binary writer to the given stream:
/// <code>
/// System.IO.FileStream MyStream;
/// System.IO.BinaryWriter MyWriter;
/// public override void BeginExport(string filename)
/// {
/// FileInfo fi =3D new FileInfo(filename);
/// if (fi.Exists) {fi.Delete();} =20
/// MyStream =3D new =
System.IO.FileStream(filename,FileMode.CreateNew);
/// BeginExport();
/// }
/// public override void BeginExport(System.IO.Stream stream)
/// {
/// MyStream =3D stream;
/// BeginExport();
/// }
/// private void BeginExport()
/// {
/// MyWriter =3D new System.IO.BinaryWriter(MyStream);
/// MyWriter.Write("Hello World".ToCharArray());=20
/// } //The EndExport function will close both the writer and the =
stream.
/// </code>
/// <param name=3D"stream">Stream to which we must export</param> =09
public void BeginExport(System.IO.Stream stream)
{
m_fileFull=3D""; //name of path+file but no extension
m_fileBase=3D""; //name of file with no extension
m_fileExt =3D""; //extension part of file name
DocOutStream =3D stream;
DocWriter =3D new =
System.IO.StreamWriter(DocOutStream,System.Text.Encoding.ASCII);
OnStartDoc();
}
/// <summary>
/// Create a new Page in the export.=20
/// </summary>
/// <remarks>All subsequent drawing will be displayed on the new page. =
/// The size of the page is set to the current value of the
/// PageSize property. The current page and all calls to NewPage=20
/// after changing PageSize will be in the new size,=20
/// whilst all pages that were created before changing PageSize, will
/// remain in the old size.
/// </remarks>
abstract public void NewPage();
/// <summary>
/// End the export by writing the proper document termination =
characters to the stream.
/// </summary>
public void EndExport()
{
OnEndDoc();
CloseStream(); =09
}
#region WriteText
///<summary>Write text on the current page. Font style is =
regular.</summary>
/// <param name=3D"text">text to be written</param>
/// <param name=3D"left">Position in pixels from left edge of =
page</param>
/// <param name=3D"top">Position in pixels from top edge of =
page</param>
/// <param name=3D"fontName">Name of font to use</param>
/// <param name=3D"fontsize">Font Size of text</param>
public void WriteText(string text,int left, int top,string =
fontName,int fontsize)
{
SBReport.Font font =3D new SBReport.Font(fontName,fontsize);
WriteText(text,left,top,font);
}
///<summary>Write text on the current page. Font style is =
regular.</summary>
/// <param name=3D"text">text to be written</param>
/// <param name=3D"left">Position in pixels from left edge of =
page</param>
/// <param name=3D"top">Position in pixels from top edge of =
page</param>
/// <param name=3D"font">Defines the font to be used</param> =09
abstract public void WriteText(string text,int left, int =
top,SBReport.Font font);
#endregion WriteText
#region DrawHLine
///<summary>Draw solid black line of width 1 on the current =
page.</summary>
/// <param name=3D"fromX">Start position in pixels from left edge of =
page</param>
/// <param name=3D"fromY">Start position in pixels from top edge of =
page</param>
/// <param name=3D"length">Width of the line measured in pixels =
(difference between line left and right)</param> =09
public void DrawHLine(int fromX, int fromY,int length)
{
LineStyles style =3D SBReport.Export.LineStyles.Solid;
SBReport.RptColour clr =3D new RptColour(0,0,0); //Black
DrawHLine(fromX,fromY,length,style,1,clr);
}
///<summary>Draw black line of specified width and style on the =
current page.</summary>
/// <param name=3D"fromX">Start position in pixels from left edge of =
page</param>
/// <param name=3D"fromY">Start position in pixels from top edge of =
page</param>
/// <param name=3D"length">Width of the line measured in pixels =
(difference between line left and right)</param>
/// <param name=3D"style">Solid, Dashed, etc</param>
/// <param name=3D"thickness">Line width</param>
public void DrawHLine(int fromX, int fromY,int length,
LineStyles style,int thickness)
{
SBReport.RptColour clr =3D new RptColour(0,0,0); //Black
DrawHLine(fromX,fromY,length,style,thickness,clr); =09
}
=09
///<summary>Draw colour line of specified width and style on the =
current page.</summary>
/// <param name=3D"fromX">Start position in pixels from left edge of =
page</param>
/// <param name=3D"fromY">Start position in pixels from top edge of =
page</param>
/// <param name=3D"length">Width of the line measured in pixels =
(difference between line left and right)</param>
/// <param name=3D"LineStyles">Solid, Dashed, etc</param>
/// <param name=3D"style">Solid, dotted, etc</param>
/// <param name=3D"thickness">Line width measured in pixels</param>
/// <param name=3D"clr">Line colour</param>
abstract public void DrawHLine(int fromX, int fromY,int length,
LineStyles style,int thickness, RptColour clr );
#endregion DrawHLine
#region DrawVLine
///<summary>Draw solid black line of width 1 on the current =
page.</summary>
/// <param name=3D"fromX">Start position in pixels from left edge of =
page</param>
/// <param name=3D"fromY">Start position in pixels from top edge of =
page</param>
/// <param name=3D"length">Height of the line measured in pixels =
(difference between line top and bottom)</param>
public void DrawVLine(int fromX, int fromY,int length)
{
LineStyles style =3D SBReport.Export.LineStyles.Solid;
SBReport.RptColour clr =3D new RptColour(0,0,0); //Black
DrawVLine(fromX,fromY,length,style,1,clr);
}
///<summary>Draw black line of specified width and style on the =
current page.</summary>
/// <param name=3D"fromX">Start position in pixels from left edge of =
page</param>
/// <param name=3D"fromY">Start position in pixels from top edge of =
page</param>
/// <param name=3D"length">Height of the line measured in pixels =
(difference between line top and bottom)</param>
/// <param name=3D"style">Solid, Dashed, etc</param>
/// <param name=3D"thickness">Line width</param>
public void DrawVLine(int fromX, int fromY,int length,
LineStyles style,int thickness)
{
SBReport.RptColour clr =3D new RptColour(0,0,0); //Black
DrawVLine(fromX,fromY,length,style,thickness,clr); =09
}
=09
///<summary>Draw colour line of specified width and style on the =
current page.</summary>
/// <param name=3D"fromX">Start position in pixels from left edge of =
page</param>
/// <param name=3D"fromY">Start position in pixels from top edge of =
page</param>
/// <param name=3D"length">Height of the line measured in pixels =
(difference between line top and bottom)</param>
/// <param name=3D"LineStyles">Solid, Dashed, etc</param>
/// <param name=3D"style">Solid, dotted, etc</param>
/// <param name=3D"thickness">Line width measured in pixels</param>
/// <param name=3D"clr">Line colour</param>
abstract public void DrawVLine(int fromX, int fromY,int length,
LineStyles style,int thickness, RptColour clr );
#endregion DrawVLine
=09
#region DrawRectangle
///<summary>Draw solid black rectanle of width 1 on the current page.
//////The rectangle is not filled (transparent).
///</summary>
/// <param name=3D"left">Start position in pixels from left edge of =
page</param>
/// <param name=3D"top">Start position in pixels from top edge of =
page</param>
/// <param name=3D"width">Distance in pixels from left edge to right =
edge of rectangle</param>
/// <param name=3D"height">Distance in pixels from top edge to bottom =
edge of rectangle</param> =09
public void DrawRectangle(int left, int top,int width, int height)
{
RptColour C=3Dnew RptColour(); //Black
=
DrawRectangle(left,top,width,height,LineStyles.Solid,1,C,null,FillPattern=
s.Solid);
}
///<summary>Draw black rectangle of specified width and style on the =
current page.
///The rectangle is not filled (transparent).
///</summary>
/// <param name=3D"left">Start position in pixels from left edge of =
page</param>
/// <param name=3D"top">Start position in pixels from top edge of =
page</param>
/// <param name=3D"width">Distance in pixels from left edge to right =
edge of rectangle</param>
/// <param name=3D"height">Distance in pixels from top edge to bottom =
edge of rectangle</param>
/// <param name=3D"style">Solid, Dashed, etc</param>
/// <param name=3D"thickness">Line width</param> =09
public void DrawRectangle(int left, int top,int width, int height,
LineStyles style,int thickness)
{
RptColour C=3Dnew RptColour(); //Black
DrawRectangle(left,top,width,height,style,thickness,C,null,
FillPatterns.Solid );
}=09
///<summary>Draw colour rectangle of specified width and style on the =
current page.
///If the fill colour is null, the rectangle is not filled. If the =
fill colour is=20
///not null, it is filled with a solid fill type of the specified =
colour.
///</summary>
/// <param name=3D"left">Start position in pixels from left edge of =
page</param>
/// <param name=3D"top">Start position in pixels from top edge of =
page</param>
/// <param name=3D"width">Distance in pixels from left edge to right =
edge of rectangle</param>
/// <param name=3D"height">Distance in pixels from top edge to bottom =
edge of rectangle</param>
/// <param name=3D"LineStyles">Solid, Dashed, etc</param>
/// <param name=3D"style">Solid, dotted, etc</param>
/// <param name=3D"thickness">Line width measured in pixels</param>
/// <param name=3D"lineClr">Line colour</param>
/// <param name=3D"fillClr">Fill colour. Pass null for no =
fill.</param>
public void DrawRectangle(int left, int top,int width, int height,
LineStyles style,int thickness, RptColour lineClr, RptColour fillClr)
{
DrawRectangle(left, top,width, height,style,thickness, =
lineClr,fillClr,FillPatterns.Solid);
}
///<summary>Draw colour rectangle of specified width and style on the =
current page.
///If the fill colour is null, the rectangle is not filled. If the =
fill colour is=20
///not null, it is filled with the specified pattern in the specified =
colour.
///</summary>
/// <param name=3D"left">Start position in pixels from left edge of =
page</param>
/// <param name=3D"top">Start position in pixels from top edge of =
page</param>
/// <param name=3D"width">Distance in pixels from left edge to right =
edge of rectangle</param>
/// <param name=3D"height">Distance in pixels from top edge to bottom =
edge of rectangle</param>
/// <param name=3D"LineStyles">Solid, Dashed, etc</param>
/// <param name=3D"style">Solid, dotted, etc</param>
/// <param name=3D"thickness">Line width measured in pixels</param>
/// <param name=3D"lineClr">Line colour</param>
/// <param name=3D"fillClr">Fill colour. Pass null for no =
fill.</param>
/// <param name=3D"pattern">Pattern to fill the box</param>
abstract public void DrawRectangle(int left, int top,int width, int =
height,
LineStyles style,int thickness, RptColour lineClr, RptColour fillClr,
FillPatterns pattern);
#endregion DrawRectangle
#endregion Public methods
#region Protected properties
/// <summary>
/// Code common to both public BeginExport methods is placed here
/// </summary>
protected abstract void OnStartDoc();
protected abstract void OnEndDoc();
=09
/// <summary>Output the data to the file or stream</summary>
/// <param name=3D"s">String of data to write</param>
protected void StreamWrite(string s)
{ //If we write a string, the length is first written - we DONT want =
that: make charArray
DocWriter.Write(s.ToCharArray());
}
/// <summary>
/// To be called by child classes when they output to more than one =
file, e.g. HTML class
/// </summary>
/// <param name=3D"fileName">File name to create</param>
protected void CreateFileStream(string fileName)
{
System.IO.FileInfo fi =3D new FileInfo(fileName);
if (fi.Exists) {fi.Delete();} =09
DocOutStream =3D new =
System.IO.FileStream(fileName,System.IO.FileMode.CreateNew);
DocWriter =3D new =
System.IO.StreamWriter(DocOutStream,System.Text.Encoding.ASCII);
}
/// <summary>
/// To be called by child classes when they output to more than one =
file, e.g. HTML class
/// </summary>
/// <param name=3D"fileName">File name to create</param>
protected void CloseStream()
{ =09
DocWriter.Close();
DocOutStream.Close();
}
=09
protected const string CRLF =3D "\r\n";
protected const string ProductVersion =3D "Seabreeze SBReports (c) =
Willem Semmelink";
protected System.IO.Stream DocOutStream; // Stream in which the HTML =
output is sent
protected System.IO.StreamWriter DocWriter; //
protected static readonly int[,] PAGE_DIMENSIONS=3D{
//PgWidth PgHeight [Pixels]
{612, 792}, //A4
{612, 792} //Letter
};
protected string m_fileFull=3D""; //name of path+file but no extension
protected string m_fileBase=3D""; //name of file with no extension
protected string m_fileExt =3D""; //extension part of file name
#endregion protected properties
}
}