using FastReport.Utils;
using System;
using System.Drawing;
using System.IO;
using System.Text;
namespace FastReport.Export.Pdf
{
public partial class PDFExport : ExportBase
{
private float GetTop(float p)
{
return marginWoBottom - p * PDF_DIVIDER;
}
private float GetLeft(float p)
{
return marginLeft + p * PDF_DIVIDER;
}
private string FloatToString(double value)
{
return ExportUtils.FloatToString(value);
}
private string FloatToStringSmart(double value)
{
if (value > 1 || value < -1)
return FloatToString(value);
if (value > 0)
{
double testValue = value;
int i;
for (i = 0; i < 6; i++)
if ((testValue *= 10) > 1)
break;
// prevent exponential format for near zero values
if (testValue < 1)
i = 0;
return FloatToString(value, i + 2);
}
if (value < 0)
{
double testValue = -value;
int i;
for (i = 0; i < 6; i++)
if ((testValue *= 10) > 1)
break;
// prevent exponential format for near zero values
if (testValue < 1)
i = 0;
return FloatToString(value, i + 2);
}
return "0";
}
private string FloatToString(double value, int digits)
{
return ExportUtils.FloatToString(value, digits);
}
private string StringToPdfUnicode(string s)
{
StringBuilder sb = new StringBuilder(s.Length * 2 + 2);
sb.Append((char)254).Append((char)255);
foreach (char c in s)
sb.Append((char)(c >> 8)).Append((char)(c & 0xFF));
return sb.ToString();
}
private void PrepareString(string text, byte[] key, bool encode, long id, StringBuilder sb)
{
string s = encode ? RC4CryptString(StringToPdfUnicode(text), key, id) : StringToPdfUnicode(text);
if (PdfCompliance == PdfStandard.PdfA_1a)
{
s = encode ? RC4CryptString(text, key, id) : text;
}
sb.Append("(");
EscapeSpecialChar(s, sb);
sb.Append(")");
}
private void Write(Stream stream, string value)
{
stream.Write(ExportUtils.StringToByteArray(value), 0, value.Length);
}
private void WriteLn(Stream stream, string value)
{
stream.Write(ExportUtils.StringToByteArray(value), 0, value.Length);
stream.WriteByte(0x0d);
stream.WriteByte(0x0a);
}
private void StrToUTF16(string str, StringBuilder sb)
{
if (!string.IsNullOrEmpty(str))
{
sb.Append("FEFF");
foreach (char c in str)
sb.Append(((int)c).ToString("X4"));
}
}
private void EscapeSpecialChar(string input, StringBuilder sb)
{
for (int i = 0; i < input.Length; i++)
{
switch (input[i])
{
case '(':
sb.Append(@"\(");
break;
case ')':
sb.Append(@"\)");
break;
case '\\':
sb.Append(@"\\");
break;
case '\r':
sb.Append(@"\r");
break;
case '\n':
sb.Append(@"\n");
break;
default:
sb.Append(input[i]);
break;
}
}
}
private float GetBaseline(Font f)
{
float baselineOffset = f.SizeInPoints / f.FontFamily.GetEmHeight(f.Style) * f.FontFamily.GetCellAscent(f.Style);
return DrawUtils.ScreenDpi / 72f * baselineOffset;
}
private void GetPDFFillColor(Color color, StringBuilder sb)
{
GetPDFFillTransparent(color, sb);
if (ColorSpace == PdfColorSpace.CMYK)
{
GetCMYKColor(color, sb);
sb.AppendLine(" k");
}
else if (ColorSpace == PdfColorSpace.RGB)
{
GetPDFColor(color, sb);
sb.AppendLine(" rg");
}
}
private void GetPDFFillTransparent(Color color, StringBuilder sb)
{
string value = FloatToString((float)color.A / 255f);
int i = trasparentStroke.IndexOf(value);
if (i == -1)
{
trasparentStroke.Add(value);
i = trasparentStroke.Count - 1;
}
sb.Append("/GS").Append(i).AppendLine("S gs");
}
private void GetPDFStrokeColor(Color color, StringBuilder sb)
{
GetPDFStrokeTransparent(color, sb);
if (ColorSpace == PdfColorSpace.CMYK)
{
GetCMYKColor(color, sb);
sb.AppendLine(" K");
}
else if (ColorSpace == PdfColorSpace.RGB)
{
GetPDFColor(color, sb);
sb.AppendLine(" RG");
}
}
private void GetPDFStrokeTransparent(Color color, StringBuilder sb)
{
string value = FloatToString((float)color.A / 255f);
if (PdfCompliance == PdfStandard.PdfA_1a)
{
value = "1";
}
int i = trasparentFill.IndexOf(value);
if (i == -1)
{
trasparentFill.Add(value);
i = trasparentFill.Count - 1;
}
sb.Append("/GS").Append(i).AppendLine("F gs");
}
private void GetPDFColor(Color color, StringBuilder sb)
{
if (color == Color.Black)
sb.Append("0 0 0");
else if (color == Color.White)
sb.Append("1 1 1");
else
{
sb.Append(FloatToString((float)color.R / 255f, 3)).Append(" ").
Append(FloatToString((float)color.G / 255f, 3)).Append(" ").
Append(FloatToString((float)color.B / 255f, 3));
}
}
private void GetCMYKColor(Color color, StringBuilder sb)
{
if (color == Color.Black)
sb.Append("0 0 0 1");
else if (color == Color.White)
sb.Append("0 0 0 0");
else
{
CMYKColor cmyk = new CMYKColor(color);
sb.Append(FloatToString((float)cmyk.c / 100f, 3)).Append(" ").
Append(FloatToString((float)cmyk.m / 100f, 3)).Append(" ").
Append(FloatToString((float)cmyk.y / 100f, 3)).Append(" ").
Append(FloatToString((float)cmyk.k / 100f, 3));
}
}
private bool FontEquals(Font font1, Font font2)
{
// 20200415 - Underline and strikeout styles should not be considered as different fonts
FontStyle style1 = font1.Style & (FontStyle.Regular | FontStyle.Bold | FontStyle.Italic);
FontStyle style2 = font2.Style & (FontStyle.Regular | FontStyle.Bold | FontStyle.Italic);
return (font1.Name == font2.Name) && style1.Equals(style2);
}
private string PrepXRefPos(long p)
{
string pos = p.ToString();
return new string('0', 10 - pos.Length) + pos;
}
private string ObjNumber(long FNumber)
{
return String.Concat(FNumber.ToString(), " 0 obj");
}
private string ObjNumberRef(long FNumber)
{
return String.Concat(FNumber.ToString(), " 0 R");
}
private long UpdateXRef()
{
xRef.Add(pdf.Position);
return xRef.Count;
}
///
/// Update stream position for object number, only for int value
///
/// int value
private void UpdateXRef(long objectNumber)
{
xRef[(int)(objectNumber - 1)] = pdf.Position;
}
private void WritePDFStream(Stream target, Stream source, long id, bool compress, bool encrypt, bool startingBrackets, bool endingBrackets)
{
WritePDFStream(target, source, id, compress, encrypt, startingBrackets, endingBrackets, false);
}
private void WritePDFStream(Stream target, Stream source, long id, bool compress, bool encrypt, bool startingBrackets, bool endingBrackets, bool enableLength1)
{
MemoryStream tempStream;
if (startingBrackets)
WriteLn(target, "<<");
using (tempStream = new MemoryStream())
{
if (compress)
{
ExportUtils.ZLibDeflate(source, tempStream);
WriteLn(pdf, "/Filter /FlateDecode");
}
else
{
source.CopyTo(tempStream, (int)source.Length);
tempStream.Position = 0;
}
WriteLn(pdf, "/Length " + tempStream.Length.ToString());
if (enableLength1)
WriteLn(pdf, "/Length1 " + source.Length.ToString());
if (endingBrackets)
WriteLn(target, ">>");
else
WriteLn(target, "");
WriteLn(target, "stream");
if (encrypt)
RC4CryptStream(tempStream, target, encKey, id);
else
tempStream.WriteTo(target);
target.WriteByte(0x0a);
WriteLn(target, "endstream");
WriteLn(target, "endobj");
}
}
}
}