123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315 |
- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.Drawing;
- using System.IO;
- using FastReport.Utils;
- using FastReport.Export;
- using FastReport.Preview;
- using FastReport.Export.TTF;
- using System.Text.RegularExpressions;
- namespace FastReport.Export.Pdf
- {
- internal class PDFExportAnnotation
- {
- public long reference;
- public string rect;
- public string hyperlink;
- public int destPage;
- public int destY;
- }
- public partial class PDFExport : ExportBase
- {
- private List<PDFExportAnnotation> annots;
- private StringBuilder pageAnnots;
- private string GetPageAnnots()
- {
- return "/Annots [ " + pageAnnots.ToString() + "]";
- }
- private void WriteAnnots()
- {
- foreach (PDFExportAnnotation annot in annots)
- {
- xRef[(int)annot.reference - 1] = pdf.Position;
- WriteLn(pdf, ObjNumber(annot.reference));
- WriteLn(pdf, "<<");
- WriteLn(pdf, "/Type /Annot");
- WriteLn(pdf, "/Subtype /Link");
- if (isPdfA())
- WriteLn(pdf, "/F 4");
- WriteLn(pdf, "/Rect [" + annot.rect + "]");
- if (!isPdfX() && !String.IsNullOrEmpty(annot.hyperlink))
- {
- WriteLn(pdf, "/BS << /W 0 >>");
- WriteLn(pdf, "/A <<");
- WriteLn(pdf, "/URI (" + annot.hyperlink + ")");
- WriteLn(pdf, "/Type /Action");
- WriteLn(pdf, "/S /URI");
- WriteLn(pdf, ">>");
- }
- else
- {
- WriteLn(pdf, "/Border [16 16 0]");
- if (annot.destPage < pagesRef.Count)
- {
- WriteLn(pdf, "/Dest [" + pagesRef[annot.destPage].ToString() +
- " 0 R /XYZ null " + ((int)(pagesHeights[annot.destPage] - annot.destY)).ToString() + " null]");
- }
- }
- WriteLn(pdf, ">>");
- WriteLn(pdf, "endobj");
- }
- }
- private void AddAnnot(ReportComponentBase obj)
- {
- if (obj is TextObject textObject && Regex.IsMatch(textObject.Text, @"\bhttps?://\S+"))
- obj.Hyperlink.Value = Regex.Replace(textObject.Text, "<.*?>", string.Empty);
- if ((obj.Hyperlink.Kind == HyperlinkKind.Bookmark ||
- obj.Hyperlink.Kind == HyperlinkKind.PageNumber ||
- obj.Hyperlink.Kind == HyperlinkKind.URL) && !String.IsNullOrEmpty(obj.Hyperlink.Value))
- {
- string Left = FloatToString(GetLeft(obj.AbsLeft));
- string Top = FloatToString(GetTop(obj.AbsTop));
- string Right = FloatToString(GetLeft(obj.AbsLeft + obj.Width));
- string Bottom = FloatToString(GetTop(obj.AbsTop + obj.Height));
- string rect = Left + " " + Bottom + " " + Right + " " + Top;
- long reference = UpdateXRef();
- pageAnnots.Append(ObjNumberRef(reference)).Append(" ");
- PDFExportAnnotation annot = new PDFExportAnnotation();
- annot.reference = reference;
- annot.rect = rect;
- annots.Add(annot);
- switch (obj.Hyperlink.Kind)
- {
- case HyperlinkKind.URL:
- try
- {
- Uri uri = new Uri(obj.Hyperlink.Value);
- annot.hyperlink = uri.AbsoluteUri;
- }
- catch (Exception)
- { }
- //annot.hyperlink = obj.Hyperlink.Value.Replace("\\", "\\\\");
- break;
- case HyperlinkKind.Bookmark:
- Bookmarks.BookmarkItem bookmark = Report.PreparedPages.Bookmarks.Find(obj.Hyperlink.Value);
- if (bookmark != null)
- {
- annot.destPage = bookmark.pageNo;
- annot.destY = (int)(bookmark.offsetY * PDF_DIVIDER);
- }
- break;
- case HyperlinkKind.PageNumber:
- annot.destPage = int.Parse(obj.Hyperlink.Value) - 1;
- annot.destY = 0;
- break;
- }
- }
- }
- private void AddTextField(TextObject obj, long defaultValueXref)
- {
- StringBuilder sb = new StringBuilder();
- string Left = FloatToString(GetLeft(obj.AbsLeft + obj.Padding.Left));
- string Top = FloatToString(GetTop(obj.AbsTop + obj.Padding.Top));
- string Right = FloatToString(GetLeft(obj.AbsLeft + obj.Width - obj.Padding.Right));
- string Bottom = FloatToString(GetTop(obj.AbsTop + obj.Height - obj.Padding.Bottom));
- int ObjectFontNumber = GetObjFontNumberAcroForm(obj.Font);
- ExportTTFFont pdffont = fonts[ObjectFontNumber];
- pdffont.Editable = true;
- AppendFontAcroForm(sb, ObjectFontNumber, obj.Font.Size, obj.TextColor);
- if (!acroFormsFonts.Contains(ObjectFontNumber))
- acroFormsFonts.Add(ObjectFontNumber);
- long xref = UpdateXRef();
- //FAcroFormsAnnotsRefs.Add(xref);
- acroFormsRefs.Add(xref);
- pageAnnots.Append(ObjNumberRef(xref)).Append(" ");
- WriteLn(pdf, ObjNumber(xref));
- WriteLn(pdf, "<<");
- WriteLn(pdf, "/Type /Annot /Subtype /Widget /F 4");
- Write(pdf, "/FT /Tx " + (obj.VertAlign != VertAlign.Center ? "/Ff 4096 " : "") + "/H /N ");// /MK << >> ");
- if (defaultValueXref >= 0)
- {
- Write(pdf, "/AP << /N " + ObjNumberRef(defaultValueXref) + " >>");
- }
- StringBuilder text = new StringBuilder(obj.Text.Length);
- StrToUTF16(obj.Text, text);
- string align = "0";
- if (obj.HorzAlign == HorzAlign.Center) align = "1";
- else if (obj.HorzAlign == HorzAlign.Right) align = "2";
- Write(pdf, " /DA ( " + sb.ToString() + " ) /Q " + align + " /Rect [ " + Left + " " + Bottom + " " + Right + " " + Top + " ] /T (" + obj.Name + acroFormsRefs.Count + ") /V <" + text.ToString() + "> ");
- WriteLn(pdf, ">>");
- WriteLn(pdf, "endobj");
- //<< /AP << /N 10 0 R >> /DA (/Helv 8.64 Tf 0 g) /F 4 /FT /Tx /MK << >> /P 8 0 R /Q 0 /Rect [ 123.12 691.2 284.4 726.48 ] /Subtype /Widget /T (untitled1) >>
- }
- private void AddCheckBoxField(CheckBoxObject obj)
- {
- bool chk = obj.Checked;
- string Left = FloatToString(GetLeft(obj.AbsLeft));
- string Top = FloatToString(GetTop(obj.AbsTop));
- string Right = FloatToString(GetLeft(obj.AbsLeft + obj.Width));
- string Bottom = FloatToString(GetTop(obj.AbsTop + obj.Height));
- obj.Checked = true;
- long yesXRef1 = AddCheckBox(obj);
- obj.Checked = false;
- long offXRef1 = AddCheckBox(obj);
- obj.Checked = chk;
- //ExportTTFFont font;
- ////TODO font kludge
- //if (FFonts.Count == 0)
- //{
- // font = GetGlobalFont(new Font(FontFamily.GenericSansSerif, 12));
- // font.Reference = UpdateXRef();
- // font.Saved = true;
- //}
- //else
- // font = FFonts[0];
- long xref = UpdateXRef();
- //FAcroFormsAnnotsRefs.Add(xref);
- acroFormsRefs.Add(xref);
- pageAnnots.Append(ObjNumberRef(xref)).Append(" ");
- WriteLn(pdf, ObjNumber(xref));
- WriteLn(pdf, "<<");
- WriteLn(pdf, "/Type /Annot /Subtype /Widget /F 4");
- WriteLn(pdf, "/AP << /N << /Off " + ObjNumberRef(offXRef1) + " /Yes " + ObjNumberRef(yesXRef1) + " >>" /*+" /D << /Off " + ObjNumberRef(offXRef1) + " /Yes " + ObjNumberRef(yesXRef2) + " >>"*/ + " >> ");
- Write(pdf, "/FT /Btn /H /N ");// /DA (" + font.Name + " " + FloatToString(12) + " Tf 0 g)");
- Write(pdf, " " + (chk ? "/AS /Yes" : "/AS /Off") + " /Rect [ " + Left + " " + Bottom + " " + Right + " " + Top + " ] /T (" + obj.Name + acroFormsRefs.Count + ") " + (chk ? "/V /Yes" : "/V /Off"));
- WriteLn(pdf, ">>");
- WriteLn(pdf, "endobj");
- // /F 4 /FT /Btn /H /P /MK << /CA (4) >> >>
- }
- const string mark = "\u2714";
- private long AddCheckBox(CheckBoxObject obj)
- {
- StringBuilder sb_in = new StringBuilder();
- long imageIndex = AddPictureObject(obj, true, jpegQuality, sb_in, true);
- string Width = FloatToString(obj.Width * PDF_DIVIDER);
- string Height = FloatToString(obj.Height * PDF_DIVIDER);
- long xref = UpdateXRef();
- WriteLn(pdf, ObjNumber(xref));
- WriteLn(pdf, "<< /BBox [ 0 0 " + Width + " " + Height + " ] /Resources << /XObject << " + (imageIndex < 0 ? "" : "/Im" + imageIndex + " " + ObjNumberRef(imageIndex)) + " >> /ProcSet [ /PDF /Text /ImageC /ImageI /ImageB ] >> /Subtype /Form /Type /XObject ");
- using (MemoryStream ms = new MemoryStream(ExportUtils.StringToByteArray(sb_in.ToString())))
- WritePDFStream(pdf, ms, 0, false, false, false, true);
- //<< /BBox [ 0 0 163.44002 101.51996 ] /Resources << /Font << /Verdana,Bold 6 0 R >> /ProcSet [ /PDF /Text ] >> /Subtype /Form /Type /XObject /Length 98 >>
- return xref;
- }
- private long AddTextDefaultValueForEditable(TextObject obj)
- {
- if (!String.IsNullOrEmpty(obj.Text))
- {
- //TODO for forms
- if (obj.VertAlign != VertAlign.Center)
- obj.VertAlign = VertAlign.Top;
- obj.Angle = 0;
- string Width = FloatToString(obj.Width * PDF_DIVIDER);
- string Height = FloatToString(obj.Height * PDF_DIVIDER);
- StringBuilder sb = new StringBuilder();
- int ObjectFontNumber = GetObjFontNumber(obj.Font);
- RectangleF textRect = new RectangleF(
- 0,
- 0,
- obj.Width - obj.Padding.Horizontal,
- obj.Height - obj.Padding.Vertical);
- if (!pageFonts[ObjectFontNumber].Saved)
- {
- pageFonts[ObjectFontNumber].Reference = UpdateXRef();
- pageFonts[ObjectFontNumber].Saved = true;
- }
- sb.AppendLine("/Tx BMC");
- if (!obj.HasHtmlTags)
- AppendFont(sb, ObjectFontNumber, obj.Font.Size, obj.TextColor);
- AddTextObjectInternal(obj, textRect, false, sb, true);
- sb.AppendLine("EMC");
- long xref = UpdateXRef();
- WriteLn(pdf, ObjNumber(xref));
- int fontnumber = GetObjFontNumberAcroForm(obj.Font);
- ExportTTFFont font = fonts[fontnumber];
- //todo make BBOX without fill page
- WriteLn(pdf, "<< /BBox [ 0 0 " + Width + " " + Height + " ] /Resources << /Font << " + font.Name + " " + ObjNumberRef(font.Reference) + " >> /ProcSet [ /PDF /Text ] >> /Subtype /Form /Type /XObject ");
- using (MemoryStream ms = new MemoryStream(ExportUtils.StringToByteArray(sb.ToString())))
- WritePDFStream(pdf, ms, 0, false, false, false, true);
- //<< /BBox [ 0 0 163.44002 101.51996 ] /Resources << /Font << /Verdana,Bold 6 0 R >> /ProcSet [ /PDF /Text ] >> /Subtype /Form /Type /XObject /Length 98 >>
- return xref;
- }
- return -1;
- }
- private long AddAcroForm()
- {
- if (acroFormsRefs.Count > 0)
- {
- long acroForm = UpdateXRef();
- WriteLn(pdf, ObjNumber(acroForm));
- Write(pdf, "<< /SigFlags 3 /DR << /Font <<");
- foreach (int fontnumber in acroFormsFonts)
- {
- ExportTTFFont font = fonts[fontnumber];
- Write(pdf, font.Name + " " + ObjNumberRef(font.Reference) + " ");
- }
- Write(pdf, ">> >> /Fields [ ");
- foreach (long val in acroFormsRefs)
- {
- Write(pdf, ObjNumberRef(val));
- Write(pdf, " ");
- }
- WriteLn(pdf, "] >>");
- WriteLn(pdf, "endobj");
- //<< /DR << /Font << /Verdana,Bold 6 0 R >> >> << /Font << /Helv 6 0 R >> >> /Fields [ 7 0 R ] >>
- return acroForm;
- }
- return -1;
- }
- }
- }
|