From 5f62c22d3c687a7b4f075d0227839e3ffffd382a Mon Sep 17 00:00:00 2001 From: cmurialdo Date: Thu, 8 Jun 2023 18:19:16 -0300 Subject: [PATCH 01/17] Add support for itext8 and .NET --- .../GxPdfReportsCS/GlobalSuppressions.cs | 2 + .../GxPdfReportsCS/GxPdfReportsCS.csproj | 9 +- .../GxPdfReportsCS/PDFReportItext7.cs | 1242 ++++++++++++ .../GxClasses/Core/gxconfig.cs | 23 + .../dotnetframework/GxClasses/Model/gxproc.cs | 6 +- .../{PDFReportItext.cs => PDFReportCommon.cs} | 1659 ++--------------- .../GxPdfReportsCS/PDFReportItext4.cs | 1504 +++++++++++++++ .../GxPdfReportsCS/PdfReportInterface.cs | 2 +- .../DotNetCoreUnitTest.csproj | 1 + .../test/DotNetUnitTest/PDF/apdfbasictest.cs | 131 +- 10 files changed, 2991 insertions(+), 1588 deletions(-) create mode 100644 dotnet/src/dotnetcore/GxPdfReportsCS/PDFReportItext7.cs rename dotnet/src/dotnetframework/GxPdfReportsCS/{PDFReportItext.cs => PDFReportCommon.cs} (52%) create mode 100644 dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportItext4.cs diff --git a/dotnet/src/dotnetcore/GxPdfReportsCS/GlobalSuppressions.cs b/dotnet/src/dotnetcore/GxPdfReportsCS/GlobalSuppressions.cs index 37a5076e3..dc00e11aa 100644 --- a/dotnet/src/dotnetcore/GxPdfReportsCS/GlobalSuppressions.cs +++ b/dotnet/src/dotnetcore/GxPdfReportsCS/GlobalSuppressions.cs @@ -16,3 +16,5 @@ [assembly: SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "", Scope = "member", Target = "~M:com.genexus.reports.NativeSharpFunctionsMS.getRegistrySubValues(System.String,System.String)~System.Collections.ArrayList")] [assembly: SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "", Scope = "member", Target = "~M:com.genexus.reports.NativeSharpFunctionsMS.ReadRegKey(System.String)~System.String")] [assembly: SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "", Scope = "member", Target = "~M:com.genexus.reports.MSPDFFontDescriptor.getTrueTypeFontLocation(System.String)~System.String")] +[assembly: SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "", Scope = "member", Target = "~M:com.genexus.reports.PDFReportItextBase.getAcrobatLocation~System.String")] +[assembly: SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "", Scope = "member", Target = "~M:com.genexus.reports.PDFReportItextBase.loadSubstituteTable")] diff --git a/dotnet/src/dotnetcore/GxPdfReportsCS/GxPdfReportsCS.csproj b/dotnet/src/dotnetcore/GxPdfReportsCS/GxPdfReportsCS.csproj index 6f996b82c..5e2f26883 100644 --- a/dotnet/src/dotnetcore/GxPdfReportsCS/GxPdfReportsCS.csproj +++ b/dotnet/src/dotnetcore/GxPdfReportsCS/GxPdfReportsCS.csproj @@ -9,11 +9,16 @@ - + + - + + + + + all diff --git a/dotnet/src/dotnetcore/GxPdfReportsCS/PDFReportItext7.cs b/dotnet/src/dotnetcore/GxPdfReportsCS/PDFReportItext7.cs new file mode 100644 index 000000000..28db803e7 --- /dev/null +++ b/dotnet/src/dotnetcore/GxPdfReportsCS/PDFReportItext7.cs @@ -0,0 +1,1242 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Text; +using GeneXus; +using iText.Barcodes; +using iText.Html2pdf; +using iText.Html2pdf.Resolver.Font; +using iText.IO.Font; +using iText.IO.Font.Otf; +using iText.IO.Image; +using iText.Kernel.Colors; +using iText.Kernel.Exceptions; +using iText.Kernel.Font; +using iText.Kernel.Geom; +using iText.Kernel.Pdf; +using iText.Kernel.Pdf.Action; +using iText.Kernel.Pdf.Canvas; +using iText.Layout; +using iText.Layout.Borders; +using iText.Layout.Element; +using iText.Layout.Font; +using iText.Layout.Properties; +using log4net; +using NetTopologySuite.Utilities; +using Path = System.IO.Path; +using Text = iText.Layout.Element.Text; + +namespace GeneXus.Printer +{ + + public class GxReportBuilderPdf7 : GxReportBuilderPdf + { + static ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + public GxReportBuilderPdf7() { } + public GxReportBuilderPdf7(string appPath, Stream outputStream) + { + + _pdfReport = new com.genexus.reports.PDFReportItextSharp7(appPath); + if (outputStream != null) + { + + _pdfReport.setOutputStream(outputStream); + GXLogging.Debug(log, "GxReportBuilderPdf outputStream: binaryWriter"); + } + } + } + +} +namespace com.genexus.reports +{ + + public class PDFReportItextSharp7 : PDFReportItextBase + { + + static ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + //const int ASCENT_NORMALIZED_UNITS = 1000; + + private PageSize pageSize; + private PdfFont baseFont; + private Style fontStyle; + //Color for, BaseColor for => Itext5 + private Color backColor, foreColor, templateColorFill; + private Document document; + PdfDocument pdfDocument; + private PdfPage pdfPage; + private PdfWriter writer; + private Rectangle templateRectangle; + private float templatex, templatey; + private PdfFont templateFont; + internal Dictionary documentImages; + TextAlignment justifiedType; + Barcode128 barcode; + int ASCENT_CHAR_A = 65; + float ITEXT_DEFAULT_UNDERLINE_THICKNESS = 0.75f; + public PDFReportItextSharp7(String appPath) : base(appPath) + { + documentImages = new Dictionary(); + } + protected override void init(ref int gxYPage, ref int gxXPage, int pageWidth, int pageLength) + { + this.pageSize = ComputePageSize(leftMargin, topMargin, pageWidth, pageLength, props.getBooleanGeneralProperty(Const.MARGINS_INSIDE_BORDER, Const.DEFAULT_MARGINS_INSIDE_BORDER)); + gxXPage = (int)this.pageSize.GetRight(); + if (props.getBooleanGeneralProperty(Const.FIX_SAC24437, true)) + gxYPage = (int)(pageLength / GX_PAGE_SCALE_Y); + else + gxYPage = (int)(pageLength / GX_PAGE_SCALE_Y_OLD); + + if (props.getBooleanGeneralProperty(Const.JUSTIFIED_TYPE_ALL, false)) + justifiedType = TextAlignment.JUSTIFIED_ALL; + else + justifiedType = TextAlignment.JUSTIFIED; + + writer = new PdfWriter(outputStream); + writer.SetCompressionLevel(CompressionConstants.BEST_COMPRESSION); + try + { + pdfDocument = new PdfDocument(writer); + pdfDocument.SetDefaultPageSize(this.pageSize); + document = new Document(pdfDocument); + + } + catch (PdfException de) + { + GXLogging.Debug(log, "GxDrawRect error", de); + } + } + + + + /** + * @param hideCorners indicates whether corner triangles should be hidden when the side that joins them is hidden. + */ + + private void drawRectangle(PdfCanvas cb, float x, float y, float w, float h, + int styleTop, int styleBottom, int styleRight, int styleLeft, + float radioTL, float radioTR, float radioBL, float radioBR, float penAux, bool hideCorners) + { + + float[] dashPatternTop = getDashedPattern(styleTop); + float[] dashPatternBottom = getDashedPattern(styleBottom); + float[] dashPatternLeft = getDashedPattern(styleLeft); + float[] dashPatternRight = getDashedPattern(styleRight); + + //-------------------bottom line--------------------- + if (styleBottom != STYLE_NONE_CONST) + { + cb.SetLineDash(dashPatternBottom, 0); + } + + float b = 0.4477f; + if (radioBL > 0) + { + cb.MoveTo(x + radioBL, y); + } + else + { + if (hideCorners && styleLeft == STYLE_NONE_CONST && radioBL == 0) + { + cb.MoveTo(x + penAux, y); + } + else + { + cb.MoveTo(x, y); + } + } + + //-------------------bottom right corner--------------------- + + if (styleBottom != STYLE_NONE_CONST) + { + if (hideCorners && styleRight == STYLE_NONE_CONST && radioBR == 0) + { + cb.LineTo(x + w - penAux, y); + } + else + { + cb.LineTo(x + w - radioBR, y); + } + if (radioBR > 0 && styleRight != STYLE_NONE_CONST) + { + cb.CurveTo(x + w - radioBR * b, y, x + w, y + radioBR * b, x + w, y + radioBR); + } + } + + //-------------------right line--------------------- + + if (styleRight != STYLE_NONE_CONST && dashPatternRight != dashPatternBottom) + { + cb.Stroke(); + cb.SetLineDash(dashPatternRight, 0); + if (hideCorners && styleBottom == STYLE_NONE_CONST && radioBR == 0) + { + cb.MoveTo(x + w, y + penAux); + } + else + { + cb.MoveTo(x + w, y + radioBR); + } + } + + //-------------------top right corner--------------------- + if (styleRight != STYLE_NONE_CONST) + { + if (hideCorners && styleTop == STYLE_NONE_CONST && radioTR == 0) + { + cb.LineTo(x + w, y + h - penAux); + } + else + { + cb.LineTo(x + w, y + h - radioTR); + } + if (radioTR > 0 && styleTop != STYLE_NONE_CONST) + { + cb.CurveTo(x + w, y + h - radioTR * b, x + w - radioTR * b, y + h, x + w - radioTR, y + h); + } + } + + //-------------------top line--------------------- + + if (styleTop != STYLE_NONE_CONST && dashPatternTop != dashPatternRight) + { + cb.Stroke(); + cb.SetLineDash(dashPatternTop, 0); + if (hideCorners && styleRight == STYLE_NONE_CONST && radioTR == 0) + { + cb.MoveTo(x + w - penAux, y + h); + } + else + { + cb.MoveTo(x + w - radioTR, y + h); + } + } + + //-------------------top left corner--------------------- + if (styleTop != STYLE_NONE_CONST) + { + if (hideCorners && styleLeft == STYLE_NONE_CONST && radioTL == 0) + { + cb.LineTo(x + penAux, y + h); + } + else + { + cb.LineTo(x + radioTL, y + h); + } + if (radioTL > 0 && styleLeft != STYLE_NONE_CONST) + { + cb.CurveTo(x + radioTL * b, y + h, x, y + h - radioTL * b, x, y + h - radioTL); + } + } + + //-------------------left line--------------------- + + if (styleLeft != STYLE_NONE_CONST && dashPatternLeft != dashPatternTop) + { + cb.Stroke(); + cb.SetLineDash(dashPatternLeft, 0); + if (hideCorners && styleTop == STYLE_NONE_CONST && radioTL == 0) + { + cb.MoveTo(x, y + h - penAux); + } + else + { + cb.MoveTo(x, y + h - radioTL); + } + } + + //-------------------bottom left corner--------------------- + if (styleLeft != STYLE_NONE_CONST) + { + if (hideCorners && styleBottom == STYLE_NONE_CONST && radioBL == 0) + { + cb.LineTo(x, y + penAux); + } + else + { + cb.LineTo(x, y + radioBL); + } + if (radioBL > 0 && styleBottom != STYLE_NONE_CONST) + { + cb.CurveTo(x, y + radioBL * b, x + radioBL * b, y, x + radioBL, y); + } + } + cb.Stroke(); + + } + private void roundRectangle(PdfCanvas cb, float x, float y, float w, float h, + float radioTL, float radioTR, float radioBL, float radioBR) + { + //-------------------bottom line--------------------- + + + float b = 0.4477f; + if (radioBL > 0) + { + cb.MoveTo(x + radioBL, y); + } + else + { + cb.MoveTo(x, y); + } + + //-------------------bottom right corner--------------------- + + cb.LineTo(x + w - radioBR, y); + if (radioBR > 0) + { + cb.CurveTo(x + w - radioBR * b, y, x + w, y + radioBR * b, x + w, y + radioBR); + } + + + cb.LineTo(x + w, y + h - radioTR); + if (radioTR > 0) + { + cb.CurveTo(x + w, y + h - radioTR * b, x + w - radioTR * b, y + h, x + w - radioTR, y + h); + } + + cb.LineTo(x + radioTL, y + h); + if (radioTL > 0) + { + cb.CurveTo(x + radioTL * b, y + h, x, y + h - radioTL * b, x, y + h - radioTL); + } + cb.LineTo(x, y + radioBL); + if (radioBL > 0) + { + cb.CurveTo(x, y + radioBL * b, x + radioBL * b, y, x + radioBL, y); + } + } + public override void GxDrawRect(int left, int top, int right, int bottom, int pen, int foreRed, int foreGreen, int foreBlue, int backMode, int backRed, int backGreen, int backBlue, + int styleTop, int styleBottom, int styleRight, int styleLeft, int cornerRadioTL, int cornerRadioTR, int cornerRadioBL, int cornerRadioBR) + { + Color rectBackColor = new DeviceRgb(backRed, backGreen, backBlue); + Color rectForeColor = new DeviceRgb(foreRed, foreGreen, foreBlue); + GxDrawRect(left, top, right, bottom, pen, rectForeColor, backMode, rectBackColor, styleTop, styleBottom, styleRight, styleLeft, cornerRadioTL, cornerRadioTR, cornerRadioBL, cornerRadioBR); + } + void GxDrawRect(int left, int top, int right, int bottom, int pen, Color foreColor, int backMode, Color backColor, + int styleTop, int styleBottom, int styleRight, int styleLeft, int cornerRadioTL, int cornerRadioTR, int cornerRadioBL, int cornerRadioBR) + { + PdfCanvas cb = new PdfCanvas(pdfPage); + + float penAux = (float)convertScale(pen); + float rightAux = (float)convertScale(right); + float bottomAux = (float)convertScale(bottom); + float leftAux = (float)convertScale(left); + float topAux = (float)convertScale(top); + GXLogging.Debug(log, "GxDrawRect -> (" + left + "," + top + ") - (" + right + "," + bottom + ") BackMode: " + backMode + " Pen:" + pen + ",leftMargin:" + leftMargin); + cb.SaveState(); + + float x1, y1, x2, y2; + x1 = leftAux + leftMargin; + y1 = pageSize.GetTop() - bottomAux - topMargin - bottomMargin; + x2 = rightAux + leftMargin; + y2 = pageSize.GetTop() - topAux - topMargin - bottomMargin; + + cb.SetLineWidth(penAux); + + cb.SetLineCapStyle(PdfCanvasConstants.LineCapStyle.PROJECTING_SQUARE); + + if (cornerRadioBL == 0 && cornerRadioBR == 0 && cornerRadioTL == 0 && cornerRadioTR == 0 && styleBottom == 0 && styleLeft == 0 && styleRight == 0 && styleTop == 0) + { + //border color must be the same as the fill if border=0 since setLineWidth does not work. + if (pen > 0) + cb.SetStrokeColor(foreColor); + else + cb.SetStrokeColor(backColor); + cb.Rectangle(x1, y1, x2 - x1, y2 - y1); + + if (backMode != 0) + { + cb.SetFillColor(backColor); + cb.FillStroke(); + } + cb.ClosePathStroke(); + } + else + { + float w = x2 - x1; + float h = y2 - y1; + if (w < 0) + { + x1 += w; + w = -w; + } + if (h < 0) + { + y1 += h; + h = -h; + } + + float cRadioTL = (float)convertScale(cornerRadioTL); + float cRadioTR = (float)convertScale(cornerRadioTR); + float cRadioBL = (float)convertScale(cornerRadioBL); + float cRadioBR = (float)convertScale(cornerRadioBR); + + // Scale the radius if it's too large or to small to fit. + int max = (int)Math.Min(w, h); + cRadioTL = Math.Max(0, Math.Min(cRadioTL, max / 2)); + cRadioTR = Math.Max(0, Math.Min(cRadioTR, max / 2)); + cRadioBL = Math.Max(0, Math.Min(cRadioBL, max / 2)); + cRadioBR = Math.Max(0, Math.Min(cRadioBR, max / 2)); + + if (backMode != 0) + { + cb.SetStrokeColor(backColor); + cb.SetLineWidth(0); + roundRectangle(cb, x1, y1, w, h, + cRadioTL, cRadioTR, + cRadioBL, cRadioBR); + cb.SetFillColor(backColor); + cb.FillStroke(); + cb.SetLineWidth(penAux); + } + if (pen > 0) + { + //Rectangle edge + cb.SetStrokeColor(foreColor); + drawRectangle(cb, x1, y1, w, h, + styleTop, styleBottom, styleRight, styleLeft, + cRadioTL, cRadioTR, + cRadioBL, cRadioBR, penAux, false); + } + } + cb.RestoreState(); + } + public override void GxDrawLine(int left, int top, int right, int bottom, int width, int foreRed, int foreGreen, int foreBlue, int style) + { + PdfCanvas cb = new PdfCanvas(pdfPage); + Color foreColor = new DeviceRgb(foreRed, foreGreen, foreBlue); + + float widthAux = (float)convertScale(width); + float rightAux = (float)convertScale(right); + float bottomAux = (float)convertScale(bottom); + float leftAux = (float)convertScale(left); + float topAux = (float)convertScale(top); + + GXLogging.Debug(log, "GxDrawLine leftAux: " + leftAux + ",leftMargin:" + leftMargin + ",pageSize.Top:" + pageSize.GetTop() + ",bottomAux:" + bottomAux + ",topMargin:" + topMargin + ",bottomMargin:" + bottomMargin); + + GXLogging.Debug(log, "GxDrawLine -> (" + left + "," + top + ") - (" + right + "," + bottom + ") Width: " + width); + float x1, y1, x2, y2; + x1 = leftAux + leftMargin; + y1 = pageSize.GetTop() - bottomAux - topMargin - bottomMargin; + x2 = rightAux + leftMargin; + y2 = pageSize.GetTop() - topAux - topMargin - bottomMargin; + + GXLogging.Debug(log, "Line-> (" + (x1) + "," + y1 + ") - (" + x2 + "," + y2 + ") "); + cb.SaveState(); + cb.SetStrokeColor(foreColor); + cb.SetLineWidth(widthAux); + + if (lineCapProjectingSquare) + { + cb.SetLineCapStyle(PdfCanvasConstants.LineCapStyle.PROJECTING_SQUARE); + } + if (style != 0) + { + float[] dashPattern = getDashedPattern(style); + cb.SetLineDash(dashPattern, 0); + } + + cb.MoveTo(x1, y1); + cb.LineTo(x2, y2); + cb.Stroke(); + + cb.RestoreState(); + } + public override void GxDrawBitMap(String bitmap, int left, int top, int right, int bottom, int aspectRatio) + { + try + { + Image image; + Image imageRef; + if (documentImages != null && documentImages.TryGetValue(bitmap, out imageRef)) + { + image = imageRef; + } + else + { + try + { + if (!Path.IsPathRooted(bitmap)) + { + + image = new Image(ImageDataFactory.Create(defaultRelativePrepend + bitmap)); + if (image == null) + { + bitmap = webAppDir + bitmap; + image = new Image(ImageDataFactory.Create(bitmap)); + } + else + { + bitmap = defaultRelativePrepend + bitmap; + } + } + else + { + image = new Image(ImageDataFactory.Create(bitmap)); + } + } + catch (Exception)//absolute url + { + Uri uri = new Uri(bitmap); + image = new Image(ImageDataFactory.Create(uri)); + } + if (documentImages == null) + { + documentImages = new Dictionary(); + } + documentImages[bitmap] = image; + } + GXLogging.Debug(log, "GxDrawBitMap -> '" + bitmap + "' [" + left + "," + top + "] - Size: (" + (right - left) + "," + (bottom - top) + ")"); + + if (image != null) + { + float rightAux = (float)convertScale(right); + float bottomAux = (float)convertScale(bottom); + float leftAux = (float)convertScale(left); + float topAux = (float)convertScale(top); + image.SetFixedPosition(leftAux + leftMargin, this.pageSize.GetTop() - bottomAux - topMargin - bottomMargin); + if (aspectRatio == 0) + image.ScaleAbsolute(rightAux - leftAux, bottomAux - topAux); + else + image.ScaleToFit(rightAux - leftAux, bottomAux - topAux); + document.Add(image); + } + } + catch (PdfException de) + { + GXLogging.Error(log, "GxDrawBitMap document error", de); + } + catch (IOException ioe) + { + GXLogging.Error(log, "GxDrawBitMap io error", ioe); + } + catch (Exception e) + { + GXLogging.Error(log, "GxDrawBitMap error", e); + } + + } + + public override void GxAttris(String fontName, int fontSize, bool fontBold, bool fontItalic, bool fontUnderline, bool fontStrikethru, int Pen, int foreRed, int foreGreen, int foreBlue, int backMode, int backRed, int backGreen, int backBlue) + { + fontStyle = null; + bool _isCJK = false; + bool embeedFont = IsEmbeddedFont(fontName); + if (!embeedFont) + { + fontName = getSubstitute(fontName); + } + + GXLogging.Debug(log, "GxAttris: "); + GXLogging.Debug(log, "\\-> Font: " + fontName + " (" + fontSize + ")" + (fontBold ? " BOLD" : "") + (fontItalic ? " ITALIC" : "") + (fontStrikethru ? " Strike" : "")); + GXLogging.Debug(log, "\\-> Fore (" + foreRed + ", " + foreGreen + ", " + foreBlue + ")"); + GXLogging.Debug(log, "\\-> Back (" + backRed + ", " + backGreen + ", " + backBlue + ")"); + if (barcode128AsImage && fontName.ToLower().IndexOf("barcode 128") >= 0 || fontName.ToLower().IndexOf("barcode128") >= 0) + { + barcode = new Barcode128(pdfDocument); + barcode.SetCodeType(Barcode128.CODE128); + } + else + { + barcode = null; + } + this.fontUnderline = fontUnderline; + this.fontStrikethru = fontStrikethru; + this.fontSize = fontSize; + foreColor = new DeviceRgb(foreRed, foreGreen, foreBlue); + backColor = new DeviceRgb(backRed, backGreen, backBlue); + + backFill = (backMode != 0); + try + { + //LoadAsianFontsDll(); + string f = fontName.ToLower(); + if (PDFFont.isType1(fontName)) + { + //Asian font + for (int i = 0; i < Type1FontMetrics.CJKNames.Length; i++) + { + if (Type1FontMetrics.CJKNames[i][0].ToLower().Equals(f) || + Type1FontMetrics.CJKNames[i][1].ToLower().Equals(f)) + { + fontStyle = new Style(); + if (fontItalic) fontStyle.SetItalic(); + if (fontBold) fontStyle.SetBold(); + + setAsianFont(fontName, string.Empty); + fontStyle.SetFont(baseFont); + + _isCJK = true; + break; + } + } + if (!_isCJK) + { + int style = 0; + if (fontBold && fontItalic) + style = style + 3; + else + { + if (fontItalic) + style = style + 2; + if (fontBold) + style = style + 1; + } + for (int i = 0; i < PDFFont.base14.Length; i++) + { + if (PDFFont.base14[i][0].ToLower().Equals(f)) + { + fontName = PDFFont.base14[i][1 + style].Substring(1); + break; + } + } + + baseFont = PdfFontFactory.CreateFont(fontName, PdfEncodings.WINANSI, PdfFontFactory.EmbeddingStrategy.PREFER_NOT_EMBEDDED); + } + } + else + {//True type font + + if (IsEmbeddedFont(fontName)) + { + fontStyle = new Style(); + if (fontItalic) fontStyle.SetItalic(); + if (fontBold) fontStyle.SetBold(); + + } + string fontPath = GetFontLocation(fontName); + bool foundFont = true; + if (string.IsNullOrEmpty(fontPath)) + { + MSPDFFontDescriptor fontDescriptor = new MSPDFFontDescriptor(); + fontPath = fontDescriptor.getTrueTypeFontLocation(fontName); + if (string.IsNullOrEmpty(fontPath)) + { + baseFont = CreateDefaultFont(); + foundFont = false; + } + else + { + props.setProperty(Const.MS_FONT_LOCATION, fontName, fontPath); + } + } + if (foundFont) + { + if (IsEmbeddedFont(fontName)) + { + try + { + baseFont = PdfFontFactory.CreateFont(fontPath, PdfEncodings.IDENTITY_H, PdfFontFactory.EmbeddingStrategy.PREFER_EMBEDDED); + GXLogging.Debug(log, "EMBEED_SECTION Font"); + } + catch (IOException ioEx) + { + Exception exDetailed = new Exception($"Error creating {fontPath}. Check font is installed for the current user", ioEx); + throw exDetailed; + } + } + else + { + + fontStyle = new Style(); + if (fontItalic) fontStyle.SetItalic(); + if (fontBold) fontStyle.SetBold(); + + GXLogging.Debug(log, "NOT EMBEED_SECTION Font"); + + baseFont = PdfFontFactory.CreateFont(fontPath, PdfEncodings.WINANSI, PdfFontFactory.EmbeddingStrategy.PREFER_NOT_EMBEDDED); + fontStyle.SetFont(baseFont); + } + } + else + { + GXLogging.Debug(log, "NOT foundFont fontName:" + fontName); + } + } + } + catch (PdfException de) + { + GXLogging.Debug(log, "GxAttris DocumentException", de); + throw de; + } + catch (Exception e) + { + GXLogging.Debug(log, "GxAttris error", e); + baseFont = CreateDefaultFont(); + } + } + private PdfFont CreateDefaultFont() + { + return PdfFontFactory.CreateFont("Helvetica", PdfEncodings.WINANSI, PdfFontFactory.EmbeddingStrategy.PREFER_NOT_EMBEDDED); + } + public override void setAsianFont(String fontName, String style) + { + //LoadAsianFontsDll(); + try + { + if (fontName.Equals("Japanese")) + baseFont = PdfFontFactory.CreateFont("HeiseiMin-W3", "UniJIS-UCS2-H", PdfFontFactory.EmbeddingStrategy.PREFER_NOT_EMBEDDED); + if (fontName.Equals("Japanese2")) + baseFont = PdfFontFactory.CreateFont("HeiseiKakuGo-W5", "UniJIS-UCS2-H", PdfFontFactory.EmbeddingStrategy.PREFER_NOT_EMBEDDED); + if (fontName.Equals("SimplifiedChinese")) + baseFont = PdfFontFactory.CreateFont("STSong-Light", "UniGB-UCS2-H", PdfFontFactory.EmbeddingStrategy.PREFER_NOT_EMBEDDED); + if (fontName.Equals("TraditionalChinese")) + baseFont = PdfFontFactory.CreateFont("MHei-Medium", "UniCNS-UCS2-H", PdfFontFactory.EmbeddingStrategy.PREFER_NOT_EMBEDDED); + if (fontName.Equals("Korean")) + baseFont = PdfFontFactory.CreateFont("HYSMyeongJo-Medium", "UniKS-UCS2-H", PdfFontFactory.EmbeddingStrategy.PREFER_NOT_EMBEDDED); + } + catch (PdfException de) + { + GXLogging.Debug(log, "setAsianFont error", de); + } + catch (IOException ioe) + { + GXLogging.Debug(log, "setAsianFont io error", ioe); + } + } + public override void GxDrawText(String sTxt, int left, int top, int right, int bottom, int align, int htmlformat, int border, int valign) + { + GXLogging.Debug(log, "GxDrawText, text:" + sTxt); + bool printRectangle = false; + if (props.getBooleanGeneralProperty(Const.BACK_FILL_IN_CONTROLS, true)) + printRectangle = true; + + if (printRectangle && (border == 1 || backFill)) + { + GxDrawRect(left, top, right, bottom, border, foreColor, backFill ? 1 : 0, backColor, 0, 0, 0, 0, 0, 0, 0, 0); + } + PdfCanvas canvas = new PdfCanvas(pdfPage); + + //int arabicOptions = 0; + canvas.SetFontAndSize(this.baseFont, fontSize); + canvas.SetFillColor(foreColor); + sTxt = sTxt.TrimEnd(TRIM_CHARS); + + float captionHeight = baseFont.GetAscent(ASCENT_CHAR_A, fontSize); + float rectangleWidth = baseFont.GetWidth(sTxt, fontSize); + + int bottomOri = bottom; + int topOri = top; + + float bottomAux = (float)convertScale(bottom) - ((float)convertScale(bottom - top) - captionHeight) / 2; + //Space between the text and the edge of the textblock is substracted from bottom + //Because coordinates x,y for a genexus report corresponds to the box containing the text, + //and itext expects x,y of the text itself. + //The box is bigger thant the text (depends on the type of font) + float topAux = (float)convertScale(top) + ((float)convertScale(bottom - top) - captionHeight) / 2; + + float startHeight = bottomAux - topAux - captionHeight; + + float leftAux = (float)convertScale(left); + float rightAux = (float)convertScale(right); + int alignment = align & 3; + bool autoResize = (align & 256) == 256; + + GXLogging.Debug(log, "GxDrawText left: " + left + ",top:" + top + ",right:" + right + ",bottom:" + bottom + ",captionHeight:" + captionHeight + ",fontSize:" + fontSize); + GXLogging.Debug(log, "GxDrawText leftAux: " + leftAux + ",leftMargin:" + leftMargin + ",pageSize.Top:" + pageSize.GetTop() + ",bottomAux:" + bottomAux + ",topMargin:" + topMargin + ",bottomMargin:" + bottomMargin); + if (htmlformat == 1) + { + ConverterProperties properties = new ConverterProperties(); + if (IsTrueType(this.baseFont)) + { + Hashtable locations = GetFontLocations(); + foreach (string fontName in locations.Keys) + { + string fontPath = (string)locations[fontName]; + if (string.IsNullOrEmpty(fontPath)) + { + MSPDFFontDescriptor fontDescriptor = new MSPDFFontDescriptor(); + fontPath = fontDescriptor.getTrueTypeFontLocation(fontName); + } + if (!string.IsNullOrEmpty(fontPath)) + { + FontProvider fontProvider = new DefaultFontProvider(); + + if (IsEmbeddedFont(fontName)) + fontProvider.AddFont(fontPath, PdfEncodings.IDENTITY_H); + else + fontProvider.AddFont(fontPath, PdfEncodings.WINANSI); + + properties.SetFontProvider(fontProvider); + } + } + } + + //Bottom and top are the absolutes, regardless of the actual height at which the letters are written. + bottomAux = (float)convertScale(bottom); + topAux = (float)convertScale(top); + + + Canvas cb = new Canvas(canvas, new Rectangle(leftAux + leftMargin, this.pageSize.GetTop() - bottomAux - topMargin - bottomMargin, rightAux - leftAux, bottomAux - topAux)); + TextAlignment colAlignment = (TextAlignment)GetTextAlignment(alignment); + cb.SetTextAlignment(colAlignment); + + try + { + IList objects = HtmlConverter.ConvertToElements(sTxt, properties); + + foreach (IElement element in objects) + { + Paragraph p = element as Paragraph; + if (p != null) + { + if (alignment != 0) + p.SetTextAlignment(colAlignment); + } + + cb.Add((IBlockElement)element); + } + } + catch (Exception ex1) + { + GXLogging.Debug(log, "Error adding html: ", ex1); + } + + } + else if (barcode != null) + { + GXLogging.Debug(log, "Barcode" + barcode.GetType().ToString()); + try + { + barcode.SetCode(sTxt); + barcode.SetTextAlignment(alignment); + Rectangle rectangle = new Rectangle(0, 0); + + switch (alignment) + { + case 1: // Center Alignment + rectangle = rectangle.SetBbox((leftAux + rightAux) / 2 + leftMargin - rectangleWidth / 2, + (float)this.pageSize.GetTop() - (float)convertScale(bottom) - topMargin - bottomMargin, + (leftAux + rightAux) / 2 + leftMargin + rectangleWidth / 2, + (float)this.pageSize.GetTop() - (float)convertScale(top) - topMargin - bottomMargin); + break; + case 2: // Right Alignment + rectangle = rectangle.SetBbox(rightAux + leftMargin - rectangleWidth, + (float)this.pageSize.GetTop() - (float)convertScale(bottom) - topMargin - bottomMargin, + rightAux + leftMargin, + (float)this.pageSize.GetTop() - (float)convertScale(top) - topMargin - bottomMargin); + break; + case 0: // Left Alignment + rectangle = rectangle.SetBbox(leftAux + leftMargin, + (float)this.pageSize.GetTop() - (float)convertScale(bottom) - topMargin - bottomMargin, + leftAux + leftMargin + rectangleWidth, + (float)this.pageSize.GetTop() - (float)convertScale(top) - topMargin - bottomMargin); + break; + } + barcode.SetAltText(string.Empty); + barcode.SetBaseline(0); + + if (fontSize < Const.LARGE_FONT_SIZE) + barcode.SetX(Const.OPTIMAL_MINIMU_BAR_WIDTH_SMALL_FONT); + else + barcode.SetX(Const.OPTIMAL_MINIMU_BAR_WIDTH_LARGE_FONT); + + + Image imageCode = new Image(barcode.CreateFormXObject(backFill ? backColor : null, foreColor, pdfDocument)); + imageCode.SetFixedPosition(leftAux + leftMargin, rectangle.GetBottom()); + barcode.SetBarHeight(rectangle.GetHeight()); + imageCode.ScaleToFit(rectangle.GetWidth(), rectangle.GetHeight()); + document.Add(imageCode); + } + catch (Exception ex) + { + GXLogging.Error(log, "Error generating Barcode " + barcode.GetType().ToString(), ex); + } + } + else + { + + if (backFill) + { + Rectangle rectangle = new Rectangle(0, 0); + //Text with background + switch (alignment) + { + case 1: // Center Alignment Element.ALIGN_CENTER + rectangle = rectangle.SetBbox((float)(leftAux + rightAux) / 2 + leftMargin - rectangleWidth / 2, (float)this.pageSize.GetTop() - bottomAux - topMargin - bottomMargin, (leftAux + rightAux) / 2 + leftMargin + rectangleWidth / 2, (float)this.pageSize.GetTop() - topAux - topMargin - bottomMargin); + break; + case 2: // Right Alignment Element.ALIGN_RIGHT + rectangle = rectangle.SetBbox(rightAux + leftMargin - rectangleWidth, (float)this.pageSize.GetTop() - bottomAux - topMargin - bottomMargin, rightAux + leftMargin, (float)this.pageSize.GetTop() - topAux - topMargin - bottomMargin); + break; + case 0: // Left Alignment Element.ALIGN_LEFT + rectangle = rectangle.SetBbox(leftAux + leftMargin, (float)this.pageSize.GetTop() - bottomAux - topMargin - bottomMargin, leftAux + leftMargin + rectangleWidth, (float)this.pageSize.GetTop() - topAux - topMargin - bottomMargin); + break; + } + canvas.SetFillColor(backColor); + try + { + canvas.Rectangle(rectangle); + canvas.Fill(); + } + catch (PdfException de) + { + GXLogging.Error(log, "GxDrawText error", de); + } + } + + Canvas cb = new Canvas(canvas, new Rectangle(leftAux + leftMargin, this.pageSize.GetTop() - bottomAux - topMargin - bottomMargin, rightAux - leftAux, bottomAux - topAux)); + + //Underlined text + if (fontUnderline) + { + cb.SetUnderline(); + } + //Crossed text + if (fontStrikethru) + { + cb.SetUnderline(ITEXT_DEFAULT_UNDERLINE_THICKNESS, fontSize / 2); + } + + if (sTxt.Trim().ToLower().Equals("{{pages}}")) + { + if (!templateCreated) + { + + GXLogging.Debug(log, "GxDrawText addTemplate-> (" + (leftAux + leftMargin) + "," + (this.pageSize.GetTop() - bottomAux - topMargin - bottomMargin) + ") "); + templateRectangle = new Rectangle(leftAux + leftMargin, (float)this.pageSize.GetTop() - bottomAux - topMargin - bottomMargin, rightAux + leftMargin, (float)this.pageSize.GetTop() - topAux - topMargin - bottomMargin); + + templatex = leftAux + leftMargin; + templatey = this.pageSize.GetTop() - bottomAux - topMargin - bottomMargin; + templateFont = this.baseFont; + templateFontSize = fontSize; + templateColorFill = foreColor; + templateAlignment = alignment; + templateCreated = true; + } + return; + } + + float textBlockWidth = rightAux - leftAux; + float TxtWidth = this.baseFont.GetWidth(sTxt, fontSize); + bool justified = (alignment == 3) && textBlockWidth < TxtWidth; + bool wrap = (align & 16) == 16; + + if (wrap || justified) + { + + bottomAux = (float)convertScale(bottomOri); + topAux = (float)convertScale(topOri); + + float leading = (float)Convert.ToDouble(props.getGeneralProperty(Const.LEADING), CultureInfo.InvariantCulture.NumberFormat); + Paragraph p = new Paragraph(sTxt).SetFont(baseFont).SetFontSize(fontSize); + if (fontStyle!=null) + p.AddStyle(fontStyle); + + float llx = leftAux + leftMargin; + float lly = (float)this.pageSize.GetTop() - bottomAux - topMargin - bottomMargin; + float urx = rightAux + leftMargin; + float ury = (float)this.pageSize.GetTop() - topAux - topMargin - bottomMargin; + + DrawColumnText(canvas, llx, lly, urx, ury, p, leading, runDirection, valign, alignment); + + } + else //no wrap + { + startHeight = 0; + if (!autoResize) + { + //It removes the last char from the text until it reaches a string whose width is passed only by one character + // of the width of the textblock. That is the most similar text to design in genexus + String newsTxt = sTxt; + while (TxtWidth > textBlockWidth && (newsTxt.Length - 1 >= 0)) + { + sTxt = newsTxt; + newsTxt = newsTxt.Remove(newsTxt.Length - 1, 1); + TxtWidth = this.baseFont.GetWidth(newsTxt, fontSize); + } + } + Text text = new Text(sTxt).SetFont(baseFont).SetFontSize(fontSize).SetHorizontalAlignment(HorizontalAlignment.LEFT); + if (fontStyle != null) + text.AddStyle(fontStyle); + + Paragraph phrase = new Paragraph(text).SetVerticalAlignment(VerticalAlignment.TOP).SetFontColor(foreColor); + + switch (alignment) + { + case 1: // Center Alignment + cb.ShowTextAligned(phrase, ((leftAux + rightAux) / 2) + leftMargin, this.pageSize.GetTop() - bottomAux - topMargin - bottomMargin + startHeight, TextAlignment.CENTER);//0, runDirection, arabicOptions); + break; + case 2: // Right Alignment + cb.ShowTextAligned(phrase, rightAux + leftMargin, this.pageSize.GetTop() - bottomAux - topMargin - bottomMargin + startHeight, TextAlignment.RIGHT);//0, runDirection, arabicOptions); + break; + case 0: // Left Alignment + cb.ShowTextAligned(phrase, leftAux + leftMargin, this.pageSize.GetTop() - bottomAux - topMargin - bottomMargin + startHeight, TextAlignment.LEFT);//0, runDirection, arabicOptions); + break; + case 3: // Justified, only one text line + cb.ShowTextAligned(phrase, leftAux + leftMargin, this.pageSize.GetTop() - bottomAux - topMargin - bottomMargin + startHeight, justifiedType);//0, runDirection, arabicOptions); + break; + } + } + } + + } + + private BaseDirection? GetBaseDirection(int runDirection) + { + switch (runDirection) + { + case 2: return BaseDirection.LEFT_TO_RIGHT; + default: return null; + } + } + private VerticalAlignment GetVericalAlignment(float valign) + { + if (valign == (int)VerticalAlign.TOP) + return VerticalAlignment.TOP; + else if (valign == (int)VerticalAlign.BOTTOM) + return VerticalAlignment.BOTTOM; + else + return VerticalAlignment.MIDDLE; + + } + private TextAlignment? GetTextAlignment(int alignment) + { + switch (alignment) + { + case 1: return TextAlignment.CENTER; + case 2: return TextAlignment.RIGHT; + case 0: return TextAlignment.LEFT; + case 3: return TextAlignment.JUSTIFIED; + } + return null; + } + + void DrawColumnText(PdfCanvas pdfCanvas, float llx, float lly, float urx, float ury, Paragraph p, float leading, int runDirection, int valign, int alignment) + { + float width = urx - llx; + float height = ury - lly; + + p.SetTextAlignment(GetTextAlignment(alignment)) + .SetVerticalAlignment(GetVericalAlignment(valign)) + .SetMultipliedLeading(MULTIPLIED_LEADING) + .SetWidth(width) + .SetMaxHeight(height); + //.SetMargin(10); + Canvas cb = new Canvas(pdfCanvas, new Rectangle(llx, lly, width, height)); + cb.Add(p); + } + +#pragma warning restore CS0612 // Type or member is obsolete + + private PageSize ComputePageSize(float leftMargin, float topMargin, int width, int length, bool marginsInsideBorder) + { + if ((leftMargin == 0 && topMargin == 0) || marginsInsideBorder) + { + if (length == 23818 && width == 16834) + return PageSize.A3; + else if (length == 16834 && width == 11909) + return PageSize.A4; + else if (length == 11909 && width == 8395) + return PageSize.A5; + else if (length == 20016 && width == 5731) + return PageSize.B4; + else if (length == 14170 && width == 9979) + return PageSize.B5; + else if (length == 15120 && width == 10440) + return PageSize.EXECUTIVE; + else if (length == 20160 && width == 12240) + return PageSize.LEGAL; + else if (length == 15840 && width == 12240) + return PageSize.LETTER; + else + return new PageSize(new Rectangle((int)(width / PAGE_SCALE_X), (int)(length / PAGE_SCALE_Y))); + } + return new PageSize(new Rectangle((int)(width / PAGE_SCALE_X) + leftMargin, (int)(length / PAGE_SCALE_Y) + topMargin)); + } + public override void GxEndDocument() + { + //{{Pages}} + if (templateCreated) + { + int totalPages = pdfDocument.GetNumberOfPages(); + for (int i = 0; i < totalPages; i++) + { + PdfPage page = pdfDocument.GetPage(i); + Canvas canvas = new Canvas(page, templateRectangle); + canvas.ShowTextAligned(i.ToString(CultureInfo.InvariantCulture), templatex, templatey, TextAlignment.CENTER).SetBackgroundColor(templateColorFill).SetFont(templateFont).SetFontSize(templateFontSize); + } + + } + int copies = 1; + + try + { + copies = Convert.ToInt32(printerSettings.getProperty(form, Const.COPIES)); + GXLogging.Debug(log, "Setting number of copies to " + copies); + PdfViewerPreferences preferences = new PdfViewerPreferences(); + preferences.SetNumCopies(copies); + + int duplex = Convert.ToInt32(printerSettings.getProperty(form, Const.DUPLEX)); + PdfViewerPreferences.PdfViewerPreferencesConstants duplexValue; + if (duplex == 1) + duplexValue = PdfViewerPreferences.PdfViewerPreferencesConstants.SIMPLEX; + else if (duplex == 2) + duplexValue = PdfViewerPreferences.PdfViewerPreferencesConstants.DUPLEX_FLIP_LONG_EDGE; + else if (duplex == 3) + duplexValue = PdfViewerPreferences.PdfViewerPreferencesConstants.DUPLEX_FLIP_SHORT_EDGE; + else if (duplex == 4) + duplexValue = PdfViewerPreferences.PdfViewerPreferencesConstants.DUPLEX_FLIP_LONG_EDGE; + else + duplexValue = PdfViewerPreferences.PdfViewerPreferencesConstants.NONE; + GXLogging.Debug(log, "Setting duplex to " + duplexValue.ToString()); + preferences.SetDuplex(duplexValue); + } + catch (Exception ex) + { + GXLogging.Error(log, "Setting viewer preference error", ex); + } + + bool printingScript = false; + String serverPrinting = props.getGeneralProperty(Const.SERVER_PRINTING); + bool fit = props.getGeneralProperty(Const.ADJUST_TO_PAPER).Equals("true"); + if ((outputType == Const.OUTPUT_PRINTER || outputType == Const.OUTPUT_STREAM_PRINTER) && serverPrinting.Equals("false")) + { + + printingScript = true; + StringBuilder javascript = new StringBuilder(); ; + + javascript.Append("var pp = this.getPrintParams();"); + String printer = printerSettings.getProperty(form, Const.PRINTER).Replace("\\", "\\\\"); + if (!string.IsNullOrEmpty(printer)) + javascript.Append("pp.printerName = \"" + printer + "\";\n"); + + if (fit) + { + javascript.Append("pp.pageHandling = pp.constants.handling.fit;\n"); + } + else + { + javascript.Append("pp.pageHandling = pp.constants.handling.none;\n"); + } + + GXLogging.Debug(log, "MODE:" + printerSettings.getProperty(form, Const.MODE) + ",form:" + form); + + if (printerSettings.getProperty(form, Const.MODE, "3").StartsWith("0"))//Show printer dialog Never + { + javascript.Append("pp.interactive = pp.constants.interactionLevel.automatic;\n"); + + for (int i = 0; i < copies; i++) + { + javascript.Append("this.print(pp);\n"); + } + + //writer.addJavaScript("this.print({bUI: false, bSilent: true, bShrinkToFit: true});"); + //No print dialog is displayed. During printing a progress monitor and cancel + //dialog is displayed and removed automatically when printing is complete. + } + else //Show printer dialog is sent directly to printer | always + { + javascript.Append("pp.interactive = pp.constants.interactionLevel.full;\n"); + //Displays the print dialog allowing the user to change print settings and requiring + //the user to press OK to continue. During printing a progress monitor and cancel + //dialog is displayed and removed automatically when printing is complete. + + javascript.Append("this.print(pp);\n"); + + } + pdfDocument.GetCatalog().SetOpenAction(PdfAction.CreateJavaScript(javascript.ToString())); + } + + document.Close(); + + + GXLogging.Debug(log, "GxEndDocument!"); + + try + { + props.save(); + GXLogging.Debug(log, "props.save()"); + } + catch (IOException e) + { + GXLogging.Error(log, "props.save() error", e); + + } + GXLogging.Debug(log, "outputType: " + outputType + ",docName:" + docName); + + switch (outputType) + { + case Const.OUTPUT_SCREEN: + try + { + outputStream.Close(); + GXLogging.Debug(log, "GxEndDocument OUTPUT_SCREEN outputstream length" + outputStream.ToString().Length); + + } + catch (IOException e) + { + ; + + GXLogging.Error(log, "GxEndDocument OUTPUT_SCREEN error", e); + + } + try { showReport(docName, modal); } + catch (Exception) + { + + } + + break; + case Const.OUTPUT_PRINTER: + try { outputStream.Close(); } + catch (IOException) {; } // Cierro el archivo + try + { + if (!serverPrinting.Equals("false") && !printingScript) + { + printReport(docName, this.printerOutputMode == 0, printerSettings.getProperty(form, Const.PRINTER)); + } + } + catch (Exception) + { + + } + break; + case Const.OUTPUT_FILE: + try + { + outputStream.Close(); + GXLogging.Debug(log, "GxEndDocument OUTPUT_FILE outputstream length" + outputStream.ToString().Length); + } + catch (IOException e) + { + GXLogging.Error(log, "GxEndDocument OUTPUT_FILE error", e); + + ; + } + break; + case Const.OUTPUT_STREAM: + case Const.OUTPUT_STREAM_PRINTER: + + default: break; + } + outputStream = null; + + GXLogging.Debug(log, "GxEndDocument End"); + + } + public override void GxStartPage() + { + try + { + pdfPage = pdfDocument.AddNewPage(); + GXLogging.Debug(log, "GxStartPage pages:" + pages + ",new page:" + pages + 1); + pages = pages + 1; + } + catch (PdfException de) + { + GXLogging.Error(log, "GxStartPage error", de); + } + } + + private bool IsTrueType(PdfFont font) + { + return font.GetFontProgram() is TrueTypeFont; + } + } + +} + diff --git a/dotnet/src/dotnetframework/GxClasses/Core/gxconfig.cs b/dotnet/src/dotnetframework/GxClasses/Core/gxconfig.cs index 60cffccca..ecc3fca60 100644 --- a/dotnet/src/dotnetframework/GxClasses/Core/gxconfig.cs +++ b/dotnet/src/dotnetframework/GxClasses/Core/gxconfig.cs @@ -762,6 +762,7 @@ public class Preferences static int oldSTR = -1; static int instrumented = -1; static string mediaPath; + static string pdfLib; static string blobPath; static string blobPathFolderName; static int blankEmptyDates = -1; @@ -1175,6 +1176,28 @@ public static string getPRINT_LAYOUT_METADATA_DIR() } return mediaPath; } + internal static string PdfReportLibrary() + { + if (pdfLib == null) + { + lock (syncRoot) + { + if (pdfLib == null) + { + if (Config.GetValueOf("PDF_RPT_LIBRARY", out pdfLib)) + { + pdfLib = pdfLib.Trim(); + } + else + { + pdfLib = string.Empty; + } + GXLogging.Debug(log, "PDF_RPT_LIBRARY:", pdfLib); + } + } + } + return pdfLib; + } public enum StorageTimeZonePty { Undefined = 0, Utc = 1, Local = 2 }; public static Boolean useTimezoneFix() diff --git a/dotnet/src/dotnetframework/GxClasses/Model/gxproc.cs b/dotnet/src/dotnetframework/GxClasses/Model/gxproc.cs index f45d80700..918634c7d 100644 --- a/dotnet/src/dotnetframework/GxClasses/Model/gxproc.cs +++ b/dotnet/src/dotnetframework/GxClasses/Model/gxproc.cs @@ -335,6 +335,9 @@ public class GxReportUtils public static int OUTPUT_RVIEWER_NATIVE = 1; public static int OUTPUT_RVIEWER_DLL = 2; public static int OUTPUT_PDF = 3; +#if NETCORE + const string PDF_LIBRARY_ITEXT8 = "ITEXT8"; +#endif static readonly ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); static public IReportHandler GetPrinter( int outputType, string path, Stream reportOutputStream) @@ -369,7 +372,8 @@ static public IReportHandler GetPrinter( int outputType, string path, Stream rep Type classType = assem.GetType( "GeneXus.Printer.GxReportBuilderPdf", false, true); reportHandler = (IReportHandler) Activator.CreateInstance(classType,new Object[]{path, reportOutputStream}); #else - reportHandler = (IReportHandler)(ClassLoader.FindInstance("GxPdfReportsCS", "GeneXus.Printer", "GxReportBuilderPdf", new Object[] { path, reportOutputStream }, null)); + string reportBuidler = Preferences.PdfReportLibrary().Equals(PDF_LIBRARY_ITEXT8, StringComparison.OrdinalIgnoreCase) ? "GxReportBuilderPdf7" : "GxReportBuilderPdf"; + reportHandler = (IReportHandler)(ClassLoader.FindInstance("GxPdfReportsCS", "GeneXus.Printer", reportBuidler, new Object[] { path, reportOutputStream }, null)); #endif } catch (TargetInvocationException ex) diff --git a/dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportItext.cs b/dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportCommon.cs similarity index 52% rename from dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportItext.cs rename to dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportCommon.cs index 3a8eb6d38..60f38ea56 100644 --- a/dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportItext.cs +++ b/dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportCommon.cs @@ -1,3 +1,4 @@ + using System; using System.IO; @@ -11,11 +12,8 @@ using System.util; using System.Diagnostics; using log4net; -using iTextSharp.text.pdf; -using iTextSharp.text; using GeneXus.Printer; -using iTextSharp.text.html.simpleparser; using System.Collections.Generic; using System.Security; using GeneXus; @@ -33,73 +31,61 @@ internal enum VerticalAlign BOTTOM = 2, } - public class PDFReportItextSharp : IReportHandler + public class PDFReportItextBase : IReportHandler { - private int lineHeight, pageLines; + protected int lineHeight, pageLines; static ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - private iTextSharp.text.Rectangle pageSize; - private BaseFont baseFont; - Barcode barcode = null; - private bool fontUnderline; - private bool fontStrikethru; - private int fontSize; - - //Color for, BaseColor for => Itext5 - private object backColor, foreColor, templateColorFill; - private Stream outputStream = null; - - private static object syncRoot = new Object(); - private static ParseINI props; - private ParseINI printerSettings; - private String form; - private ArrayList stringTotalPages; - private int outputType = -1; - private int printerOutputMode = -1; - private bool modal = false; - private String docName = "PDFReport.pdf"; - private static NativeSharpFunctionsMS nativeCode = new NativeSharpFunctionsMS(); - private Hashtable fontSubstitutes = new Hashtable(); - private static String configurationFile = null; - private static String configurationTemplateFile = null; - private static String defaultRelativePrepend = null; - private static String webAppDir = null; + protected bool fontUnderline; + protected bool fontStrikethru; + protected int fontSize; + + protected Stream outputStream = null; + + protected static object syncRoot = new Object(); + protected static ParseINI props; + protected ParseINI printerSettings; + protected String form; + protected ArrayList stringTotalPages; + protected int outputType = -1; + protected int printerOutputMode = -1; + protected bool modal = false; + protected String docName = "PDFReport.pdf"; + protected static NativeSharpFunctionsMS nativeCode = new NativeSharpFunctionsMS(); + protected Hashtable fontSubstitutes = new Hashtable(); + protected static String configurationFile = null; + protected static String configurationTemplateFile = null; + protected static String defaultRelativePrepend = null; + protected static String webAppDir = null; public static bool DEBUG = false; - private Document document; - private PdfWriter writer; - private static String predefinedSearchPath = ""; - private float leftMargin; - private float topMargin; - private float bottomMargin; - private PdfTemplate template; - private BaseFont templateFont; - private int templateFontSize; - private bool backFill = true; - private int templateAlignment; - private int pages = 0; - private bool templateCreated = false; - private bool asianFontsDllLoaded = false; - private static char[] TRIM_CHARS = { ' ' }; - private int M_top, M_bot; + protected static String predefinedSearchPath = ""; + protected float leftMargin; + protected float topMargin; + protected float bottomMargin; + protected int templateFontSize; + protected bool backFill = true; + protected int templateAlignment; + protected int pages = 0; + protected bool templateCreated = false; + protected static char[] TRIM_CHARS = { ' ' }; + protected int M_top, M_bot; public static float DASHES_UNITS_ON = 10; public static float DASHES_UNITS_OFF = 10; public static float DOTS_UNITS_OFF = 3; public static float DOTS_UNITS_ON = 1; public bool lineCapProjectingSquare = true; public bool barcode128AsImage = true; - internal Dictionary documentImages; - float[] STYLE_SOLID = new float[] { 1, 0 };//0 - float[] STYLE_NONE = null;//1 - float[] STYLE_DOTTED, //2 + protected float[] STYLE_SOLID = new float[] { 1, 0 };//0 + protected float[] STYLE_NONE = null;//1 + protected float[] STYLE_DOTTED, //2 STYLE_DASHED, //3 STYLE_LONG_DASHED, //4 STYLE_LONG_DOT_DASHED; //5 - int STYLE_NONE_CONST = 1; - int runDirection; - int justifiedType; - static Assembly iTextAssembly = typeof(Document).Assembly; + protected int STYLE_NONE_CONST = 1; + protected int runDirection; + protected int MULTIPLIED_LEADING = 1; public bool GxOpenDoc(string fileName) { @@ -244,14 +230,11 @@ public static void showReport(String filename1, bool modal) } private static char alternateSeparator = Path.DirectorySeparatorChar == '/' ? '\\' : '/'; - public PDFReportItextSharp(String appPath) + public PDFReportItextBase(String appPath) { try { - document = null; - pageSize = null; stringTotalPages = new ArrayList(); - documentImages = new Dictionary(); defaultRelativePrepend = appPath; webAppDir = defaultRelativePrepend; if (appPath.Length > 0) @@ -409,20 +392,31 @@ public static String getPredefinedSearchPaths() return predefinedSearchPath; } - private void init() + protected virtual void init(ref int gxYPage, ref int gxXPage, int pageWidth, int pageLength) { - Document.Compress = true; - try - { - writer = PdfWriter.GetInstance(document, outputStream); - } - catch (DocumentException de) + + } + private float[] parsePattern(String patternStr) + { + if (patternStr!=null) { - GXLogging.Debug(log,"GxDrawRect error", de); + patternStr = patternStr.Trim(); + String[] values = patternStr.Split(new char[]{';'}); + if (values.Length>0) + { + float[] pattern = new float[values.Length]; + for (int i=0; i