Examples / text_formatting / csharp

Text Formatting

A complete, runnable csharp program — 131 lines, shipped in your download.

Demonstrates Text

Same example, other languages: activex_cpp c cpp cpp_linux delphi php python vbnet

examples/csharp/text_formatting/text_formatting.cs 131 lines
//  text_formatting -- C# port of examples\Vb6\text_formatting\text_formatting.bas
//  Lays out sample.txt into N columns using a page-break callback and writes
//  out.pdf. The combo box that selected the number of columns is replaced by a
//  constant (the form's default selection was 3 columns).
using System;
using System.IO;
using System.Text;
using System.Runtime.InteropServices;
using LumasPdfSdk;

class TextFormatting
{
    // Holds the formatting options.
    struct TOutRect
    {
        public double PosX;      // Original x-coordinate of first output rectangle
        public double PosY;      // Original y-coordinate of first output rectangle
        public double Width_;    // Original width of first output rectangle
        public double Height_;   // Original height of first output rectangle
        public double Distance;  // Space between columns
        public int Column;       // Current column
        public int ColCount;     // Number of columns
    }

    static TOutRect gRect;
    static IntPtr gPDF;

    static TErrorProc _errCb = ErrProc;
    static TOnPageBreakProc _breakCb = OnPageBreakProc;

    public static int ErrProc(IntPtr Data, int ErrCode, string ErrMessage, int ErrType)
    {
        Console.WriteLine(ErrMessage);
        return -1;                       // we break processing if an error occurred.
    }

    // Page-break callback. Places the next column or starts a new page.
    public static int OnPageBreakProc(IntPtr Data, double LastPosX, double LastPosY, bool PageBreak)
    {
        LumasPdf.pdfSetPageCoords(gPDF, (int)TPageCoord.pcTopDown);   // we use top down coordinates
        gRect.Column = gRect.Column + 1;
        // PageBreak is nonzero if the string contains a page break tag.
        if ((!PageBreak) && (gRect.Column < gRect.ColCount))
        {
            // Calculate the x-coordinate of the column
            double x = gRect.PosX + gRect.Column * (gRect.Width_ + gRect.Distance);
            // change the output rectangle, do not close the page!
            LumasPdf.pdfSetTextRect(gPDF, x, gRect.PosY, gRect.Width_, gRect.Height_);
            return 0;            // we do not change the alignment
        }
        else
        {
            // the page is full, close the current one and append a new page
            LumasPdf.pdfEndPage(gPDF);
            LumasPdf.pdfAppend(gPDF);
            LumasPdf.pdfSetTextRect(gPDF, gRect.PosX, gRect.PosY, gRect.Width_, gRect.Height_);
            gRect.Column = 0;
            return 0;
        }
    }

    static string LoadTextFile(string fileName)
    {
        if (!File.Exists(fileName)) return "";
        byte[] b = File.ReadAllBytes(fileName);
        return Encoding.Default.GetString(b);   // sample.txt is an ANSI text file
    }

    static void Main()
    {
        // The text is stored in a file. Original: ..\..\test_files\sample.txt
        string txtPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "sample.txt");
        if (!File.Exists(txtPath)) txtPath = System.IO.Path.Combine(System.AppContext.BaseDirectory, "..", "..", "..", "..", "test_files") + "\\sample.txt";
        string fText = LoadTextFile(txtPath);

        gPDF = LumasPdf.pdfNewPDF();
        LumasPdf.pdfSetOnErrorProc(gPDF, IntPtr.Zero, _errCb);
        LumasPdf.pdfSetDocInfoW(gPDF, TDocumentInfo.diCreator, "C++ test app");
        LumasPdf.pdfSetDocInfoW(gPDF, TDocumentInfo.diSubject, "Multi-column text");
        LumasPdf.pdfSetDocInfoW(gPDF, TDocumentInfo.diTitle, "Multi-column text");
        LumasPdf.pdfSetPageCoords(gPDF, (int)TPageCoord.pcTopDown);

        if (!LumasPdf.pdfCreateNewPDFW(gPDF, ""))     // The output file is opened later
        {
            LumasPdf.pdfDeletePDF(gPDF);
            return;
        }

        // Initialize the output rectangle, number of columns and so on.
        gRect.ColCount = 3;                 // Form combo default was 3 columns
        gRect.Column = 0;
        gRect.Distance = 10.0;
        gRect.PosX = 50.0;
        gRect.PosY = 50.0;
        gRect.Height_ = LumasPdf.pdfGetPageHeight(gPDF) - 100.0;
        gRect.Width_ = (LumasPdf.pdfGetPageWidth(gPDF) - 100.0 - (gRect.ColCount - 1) * gRect.Distance) / gRect.ColCount;

        // Pass the structure to the callback function (via the static field here).
        LumasPdf.pdfSetOnPageBreakProc(gPDF, IntPtr.Zero, _breakCb);
        LumasPdf.pdfAppend(gPDF);                     // Append a new page
        LumasPdf.pdfSetTextRect(gPDF, gRect.PosX, gRect.PosY, gRect.Width_, gRect.Height_);
        LumasPdf.pdfSetFontW(gPDF, "Arial", LumasPdfConsts.fsNone, 9.0, true, TCodepage.cp1252);   // A font is always required
        // NOTE: this call must stay on the *Ansi* entry point. The Delphi original declares
        // `fText: AnsiString` (Unit1.pas), so `WriteFText(taJustify, fText)` binds to the
        // AnsiString overload -> pdfWriteFTextA. sample.txt is a cp1252 file and the font was
        // created with cp1252, so the Ansi path is the faithful one; pdfWriteFTextW takes a
        // different line-breaking/justification path in the engine and repaginates the document.
        LumasPdf.pdfWriteFTextA(gPDF, LumasPdfConsts.taJustify, fText);              // Now print the text

        LumasPdf.pdfEndPage(gPDF);                    // Close the last page
        string outFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "out.pdf");
        // No fatal error occurred?
        if (LumasPdf.pdfHaveOpenDoc(gPDF))
        {
            LumasPdf.pdfSetOnErrorProc(gPDF, IntPtr.Zero, null);
            if (!LumasPdf.pdfOpenOutputFileW(gPDF, outFile))
            {
                LumasPdf.pdfDeletePDF(gPDF);
                return;
            }
            LumasPdf.pdfSetOnErrorProc(gPDF, IntPtr.Zero, _errCb);
        }
        if (LumasPdf.pdfCloseFile(gPDF))
        {
            Console.WriteLine("OK: " + outFile);
        }

        LumasPdf.pdfDeletePDF(gPDF);
    }
}

This file is in the SDK at examples/csharp/text_formatting/text_formatting.cs. The build fails if this page and that file ever differ.