۱۳۹۰/۰۴/۱۰

فارسى نويسى و iTextSharp


شرح يك سري سعي و خطا!
سعي اول:
using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;

namespace iTextSharpTests
{
class Program
{
static void Main(string[] args)
{
using (var pdfDoc = new Document(PageSize.A4))
{
PdfWriter.GetInstance(pdfDoc, new FileStream("Test.pdf", FileMode.Create));
pdfDoc.Open();

var chunk = new Chunk("آزمايش");
pdfDoc.Add(chunk);
}
}
}
}

نتيجه:



بله! هيچي!

مشكل از كجاست؟
در iTextSharp بر اساس نوع فونت انتخابي و encoding مرتبط،‌ نحوه‌ي رندر سازي حروف مشخص مي‌شود:



همانطور كه ملاحظه مي‌كنيد، فونت پايه متني كه قرار است اضافه شود، null است.

سعي دوم:
اينبار فونت را تنظيم مي‌كنيم:
using System;
using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;

namespace iTextSharpTests
{
class Program
{
static void Main(string[] args)
{
using (var pdfDoc = new Document(PageSize.A4))
{
PdfWriter.GetInstance(pdfDoc, new FileStream("Test.pdf", FileMode.Create));
pdfDoc.Open();

var fontPath = Environment.GetEnvironmentVariable("SystemRoot") + "\\fonts\\tahoma.ttf";
var baseFont = BaseFont.CreateFont(fontPath, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
var tahomaFont = new Font(baseFont, 10, Font.NORMAL, BaseColor.BLACK);

var chunk = new Chunk("آزمايش",tahomaFont);
pdfDoc.Add(chunk);
}
}
}
}

توضيحات:
متد BaseFont.CreateFont مي‌تواند مسيري از فونت مورد نظر را دريافت كند. اين حالت خصوصا براي برنامه‌هاي وب كه ممكن است فونت مورد نظر آن‌ها در سرور نصب نشده باشد، بسيار مفيد است و لزومي ندارد كه الزاما فونت مورد استفاده در پوشه fonts‌ ويندوز نصب شده باشد.
نكات مهم ديگر بكار گرفته شده در اين متد، استفاده از BaseFont.IDENTITY_H و BaseFont.EMBEDDED است. به اين صورت encoding متن، جهت نوشتن متون غير Ansi تنظيم مي‌شود و در اين حالت حتما بايد فونت را در فايل، مدفون (embed) نمود. از اين لحاظ كه عموما اين نوع فونت‌ها در سيستم‌هاي كاربران نصب نيستند.

نتيجه:



بد نيست! حداقل حروف نمايش داده شدند؛ اما نياز است تا چرخانده يا معكوس شوند. براي انجام خودكار آن حداقل دو كار را مي‌توان انجام داد.

الف) استفاده از ColumnText و اعمال تنظيمات راست به چپ آن
using System;
using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;

namespace iTextSharpTests
{
class Program
{
static void Main(string[] args)
{
using (var pdfDoc = new Document(PageSize.A4))
{
var pdfWriter = PdfWriter.GetInstance(pdfDoc, new FileStream("Test.pdf", FileMode.Create));
pdfDoc.Open();

var fontPath = Environment.GetEnvironmentVariable("SystemRoot") + "\\fonts\\tahoma.ttf";
var baseFont = BaseFont.CreateFont(fontPath, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
var tahomaFont = new Font(baseFont, 10, Font.NORMAL, BaseColor.BLACK);

ColumnText ct = new ColumnText(pdfWriter.DirectContent);
ct.RunDirection = PdfWriter.RUN_DIRECTION_RTL;
ct.SetSimpleColumn(100, 100, 500, 800, 24, Element.ALIGN_RIGHT);

var chunk = new Chunk("آزمايش", tahomaFont);

ct.AddElement(chunk);
ct.Go();
}
}
}
}

توضيحات:
در اينجا يك ColumnTex جديد تعريف و سپس خصوصيات اين ستون تنظيم شده، به همراه RunDirection آن كه اصل قضيه است. سپس chunk تعريف شده را به اين ستون اضافه كرده‌ايم.

نتيجه:



بله! كار كرد!

ب) استفاده از PdfTable و اعمال تنظيمات راست به چپ آن
using System;
using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;

