diff --git a/dotnet/src/dotnetcore/GxPdfReportsCS/GxPdfReportsCS.csproj b/dotnet/src/dotnetcore/GxPdfReportsCS/GxPdfReportsCS.csproj index 6f996b82c..3818d8a4f 100644 --- a/dotnet/src/dotnetcore/GxPdfReportsCS/GxPdfReportsCS.csproj +++ b/dotnet/src/dotnetcore/GxPdfReportsCS/GxPdfReportsCS.csproj @@ -12,6 +12,10 @@ + + + + diff --git a/dotnet/src/dotnetcore/GxPdfReportsCS/Properties/AssemblyInfo.cs b/dotnet/src/dotnetcore/GxPdfReportsCS/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..d916f63fa --- /dev/null +++ b/dotnet/src/dotnetcore/GxPdfReportsCS/Properties/AssemblyInfo.cs @@ -0,0 +1,3 @@ +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("DotNetCoreWebUnitTest")] diff --git a/dotnet/src/dotnetframework/GxPdfReportsCS/GxPdfReportsCS.csproj b/dotnet/src/dotnetframework/GxPdfReportsCS/GxPdfReportsCS.csproj index 491c8720e..1c2d10b46 100644 --- a/dotnet/src/dotnetframework/GxPdfReportsCS/GxPdfReportsCS.csproj +++ b/dotnet/src/dotnetframework/GxPdfReportsCS/GxPdfReportsCS.csproj @@ -6,6 +6,12 @@ Itext PDF Report GeneXus.PdfReportsCS + + + + + + diff --git a/dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportItext.cs b/dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportItext.cs index 2faa34b7a..61b8d0b30 100644 --- a/dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportItext.cs +++ b/dotnet/src/dotnetframework/GxPdfReportsCS/PDFReportItext.cs @@ -22,6 +22,7 @@ using GeneXus.Utils; using System.Reflection; using GeneXus.Metadata; +using GeneXus.Configuration; namespace com.genexus.reports { @@ -45,6 +46,7 @@ public class PDFReportItextSharp : IReportHandler private bool fontUnderline; private bool fontStrikethru; private int fontSize; + private string language; //Color for, BaseColor for => Itext5 private object backColor, foreColor, templateColorFill; @@ -89,6 +91,7 @@ public class PDFReportItextSharp : IReportHandler public static float DOTS_UNITS_ON = 1; public bool lineCapProjectingSquare = true; public bool barcode128AsImage = true; + private PdfConformanceLevel complianceLevel = PdfConformanceLevel.None; internal Dictionary documentImages; float[] STYLE_SOLID = new float[] { 1, 0 };//0 float[] STYLE_NONE = null;//1 @@ -312,7 +315,11 @@ private void loadPrinterSettingsProps(String iniFile, String form, String printe printerSettings.setupProperty(form, Const.COLOR, color + ""); printerSettings.setupProperty(form, Const.DUPLEX, duplex + ""); } - + internal static void SetDefaultComplianceLevel(PdfConformanceLevel level) + { + if (props!=null) + props.setGeneralProperty(Const.COMPLIANCE_LEVEL, level.ToString()); + } private void loadProps() { if (props == null) @@ -350,6 +357,7 @@ private void loadProps() props.setupGeneralProperty(Const.MARGINS_INSIDE_BORDER, Const.DEFAULT_MARGINS_INSIDE_BORDER.ToString().ToLower()); props.setupGeneralProperty(Const.OUTPUT_FILE_DIRECTORY, "."); props.setupGeneralProperty(Const.LEADING, "2"); + props.setupGeneralProperty(Const.COMPLIANCE_LEVEL, PdfConformanceLevel.None.ToString()); props.setupGeneralProperty(Const.RUN_DIRECTION, Const.RUN_DIRECTION_LTR); props.setupGeneralProperty(Const.JUSTIFIED_TYPE_ALL, "false"); @@ -415,16 +423,24 @@ private void init() try { writer = PdfWriter.GetInstance(document, outputStream); + string level = props.getGeneralProperty(Const.COMPLIANCE_LEVEL); + if (Enum.TryParse(level, true, out complianceLevel)) + { + if (SetComplainceLevel(complianceLevel)) + writer.SetTagged(); + } + document.Open(); + } catch (DocumentException de) { - GXLogging.Debug(log,"GxDrawRect error", de); + GXLogging.Debug(log, "init error", de); } - document.Open(); } public void GxRVSetLanguage(String lang) { + language = lang; } public void GxSetTextMode(int nHandle, int nGridX, int nGridY, int nPageLength) @@ -795,6 +811,7 @@ public void GxDrawBitMap(String bitmap, int left, int top, int right, int bottom { iTextSharp.text.Image image; iTextSharp.text.Image imageRef; + if (documentImages != null && documentImages.TryGetValue(bitmap, out imageRef)) { image = imageRef; @@ -848,7 +865,9 @@ public void GxDrawBitMap(String bitmap, int left, int top, int right, int bottom image.ScaleToFit(rightAux - leftAux, bottomAux - topAux); PdfContentByte cb = writer.DirectContent; + image.Alt = Path.GetFileName(bitmap); cb.AddImage(image); + } } catch (DocumentException de) @@ -1046,8 +1065,16 @@ public void GxAttris(String fontName, int fontSize, bool fontBold, bool fontItal baseFont = CreateDefaultFont(); } } + BaseFont defaultFont; private BaseFont CreateDefaultFont() { - return BaseFont.CreateFont("Helvetica", BaseFont.WINANSI, BaseFont.NOT_EMBEDDED); + if (defaultFont == null) + { + if (IsPdfA()) + defaultFont = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.EMBEDDED); + else + defaultFont = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.NOT_EMBEDDED); + } + return defaultFont; } private string GetFontLocation(string fontName) { @@ -1082,9 +1109,14 @@ private Hashtable GetFontLocations() private bool IsEmbeddedFont(string fontName) { - bool generalEmbeedFont = props.getBooleanGeneralProperty(Const.EMBEED_SECTION, false); - bool generalEmbeedNotSpecified = props.getBooleanGeneralProperty(Const.EMBEED_NOT_SPECIFIED_SECTION, false); - return generalEmbeedFont && props.getBooleanProperty(Const.EMBEED_SECTION, fontName, generalEmbeedNotSpecified); + if (IsPdfA()) + return true; + else + { + bool generalEmbeedFont = props.getBooleanGeneralProperty(Const.EMBEED_SECTION, false); + bool generalEmbeedNotSpecified = props.getBooleanGeneralProperty(Const.EMBEED_NOT_SPECIFIED_SECTION, false); + return generalEmbeedFont && props.getBooleanProperty(Const.EMBEED_SECTION, fontName, generalEmbeedNotSpecified); + } } private void LoadAsianFontsDll() { @@ -1970,7 +2002,22 @@ public void GxEndDocument() } } + if (IsPdfA()) + { + using (Stream iccProfile = ReadResource("sRGB Color Space Profile.icm")) + { + ICC_Profile icc = ICC_Profile.GetInstance(iccProfile); + writer.SetOutputIntents("Custom", "", "http://www.color.org", "sRGB IEC61966-2.1", icc); + } + writer.ExtraCatalog.Put(PdfName.LANG, new PdfString(Config.GetCultureForLang(language).Name)); + PdfDictionary markInfo = new PdfDictionary(PdfName.MARKINFO); + markInfo.Put(PdfName.MARKED, new PdfBoolean(PdfBoolean.TRUE)); + writer.ExtraCatalog.Put(PdfName.MARKINFO, markInfo); + + writer.CreateXmpMetadata(); + + } document.Close(); @@ -2047,6 +2094,17 @@ public void GxEndDocument() GXLogging.Debug(log,"GxEndDocument End"); } + Stream ReadResource(string fileName) + { + Assembly assembly = GetType().Assembly; + string resourcePath = $"{assembly.GetName().Name}.{fileName}"; + return assembly.GetManifestResourceStream(resourcePath); + } + + private bool IsPdfA() + { + return complianceLevel != 0; + } public void GxEndPrinter() { @@ -2286,6 +2344,20 @@ private void SetSimpleColumn(ColumnText col, Rectangle rect) { col.SetSimpleColumn(rect.Left, rect.Bottom, rect.Right, rect.Top); } + internal bool SetComplainceLevel(PdfConformanceLevel level) + { + switch (level) + { + case PdfConformanceLevel.Pdf_A1A: + writer.PDFXConformance = PdfWriter.PDFA1A; + return true; + case PdfConformanceLevel.Pdf_A1B: + writer.PDFXConformance = PdfWriter.PDFA1B; + return true; + default: + return false; + } + } } public class ParseINI @@ -2737,7 +2809,8 @@ public class Const public static String ADJUST_TO_PAPER = "AdjustToPaper"; //fit to page public static String LINE_CAP_PROJECTING_SQUARE = "LineCapProjectingSquare"; public static String BARCODE128_AS_IMAGE = "Barcode128AsImage"; - public static String LEADING = "Leading"; + public static String LEADING = "Leading"; + internal static String COMPLIANCE_LEVEL = "ComplianceLevel"; //Printer settings public static String PRINTER = "Printer"; @@ -3227,6 +3300,16 @@ public static ArrayList parseLine(String line, String separator) } } - + internal enum PdfConformanceLevel + { + None, + Pdf_A1B, + Pdf_X1A2001, + Pdf_A1A, + Pdf_A2A, + Pdf_A2B, + Pdf_A3A, + Pdf_A3B + } } diff --git a/dotnet/src/dotnetframework/GxPdfReportsCS/sRGB Color Space Profile.icm b/dotnet/src/dotnetframework/GxPdfReportsCS/sRGB Color Space Profile.icm new file mode 100644 index 000000000..7f9d18d09 Binary files /dev/null and b/dotnet/src/dotnetframework/GxPdfReportsCS/sRGB Color Space Profile.icm differ diff --git a/dotnet/test/DotNetCoreWebUnitTest/DotNetCoreWebUnitTest.csproj b/dotnet/test/DotNetCoreWebUnitTest/DotNetCoreWebUnitTest.csproj index 75b8a1aaa..bac7e207c 100644 --- a/dotnet/test/DotNetCoreWebUnitTest/DotNetCoreWebUnitTest.csproj +++ b/dotnet/test/DotNetCoreWebUnitTest/DotNetCoreWebUnitTest.csproj @@ -14,6 +14,8 @@ + + @@ -34,6 +36,7 @@ + @@ -67,6 +70,12 @@ PreserveNewest + + PreserveNewest + + + Always + PreserveNewest diff --git a/dotnet/test/DotNetCoreWebUnitTest/Middleware/WebReportTest.cs b/dotnet/test/DotNetCoreWebUnitTest/Middleware/WebReportTest.cs new file mode 100644 index 000000000..c03d7d4ae --- /dev/null +++ b/dotnet/test/DotNetCoreWebUnitTest/Middleware/WebReportTest.cs @@ -0,0 +1,61 @@ +using System; +using System.IO; +using System.Net.Http; +using System.Reflection; +using System.Threading.Tasks; +using Codeuctivity; +using com.genexus.reports; +using GeneXus.Metadata; +using GeneXus.Programs; +using Spire.Pdf; +using Xunit; +namespace xUnitTesting +{ + public class WebReportTest : MiddlewareTest + { + public WebReportTest() : base() + { + ClassLoader.FindType("apdfwebbasictest", "GeneXus.Programs", "apdfwebbasictest", Assembly.GetExecutingAssembly(), true);//Force loading assembly for webhook procedure + ClassLoader.FindType("apdfwebwoutimage", "GeneXus.Programs", "apdfwebwoutimage", Assembly.GetExecutingAssembly(), true); + server.AllowSynchronousIO = true; + } + [Fact(Skip = "temporary turned off due to timeout error")] + public void TestPDFA() + { + HttpClient client = server.CreateClient(); + TestPDFA_1AB(client, "apdfwebbasictest.aspx", Spire.Pdf.PdfConformanceLevel.Pdf_A1A).GetAwaiter().GetResult(); + TestPDFA_1AB(client, "apdfwebwoutimage.aspx", Spire.Pdf.PdfConformanceLevel.Pdf_A1A).GetAwaiter().GetResult(); + PDFReportItextSharp.SetDefaultComplianceLevel(com.genexus.reports.PdfConformanceLevel.Pdf_A1B); + TestPDFA_1AB(client, "apdfwebbasictest.aspx", Spire.Pdf.PdfConformanceLevel.Pdf_A1B).GetAwaiter().GetResult(); + TestPDFA_1AB(client, "apdfwebwoutimage.aspx", Spire.Pdf.PdfConformanceLevel.Pdf_A1B).GetAwaiter().GetResult(); + + } + async Task TestPDFA_1AB(HttpClient client, string serviceName, Spire.Pdf.PdfConformanceLevel expectedLevel) + { + HttpResponseMessage response = await client.GetAsync(serviceName); + response.EnsureSuccessStatusCode(); + Assert.Equal(System.Net.HttpStatusCode.OK, response.StatusCode); + String fileName = response.Content.Headers.ContentDisposition.FileName; + //Assert.Equal("Report.pdf", fileName); + using (var fs = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None)) + { + await response.Content.CopyToAsync(fs); + } + PdfDocument pdf = new PdfDocument(); + pdf.LoadFromFile(fileName); + Spire.Pdf.PdfConformanceLevel conformance = pdf.Conformance; + + Assert.True(expectedLevel == conformance, $"Conformance level is {conformance} but {expectedLevel} was expected"); + + PdfAValidator pdfAValidator = new PdfAValidator(); + Report result = await pdfAValidator.ValidateWithDetailedReportAsync(fileName); + bool isValid = await pdfAValidator.ValidateAsync(fileName); + Assert.True(isValid, result.RawOutput); + + + + } + + } + +} diff --git a/dotnet/test/DotNetCoreWebUnitTest/PDFReport.ini b/dotnet/test/DotNetCoreWebUnitTest/PDFReport.ini new file mode 100644 index 000000000..10e61db72 --- /dev/null +++ b/dotnet/test/DotNetCoreWebUnitTest/PDFReport.ini @@ -0,0 +1,27 @@ +ComplianceLevel= pdf_a1a +JustifiedTypeAll= false +OutputFileDirectory= . +ServerPrinting= false +EmbeedNotSpecifiedFonts= false +Leading= 2 +Embeed Fonts= false +DottedStyle= 1;2 +LeftMargin= 0.75 +Barcode128AsImage= true +LongDotDashedStyle= 6;2;1;2 +DEBUG= false +SearchNewFontsOnce= true +TopMargin= 0.75 +LongDashedStyle= 6;2 +DashedStyle= 4;2 +SearchNewFonts= false +BottomMargin= 6 +AdjustToPaper= true +MarginsInsideBorder= false +LineCapProjectingSquare= true +RunDirection= 2 +Version= 1.0.0.0 + +[Fonts Location (MS)] +Microsoft Sans Serif= C:\Windows\fonts\micross.ttf +Microsoft Sans Serif,Bold= C:\Windows\fonts\micross.ttf diff --git a/dotnet/test/DotNetCoreWebUnitTest/apps/apdfwebbasictest.cs b/dotnet/test/DotNetCoreWebUnitTest/apps/apdfwebbasictest.cs new file mode 100644 index 000000000..6924bf049 --- /dev/null +++ b/dotnet/test/DotNetCoreWebUnitTest/apps/apdfwebbasictest.cs @@ -0,0 +1,196 @@ +/* + File: PDFBasicTest + Description: PDFBasic Test + Author: GeneXus .NET Framework Generator version 17_0_8-156507 + Generated on: 12/21/2021 16:34:13.62 + Program type: Main program + Main DBMS: SQL Server +*/ +using GeneXus.Application; +using GeneXus.Data.NTier; +using GeneXus.Http.Server; +using GeneXus.Procedure; +using GeneXus.Utils; + +namespace GeneXus.Programs +{ + public class apdfwebbasictest : GXWebProcedure + { + + public apdfwebbasictest( ) + { + context = new GxContext( ); + DataStoreUtil.LoadDataStores( context); + IsMain = true; + context.SetDefaultTheme("Carmine"); + } + + public apdfwebbasictest( IGxContext context ) + { + this.context = context; + IsMain = false; + } + public override void webExecute() + { + context.SetDefaultTheme("PDFReportTest", true); + GxContext gxcontext = context as GxContext; + gxcontext.SetPhysicalPath(System.IO.Directory.GetCurrentDirectory()); + initialize(); + executePrivate(); + cleanup(); + } + + public void execute() + { + initialize(); + executePrivate(); + } + void executePrivate() + { + /* GeneXus formulas */ + /* Output device settings */ + M_top = 0; + M_bot = 6; + P_lines = (int)(66-M_bot); + getPrinter().GxClearAttris() ; + AddMetrics( ) ; + lineHeight = 15; + gxXPage = 100; + gxYPage = 100; + GxHttpResponse httpResponse = new GxHttpResponse(context); + httpResponse.AppendHeader("Content-Disposition", "inline; filename=Report.pdf"); + getPrinter().GxSetDocFormat("PDF") ; + try + { + Gx_out = "FIL" ; + if (!initPrinter (Gx_out, gxXPage, gxYPage, "GXPRN.INI", "", "", 2, 1, 256, 16834, 9504, 0, 1, 1, 0, 1, 1) ) + { + cleanup(); + return; + } + getPrinter().setModal(false) ; + P_lines = (int)(gxYPage-(lineHeight*6)); + Gx_line = (int)(P_lines+1); + getPrinter().setPageLines(P_lines); + getPrinter().setLineHeight(lineHeight); + getPrinter().setM_top(M_top); + getPrinter().setM_bot(M_bot); + AV8htmlvar = "

This is an example of a simple HTML page with one paragraph.

"; + H1N0( false, 193) ; + getPrinter().GxAttris("Microsoft Sans Serif", 14, false, false, false, false, 0, 0, 0, 0, 0, 255, 255, 255) ; + getPrinter().GxDrawText("Item List", 17, Gx_line+33, 400, Gx_line+66, 0, 0, 0, 0) ; + getPrinter().GxDrawRect(33, Gx_line+33, 133, Gx_line+63, 1, 0, 0, 0, 0, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0) ; + getPrinter().GxAttris("Microsoft Sans Serif", 10, true, false, false, false, 0, 0, 0, 0, 0, 255, 255, 255) ; + getPrinter().GxDrawText("Code", 100, Gx_line+83, 140, Gx_line+101, 0+256, 0, 0, 0) ; + getPrinter().GxDrawText("Name", 183, Gx_line+83, 283, Gx_line+101, 0, 0, 0, 0) ; + getPrinter().GxDrawBitMap("lamp.png", 411, Gx_line+33, 619, Gx_line+241) ; + getPrinter().GxAttris("Microsoft Sans Serif", 8, false, false, false, false, 0, 0, 0, 0, 0, 255, 255, 255) ; + getPrinter().GxDrawText(StringUtil.RTrim( AV8htmlvar), 22, Gx_line+122, 400, Gx_line+178, 0, 1, 0, 0) ; + Gx_OldLine = Gx_line; + Gx_line = (int)(Gx_line+193); + /* Print footer for last page */ + ToSkip = (int)(P_lines+1); + H1N0( true, 0) ; + } + catch ( GeneXus.Printer.ProcessInterruptedException ) + { + } + finally + { + /* Close printer file */ + try + { + getPrinter().GxEndPage() ; + getPrinter().GxEndDocument() ; + } + catch ( GeneXus.Printer.ProcessInterruptedException ) + { + } + endPrinter(); + } + this.cleanup(); + } + + protected void H1N0( bool bFoot , + int Inc ) + { + /* Skip the required number of lines */ + while ( ( ToSkip > 0 ) || ( Gx_line + Inc > P_lines ) ) + { + if ( Gx_line + Inc >= P_lines ) + { + if ( Gx_page > 0 ) + { + /* Print footers */ + Gx_line = P_lines; + getPrinter().GxEndPage() ; + if ( bFoot ) + { + return ; + } + } + ToSkip = 0; + Gx_line = 0; + Gx_page = (int)(Gx_page+1); + /* Skip Margin Top Lines */ + Gx_line = (int)(Gx_line+(M_top*lineHeight)); + /* Print headers */ + getPrinter().GxStartPage() ; + if (true) break; + } + else + { + Gx_line = (int)(Gx_line+1); + } + ToSkip = (int)(ToSkip-1); + } + getPrinter().setPage(Gx_page); + } + + protected void AddMetrics( ) + { + AddMetrics0( ) ; + AddMetrics1( ) ; + } + + protected void AddMetrics0( ) + { + getPrinter().setMetrics("Microsoft Sans Serif", false, false, 58, 14, 72, 171, new int[] {48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 18, 20, 23, 36, 36, 57, 43, 12, 21, 21, 25, 37, 18, 21, 18, 18, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 18, 18, 37, 37, 37, 36, 65, 43, 43, 46, 46, 43, 39, 50, 46, 18, 32, 43, 36, 53, 46, 50, 43, 50, 46, 43, 40, 46, 43, 64, 41, 42, 39, 18, 18, 18, 27, 36, 21, 36, 36, 32, 36, 36, 18, 36, 36, 14, 15, 33, 14, 55, 36, 36, 36, 36, 21, 32, 18, 36, 33, 47, 31, 31, 31, 21, 17, 21, 37, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 18, 20, 36, 36, 36, 36, 17, 36, 21, 47, 24, 36, 37, 21, 47, 35, 26, 35, 21, 21, 21, 37, 34, 21, 21, 21, 23, 36, 53, 53, 53, 39, 43, 43, 43, 43, 43, 43, 64, 46, 43, 43, 43, 43, 18, 18, 18, 18, 46, 46, 50, 50, 50, 50, 50, 37, 50, 46, 46, 46, 46, 43, 43, 39, 36, 36, 36, 36, 36, 36, 57, 32, 36, 36, 36, 36, 18, 18, 18, 18, 36, 36, 36, 36, 36, 36, 36, 35, 39, 36, 36, 36, 36, 32, 36, 32}) ; + } + + protected void AddMetrics1( ) + { + getPrinter().setMetrics("Microsoft Sans Serif", true, false, 57, 15, 72, 163, new int[] {47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 17, 19, 29, 34, 34, 55, 45, 15, 21, 21, 24, 36, 17, 21, 17, 17, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 21, 21, 36, 36, 36, 38, 60, 43, 45, 45, 45, 41, 38, 48, 45, 17, 34, 45, 38, 53, 45, 48, 41, 48, 45, 41, 38, 45, 41, 57, 41, 41, 38, 21, 17, 21, 36, 34, 21, 34, 38, 34, 38, 34, 21, 38, 38, 17, 17, 34, 17, 55, 38, 38, 38, 38, 24, 34, 21, 38, 33, 49, 34, 34, 31, 24, 17, 24, 36, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 17, 21, 34, 34, 34, 34, 17, 34, 21, 46, 23, 34, 36, 21, 46, 34, 25, 34, 21, 21, 21, 36, 34, 21, 20, 21, 23, 34, 52, 52, 52, 38, 45, 45, 45, 45, 45, 45, 62, 45, 41, 41, 41, 41, 17, 17, 17, 17, 45, 45, 48, 48, 48, 48, 48, 36, 48, 45, 45, 45, 45, 41, 41, 38, 34, 34, 34, 34, 34, 34, 55, 34, 34, 34, 34, 34, 17, 17, 17, 17, 38, 38, 38, 38, 38, 38, 38, 34, 38, 38, 38, 38, 38, 34, 38, 34}) ; + } + + public override int getOutputType( ) + { + return GxReportUtils.OUTPUT_PDF ; + } + + public override void cleanup( ) + { + if (IsMain) waitPrinterEnd(); + if ( IsMain ) + { + context.CloseConnections(); + } + ExitApp(); + } + + public override void initialize( ) + { + AV8htmlvar = ""; + /* GeneXus formulas. */ + Gx_line = 0; + context.Gx_err = 0; + } + + private int M_top ; + private int M_bot ; + private int ToSkip ; + private int Gx_OldLine ; + private string AV8htmlvar ; + } + +} diff --git a/dotnet/test/DotNetCoreWebUnitTest/lamp.png b/dotnet/test/DotNetCoreWebUnitTest/lamp.png new file mode 100644 index 000000000..840d5d514 Binary files /dev/null and b/dotnet/test/DotNetCoreWebUnitTest/lamp.png differ