using System; using System.Drawing; using System.IO; using System.Text; using System.Collections.Generic; using FastReport.Table; using FastReport.Utils; using FastReport.Export; using FastReport.SVG; using System.Drawing.Imaging; using System.Windows.Forms; using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Rendering; using FastReport.Web.Blazor.Export.ReportComponent; using FastReport.AdvMatrix; using static FastReport.Web.Blazor.Export.BlazorConstants; using System.Diagnostics; using System.Drawing.Text; using System.Runtime.CompilerServices; namespace FastReport.Web.Blazor.Export { public class InputChanged { private readonly BlazorExport export; private readonly ReportComponentBase obj; private readonly int CurPage; public void Invoke() { export.OnClick(null, new OnClickEventArgs(obj, ClickType.TextEdit, CurPage)); } public InputChanged(BlazorExport export, TextObject obj, int curPage) { this.export = export; this.obj = obj; this.CurPage = curPage; } } public partial class BlazorExport { private bool doPageBreak; const string defaultStyle = "position:absolute;"; private StringBuilder GetStyle(Font? Font, in Color TextColor, in Color FillColor, bool RTL, HorzAlign HAlign, Border Border, bool WordWrap, float LineHeight, float Width, float Height, bool Clip) { StringBuilder style = new StringBuilder(256); if (Font != null) { if (Zoom != 1) { using (Font newFont = new Font(Font.FontFamily, Font.Size * Zoom, Font.Style, Font.Unit, Font.GdiCharSet, Font.GdiVerticalFont)) HTMLFontStyle(style, newFont, LineHeight); } else HTMLFontStyle(style, Font, LineHeight); } style.Append("text-align:"); if (HAlign == HorzAlign.Left) style.Append(RTL ? "right" : "left"); else if (HAlign == HorzAlign.Right) style.Append(RTL ? "left" : "right"); else if (HAlign == HorzAlign.Center) style.Append("center"); else style.Append("justify"); style.Append(';'); if (WordWrap) style.Append("word-wrap:break-word;"); if (Clip) style.Append("overflow:hidden;"); style.Append("position:absolute;color:"). Append(HTMLColor(TextColor)). Append(";background-color:"). Append(FillColor.A == 0 ? "transparent" : HTMLColor(FillColor)). Append(';').Append(RTL ? "direction:rtl;" : String.Empty); Border newBorder = Border; HTMLBorder(style, newBorder); style.Append("width:").Append(Px(Math.Abs(Width) * Zoom)).Append("px;height:").Append(Px(Math.Abs(Height) * Zoom)).Append("px;"); return style; } private int UpdateCSSTable(ReportComponentBase obj) { StringBuilder style; if (obj is TextObject textObj) { style = GetStyle(textObj.Font, textObj.TextColor, textObj.FillColor, textObj.RightToLeft, textObj.HorzAlign, textObj.Border, textObj.WordWrap, textObj.LineHeight, textObj.Width, textObj.Height, textObj.Clip); } else if (obj is HtmlObject htmlObj) { style = GetStyle(DrawUtils.DefaultTextObjectFont, Color.Black, htmlObj.FillColor, false, HorzAlign.Left, htmlObj.Border, true, 0, htmlObj.Width, htmlObj.Height, false); } else style = GetStyle(null, Color.White, obj.FillColor, false, HorzAlign.Center, obj.Border, false, 0, obj.Width, obj.Height, false); return UpdateCSSTable(style); } private int UpdateCSSTable(StringBuilder style) { int i = cssStyles.IndexOf(style); if (i == -1) { i = cssStyles.Count; cssStyles.Add(style); } return i; } private void ExportPageStylesLayers(IRenderContext context) { if (prevStyleListIndex < cssStyles.Count) { HTMLGetStylesHeader(context); context.OpenElement(STYLE); context.AddAttribute(TYPE, "text/css"); var styles = new StringBuilder(256); styles.AppendLine(""); context.AddContent(styles.ToString()); context.CloseElement(); } } private string GetStyleTag(int index) { return $"{stylePrefix}s{index}"; } private void Layer(in IRenderContext context, ReportComponentBase obj, float left, float top, float width, float height, RenderFragment? content, string? styleClass, StringBuilder? addstyletag) { Debug.Assert(obj != null); var currentContext = new ElementContext(context); ClickType onclick = ClickType.Empty; if (!string.IsNullOrEmpty(obj.ClickEvent) || obj.HasClickListeners()) { onclick = ClickType.Click; } if (obj is CheckBoxObject checkBoxObject && checkBoxObject.Editable) { onclick = ClickType.CheckboxClick; } if (obj is MatrixButton) { onclick = ClickType.AdvancedMatrixClick; } // we need to adjust left, top, width and height values because borders take up space in html elements float borderLeft; float borderRight; float borderTop; float borderBottom; HTMLBorderWidthValues(obj, out borderLeft, out borderTop, out borderRight, out borderBottom); bool needHref = !String.IsNullOrEmpty(obj.Hyperlink.Value); if (needHref) { GetHref(obj, currentContext); // return don't close } currentContext.OpenElement(DIV); if (!string.IsNullOrEmpty(styleClass)) { currentContext.AddAttribute(CLASS, styleClass); } StringBuilder sb = new StringBuilder(32); if (onclick != ClickType.Empty || needHref) sb.Append("cursor:pointer;"); sb.Append("left:").Append(Px((leftMargin + left) * Zoom - borderLeft / 2f)). Append("px;top:").Append(Px((topMargin + top) * Zoom - borderTop / 2f)). Append("px;width:").Append(Px(width * Zoom - borderRight / 2f - borderLeft / 2f)). Append("px;height:").Append(Px(height * Zoom - borderBottom / 2f - borderTop / 2f)). Append("px;"); sb.Append(addstyletag); currentContext.AddAttribute(STYLE, sb.ToString()); if (obj is MatrixButton) { currentContext.AddOnClick(new OnClickEventArgs(obj, onclick, CurPage)); } if (obj is TextObject textObject && textObject.Editable) { currentContext.AddContent(AddTextInput(textObject, styleClass)); } else { if (onclick != ClickType.Empty) { currentContext.AddOnClick(new OnClickEventArgs(obj, onclick, CurPage)); } if (content == null) currentContext.AddMarkupContent(NBSP); else currentContext.AddContent(content); } currentContext.Dispose(); } private static void GetHref(ReportComponentBase obj, IRenderContext context) { context.OpenElement(A); if (obj is TextObject textObject) { string hrefStyle = "color:" + HTMLColor(textObject.TextColor); if (!textObject.Font.Underline) hrefStyle += ";text-decoration:none"; context.AddAttribute(STYLE, hrefStyle); } var hyperlink = obj.Hyperlink; if (hyperlink.Kind == HyperlinkKind.URL) { context.AddAttribute(HREF, hyperlink.Value); if (hyperlink.OpenLinkInNewTab) context.AddAttribute("target", "_blank"); } else if (hyperlink.Kind == HyperlinkKind.DetailReport) { context.AddOnClick(new OnClickEventArgs(obj, ClickType.DetailedReport)); } else if (hyperlink.Kind == HyperlinkKind.DetailPage) { context.AddOnClick(new OnClickEventArgs(obj, ClickType.DetailedPage)); } else if (hyperlink.Kind == HyperlinkKind.Bookmark) { context.AddOnClick(new OnClickEventArgs(obj, ClickType.Bookmark)); } else if (hyperlink.Kind == HyperlinkKind.PageNumber) { context.AddOnClick(new OnClickEventArgs(obj, ClickType.PageNumber)); } //context.CloseElement(); } private RenderFragment AddTextInput(TextObject obj, string classTag) { return b => { var context = new RenderContext(b); context.OpenComponent(); context.AddAttribute(nameof(TextInput.TextObject), obj); context.AddAttribute(nameof(TextInput.ClassTag), classTag); context.AddAttribute(nameof(TextInput.OnChange), new InputChanged(this, obj, CurPage)); context.CloseComponent(); }; } private RenderFragment GetSpanText(TextObjectBase obj, RenderFragment text, float top, float width, float ParagraphOffset) { return builder => { var context = new RenderContext(builder); StringBuilder style = new StringBuilder(64); style.Append("display:block;border:0;white-space: pre-wrap;width:").Append(PxClosed(width * Zoom)); if (ParagraphOffset != 0) style.Append("text-indent:").Append(PxClosed(ParagraphOffset * Zoom)); if (obj.Padding.Left != 0) style.Append("padding-left:").Append(PxClosed(obj.Padding.Left * Zoom)); if (obj.Padding.Right != 0) style.Append("padding-right:").Append(PxClosed(obj.Padding.Right * Zoom)); if (top != 0) style.Append("margin-top:").Append(PxClosed(top * Zoom)); if (obj is TextObject { WordWrap: false }) style.Append("overflow: hidden; text-wrap: nowrap;"); // we need to apply border width in order to position our div perfectly float borderLeft; float borderTop; if (HTMLBorderWidthValues(obj, out borderLeft, out borderTop, out _, out _)) { style.Append("position:absolute;left:").Append(Px(-1 * borderLeft / 2f)) .Append("px;top:").Append(Px(-1 * borderTop / 2f)).Append("px;"); } context.OpenElement(DIV); context.AddAttribute(CLASS, GetStyleTag(UpdateCSSTable(style))); context.AddContent(text); context.CloseElement(); }; } private void LayerText(IRenderContext context, TextObject obj) { float top = 0; RenderFragment text; switch (obj.TextRenderType) { case TextRenderType.HtmlParagraph: RenderFragment htmlParagraph; using (HtmlTextRenderer htmlTextRenderer = obj.GetHtmlTextRenderer(Zoom, Zoom)) { if (obj.VertAlign == VertAlign.Center) { top = (obj.Height - htmlTextRenderer.CalcHeight()) / 2; } else if (obj.VertAlign == VertAlign.Bottom) { top = obj.Height - htmlTextRenderer.CalcHeight(); } htmlParagraph = GetHtmlParagraph(htmlTextRenderer); } text = GetSpanText(obj, htmlParagraph, top + obj.Padding.Top, obj.Width - obj.Padding.Horizontal, obj.ParagraphOffset); break; default: if (obj.VertAlign != VertAlign.Top) { IGraphics g = htmlMeasureGraphics; using (Font f = new Font(obj.Font.FontFamily, obj.Font.Size * DrawUtils.ScreenDpiFX, obj.Font.Style)) { RectangleF textRect = new RectangleF(obj.AbsLeft + obj.Padding.Left, obj.AbsTop + obj.Padding.Top, obj.Width - obj.Padding.Left - obj.Padding.Right, obj.Height - obj.Padding.Top - obj.Padding.Bottom); StringFormat format = obj.GetStringFormat(Report.GraphicCache, 0); Brush textBrush = Report.GraphicCache.GetBrush(obj.TextColor); AdvancedTextRenderer renderer = new AdvancedTextRenderer(obj.Text, g, f, textBrush, null, textRect, format, obj.HorzAlign, obj.VertAlign, obj.LineHeight, obj.Angle, obj.FontWidthRatio, obj.ForceJustify, obj.Wysiwyg, obj.HasHtmlTags, false, Zoom, Zoom, obj.InlineImageCache); if (renderer.Paragraphs.Count > 0) { if (renderer.Paragraphs[0].Lines.Count > 0) { float height = renderer.Paragraphs[0].Lines[0].CalcHeight(); if (height > obj.Height) top = -(height - obj.Height) / 2; else { top = renderer.Paragraphs[0].Lines[0].Top - obj.AbsTop; height = renderer.CalcHeight(); if (obj.VertAlign == VertAlign.Center) { top = (obj.Height - height - obj.Padding.Bottom + obj.Padding.Top) / 2; if (top < 0) { if (obj.Height > height) top = (obj.Height - height - obj.Padding.Bottom + obj.Padding.Top) / 2; else top = (height - obj.Height - obj.Padding.Bottom + obj.Padding.Top) / 2; } } else if (obj.VertAlign == VertAlign.Bottom) { // (float)(Math.Round(obj.Font.Size * 96 / 72) / 2 // necessary to compensate for paragraph offset error in GetSpanText method below top = obj.Height - height - obj.Padding.Bottom - (float)(Math.Round(obj.Font.Size * 96 / 72) / 2); } } } } } } void htmlStringParse(RenderTreeBuilder builder) { var content = ExportUtils.HtmlString(obj.Text, obj.TextRenderType).ToString(); var context = new RenderContext(builder); context.AddMarkupContent(content); } text = GetSpanText(obj, htmlStringParse, top + obj.Padding.Top, obj.Width - obj.Padding.Horizontal, obj.ParagraphOffset); break; } context.AddContent(LayerBack(obj, text)); } private static RenderFragment GetHtmlParagraph(HtmlTextRenderer renderer) { return builder => { var context = new RenderContext(builder); foreach (HtmlTextRenderer.Paragraph paragraph in renderer.Paragraphs) foreach (HtmlTextRenderer.Line line in paragraph.Lines) { StringBuilder sb = new StringBuilder(128); context.OpenElement(SPAN); sb.Append("display:block;"); if (line.Top + line.Height > renderer.DisplayRect.Bottom) sb.Append("height:").Append(Math.Max(renderer.DisplayRect.Bottom - line.Top, 0).ToString(HtmlTextRenderer.CultureInfo)).Append("px;"); else { //sb.Append("height:").Append(line.Height.ToString(HtmlTextRenderer.CultureInfo)).Append("px;"); if (line.LineSpacing > 0) { sb.Append("margin-bottom:").Append(line.LineSpacing.ToString(HtmlTextRenderer.CultureInfo)).Append("px;"); } } sb.Append("overflow:hidden;"); sb.Append("line-height:").Append(line.Height.ToString(HtmlTextRenderer.CultureInfo)).Append("px;"); if (line.HorzAlign == HorzAlign.Justify) sb.Append("text-align-last:justify;"); else sb.Append("white-space:pre;"); context.AddAttribute(STYLE, sb.ToString()); FastString htmlText = new FastString(); HtmlTextRenderer.StyleDescriptor? styleDesc = null; foreach (HtmlTextRenderer.Word word in line.Words) { foreach (HtmlTextRenderer.Run run in word.Runs) { if (!run.Style.FullEquals(styleDesc)) { if (styleDesc != null) styleDesc.ToHtml(htmlText, true); // TODO: close ??? styleDesc = run.Style; styleDesc.ToHtml(htmlText, false); } if (run is HtmlTextRenderer.RunText runText) { foreach (char ch in runText.Text) { switch (ch) { case '"': htmlText.Append("""); break; case '&': htmlText.Append("&"); break; case '<': htmlText.Append("<"); break; case '>': htmlText.Append(">"); break; case '\t': htmlText.Append(" "); break; default: htmlText.Append(ch); break; } } } else if (run is HtmlTextRenderer.RunImage runImage) { using (MemoryStream ms = new MemoryStream()) { try { float w, h; using (Bitmap bmp = runImage.GetBitmap(out w, out h)) { bmp.Save(ms, ImageFormat.Png); } ms.Flush(); htmlText.Append(""); } catch (Exception /*e*/) { } } } //run.ToHtml(htmlText, true); } } if (styleDesc != null) styleDesc.ToHtml(htmlText, true); else htmlText.Append("
"); Debug.WriteLine($"BlazorExportLayers[485] SB.Length: {htmlText.Length}"); context.AddMarkupContent(htmlText.ToString()); context.CloseElement(); } }; } private RenderFragment LayerHtml(HtmlObject obj) { void textFragment(RenderTreeBuilder builder) { var context = new RenderContext(builder); context.AddContent(obj.Text); } return LayerBack(obj, GetSpanText(obj, textFragment, obj.Padding.Top, obj.Width - obj.Padding.Horizontal, 0)); } private string? GetLayerPicture(ReportComponentBase obj, out float Width, out float Height) { if(!pictures) { Width = 0; Height = 0; return null; } MemoryStream PictureStream = new MemoryStream(); Width = obj.Width == 0 ? obj.Border.LeftLine.Width : obj.Width; Height = obj.Height == 0 ? obj.Border.TopLine.Width : obj.Height; if (Math.Abs(Width) * Zoom < 1 && Zoom > 0) Width = 1 / Zoom; if (Math.Abs(Height) * Zoom < 1 && Zoom > 0) Height = 1 / Zoom; using (Image image = new Bitmap( (int)Math.Abs(Math.Round(Width * Zoom)), (int)Math.Abs(Math.Round(Height * Zoom))) ) { using (Graphics g = Graphics.FromImage(image)) { var needClear = obj is TextObjectBase #if MSCHART or MSChart.MSChartObject #endif or Gauge.GaugeObject; if (needClear) { g.Clear(Color.Transparent); g.TextRenderingHint = TextRenderingHint.AntiAlias; } float Left = Width > 0 ? obj.AbsLeft : obj.AbsLeft + Width; float Top = Height > 0 ? obj.AbsTop : obj.AbsTop + Height; float dx = 0; float dy = 0; g.TranslateTransform((-Left - dx) * Zoom, (-Top - dy) * Zoom); BorderLines oldLines = obj.Border.Lines; obj.Border.Lines = BorderLines.None; obj.Draw(new FRPaintEventArgs(g, Zoom, Zoom, Report.GraphicCache)); obj.Border.Lines = oldLines; } ImageFormat FPictureFormat = GetImageFormat(); if (FPictureFormat == ImageFormat.Jpeg) ExportUtils.SaveJpeg(image, PictureStream, 95); else image.Save(PictureStream, FPictureFormat); } PictureStream.Position = 0; string hash = String.Empty; if (obj is PictureObject pic) { if (pic.Image != null) { hash = Crypter.ComputeHash(PictureStream); PictureStream.Position = 0; } } else hash = Crypter.ComputeHash(PictureStream); string result = HTMLGetImage(d.CurrentPage, hash, PictureStream, false); return result; } private ImageFormat GetImageFormat() { ImageFormat FPictureFormat = ImageFormat.Bmp; if (imageFormat == ImageFormat.Png) FPictureFormat = ImageFormat.Png; else if (imageFormat == ImageFormat.Jpeg) FPictureFormat = ImageFormat.Jpeg; else if (imageFormat == ImageFormat.Gif) FPictureFormat = ImageFormat.Gif; return FPictureFormat; } #if !WASM private void LayerPicture(IRenderContext context, ReportComponentBase obj, RenderFragment? text) { if (pictures) { int styleindex = UpdateCSSTable(obj); string old_text = String.Empty; if (IsMemo(obj)) { old_text = (obj as TextObject).Text; (obj as TextObject).Text = String.Empty; } float Width, Height; string? pic = GetLayerPicture(obj, out Width, out Height); if (IsMemo(obj)) (obj as TextObject).Text = old_text; StringBuilder picStyleBuilder = new StringBuilder("background: url('") .Append(pic).Append("') no-repeat !important;-webkit-print-color-adjust:exact;"); int picStyleIndex = UpdateCSSTable(picStyleBuilder); string style = $"{stylePrefix}s{styleindex} {stylePrefix}s{picStyleIndex}"; //FastString addstyle = new FastString(128); //addstyle.Append(" background: url('").Append(pic).Append("') no-repeat !important;-webkit-print-color-adjust:exact;"); //if (String.IsNullOrEmpty(text)) // text = NBSP; float x = Width > 0 ? obj.AbsLeft : (obj.AbsLeft + Width); float y = Height > 0 ? obj.AbsTop : (obj.AbsTop + Height); Layer(context, obj, x, y, Width, Height, text, style, null); } } #endif private void LayerShape(IRenderContext context, ShapeObject obj) { StringBuilder addstyle = new StringBuilder(64); addstyle.Append(defaultStyle); addstyle.Append("background: url('"). Append(GetLayerPicture(obj, out _, out _)). Append("');no-repeat !important;-webkit-print-color-adjust:exact;"); float x = obj.Width > 0 ? obj.AbsLeft : (obj.AbsLeft + obj.Width); float y = obj.Height > 0 ? obj.AbsTop : (obj.AbsTop + obj.Height); Layer(context, obj, x, y, obj.Width, obj.Height, null, null, addstyle); } private RenderFragment LayerBack(ReportComponentBase obj, RenderFragment? text) { return (builder) => { var context = new RenderContext(builder, OnClick); if (obj.Border.Shadow) { using (TextObject shadow = new TextObject()) { shadow.Left = obj.AbsLeft + obj.Border.ShadowWidth + obj.Border.LeftLine.Width; shadow.Top = obj.AbsTop + obj.Height + obj.Border.BottomLine.Width; shadow.Width = obj.Width + obj.Border.RightLine.Width; shadow.Height = obj.Border.ShadowWidth + obj.Border.BottomLine.Width; shadow.FillColor = obj.Border.ShadowColor; shadow.Border.Lines = BorderLines.None; context.AddContent(LayerBack(shadow, null)); shadow.Left = obj.AbsLeft + obj.Width + obj.Border.RightLine.Width; shadow.Top = obj.AbsTop + obj.Border.ShadowWidth + obj.Border.TopLine.Width; shadow.Width = obj.Border.ShadowWidth + obj.Border.RightLine.Width; shadow.Height = obj.Height; context.AddContent(LayerBack(shadow, null)); } } if (!(obj is PolyLineObject)) { if (obj.Fill is SolidFill) Layer(context, obj, obj.AbsLeft, obj.AbsTop, obj.Width, obj.Height, text, GetStyleTag(UpdateCSSTable(obj)), null); else LayerPicture(context, obj, text); } }; } private void LayerTable(IRenderContext context, TableBase table) { float y = 0; for (int i = 0; i < table.RowCount; i++) { float x = 0; for (int j = 0; j < table.ColumnCount; j++) { if (!table.IsInsideSpan(table[j, i])) { TableCell textcell = table[j, i]; textcell.Left = x; textcell.Top = y; if (textcell is TextObject && !textcell.TextOutline.Enabled && IsMemo(textcell)) LayerText(context, textcell); else { context.AddContent(LayerBack(textcell, null)); LayerPicture(context, textcell, null); } } x += table.Columns[j].Width; } y += table.Rows[i].Height; } } private static bool IsMemo(ReportComponentBase Obj) { if(Obj is TextObject aObj) { return (aObj.Angle == 0) && (aObj.FontWidthRatio == 1) && (!aObj.TextOutline.Enabled) && (!aObj.Underlines); } return false; } private void Watermark(IRenderContext context, ReportPage page, bool drawText) { using (PictureObject pictureWatermark = new PictureObject()) { pictureWatermark.Left = 0; pictureWatermark.Top = 0; pictureWatermark.Width = (ExportUtils.GetPageWidth(page) - page.LeftMargin - page.RightMargin) * Units.Millimeters; pictureWatermark.Height = (ExportUtils.GetPageHeight(page) - page.TopMargin - page.BottomMargin) * Units.Millimeters; pictureWatermark.SizeMode = PictureBoxSizeMode.Normal; pictureWatermark.Image = new Bitmap((int)pictureWatermark.Width, (int)pictureWatermark.Height); using (Graphics g = Graphics.FromImage(pictureWatermark.Image)) { g.Clear(Color.Transparent); if (drawText) page.Watermark.DrawText(new FRPaintEventArgs(g, 1f, 1f, Report.GraphicCache), new RectangleF(0, 0, pictureWatermark.Width, pictureWatermark.Height), Report, true); else page.Watermark.DrawImage(new FRPaintEventArgs(g, 1f, 1f, Report.GraphicCache), new RectangleF(0, 0, pictureWatermark.Width, pictureWatermark.Height), Report, true); pictureWatermark.Transparency = page.Watermark.ImageTransparency; context.AddContent(LayerBack(pictureWatermark, null)); LayerPicture(context, pictureWatermark, null); } } } private void ExportHTMLPageLayeredBegin(in HTMLData d) { //bands = new List(); ReportPage reportPage = d.page; if (reportPage != null) { maxWidth = ExportUtils.GetPageWidth(reportPage) * Units.Millimeters; maxHeight = ExportUtils.GetPageHeight(reportPage) * Units.Millimeters; if (enableMargins) { leftMargin = reportPage.LeftMargin * Units.Millimeters; topMargin = reportPage.TopMargin * Units.Millimeters; } else { maxWidth -= (reportPage.LeftMargin + reportPage.RightMargin) * Units.Millimeters; maxHeight -= (reportPage.TopMargin + reportPage.BottomMargin) * Units.Millimeters; leftMargin = 0; topMargin = 0; } currentPage = d.PageNumber - 1; ExportHTMLPageStart(d.PageNumber, d.CurrentPage); doPageBreak = singlePage && pageBreaks; pageStyleName = "frpage" + currentPage; BeginLayer(d); } } void BeginLayer(in HTMLData d) { ReportPage reportPage = d.page; var context = globalContext; context.AddContent(HTMLGetAncor(d.PageNumber)); context.OpenElement(DIV); if (doPageBreak) context.AddAttribute(CLASS, pageStyleName); string style = $"position:relative; width:{Px(maxWidth * Zoom + 3)}px; height:{Px(maxHeight * Zoom)}px;"; if (reportPage.Fill is SolidFill fill) { style += " background-color:" + (fill.IsTransparent ? "transparent" : HTMLColor(fill.Color)); } else { // to-do for picture background } context.AddAttribute(STYLE, style); if(reportPage.Watermark.Enabled) { if (!reportPage.Watermark.ShowImageOnTop) Watermark(context, reportPage, false); if (!reportPage.Watermark.ShowTextOnTop) Watermark(context, reportPage, true); } } void EndLayer(IRenderContext context, in HTMLData d) { // to do ReportPage reportPage = d.page; if(reportPage.Watermark.Enabled) { if (reportPage.Watermark.ShowImageOnTop) Watermark(context, reportPage, false); if (reportPage.Watermark.ShowTextOnTop) Watermark(context, reportPage, true); } context.CloseElement(); // "" } private void ExportHTMLPageLayeredEnd(in HTMLData d) { var context = globalContext; EndLayer(context, d); ExportPageStylesLayers(context); if (singlePage) { prevStyleListIndex = cssStyles.Count; } ExportHTMLPageFinal(d, maxWidth, maxHeight); } private void ExportBandLayers(in BandBase band) { var context = globalContext; context.AddContent(LayerBack(band, null)); foreach (Base c in band.ForEachAllConvectedObjects(this)) { ExportObject(c as ReportComponentBase, context); } } private void ExportObject(ReportComponentBase? obj, in IRenderContext context) { if (obj == null) return; if (cancellationToken.IsCancellationRequested) return; if (obj is MatrixButton matrixButton) { matrixButton.Exportable = true; } if (obj.Exportable) { if (!String.IsNullOrEmpty(obj.Bookmark)) { context.OpenElement(A); context.AddAttribute(NAME, obj.Bookmark); context.CloseElement(); } if (obj is CellularTextObject cellularTextObject) obj = cellularTextObject.GetTable(); if (obj is TableCell) return; else if (obj is TableBase table) { if (table.ColumnCount > 0 && table.RowCount > 0) { using (TextObject tableback = new TextObject()) { tableback.Border = table.Border; tableback.Fill = table.Fill; tableback.FillColor = table.FillColor; tableback.Left = table.AbsLeft; tableback.Top = table.AbsTop; float tableWidth = 0; float tableHeight = 0; for (int i = 0; i < table.ColumnCount; i++) tableWidth += table[i, 0].Width; for (int i = 0; i < table.RowCount; i++) tableHeight += table.Rows[i].Height; tableback.Width = (tableWidth < table.Width) ? tableWidth : table.Width; tableback.Height = tableHeight; LayerText(context, tableback); } LayerTable(context, table); } } else if (IsMemo(obj)) { LayerText(context, obj as TextObject); } else if (obj is HtmlObject htmlObject) { context.AddContent(LayerHtml(htmlObject)); } else if (obj is BandBase) { context.AddContent(LayerBack(obj, null)); } else if (obj is LineObject) { LayerPicture(context, obj, null); } else if (obj is ShapeObject shapeObject) { LayerShape(context, shapeObject); } else if (HasExtendedExport(obj)) { LayerSVG(context, obj as SVGObject); } else { context.AddContent(LayerBack(obj, null)); LayerPicture(context, obj, null); } } } } }