From 1638203957392f24aa62432cb135339bebc3bd97 Mon Sep 17 00:00:00 2001 From: claudiamurialdo <33756655+claudiamurialdo@users.noreply.github.com> Date: Thu, 27 Jul 2023 15:50:39 -0300 Subject: [PATCH] Initial support for Pdf reports in PDF/A 1A and 1B (#762) * Initial support for PDF/A 1a and 1b for .NET and .NET Framework reports. * Initialize default complianceLevel with None (default used until now). * Do not check report name in test until while #761 is open. * Set sRGB Color Space Profile for PDFA_1B. * Turn off test of PDFA. It seems to cause a timeout when running on github actions. --- .../GxPdfReportsCS/GxPdfReportsCS.csproj | 4 + .../GxPdfReportsCS/Properties/AssemblyInfo.cs | 3 + .../GxPdfReportsCS/GxPdfReportsCS.csproj | 6 + .../GxPdfReportsCS/PDFReportItext.cs | 101 ++++++++- .../sRGB Color Space Profile.icm | Bin 0 -> 3144 bytes .../DotNetCoreWebUnitTest.csproj | 9 + .../Middleware/WebReportTest.cs | 61 ++++++ .../test/DotNetCoreWebUnitTest/PDFReport.ini | 27 +++ .../apps/apdfwebbasictest.cs | 196 ++++++++++++++++++ dotnet/test/DotNetCoreWebUnitTest/lamp.png | Bin 0 -> 3232 bytes 10 files changed, 398 insertions(+), 9 deletions(-) create mode 100644 dotnet/src/dotnetcore/GxPdfReportsCS/Properties/AssemblyInfo.cs create mode 100644 dotnet/src/dotnetframework/GxPdfReportsCS/sRGB Color Space Profile.icm create mode 100644 dotnet/test/DotNetCoreWebUnitTest/Middleware/WebReportTest.cs create mode 100644 dotnet/test/DotNetCoreWebUnitTest/PDFReport.ini create mode 100644 dotnet/test/DotNetCoreWebUnitTest/apps/apdfwebbasictest.cs create mode 100644 dotnet/test/DotNetCoreWebUnitTest/lamp.png 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 0000000000000000000000000000000000000000..7f9d18d097d1bcccb32e6d5743ac4af593170b6f GIT binary patch literal 3144 zcmbW3cT`i^7KhKhH@(mjA|NI78hQyJ(mO~M1W}1efKUR4geG=G1x6GRDOO}uzyU{x zB4b4q3xk4U*9r0vP{zSgL`CJ@jB5$+tu^!Bn*GOF-`VH4*V$+9eb>4GQ2c@f!gN>x zfHa|46z=Q6ToMz@#P0Oj{6)6@8zOaL$xnP1H3 zCZTMJGDQ>_?uqgO00@-CIlOWXi}^Wdo&b2JXXJ_miAiFn5!aY$<><&}`th?<`C>6E zl*3KohJ5ztS`M50QMwWn;o;hl~n+=Z3aN);jB;ZAOP|O0JPqm^B#t5UXsM(3?~bV z?CflF0iSCwE9f`-pMr17zlJ&Ynal3`Ry(E_KY=4j6*FZ;<)){mOGM1f3=WsiWc~LL z|Kq?pY0b&QES#Uf7x9JYRZ-}a351DgyM;V~SdcDc3WR^v;eQx5CkGjRoof_mbzcB| zg*i~TNe9SpJpe-^10-%gdIEjxTM#h{$iBR2t&y*Dk1~4x=lUNDT#9btOhF=3=JpJa zWO5~-11?AcX+Q+BK|a_3 z3PCa00d|9GZ~)YSde8(;f;MmlTm)CZ4R8w#fJZ5%ns2D1Ps-Z(rJ@g}V8oCHwgZiKc&>%Dh{Q-T1 z5tstgVGY;-wt(5NI~)i{!pq=9com!n7r@)$O1Kt24!6P=;T!M(EQMdflL$b_2m{eZ zSO^>OL_&~QBmog2Ymp+P0;xrskPf69xs6DXapVIAhoNDZ7#7AEHf9hrf%$@^V%4#xSSPGMb_q5Sn~g2RR$z}{Td>%$GT@D&7?Df)BxS@M3%+z6yUFe;(hDAI85YkO^7@ zYl06UmLMc-BvcR@2gb~6tQGuvWbRvcjdBj{|DY1^&LA*&ECQg$SNrogBQY0yv zw1HGfY9d`GJtn;&lgT<{M{*chKweL-B%dH(B@dE6P?RVp6i-SVMMBw5IZC-ec|dtX zrBV&3Zq!(+n7W->PrXEaN_{U!lQWm|m*dH;ldF+ymFt&#B~O&smv@(6E}th~A%9B# zru?`9QNcjLQ-PzfR-s1Ww8A}wNky8Xm12lunqrA!gW@&CQ6;>Rfs(fpPpLrZu+k-^ zAsRx{rFqi0v`w@++GW}>9Y;5$`_q%@#q=NOz4QrXC1qRXDCHdG8s)RfQU<~>VE8jq z8KsPqjJu4F^EBqU&*RVAHm_-3|GX)c`6_NIe3c@VW|aYzkE%>nZ`BmlovLlBPt-7K zCTd}7*=qaME~|~tr_Xnu&z)a1|K$9K>aeXRCp8onAC8dVyXG{!X< znr@oOn&q13G{>}PS_`!VTIE{jwO%llneNO~W+k(WIiant?WZl#KBV2NJ*{J?vsh=N zPP5JvU6L+aH$k^tw^MgQPfIUYFJG@w@1Z_XpRJ#yzem4Yf6BnnAlhJyL7Ty-p^Blu zVV+^5;bSAJk*m=vqgtao#yDfPafahC5 z+Qgb`U1NR6hHB$uv(Bd7=C!S z*mQO%yM%q!5$ovTxX$s6;|C{uC$ZB>r{A4f&MD3f&Z7$q7w{L-x-1*Nx|P#BIdg*ge_(xce&)OAnDpi^r6wljj=G3totquUC;* zueXx-V()72r#?D9i9U@!6TWu7t9>u{Vf_OAcKY4(*YM~1*ZWTdI0UQ-=nA9+Mg&#| zJ_|Al5(RYx!@&W;yMiAt(qAN8)D{9l{6ltyJP9=nT^0Is7%nU{tS0PvxK((5cy|OX zVnswl#Jfn3$kND1i;Wgb7I#L;N5w_eM@>b0MVCcOmsl)Wv*bpMT8tp3Jr*Au6?-Ih za;f*y-Ajk#?BWXJ?k+Q2mb2{Ia<%2D%g?TmU%^>%Djpjj9p4cDi4(%93l#rC8 zDKn|jsm*DGwD`2sLM35}uq$0NJtw^{!!)BXL%Pao)$UajqCnA+Oek|%X1kb<{!H~q zj3k>SgINo+YO>yEM`fSNQOptM^yHf4Zp$6X^U3>uHD)z;b!WbI{)YU)HSTK;t%cUE zT-&)$cU{4{;q|`jk8L1rNZIhqM$3(58{ck<-qcZ`QLw&XXtVF;#zMJ5QQ^HU&RY&_ z#cUO9?cHXxt!mqsB3{w;V$0%+;!h>qlI!1DeOLM2%=U!sy`}c0`*+}W2zT7w>ALe+ znPOR9+0d@wU9IKJ@}ly$yI1VKR$*IlU=L}JWRJ8msIt9EuWCotr|P8Yff|pR=Dq5B zx9y$U$J^Jx-)(=>0gVI22Rfw1Ho}dP#Y+O@16`i z*?Ee6s_7^FpZ2!UT8dhs*4);Kwxl*`drW)Z>44Ln9nKvsKb!x2^o;hInzPDhOV5$c z6`Y$npLc%pLdJ#hi-{M9I#+Z)y0qldovyI1-phfPuU_%Fa;e+B`}|dxt7on`T|0f9 zeZB35{f*WhyPlR`?0#wKweM}c>2S0CmgB9Cz6E{f`d#}k-uAkE<&OWI8v~05`tB~i zd;ebCJ?VYk{m}=h4_-gadN}=P{bTIoq9+PZDxRu8t^L*b*Ji1`^z5M5V9&FNXOD)s zLoff8`L9pI1<$F^D@L?N>PM|d&y4wu-FmU~#qi6Fm($~gzbXE<_m$DBpMH1yy=P*{ z#PDm;>zO}F-l)Dg`quVs=Va*Q(|2j_rl*SDtG++>f&HQTWAw+7>FiJVPnDmIKX-fy L{PK7vZD!`*_k{EN literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..840d5d5148aeffe5f60d12eb72b2af91f08b6b6e GIT binary patch literal 3232 zcmV;R3}5q!P)HqoS|LKhX-cxymeT$E9|KxDnzBTR1C;#`< z|L&>(;bQ;WMgQ41ota~%pIqd_F0Z6k|LmIo@wdseLejZAz^+LD=6}u3rGkog-q3gM z(MaOZYuV3&#Lc|G%*VIK&g#)r-P*9`&|lThj_&HoKLOgM000Y{Nkl;DCCB(eIq#)a6+Vw_DYquX0dY5~`|52S6pqF-l+&h+ z>Mz9PMmLbRG8sp^Zj6}+!QB`ZKLC%ycl}Lxj1W)Ghv8w}Obq)g3YL|tQ_8M}W1BoK zhT~yXB*(p1d$QkbHgDI$_v~58Y2QG2^5`I3z6##Gutub>Vm<8~f`^mZ+xND3ocH8$ zuyrV0)|uGSE!6_#`u*Y3*=--+_}3AE&D-1N0m!8G!CN~#6fON}D|_fC;H4-0b3vtM z@>h0bV`LgVDpVW7mlf)yf4HQ@tX{%-sH3>9pvNyLV= zpQT=BPDI&~t>vM&)y#eT9Yh=BhI7a*JM=6%0s7rNhX9;wEipoLwt5SRS9mt^IS zZeJp@r16P7*^}4D?+%OI7J+;9S=64Wr&)wZ8dqA@TOw-p$o1F@O( zY)x&R3(W%mzwH}cnsC>xj2@1chxyWv0|PV$E)kD}a}SjN1=7ee6Fg=!)8i*JB-69; zA)}hTJr=@%rIj$rf(WBZDqdoSh*A@~6PgEV79|e@`3b^MB551eGRZ`;Bd#EG!VSnl)40 zf73u~YY_{?tY(>KBFK4JV1byZaR+76dax%mnw+pWHfQmzgAOr{>iw$_5zdWGHMY*s zxIY4N?d zsyZB&hXE=r6O0kAaECJxipp)D`nPe+*FQ8~hBV{2!=Bvz&!7ML@#Dw8&j7>^eBoK< zF#}>zoie}w`Rm8GZ*vxcD<*l_2udyT062eX<8t?(Kfe8QE&_k8IH+1Dt_}O(aC$4P zx_&^g%cv+#DU;{a29%CgQq5 z9vbS08pNM1=FMU~OwH6E$y$fTe110CLi42yundAlSc|*9CXLaEgiFrJcm<<_hG7t794U`xvMy9kC=A5WGLLeDRbC+YVV;rP^{}Gh%Utrhuo;^a zAj*Pm*_J~1VRTsh?UH)lBAp@}e7juA{YaILUp$}x{#{8U7HCsR;tWt6bm1II9%_Sl zj8fG_fnc_-Ka@lLu0!bv<2KLl%`NY!eAJc|hGtYS{|% zc03DXg;EPNr@3K1S9JZ9@ zfqgz7-fiVfv83}!pjBMlfOank>^4F>(=kc)KFiaP*SZ4}Sw(5W^vJc&(r{W;OIhYH z7M>-^(9(#3-<>f6@pV+$=V-7Q%UNtQQS=rJ5jW5}gF2$3fR<}FQa;-Fz-^%xoD$6DM?ara9DVQ49noVfTnbiEd%_h{K$2)l?$Dg zqcIjjnhr30B#S6@1n`!DdDRNId$^T^3YAFE%#r%6XT>7S_^nQkOm5VNg^~_+MF_Yu zbsw`v8ObUVUv?Qp6umSvw`~ z)Fsr8d?_H3X3UBy#q%-)I#zhxAa33Mpx5In9h*&7K|~yG>ShbUT9ce`aeJ#63=*Ma z(Gn^;7jMa(6QYDY$7o>X;Z_x)0zBotecw?SK=v2dLH8TbLJWeLx^_iL>kdPSl?su9 z3idX=W`c0#v6v;2?KBQVgaZ9aLR z9Z}gvk&XI6BNZ@41g_){;YXLA3^@1NC zsOrds5rGF2#*mu^E8^e^#sG4{Q8f|+>1oU$BO}#pq+!Gk2a+x%Aw+rAB8#m!t3EW~ zRyFECoM3c1pCHPzxOwy>TrhK!>e`a%s38Cj0dj-)r4dY&WRYiB6ePkVOf|5>=9pII zfn1NY8Vx;JMdpjvSvuE5^d|iWZE!WDhp}wBLE=fDqA)Qj%~P7(D{6~RUrZ5xlX4-q z*6I=Utn=wqoRiT+Le@repgdgL0wl`n}SKcY{(A< zAcg)QU&c^^i%p6HG0aGK3taNJ20d%eD1EBuHt4-$IdW1u4!TcHnY$>pR=NaqJ2D<1 zv