namespace iTextSharpTests
{
class Program
{
static void Main(string[] args)
{
using (var pdfDoc = new Document(PageSize.A4))
{
var pdfWriter = PdfWriter.GetInstance(pdfDoc, new FileStream("Test.pdf", FileMode.Create));
pdfDoc.Open();

var fontPath = Environment.GetEnvironmentVariable("SystemRoot") + "\\fonts\\tahoma.ttf";
var baseFont = BaseFont.CreateFont(fontPath, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
var tahomaFont = new Font(baseFont, 10, Font.NORMAL, BaseColor.BLACK);

PdfPTable table = new PdfPTable(numColumns: 1);
table.RunDirection = PdfWriter.RUN_DIRECTION_RTL;
table.ExtendLastRow = true;

PdfPCell pdfCell = new PdfPCell(new Phrase("آزمايش", tahomaFont));
pdfCell.RunDirection = PdfWriter.RUN_DIRECTION_RTL;

table.AddCell(pdfCell);
pdfDoc.Add(table);
}
}
}
}

در حين استفاده از PdfTable هم لازم است تا RunDirection مربوط به خود جدول و همچنين هر سلول اضافه شده به آن به RTL تنظيم شوند.

اين نكات در هر جايي كه با اين كتابخانه سر و كار داريم بايد اعمال شوند. براي مثال:

افزودن Header به صفحات Pdf :
افزودن header در نگارش‌هاي جديد iTextSharp شامل نكته استفاده از كلاس PdfPageEventHelper به شرح زير است (و مثال‌هايي را كه در وب پيدا خواهيد كرد، هيچكدام با آخرين نگارش موجود iTextSharp كار نمي‌كنند):
using System;
using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;

namespace iTextSharpTests
{
public class PageEvents : PdfPageEventHelper
{
Font _font;
public PageEvents()
{
var fontPath = Environment.GetEnvironmentVariable("SystemRoot") + "\\fonts\\tahoma.ttf";
var baseFont = BaseFont.CreateFont(fontPath, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
_font = new Font(baseFont, 10, Font.NORMAL, BaseColor.BLACK);
}

public override void OnStartPage(PdfWriter writer, Document document)
{
base.OnStartPage(writer, document);

PdfPTable table = new PdfPTable(numColumns: 1);
table.RunDirection = PdfWriter.RUN_DIRECTION_RTL;

PdfPCell pdfCell = new PdfPCell(new Phrase("سر صفحه در صفحه: " + writer.PageNumber, _font));
pdfCell.RunDirection = PdfWriter.RUN_DIRECTION_RTL;
pdfCell.HorizontalAlignment = Element.ALIGN_CENTER;

table.AddCell(pdfCell);
document.Add(table);
}
}

class Program
{
static void Main(string[] args)
{
using (var pdfDoc = new Document(PageSize.A4))
{
var pdfWriter = PdfWriter.GetInstance(pdfDoc, new FileStream("Test.pdf", FileMode.Create));
pdfWriter.PageEvent = new PageEvents();
pdfDoc.Open();

var fontPath = Environment.GetEnvironmentVariable("SystemRoot") + "\\fonts\\tahoma.ttf";
var baseFont = BaseFont.CreateFont(fontPath, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
var tahomaFont = new Font(baseFont, 10, Font.NORMAL, BaseColor.BLACK);

PdfPTable table = new PdfPTable(numColumns: 1);
table.RunDirection = PdfWriter.RUN_DIRECTION_RTL;
table.ExtendLastRow = true;

PdfPCell pdfCell = new PdfPCell(new Phrase("آزمايش", tahomaFont));
pdfCell.RunDirection = PdfWriter.RUN_DIRECTION_RTL;

table.AddCell(pdfCell);
pdfDoc.Add(table);

pdfDoc.NewPage();
}
}
}
}

نتيجه:



تنها نكته‌اي كه اينجا اضافه شده، تعريف كلاس PageEvents است كه از كلاس PdfPageEventHelper مشتق شده است. در اين كلاس مي‌توان يك سري متد كلاس پايه را تحريف كرد و header و footer و غيره را اضافه نمود. سپس جهت اضافه كردن آن، pdfWriter.PageEvent بايد مقدار دهي شود.
در اينجا هم اگر نوع فونت، encoding و PdfTable به همراه RunDirection آن اضافه نمي‌شد، يا چيزي در header صفحه قابل مشاهده نبود يا متن مورد نظر معكوس نمايش داده مي‌شد.