private void DrawString(PageText pt, Xwt.Drawing.Context g, Xwt.Rectangle r) { StyleInfo si = pt.SI; string s = pt.Text; g.Save(); layout = new Xwt.Drawing.TextLayout(g); layout.Font = g.Font; float fontsize = (si.FontSize * 72 / 96); layout.Font.WithFamily(si.GetFontFamily().Name); layout.Font.WithPixelSize(fontsize * PixelsX(1)); if (si.FontStyle == FontStyleEnum.Italic) layout.Font.WithStyle(Xwt.Drawing.FontStyle.Italic); switch (si.FontWeight) { case FontWeightEnum.Bold: case FontWeightEnum.Bolder: case FontWeightEnum.W500: case FontWeightEnum.W600: case FontWeightEnum.W700: case FontWeightEnum.W800: case FontWeightEnum.W900: layout.Font.WithWeight(Xwt.Drawing.FontWeight.Bold); break; } // TODO: Fix Alignment //switch (si.TextAlign) //{ // case TextAlignEnum.Right: // layout.Alignment = Pango.Alignment.Right; // break; // case TextAlignEnum.Center: // layout.Alignment = Pango.Alignment.Center; // break; // case TextAlignEnum.Left: // default: // layout.Alignment = Pango.Alignment.Left; // break; //} // TODO: Fix with //layout.Width = Pango.Units.FromPixels((int)(r.Width - si.PaddingLeft - si.PaddingRight - 2)); layout.Text = s; //Xwt.Rectangle logical; // Xwt.Rectangle ink; // TODO: Fix //layout.GetExtents(out ink, out logical); double height = 12; // logical.Height / Pango.Scale.PangoScale; double y = 0; switch (si.VerticalAlign) { case VerticalAlignEnum.Top: y = r.Y + si.PaddingTop; break; case VerticalAlignEnum.Middle: y = r.Y + (r.Height - height) / 2; break; case VerticalAlignEnum.Bottom: y = r.Y + (r.Height - height) - si.PaddingBottom; break; } // draw the background DrawBackground(g, r, si); Xwt.Rectangle box = new Xwt.Rectangle( r.X + si.PaddingLeft + 1, y, r.Width, r.Height); Xwt.Drawing.Color sicolor = XwtColor.SystemColorToXwtColor(si.Color); g.SetColor(sicolor); g.MoveTo(box.X, box.Y); g.DrawTextLayout(layout, box.X, box.Y); g.Restore(); }
private void DrawString(PageText pt, Graphics g, RectangleF r) { StyleInfo si = pt.SI; string s = pt.Text; Font drawFont = null; StringFormat drawFormat = null; Brush drawBrush = null; try { // STYLE System.Drawing.FontStyle fs = 0; if (si.FontStyle == FontStyleEnum.Italic) fs |= System.Drawing.FontStyle.Italic; switch (si.TextDecoration) { case TextDecorationEnum.Underline: fs |= System.Drawing.FontStyle.Underline; break; case TextDecorationEnum.LineThrough: fs |= System.Drawing.FontStyle.Strikeout; break; case TextDecorationEnum.Overline: case TextDecorationEnum.None: break; } // WEIGHT switch (si.FontWeight) { case FontWeightEnum.Bold: case FontWeightEnum.Bolder: case FontWeightEnum.W500: case FontWeightEnum.W600: case FontWeightEnum.W700: case FontWeightEnum.W800: case FontWeightEnum.W900: fs |= System.Drawing.FontStyle.Bold; break; default: break; } try { drawFont = new Font(si.GetFontFamily(), si.FontSize, fs); // si.FontSize already in points } catch (ArgumentException) { drawFont = new Font("Arial", si.FontSize, fs); // if this fails we'll let the error pass thru } // ALIGNMENT drawFormat = new StringFormat(); switch (si.TextAlign) { case TextAlignEnum.Right: drawFormat.Alignment = StringAlignment.Far; break; case TextAlignEnum.Center: drawFormat.Alignment = StringAlignment.Center; break; case TextAlignEnum.Left: default: drawFormat.Alignment = StringAlignment.Near; break; } if (pt.SI.WritingMode == WritingModeEnum.tb_rl) { drawFormat.FormatFlags |= StringFormatFlags.DirectionRightToLeft; drawFormat.FormatFlags |= StringFormatFlags.DirectionVertical; } switch (si.VerticalAlign) { case VerticalAlignEnum.Bottom: drawFormat.LineAlignment = StringAlignment.Far; break; case VerticalAlignEnum.Middle: drawFormat.LineAlignment = StringAlignment.Center; break; case VerticalAlignEnum.Top: default: drawFormat.LineAlignment = StringAlignment.Near; break; } // draw the background DrawBackground(g, r, si); // adjust drawing rectangle based on padding // http://www.fyireporting.com/forum/viewtopic.php?t=892 //A.S.> convert pt to px if needed(when printing we need px, when draw preview - pt) RectangleF r2; if (g.PageUnit == GraphicsUnit.Pixel) { r2 = new RectangleF(r.Left + (si.PaddingLeft * g.DpiX) / 72, r.Top + (si.PaddingTop * g.DpiX) / 72, r.Width - ((si.PaddingLeft + si.PaddingRight) * g.DpiX) / 72, r.Height - ((si.PaddingTop + si.PaddingBottom) * g.DpiX) / 72); } else { // adjust drawing rectangle based on padding r2 = new RectangleF(r.Left + si.PaddingLeft, r.Top + si.PaddingTop, r.Width - si.PaddingLeft - si.PaddingRight, r.Height - si.PaddingTop - si.PaddingBottom); } drawBrush = new SolidBrush(si.Color); if (si.TextAlign == TextAlignEnum.Justified) { GraphicsExtended.DrawStringJustified(g, pt.Text, drawFont, drawBrush, r2); } else if (pt.NoClip) // request not to clip text { g.DrawString(pt.Text, drawFont, drawBrush, new PointF(r.Left, r.Top), drawFormat); HighlightString(g, pt, new RectangleF(r.Left, r.Top, float.MaxValue, float.MaxValue), drawFont, drawFormat); } else { g.DrawString(pt.Text, drawFont, drawBrush, r2, drawFormat); HighlightString(g, pt, r2, drawFont, drawFormat); } if (SelectTool) { if (pt.AllowSelect && _SelectList.Contains(pt)) g.FillRectangle(new SolidBrush(Color.FromArgb(50, _SelectItemColor)), r2); } } finally { if (drawFont != null) drawFont.Dispose(); if (drawFormat != null) drawFont.Dispose(); if (drawBrush != null) drawBrush.Dispose(); } }
override internal void RunPage(Pages pgs, Row row) { Report r = pgs.Report; TextboxRuntime tbr = TextboxRuntime.GetTextboxRuntime(r, this); tbr.RunCount++; // Increment the run count bool bHidden = IsHidden(r, row); SetPagePositionBegin(pgs); string t; if (bHidden) t = ""; else t = RunText(r, row); // get the text bool bDup = RunTextIsDuplicate(tbr, t, pgs.CurrentPage); if (bDup) { if (!(this.IsTableOrMatrixCell(r))) // don't put out anything if not in Table or Matrix bHidden = true; t = ""; // still need to put out the cell } PageText pt; PageTextHtml pth=null; if (IsHtml(r, row)) pt = pth = new PageTextHtml(t); else pt = new PageText(t); SetPagePositionAndStyle(r, pt, row); if (this.CanGrow && tbr.RunHeight == 0) // when textbox is in a DataRegion this will already be called { this.RunTextCalcHeight(r, pgs.G, row, pt is PageTextHtml? pt as PageTextHtml: null); } pt.H = Math.Max(pt.H, tbr.RunHeight); // reset height if (pt.SI.BackgroundImage != null) pt.SI.BackgroundImage.H = pt.H; // and in the background image pt.CanGrow = this.CanGrow; // check TextAlign: if General then correct based on data type if (pt.SI.TextAlign == TextAlignEnum.General) { if (DataType.IsNumeric(this.Value.GetTypeCode() )) pt.SI.TextAlign = TextAlignEnum.Right; } // Hidden objects don't affect the current page? if (!bHidden) { // Force page break if it doesn't fit on a page if (this.IsInBody && // Only force page when object directly in body pgs.CurrentPage.YOffset + pt.Y + pt.H >= pgs.BottomOfPage && // running off end of page !pgs.CurrentPage.IsEmpty()) // if page is already empty don't force new { // force page break if it doesn't fit on the page pgs.NextOrNew(); pgs.CurrentPage.YOffset = OwnerReport.TopOfPage; if (this.YParents != null) pt.Y = 0; } Page p = pgs.CurrentPage; RecordPageReference(r, p, row); // save information for late page header/footer references p.AddObject(pt); if (!bDup) { tbr.PreviousText = t; // previous text displayed tbr.PreviousPage = p; // page previous text was shown on } } SetPagePositionEnd(pgs, pt.Y+pt.H); if (pth != null) pth.Reset(); if (this.CanGrow && !Value.IsConstant()) { tbr.RunHeight = 0; // need to recalculate } }
protected internal abstract void AddBookmark(PageText pt);
protected internal override void AddBookmark(PageText pt) { }
private PageImage BuildImage(Graphics g, string token, StyleInfo oldsi, PageText model) { PageTextHtmlCmdLexer hc = new PageTextHtmlCmdLexer(token.Substring(4)); Hashtable ht = hc.Lex(); string src = (string)ht["src"]; if (src == null || src.Length < 1) return null; string alt = (string)ht["alt"]; string height = (string)ht["height"]; string width = (string)ht["width"]; string align = (string)ht["align"]; Stream strm = null; System.Drawing.Image im = null; PageImage pi = null; try { // Obtain the image stream if (src.StartsWith("http:") || src.StartsWith("file:") || src.StartsWith("https:")) { WebRequest wreq = WebRequest.Create(src); WebResponse wres = wreq.GetResponse(); strm = wres.GetResponseStream(); } else strm = new FileStream(src, System.IO.FileMode.Open, FileAccess.Read); im = System.Drawing.Image.FromStream(strm); int h = im.Height; int w = im.Width; MemoryStream ostrm = new MemoryStream(); ImageFormat imf; imf = ImageFormat.Jpeg; im.Save(ostrm, imf); byte[] ba = ostrm.ToArray(); ostrm.Close(); pi = new PageImage(imf, ba, w, h); pi.AllowSelect = false; pi.Page = this.Page; pi.HyperLink = model.HyperLink; pi.Tooltip = alt == null ? model.Tooltip : alt; pi.X = 0; pi.Y = 0; pi.W = RSize.PointsFromPixels(g, width != null? Convert.ToInt32(width): w); pi.H = RSize.PointsFromPixels(g, height != null? Convert.ToInt32(height): h); pi.SI = new StyleInfo(); } catch { pi = null; } finally { if (strm != null) strm.Close(); if (im != null) im.Dispose(); } return pi; }
SizeF MeasureString(PageText pt) { //PJR - need to identify actual text size for alignment Bitmap myBitmap = new Bitmap(1,1); Graphics g = Graphics.FromImage(myBitmap); FontStyle fs = FontStyle.Regular; g.PageUnit = GraphicsUnit.Point; if (pt.SI.FontStyle == FontStyleEnum.Italic) fs |= FontStyle.Italic ; if (pt.SI.FontWeight != FontWeightEnum.Normal) fs |= FontStyle.Bold; if (pt.SI.TextDecoration == TextDecorationEnum.Underline) fs |= FontStyle.Underline; //Add width of "w" to ensure the whole text fits SizeF textsize = new SizeF( g.MeasureString(pt.Text, (Font)new Font(pt.SI.FontFamily, pt.SI.FontSize, fs))); g.Dispose(); myBitmap.Dispose(); return textsize; }
protected internal virtual void AddBookmark(PageText pt) { }
/// <summary> /// Page Text element at the X Y position; multiple lines handled /// </summary> /// <returns></returns> protected internal virtual void AddText(PageText pt, Pages pgs) { }
override internal void RunPage(Pages pgs, Row row) { Report r = pgs.Report; if (IsHidden(r, row)) { return; } base.RunPage(pgs, row); // need to save the owner report and nest in this defintion ReportDefn saveReport = r.ReportDefinition; NeedPassword np = r.GetDataSourceReferencePassword; // get current password r.SetReportDefinition(_ReportDefn); r.Folder = _ReportDefn.ParseFolder; // folder needs to get set since the id of the report is used by the cache r.GetDataSourceReferencePassword = np; DataSourcesDefn saveDS = r.ParentConnections; if (this.MergeTransactions) { r.ParentConnections = saveReport.DataSourcesDefn; } else { r.ParentConnections = null; } r.SubreportDataRetrievalTriggerEvent(); bool bRows = true; if (_Parameters == null) { // When no parameters we only retrieve data once SubreportWorkClass wc = r.Cache.Get(this, "report") as SubreportWorkClass; if (wc == null) { // run report first time; bRows = r.RunGetData(null); if (!r.IsSubreportDataRetrievalDefined) // if use has defined subreportdataretrieval they might set data { r.Cache.Add(this, "report", new SubreportWorkClass(bRows)); // so we can't cache } } else { bRows = wc.bRows; } } else { SetSubreportParameters(r, row); // apply the parameters bRows = r.RunGetData(null); } SetPageLeft(r); // Set the Left attribute since this will be the margin for this report SetPagePositionBegin(pgs); float yOffset; if (bRows) // Only run subreport if have a row in some Dataset { // // Run the subreport -- this is the major effort in creating the display objects in the page // r.ReportDefinition.Body.RunPage(pgs); // create a the subreport items yOffset = pgs.CurrentPage.YOffset; } else { // Handle NoRows message string msg; if (this.NoRows != null) { msg = this.NoRows.EvaluateString(pgs.Report, null); } else { msg = null; } if (msg != null) { PageText pt = new PageText(msg); SetPagePositionAndStyle(pgs.Report, pt, null); if (pt.SI.BackgroundImage != null) { pt.SI.BackgroundImage.H = pt.H; // and in the background image } pgs.CurrentPage.AddObject(pt); yOffset = pt.Y + pt.H; } else { yOffset = pgs.CurrentPage.YOffset; } } r.SetReportDefinition(saveReport); // restore the current report r.ParentConnections = saveDS; // restore the data connnections SetPagePositionEnd(pgs, yOffset); }
internal abstract protected void AddBookmark(PageText pt);
private string[] MeasureString(PageText pt, Graphics g, out float[] width) { StyleInfo si = pt.SI; string s = pt.Text; System.Drawing.Font drawFont = null; StringFormat drawFormat = null; SizeF ms; string[] sa = null; width = null; try { // STYLE System.Drawing.FontStyle fs = 0; if (si.FontStyle == FontStyleEnum.Italic) { fs |= System.Drawing.FontStyle.Italic; } // WEIGHT switch (si.FontWeight) { case FontWeightEnum.Bold: case FontWeightEnum.Bolder: case FontWeightEnum.W500: case FontWeightEnum.W600: case FontWeightEnum.W700: case FontWeightEnum.W800: case FontWeightEnum.W900: fs |= System.Drawing.FontStyle.Bold; break; default: break; } drawFont = new System.Drawing.Font(StyleInfo.GetFontFamily(si.FontFamilyFull), si.FontSize, fs); drawFormat = new StringFormat(); drawFormat.Alignment = StringAlignment.Near; // Measure string // pt.NoClip indicates that this was generated by PageTextHtml Build. It has already word wrapped. if (pt.NoClip || pt.SI.WritingMode == WritingModeEnum.tb_rl) // TODO: support multiple lines for vertical text { ms = MeasureString(s, g, drawFont, drawFormat); width = new float[1]; width[0] = Measurement.PointsFromPixels(ms.Width, g.DpiX); // convert to points from pixels sa = new string[1]; sa[0] = s; return(sa); } // handle multiple lines; // 1) split the string into the forced line breaks (ie "\n and \r") // 2) foreach of the forced line breaks; break these into words and recombine s = s.Replace("\r\n", "\n"); // don't want this to result in double lines string[] flines = s.Split(LINEBREAK); List <string> lines = new List <string>(); List <float> lineWidths = new List <float>(); // remove the size reserved for left and right padding float ptWidth = pt.W - pt.SI.PaddingLeft - pt.SI.PaddingRight; if (ptWidth <= 0) { ptWidth = 1; } foreach (string tfl in flines) { string fl; if (tfl.Length > 0 && tfl[tfl.Length - 1] == ' ') { fl = tfl.TrimEnd(' '); } else { fl = tfl; } // Check if entire string fits into a line ms = MeasureString(fl, g, drawFont, drawFormat); float tw = Measurement.PointsFromPixels(ms.Width, g.DpiX); if (tw <= ptWidth) { // line fits don't need to break it down further lines.Add(fl); lineWidths.Add(tw); continue; } // Line too long; need to break into multiple lines // 1) break line into parts; then build up again keeping track of word positions string[] parts = fl.Split(WORDBREAK); // this is the maximum split of lines StringBuilder sb = new StringBuilder(fl.Length); CharacterRange[] cra = new CharacterRange[parts.Length]; for (int i = 0; i < parts.Length; i++) { int sc = sb.Length; // starting character sb.Append(parts[i]); // endding character if (i != parts.Length - 1) // last item doesn't need blank { sb.Append(" "); } int ec = sb.Length; CharacterRange cr = new CharacterRange(sc, ec - sc); cra[i] = cr; // add to character array } // 2) Measure the word locations within the line string wfl = sb.ToString(); WordStartFinish[] wordLocations = MeasureString(wfl, g, drawFont, drawFormat, cra); if (wordLocations == null) { continue; } // 3) Loop thru creating new lines as needed int startLoc = 0; CharacterRange crs = cra[startLoc]; CharacterRange cre = cra[startLoc]; float cwidth = wordLocations[0].end; // length of the first float bwidth = wordLocations[0].start; // characters need a little extra on start string ts; bool bLine = true; for (int i = 1; i < cra.Length; i++) { cwidth = wordLocations[i].end - wordLocations[startLoc].start + bwidth; if (cwidth > ptWidth) { // time for a new line cre = cra[i - 1]; ts = wfl.Substring(crs.First, cre.First + cre.Length - crs.First); lines.Add(ts); lineWidths.Add(wordLocations[i - 1].end - wordLocations[startLoc].start + bwidth); // Find the first non-blank character of the next line while (i < cra.Length && cra[i].Length == 1 && fl[cra[i].First] == ' ') { i++; } if (i < cra.Length) // any lines left? { // yes, continue on startLoc = i; crs = cre = cra[startLoc]; cwidth = wordLocations[i].end - wordLocations[startLoc].start + bwidth; } else // no, we can stop { bLine = false; } // bwidth = wordLocations[startLoc].start - wordLocations[startLoc - 1].end; } else { cre = cra[i]; } } if (bLine) { ts = fl.Substring(crs.First, cre.First + cre.Length - crs.First); lines.Add(ts); lineWidths.Add(cwidth); } } // create the final array from the Lists string[] la = lines.ToArray(); width = lineWidths.ToArray(); return(la); } finally { if (drawFont != null) { drawFont.Dispose(); } if (drawFormat != null) { drawFont.Dispose(); } } }
// render all the objects in a page in PDF private void ProcessPage(Pages pgs, IEnumerable items) { foreach (PageItem pi in items) { if (pi.SI.BackgroundImage != null) { // put out any background image PageImage bgImg = pi.SI.BackgroundImage; // elements.AddImage(images, i.Name, content.objectNum, i.SI, i.ImgFormat, // pi.X, pi.Y, pi.W, pi.H, i.ImageData,i.SamplesW, i.SamplesH, null); //Duc Phan modified 10 Dec, 2007 to support on background image float imW = Measurement.PointsFromPixels(bgImg.SamplesW, pgs.G.DpiX); float imH = Measurement.PointsFromPixels(bgImg.SamplesH, pgs.G.DpiY); int repeatX = 0; int repeatY = 0; float itemW = pi.W - (pi.SI.PaddingLeft + pi.SI.PaddingRight); float itemH = pi.H - (pi.SI.PaddingTop + pi.SI.PaddingBottom); switch (bgImg.Repeat) { case ImageRepeat.Repeat: repeatX = (int)Math.Floor(itemW / imW); repeatY = (int)Math.Floor(itemH / imH); break; case ImageRepeat.RepeatX: repeatX = (int)Math.Floor(itemW / imW); repeatY = 1; break; case ImageRepeat.RepeatY: repeatY = (int)Math.Floor(itemH / imH); repeatX = 1; break; case ImageRepeat.NoRepeat: default: repeatX = repeatY = 1; break; } //make sure the image is drawn at least 1 times repeatX = Math.Max(repeatX, 1); repeatY = Math.Max(repeatY, 1); float currX = pi.X + pi.SI.PaddingLeft; float currY = pi.Y + pi.SI.PaddingTop; float startX = currX; float startY = currY; for (int i = 0; i < repeatX; i++) { for (int j = 0; j < repeatY; j++) { currX = startX + i * imW; currY = startY + j * imH; AddImage(bgImg.Name, bgImg.SI, bgImg.ImgFormat, currX, currY, imW, imH, RectangleF.Empty, bgImg.ImageData, bgImg.SamplesW, bgImg.SamplesH, null, pi.Tooltip); } } } if (pi is PageTextHtml) { PageTextHtml pth = pi as PageTextHtml; pth.Build(pgs.G); ProcessPage(pgs, pth); continue; } if (pi is PageText) { PageText pt = pi as PageText; float[] textwidth; string[] sa = MeasureString(pt, pgs.G, out textwidth); AddText(pt.X, pt.Y, pt.H, pt.W, sa, pt.SI, textwidth, pt.CanGrow, pt.HyperLink, pt.NoClip, pt.Tooltip); if (pt.Bookmark != null) { AddBookmark(pt); } continue; } if (pi is PageLine) { PageLine pl = pi as PageLine; AddLine(pl.X, pl.Y, pl.X2, pl.Y2, pl.SI); continue; } if (pi is PageEllipse) { PageEllipse pe = pi as PageEllipse; AddEllipse(pe.X, pe.Y, pe.H, pe.W, pe.SI, pe.HyperLink); continue; } if (pi is PageImage) { PageImage i = pi as PageImage; //Duc Phan added 20 Dec, 2007 to support sized image RectangleF r2 = new RectangleF(i.X + i.SI.PaddingLeft, i.Y + i.SI.PaddingTop, i.W - i.SI.PaddingLeft - i.SI.PaddingRight, i.H - i.SI.PaddingTop - i.SI.PaddingBottom); RectangleF adjustedRect; // work rectangle RectangleF clipRect = RectangleF.Empty; switch (i.Sizing) { case ImageSizingEnum.AutoSize: adjustedRect = new RectangleF(r2.Left, r2.Top, r2.Width, r2.Height); break; case ImageSizingEnum.Clip: adjustedRect = new RectangleF(r2.Left, r2.Top, Measurement.PointsFromPixels(i.SamplesW, pgs.G.DpiX), Measurement.PointsFromPixels(i.SamplesH, pgs.G.DpiY)); clipRect = new RectangleF(r2.Left, r2.Top, r2.Width, r2.Height); break; case ImageSizingEnum.FitProportional: float height; float width; float ratioIm = (float)i.SamplesH / i.SamplesW; float ratioR = r2.Height / r2.Width; height = r2.Height; width = r2.Width; if (ratioIm > ratioR) { // this means the rectangle width must be corrected width = height * (1 / ratioIm); } else if (ratioIm < ratioR) { // this means the rectangle height must be corrected height = width * ratioIm; } adjustedRect = new RectangleF(r2.X, r2.Y, width, height); break; case ImageSizingEnum.Fit: default: adjustedRect = r2; break; } if (i.ImgFormat == System.Drawing.Imaging.ImageFormat.Wmf || i.ImgFormat == System.Drawing.Imaging.ImageFormat.Emf) { //We dont want to add it - its already been broken down into page items; } else { AddImage(i.Name, i.SI, i.ImgFormat, adjustedRect.X, adjustedRect.Y, adjustedRect.Width, adjustedRect.Height, clipRect, i.ImageData, i.SamplesW, i.SamplesH, i.HyperLink, i.Tooltip); } continue; } if (pi is PageRectangle) { PageRectangle pr = pi as PageRectangle; AddRectangle(pr.X, pr.Y, pr.H, pr.W, pi.SI, pi.HyperLink, pi.Tooltip); continue; } if (pi is PagePie) { // TODO PagePie pp = pi as PagePie; // AddPie(pp.X, pp.Y, pp.H, pp.W, pi.SI, pi.HyperLink, pi.Tooltip); continue; } if (pi is PagePolygon) { PagePolygon ppo = pi as PagePolygon; AddPolygon(ppo.Points, pi.SI, pi.HyperLink); continue; } if (pi is PageCurve) { PageCurve pc = pi as PageCurve; AddCurve(pc.Points, pi.SI); continue; } } }
private void ProcessPage(Graphics g, IEnumerable p) { foreach (PageItem pi in p) { if (pi is PageTextHtml) { // PageTextHtml is actually a composite object (just like a page) ProcessHtml(pi as PageTextHtml, g); continue; } if (pi is PageLine) { PageLine pl = pi as PageLine; DrawLine( pl.SI.BColorLeft, pl.SI.BStyleLeft, pl.SI.BWidthLeft, g, PixelsX(pl.X), PixelsY(pl.Y), PixelsX(pl.X2), PixelsY(pl.Y2) ); continue; } RectangleF rect = new RectangleF(PixelsX(pi.X), PixelsY(pi.Y), PixelsX(pi.W), PixelsY(pi.H)); if (pi.SI.BackgroundImage != null) { // put out any background image PageImage i = pi.SI.BackgroundImage; DrawImage(i, g, rect); } if (pi is PageText) { PageText pt = pi as PageText; DrawString(pt, g, rect); } else if (pi is PageImage) { PageImage i = pi as PageImage; DrawImage(i, g, rect); } else if (pi is PageRectangle) { this.DrawBackground(g, rect, pi.SI); } else if (pi is PageEllipse) { PageEllipse pe = pi as PageEllipse; DrawEllipse(pe, g, rect); } else if (pi is PagePie) { PagePie pp = pi as PagePie; DrawPie(pp, g, rect); } else if (pi is PagePolygon) { PagePolygon ppo = pi as PagePolygon; FillPolygon(ppo, g, rect); } else if (pi is PageCurve) { PageCurve pc = pi as PageCurve; DrawCurve(pc.SI.BColorLeft, pc.SI.BStyleLeft, pc.SI.BWidthLeft, g, pc.Points, pc.Offset, pc.Tension); } DrawBorder(pi, g, rect); } }
private void DrawString(PageText pt, Graphics g, RectangleF r) { StyleInfo si = pt.SI; string s = pt.Text; Font drawFont=null; StringFormat drawFormat=null; Brush drawBrush=null; try { // STYLE System.Drawing.FontStyle fs = 0; if (si.FontStyle == FontStyleEnum.Italic) fs |= System.Drawing.FontStyle.Italic; switch (si.TextDecoration) { case TextDecorationEnum.Underline: fs |= System.Drawing.FontStyle.Underline; break; case TextDecorationEnum.LineThrough: fs |= System.Drawing.FontStyle.Strikeout; break; case TextDecorationEnum.Overline: case TextDecorationEnum.None: break; } // WEIGHT switch (si.FontWeight) { case FontWeightEnum.Bold: case FontWeightEnum.Bolder: case FontWeightEnum.W500: case FontWeightEnum.W600: case FontWeightEnum.W700: case FontWeightEnum.W800: case FontWeightEnum.W900: fs |= System.Drawing.FontStyle.Bold; break; default: break; } drawFont = new Font(si.GetFontFamily(), si.FontSize, fs); // si.FontSize already in points // ALIGNMENT drawFormat = new StringFormat(); switch (si.TextAlign) { case TextAlignEnum.Right: drawFormat.Alignment = StringAlignment.Far; break; case TextAlignEnum.Center: drawFormat.Alignment = StringAlignment.Center; break; case TextAlignEnum.Left: default: drawFormat.Alignment = StringAlignment.Near; break; } if (pt.SI.WritingMode == WritingModeEnum.tb_rl) { drawFormat.FormatFlags |= StringFormatFlags.DirectionRightToLeft; drawFormat.FormatFlags |= StringFormatFlags.DirectionVertical; } switch (si.VerticalAlign) { case VerticalAlignEnum.Bottom: drawFormat.LineAlignment = StringAlignment.Far; break; case VerticalAlignEnum.Middle: drawFormat.LineAlignment = StringAlignment.Center; break; case VerticalAlignEnum.Top: default: drawFormat.LineAlignment = StringAlignment.Near; break; } // draw the background DrawBackground(g, r, si); // adjust drawing rectangle based on padding RectangleF r2 = new RectangleF(r.Left + si.PaddingLeft, r.Top + si.PaddingTop, r.Width - si.PaddingLeft - si.PaddingRight, r.Height - si.PaddingTop - si.PaddingBottom); drawBrush = new SolidBrush(si.Color); if (pt.NoClip) // request not to clip text g.DrawString(pt.Text, drawFont, drawBrush, new PointF(r.Left, r.Top), drawFormat); else g.DrawString(pt.Text, drawFont, drawBrush, r2, drawFormat); } finally { if (drawFont != null) drawFont.Dispose(); if (drawFormat != null) drawFont.Dispose(); if (drawBrush != null) drawBrush.Dispose(); } }
private void DrawString(PageText pt, Graphics g, RectangleF r) { StyleInfo si = pt.SI; string s = pt.Text; Font drawFont = null; StringFormat drawFormat = null; Brush drawBrush = null; try { // STYLE System.DrawingCore.FontStyle fs = 0; if (si.FontStyle == FontStyleEnum.Italic) { fs |= System.DrawingCore.FontStyle.Italic; } switch (si.TextDecoration) { case TextDecorationEnum.Underline: fs |= System.DrawingCore.FontStyle.Underline; break; case TextDecorationEnum.LineThrough: fs |= System.DrawingCore.FontStyle.Strikeout; break; case TextDecorationEnum.Overline: case TextDecorationEnum.None: break; } // WEIGHT switch (si.FontWeight) { case FontWeightEnum.Bold: case FontWeightEnum.Bolder: case FontWeightEnum.W500: case FontWeightEnum.W600: case FontWeightEnum.W700: case FontWeightEnum.W800: case FontWeightEnum.W900: fs |= System.DrawingCore.FontStyle.Bold; break; default: break; } try { drawFont = new Font(si.GetFontFamily(), si.FontSize, fs); // si.FontSize already in points } catch (ArgumentException) { drawFont = new Font("Arial", si.FontSize, fs); // if this fails we'll let the error pass thru } // ALIGNMENT drawFormat = new StringFormat(); switch (si.TextAlign) { case TextAlignEnum.Right: drawFormat.Alignment = StringAlignment.Far; break; case TextAlignEnum.Center: drawFormat.Alignment = StringAlignment.Center; break; case TextAlignEnum.Left: default: drawFormat.Alignment = StringAlignment.Near; break; } if (pt.SI.WritingMode == WritingModeEnum.tb_rl) { drawFormat.FormatFlags |= StringFormatFlags.DirectionRightToLeft; drawFormat.FormatFlags |= StringFormatFlags.DirectionVertical; } switch (si.VerticalAlign) { case VerticalAlignEnum.Bottom: drawFormat.LineAlignment = StringAlignment.Far; break; case VerticalAlignEnum.Middle: drawFormat.LineAlignment = StringAlignment.Center; break; case VerticalAlignEnum.Top: default: drawFormat.LineAlignment = StringAlignment.Near; break; } // draw the background DrawBackground(g, r, si); // adjust drawing rectangle based on padding RectangleF r2 = new RectangleF(r.Left + si.PaddingLeft, r.Top + si.PaddingTop, r.Width - si.PaddingLeft - si.PaddingRight, r.Height - si.PaddingTop - si.PaddingBottom); drawBrush = new SolidBrush(si.Color); if (pt.NoClip) // request not to clip text { g.DrawString(pt.Text, drawFont, drawBrush, new PointF(r.Left, r.Top), drawFormat); //HighlightString(g, pt, new RectangleF(r.Left, r.Top, float.MaxValue, float.MaxValue),drawFont, drawFormat); } else { g.DrawString(pt.Text, drawFont, drawBrush, r2, drawFormat); //HighlightString(g, pt, r2, drawFont, drawFormat); } } finally { if (drawFont != null) { drawFont.Dispose(); } if (drawFormat != null) { drawFont.Dispose(); } if (drawBrush != null) { drawBrush.Dispose(); } } }
private void DrawString(PageText pt, StringBuilder sb, Rectangle r) { StyleInfo si = pt.SI; string s = pt.Text; //r is full area rectangle // r2 is area canvas i.e. rectangle less padding amounts & border widths Rectangle r2; // Text ALIGNMENT not supported in SilverLight 1.0 // PJR - We have a cludgy work around for this though! (need to have text boxes set to whole width) //r3 is the text total area Rectangle r3; SizeF ts = MeasureString(pt); //check & correct rectangle (r) without width & height if (si.WritingMode == WritingModeEnum.lr_tb) { if (r.Width == 0) r.Width = PixelsX(ts.Width); if (r.Height == 0) r.Height = PixelsY(ts.Height); } else { if (r.Width == 0) r.Width = PixelsY(ts.Height); if (r.Height == 0) r.Height = PixelsX(ts.Width); }; //PJR recalculating width needs to ADD the padding values not SUBTRACT r2 = new Rectangle(r.X + PixelsX(si.PaddingLeft+ si.BWidthLeft ), r.Y + PixelsY(si.PaddingTop + si.BWidthTop ), r.Width - PixelsX(si.PaddingLeft + si.PaddingRight+ si.BWidthLeft+si.BWidthRight), r.Height - PixelsY(si.PaddingTop + si.PaddingBottom+ si.BWidthTop+si.BWidthBottom )); //increase font by 30% to compensate for GDI to WPF size difference si.FontSize *= 1.3f; if (si.WritingMode == WritingModeEnum.lr_tb) { r3 = new Rectangle(r.Left, r.Top, PixelsX(ts.Width), PixelsY(ts.Height)); if (r3.Width > r2.Width) { //we need to wrap the text so adjust the rectangle r3.Width = r2.Width; r3.Height += r2.Height; }; } else { r3 = new Rectangle(r.Left + PixelsY(ts.Height), r.Top, PixelsY(ts.Height), PixelsX(ts.Width)); if (r3.Height > r2.Height) { //we need to wrap the text so adjust the rectangle r3.Height = r2.Height; r3.Width += r2.Width; }; }; Point ofs = new Point(0,0); if (si.WritingMode == WritingModeEnum.lr_tb) { switch (si.TextAlign) { case TextAlignEnum.Right: ofs.X = r.Width - r3.Width; break; case TextAlignEnum.Center: ofs.X = r.Width / 2 - r3.Width / 2; break; case TextAlignEnum.Left: default: break; } switch (si.VerticalAlign) { case VerticalAlignEnum.Bottom: ofs.Y = r.Height - r3.Height; break; case VerticalAlignEnum.Middle: ofs.Y = r.Height / 2 - r3.Height / 2; break; case VerticalAlignEnum.Top: default: break; } } else { switch (si.TextAlign) { case TextAlignEnum.Right: ofs.Y = r.Height - r3.Height; break; case TextAlignEnum.Center: ofs.Y = r.Height / 2 - r3.Height / 2; break; case TextAlignEnum.Left: default: break; } switch (si.VerticalAlign) { case VerticalAlignEnum.Bottom: ofs.X = r.Width - r3.Width; break; case VerticalAlignEnum.Middle: ofs.X = r.Width / 2 - r3.Width / 2; break; case VerticalAlignEnum.Top: default: break; } }; //PJR rectangle for background - background should fill rect r sb.AppendFormat("<Rectangle Canvas.Left=\"{0}\" Canvas.Top=\"{1}\" Height=\"{2}\" Width=\"{3}\">", r.Left, r.Top, r.Height, r.Width); sb.Append("<Rectangle.Fill>"); DrawBackground(sb, si); sb.Append("</Rectangle.Fill>"); sb.Append("</Rectangle>"); //PJR - Canvas for text r2 (takes border width and padding into account) sb.AppendFormat("<Canvas Name=\"{0}\" Canvas.Left=\"{1}\" Canvas.Top=\"{2}\" Height=\"{3}\" Width=\"{4}\" >", GetName(pt), r2.Left, r2.Top, r2.Height, r2.Width); //PJR set the text clipping region (anything outside this won't be shown) sb.AppendFormat("<Canvas.Clip><RectangleGeometry Rect=\"{0},{1},{2},{3}\" /></Canvas.Clip>", ofs.X, ofs.Y, r3.Width + ofs.X, r3.Height + ofs.Y); //PJR - set text wrapping and width (based on writing mode) if (si.WritingMode == WritingModeEnum.lr_tb) { sb.AppendFormat("<TextBlock TextWrapping=\"Wrap\" FontFamily=\"{0}\" Foreground=\"{1}\" FontSize=\"{2}\" Width=\"{3}\"", si.FontFamily, GetColor(si.Color), si.FontSize, r3.Width); } else { sb.AppendFormat("<TextBlock TextWrapping=\"Wrap\" FontFamily=\"{0}\" Foreground=\"{1}\" FontSize=\"{2}\" Width=\"{3}\"", si.FontFamily, GetColor(si.Color), si.FontSize, r3.Height); }; if (si.FontStyle == FontStyleEnum.Italic) sb.Append(" FontStyle=\"Italic\""); if (si.TextDecoration == TextDecorationEnum.Underline) sb.Append(" TextDecorations=\"Underline\""); if (si.WritingMode == WritingModeEnum.tb_rl) // we need to rotate text sb.AppendFormat(" RenderTransformOrigin=\"0.0,0.0\" Canvas.Left=\"{0}\"", r3.Width); // WEIGHT switch (si.FontWeight) { case FontWeightEnum.Lighter: sb.Append(" FontWeight=\"Light\""); break; case FontWeightEnum.W500: case FontWeightEnum.Bold: sb.Append(" FontWeight=\"Bold\""); break; case FontWeightEnum.Bolder: sb.Append(" FontWeight=\"ExtraBold\""); break; case FontWeightEnum.W600: case FontWeightEnum.W700: sb.Append(" FontWeight=\"Black\""); break; case FontWeightEnum.W800: case FontWeightEnum.W900: sb.Append(" FontWeight=\"ExtraBlack\""); break; case FontWeightEnum.Normal: default: sb.Append(" FontWeight=\"Normal\""); break; } sb.Append("><Run>"); //PJR - allow for text with newline (\n) in it sb.Append(fyiReporting.RDL.XmlUtil.XmlAnsi(pt.Text).Replace("\n","</Run><LineBreak /><Run>")); sb.Append("</Run>"); //PJR - do we need to add the bits to transform this text? if ((si.WritingMode == WritingModeEnum.tb_rl) || (si.TextAlign == TextAlignEnum.Center) || (si.TextAlign == TextAlignEnum.Right) || (si.VerticalAlign == VerticalAlignEnum.Middle) || (si.VerticalAlign == VerticalAlignEnum.Bottom)) { //PJR - create a TransformGroup (it can have as little as one item in it) sb.Append("<TextBlock.RenderTransform><TransformGroup>"); //PJR - rotate if needed if (si.WritingMode == WritingModeEnum.tb_rl) { sb.AppendFormat("<RotateTransform Angle=\"90\"/>"); } // PJR - Move the block by the offset values (if it is outside the clip region it won't be shown) sb.AppendFormat("<TranslateTransform X=\"{0}\" Y=\"{1}\" />", ofs.X , ofs.Y); sb.Append("</TransformGroup></TextBlock.RenderTransform>"); }; sb.Append("</TextBlock>"); sb.Append("</Canvas>"); }
private PageImage BuildImage(Graphics g, string token, StyleInfo oldsi, PageText model) { PageTextHtmlCmdLexer hc = new PageTextHtmlCmdLexer(token.Substring(4)); Hashtable ht = hc.Lex(); string src = (string)ht["src"]; if (src == null || src.Length < 1) { return(null); } string alt = (string)ht["alt"]; string height = (string)ht["height"]; string width = (string)ht["width"]; string align = (string)ht["align"]; Stream strm = null; System.Drawing.Image im = null; PageImage pi = null; try { // Obtain the image stream if (src.StartsWith("http:") || src.StartsWith("file:") || src.StartsWith("https:")) { WebRequest wreq = WebRequest.Create(src); WebResponse wres = wreq.GetResponse(); strm = wres.GetResponseStream(); } else { strm = new FileStream(src, System.IO.FileMode.Open, FileAccess.Read); } im = System.Drawing.Image.FromStream(strm); int h = im.Height; int w = im.Width; MemoryStream ostrm = new MemoryStream(); ImageFormat imf; imf = ImageFormat.Jpeg; im.Save(ostrm, imf); byte[] ba = ostrm.ToArray(); ostrm.Close(); pi = new PageImage(imf, ba, w, h); pi.HyperLink = model.HyperLink; pi.Tooltip = alt == null ? model.Tooltip : alt; pi.X = 0; pi.Y = 0; pi.W = RSize.PointsFromPixels(g, width != null? Convert.ToInt32(width): w); pi.H = RSize.PointsFromPixels(g, height != null? Convert.ToInt32(height): h); pi.SI = new StyleInfo(); } catch { pi = null; } finally { if (strm != null) { strm.Close(); } if (im != null) { im.Dispose(); } } return(pi); }
private void BuildAnchor(string token, StyleInfo oldsi, PageText model) { StyleInfo si= oldsi.Clone() as StyleInfo; // always push a StyleInfo _StyleStack.Push(si); // since they will always be popped Hashtable ht = ParseHtmlCmd(token); string href = (string) ht["href"]; if (href == null || href.Length < 1) return; model.HyperLink = model.Tooltip = href; si.TextDecoration = TextDecorationEnum.Underline; si.Color = Color.Blue; }
public void Build(Graphics g) { PageText model = new PageText(""); model.HyperLink = null; model.Tooltip = null; int fontSizeModel = 3; if (_items != null) // this has already been built { return; } _items = new List <PageItem>(); _StyleStack = new Stack(); // The first item is always a text box with the border and background attributes PageText pt = new PageText(""); pt.X = this.X; pt.Y = this.Y; pt.H = this.H; pt.W = this.W; pt.CanGrow = false; pt.SI = this.SI.Clone() as StyleInfo; pt.SI.PaddingBottom = pt.SI.PaddingLeft = pt.SI.PaddingRight = pt.SI.PaddingTop = 0; pt.SI.TextAlign = TextAlignEnum.Left; _items.Add(pt); // Now we create multiple items that represent what is in the box PageTextHtmlLexer hl = new PageTextHtmlLexer(this.Text); List <string> tokens = hl.Lex(); float textWidth = this.W - pt.SI.PaddingLeft - pt.SI.PaddingRight; // Now set the default style for the rest of the members StyleInfo si = this.SI.Clone() as StyleInfo; si.BStyleBottom = si.BStyleLeft = si.BStyleRight = si.BStyleTop = BorderStyleEnum.None; pt.SI.TextAlign = TextAlignEnum.Left; pt.SI.VerticalAlign = VerticalAlignEnum.Top; si.BackgroundColor = Color.Empty; si.BackgroundGradientType = BackgroundGradientTypeEnum.None; si.BackgroundImage = null; bool bFirstInLine = true; StringBuilder sb = new StringBuilder(); // this will hold the accumulating line float lineXPos = 0; float xPos = 0; float yPos = 0; float maxLineHeight = 0; float maxDescent = 0; float descent; // working value for descent SizeF ms; bool bWhiteSpace = false; List <PageItem> lineItems = new List <PageItem>(); foreach (string token in tokens) { if (token[0] == PageTextHtmlLexer.HTMLCMD) // indicates an HTML command { // we need to create a PageText since the styleinfo is changing if (sb.Length != 0) { pt = new PageText(sb.ToString()); pt.HyperLink = model.HyperLink; pt.Tooltip = model.Tooltip; pt.NoClip = true; sb = new StringBuilder(); pt.X = this.X + lineXPos; pt.Y = this.Y + yPos; pt.CanGrow = false; pt.SI = CurrentStyle(si).Clone() as StyleInfo; _items.Add(pt); lineItems.Add(pt); ms = this.MeasureString(pt.Text, pt.SI, g, out descent); maxDescent = Math.Max(maxDescent, descent); pt.W = ms.Width; pt.H = ms.Height; pt.Descent = descent; maxLineHeight = Math.Max(maxLineHeight, ms.Height); lineXPos = xPos; } // Now reset the styleinfo StyleInfo cs = CurrentStyle(si); string ltoken = token.Substring(1, Math.Min(token.Length - 1, 10)).ToLower(); if (ltoken == "<b>" || ltoken == "<strong>") { cs.FontWeight = FontWeightEnum.Bold; } else if (ltoken == "</b>" || ltoken == "</strong>") { cs.FontWeight = FontWeightEnum.Normal; } else if (ltoken == "<i>" || ltoken == "<cite>" || ltoken == "<var>" || ltoken == "<em>") { cs.FontStyle = FontStyleEnum.Italic; } else if (ltoken == "</i>" || ltoken == "</cite>" || ltoken == "</var>" || ltoken == "</em>") { cs.FontStyle = FontStyleEnum.Normal; } else if (ltoken == "<code>" || ltoken == "<samp>") { cs.FontFamily = "Courier New"; } else if (ltoken == "</code>" || ltoken == "</samp>") { cs.FontFamily = this.SI.FontFamily; } else if (ltoken == "<kbd>") { cs.FontFamily = "Courier New"; cs.FontWeight = FontWeightEnum.Bold; } else if (ltoken == "</kdd>") { cs.FontFamily = this.SI.FontFamily; cs.FontWeight = FontWeightEnum.Normal; } else if (ltoken == "<big>") { // big makes it bigger by 20% for each time over the baseline of 3 fontSizeModel++; float inc = 1; for (int i = 3; i < fontSizeModel; i++) { inc += .2f; } float h = this.SI.FontSize * inc; cs.FontSize = h; } else if (ltoken == "</big>") { // undoes the effect of big fontSizeModel--; float inc = 1; for (int i = 3; i < fontSizeModel; i++) { inc += .2f; } float h = this.SI.FontSize / inc; cs.FontSize = h; } else if (ltoken == "<small>") { // small makes it smaller by 20% for each time under the baseline of 3 fontSizeModel--; float inc = 1; for (int i = 3; i > fontSizeModel; i--) { inc += .2f; } float h = this.SI.FontSize / inc; cs.FontSize = h; } else if (ltoken == "</small>") { // undoes the effect of small fontSizeModel++; float inc = 1; for (int i = 3; i > fontSizeModel; i--) { inc += .2f; } float h = this.SI.FontSize * inc; cs.FontSize = h; } else if (ltoken.StartsWith("<br")) { yPos += maxLineHeight; NormalizeLineHeight(lineItems, maxLineHeight, maxDescent); maxLineHeight = xPos = lineXPos = maxDescent = 0; bFirstInLine = true; bWhiteSpace = false; } else if (ltoken.StartsWith("<p")) { yPos += maxLineHeight * 2; NormalizeLineHeight(lineItems, maxLineHeight, maxDescent); maxLineHeight = xPos = lineXPos = maxDescent = 0; bFirstInLine = true; bWhiteSpace = false; } else if (ltoken.StartsWith("<a")) { BuildAnchor(token.Substring(1), cs, model); } else if (ltoken.StartsWith("<img")) { PageImage pimg = BuildImage(g, token.Substring(1), cs, model); if (pimg != null) // We got an image; add to process list { pimg.Y = this.Y + yPos; pimg.X = this.X; _items.Add(pimg); yPos += pimg.H; // Increment y position maxLineHeight = xPos = lineXPos = maxDescent = 0; bFirstInLine = true; bWhiteSpace = false; } } else if (ltoken == "</a>") { model.HyperLink = model.Tooltip = null; PopStyle(); } else if (ltoken.StartsWith("<span")) { HandleStyle(ltoken, si); } else if (ltoken == "</span>") { PopStyle(); } continue; } if (token == PageTextHtmlLexer.WHITESPACE) { if (!bFirstInLine) { bWhiteSpace = true; } continue; } if (token != PageTextHtmlLexer.EOF) { string ntoken = bWhiteSpace? " " + token: token; bWhiteSpace = false; // can only use whitespace once ms = this.MeasureString(ntoken, CurrentStyle(si), g, out descent); if (xPos + ms.Width < textWidth) { bFirstInLine = false; sb.Append(ntoken); maxDescent = Math.Max(maxDescent, descent); maxLineHeight = Math.Max(maxLineHeight, ms.Height); xPos += ms.Width; continue; } } else if (sb.Length == 0) // EOF and no previous string means we're done { continue; } pt = new PageText(sb.ToString()); pt.NoClip = true; pt.HyperLink = model.HyperLink; pt.Tooltip = model.Tooltip; sb = new StringBuilder(); sb.Append(token); pt.SI = CurrentStyle(si).Clone() as StyleInfo; ms = this.MeasureString(pt.Text, pt.SI, g, out descent); pt.X = this.X + lineXPos; pt.Y = this.Y + yPos; pt.H = ms.Height; pt.W = ms.Width; pt.Descent = descent; pt.CanGrow = false; _items.Add(pt); lineItems.Add(pt); maxDescent = Math.Max(maxDescent, descent); maxLineHeight = Math.Max(maxLineHeight, ms.Height); yPos += maxLineHeight; // Increment y position NormalizeLineHeight(lineItems, maxLineHeight, maxDescent); lineXPos = maxLineHeight = maxDescent = 0; // start line height over // Now set the xPos just after the current token ms = this.MeasureString(token, CurrentStyle(si), g, out descent); xPos = ms.Width; } _TotalHeight = yPos; // set the calculated height of the result _StyleStack = null; return; }
private void BuildPrivate(Graphics g) { PageText model = new PageText(""); model.AllowSelect = false; model.Page = this.Page; model.HyperLink=null; model.Tooltip=null; int fontSizeModel = 3; if (_items != null) // this has already been built return; _items = new List<PageItem>(); _StyleStack = new Stack(); // The first item is always a text box with the border and background attributes PageText pt = new PageText(""); pt.AllowSelect = true; // This item represents HTML item for selection in RdlViewer pt.Page = this.Page; pt.HtmlParent = this; pt.X = this.X; pt.Y = this.Y; pt.H = this.H; pt.W = this.W; pt.CanGrow = false; pt.SI = this.SI.Clone() as StyleInfo; pt.SI.PaddingBottom = pt.SI.PaddingLeft = pt.SI.PaddingRight = pt.SI.PaddingTop = 0; pt.SI.TextAlign = TextAlignEnum.Left; _items.Add(pt); // Now we create multiple items that represent what is in the box PageTextHtmlLexer hl = new PageTextHtmlLexer(this.Text); List<string> tokens = hl.Lex(); float textWidth = this.W - pt.SI.PaddingLeft - pt.SI.PaddingRight; // Now set the default style for the rest of the members StyleInfo si = this.SI.Clone() as StyleInfo; si.BStyleBottom = si.BStyleLeft = si.BStyleRight = si.BStyleTop = BorderStyleEnum.None; pt.SI.TextAlign = TextAlignEnum.Left; pt.SI.VerticalAlign = VerticalAlignEnum.Top; si.BackgroundColor = Color.Empty; si.BackgroundGradientType = BackgroundGradientTypeEnum.None; si.BackgroundImage = null; bool bFirstInLine=true; StringBuilder sb = new StringBuilder(); // this will hold the accumulating line float lineXPos=0; float xPos = 0; float yPos = 0; float maxLineHeight=0; float maxDescent=0; float descent; // working value for descent SizeF ms; bool bWhiteSpace=false; List<PageItem> lineItems = new List<PageItem>(); foreach (string token in tokens) { if (token[0] == PageTextHtmlLexer.HTMLCMD) // indicates an HTML command { // we need to create a PageText since the styleinfo is changing if (sb.Length != 0) { pt = new PageText(sb.ToString()); pt.AllowSelect = false; pt.Page = this.Page; pt.HtmlParent = this; pt.HyperLink = model.HyperLink; pt.Tooltip = model.Tooltip; pt.NoClip = true; sb = new StringBuilder(); pt.X = this.X + lineXPos; pt.Y = this.Y + yPos; pt.CanGrow = false; pt.SI = CurrentStyle(si).Clone() as StyleInfo; _items.Add(pt); lineItems.Add(pt); ms = this.MeasureString(pt.Text, pt.SI, g, out descent); maxDescent = Math.Max(maxDescent, descent); pt.W = ms.Width; pt.H = ms.Height; pt.Descent = descent; maxLineHeight = Math.Max(maxLineHeight, ms.Height); lineXPos = xPos; } // Now reset the styleinfo StyleInfo cs = CurrentStyle(si); string ltoken = token.Substring(1,Math.Min(token.Length-1,10)).ToLower(); if (ltoken == "<b>" || ltoken == "<strong>") cs.FontWeight = FontWeightEnum.Bold; else if (ltoken == "</b>" || ltoken == "</strong>") cs.FontWeight = FontWeightEnum.Normal; else if (ltoken == "<i>" || ltoken == "<cite>" || ltoken == "<var>" || ltoken == "<em>") cs.FontStyle = FontStyleEnum.Italic; else if (ltoken == "</i>" || ltoken == "</cite>" || ltoken == "</var>" || ltoken == "</em>") cs.FontStyle = FontStyleEnum.Normal; else if (ltoken == "<code>" || ltoken == "<samp>") cs.FontFamily = "Courier New"; else if (ltoken == "</code>" || ltoken == "</samp>") cs.FontFamily = this.SI.FontFamily; else if (ltoken == "<kbd>") { cs.FontFamily = "Courier New"; cs.FontWeight = FontWeightEnum.Bold; } else if (ltoken == "</kdd>") { cs.FontFamily = this.SI.FontFamily; cs.FontWeight = FontWeightEnum.Normal; } else if (ltoken == "<big>") { // big makes it bigger by 20% for each time over the baseline of 3 fontSizeModel++; float inc = 1; for (int i=3; i < fontSizeModel; i++) { inc += .2f; } float h = this.SI.FontSize * inc; cs.FontSize = h; } else if (ltoken == "</big>") { // undoes the effect of big fontSizeModel--; float inc = 1; for (int i=3; i < fontSizeModel; i++) { inc += .2f; } float h = this.SI.FontSize / inc; cs.FontSize = h; } else if (ltoken == "<small>") { // small makes it smaller by 20% for each time under the baseline of 3 fontSizeModel--; float inc = 1; for (int i=3; i > fontSizeModel; i--) { inc += .2f; } float h = this.SI.FontSize / inc; cs.FontSize = h; } else if (ltoken == "</small>") { // undoes the effect of small fontSizeModel++; float inc = 1; for (int i=3; i > fontSizeModel; i--) { inc += .2f; } float h = this.SI.FontSize * inc; cs.FontSize = h; } else if (ltoken.StartsWith("<br")) { yPos += maxLineHeight; NormalizeLineHeight(lineItems, maxLineHeight, maxDescent); maxLineHeight = xPos = lineXPos = maxDescent = 0; bFirstInLine = true; bWhiteSpace = false; } else if (ltoken.StartsWith("<hr")) { // Add a line // Process existing line if any yPos += maxLineHeight; NormalizeLineHeight(lineItems, maxLineHeight, maxDescent); maxLineHeight = xPos = lineXPos = maxDescent = 0; bFirstInLine = true; bWhiteSpace = false; PageLine pl = new PageLine(); pl.AllowSelect = false; pl.Page = this.Page; const int horzLineHeight = 10; pl.SI = cs.Clone() as StyleInfo; pl.SI.BStyleLeft = BorderStyleEnum.Ridge; pl.Y = pl.Y2 = this.Y + yPos + horzLineHeight / 2; pl.X = this.X; pl.X2 = pl.X + this.W; _items.Add(pl); yPos += horzLineHeight; // skip past horizontal line } else if (ltoken.StartsWith("<p")) { yPos += maxLineHeight * 2; NormalizeLineHeight(lineItems, maxLineHeight, maxDescent); maxLineHeight = xPos = lineXPos = maxDescent = 0; bFirstInLine = true; bWhiteSpace = false; } else if (ltoken.StartsWith("<a")) { BuildAnchor(token.Substring(1), cs, model); } else if (ltoken.StartsWith("<img")) { PageImage pimg = BuildImage(g, token.Substring(1), cs, model); if (pimg != null) // We got an image; add to process list { pimg.Y = this.Y + yPos; pimg.X = this.X; _items.Add(pimg); yPos += pimg.H; // Increment y position maxLineHeight = xPos = lineXPos = maxDescent = 0; bFirstInLine = true; bWhiteSpace = false; } } else if (ltoken == "</a>") { model.HyperLink = model.Tooltip = null; PopStyle(); } else if (ltoken.StartsWith("<span")) { HandleStyle(token.Substring(1), si); } else if (ltoken == "</span>") { // we really should match span and font but it shouldn't matter very often? PopStyle(); } else if (ltoken.StartsWith("<font")) { HandleFont(token.Substring(1), si); } else if (ltoken == "</font>") { // we really should match span and font but it shouldn't matter very often? PopStyle(); } continue; } if (token == PageTextHtmlLexer.WHITESPACE) { if (!bFirstInLine) bWhiteSpace = true; continue; } if (token != PageTextHtmlLexer.EOF) { string ntoken; if (token == PageTextHtmlLexer.NBSP.ToString()) ntoken = bWhiteSpace ? " " : " "; else ntoken = bWhiteSpace ? " " + token : token; ntoken = ntoken.Replace(PageTextHtmlLexer.NBSP, ' '); bWhiteSpace = false; // can only use whitespace once ms = this.MeasureString(ntoken, CurrentStyle(si), g, out descent); if (xPos + ms.Width < textWidth) { bFirstInLine = false; sb.Append(ntoken); maxDescent = Math.Max(maxDescent, descent); maxLineHeight = Math.Max(maxLineHeight, ms.Height); xPos += ms.Width; continue; } } else if (sb.Length == 0) // EOF and no previous string means we're done continue; pt = new PageText(sb.ToString()); pt.AllowSelect = false; pt.Page = this.Page; pt.HtmlParent = this; pt.NoClip = true; pt.HyperLink = model.HyperLink; pt.Tooltip = model.Tooltip; sb = new StringBuilder(); sb.Append(token.Replace(PageTextHtmlLexer.NBSP, ' ')); pt.SI = CurrentStyle(si).Clone() as StyleInfo; ms = this.MeasureString(pt.Text, pt.SI, g, out descent); pt.X = this.X + lineXPos; pt.Y = this.Y + yPos; pt.H = ms.Height; pt.W = ms.Width; pt.Descent = descent; pt.CanGrow = false; _items.Add(pt); lineItems.Add(pt); maxDescent = Math.Max(maxDescent, descent); maxLineHeight = Math.Max(maxLineHeight, ms.Height); yPos += maxLineHeight; // Increment y position NormalizeLineHeight(lineItems, maxLineHeight, maxDescent); lineXPos = maxLineHeight = maxDescent = 0; // start line height over // Now set the xPos just after the current token ms = this.MeasureString(token, CurrentStyle(si), g, out descent); xPos = ms.Width; } _TotalHeight = yPos; // set the calculated height of the result _StyleStack = null; return; }
private void DrawString(PageText pt, StringBuilder sb, Rectangle r) { StyleInfo si = pt.SI; string s = pt.Text; /* <Canvas Name ="obj3" Canvas.Left="10" Canvas.Top="2" Height="20" Width="180" Background="Blue" MouseLeftButtonDown="riDown" MouseMove="riMove" MouseLeftButtonUp="riUp" > <Canvas.Clip> <RectangleGeometry Rect="0,0,180,20" /> </Canvas.Clip> <TextBlock FontFamily="Arial" FontSize="25" Text="This text is in xxx footer"> </TextBlock> </Canvas> * */ // adjust drawing rectangle based on padding Rectangle r2; //if (si.WritingMode == WritingModeEnum.tb_rl) //{ // we're going to rotate the text so width will be height and height will be width // r2 = new Rectangle(r.Left + PixelsX(si.PaddingLeft), // r.Top + PixelsY(si.PaddingTop), // r.Height - PixelsY(si.PaddingTop - si.PaddingBottom), // r.Width - PixelsX(si.PaddingLeft - si.PaddingRight)); //} //else r2 = new Rectangle(r.Left + PixelsX(si.PaddingLeft), r.Top + PixelsY(si.PaddingTop), r.Width - PixelsX(si.PaddingLeft - si.PaddingRight), r.Height - PixelsY(si.PaddingTop - si.PaddingBottom)); if (r2.Height == 0 || r2.Width == 0) { sb.AppendFormat("<Canvas Name=\"{0}\" Canvas.Left=\"{1}\" Canvas.Top=\"{2}\" Background=\"{3}\" >", GetName(pt), r2.Left, r2.Top, GetColor(si.BackgroundColor)); } else { sb.AppendFormat("<Canvas Name=\"{0}\" Canvas.Left=\"{1}\" Canvas.Top=\"{2}\" Height=\"{3}\" Width=\"{4}\" Background=\"{5}\" >", GetName(pt), r2.Left, r2.Top, r2.Height, r2.Width, GetColor(si.BackgroundColor)); // DrawBackground(sb, si); // this would need some additional work to support gradient and textblock sb.AppendFormat("<Canvas.Clip><RectangleGeometry Rect=\"0,0,{0},{1}\" /></Canvas.Clip>", PixelsX(pt.W), PixelsY(pt.H)); } sb.AppendFormat("<TextBlock TextWrapping=\"Wrap\" FontFamily=\"{0}\" Foreground=\"{1}\" FontSize=\"{2}\"", si.FontFamily, GetColor(si.Color), si.FontSize); if (si.FontStyle == FontStyleEnum.Italic) sb.Append(" FontStyle=\"Italic\""); if (si.TextDecoration == TextDecorationEnum.Underline) sb.Append(" TextDecorations=\"Underline\""); if (si.WritingMode == WritingModeEnum.tb_rl) // we need to rotate text sb.AppendFormat(" RenderTransformOrigin=\"0.0,0.0\" Canvas.Left=\"{0}\"", r2.Width); // WEIGHT switch (si.FontWeight) { case FontWeightEnum.Lighter: sb.Append(" FontWeight=\"Light\""); break; case FontWeightEnum.W500: case FontWeightEnum.Bold: sb.Append(" FontWeight=\"Bold\""); break; case FontWeightEnum.Bolder: sb.Append(" FontWeight=\"ExtraBold\""); break; case FontWeightEnum.W600: case FontWeightEnum.W700: sb.Append(" FontWeight=\"Black\""); break; case FontWeightEnum.W800: case FontWeightEnum.W900: sb.Append(" FontWeight=\"ExtraBlack\""); break; case FontWeightEnum.Normal: default: sb.Append(" FontWeight=\"Normal\""); break; } /* // ALIGNMENT not supported in SilverLight 1.0 switch (si.TextAlign) { case TextAlignEnum.Right: break; case TextAlignEnum.Center: break; case TextAlignEnum.Left: default: break; } switch (si.VerticalAlign) { case VerticalAlignEnum.Bottom: break; case VerticalAlignEnum.Middle: break; case VerticalAlignEnum.Top: default: break; } */ sb.Append("><Run>"); sb.Append(fyiReporting.RDL.XmlUtil.XmlAnsi(pt.Text)); sb.Append("</Run>"); if (si.WritingMode == WritingModeEnum.tb_rl) { sb.AppendFormat("<TextBlock.RenderTransform><RotateTransform Angle=\"90\"/></TextBlock.RenderTransform>"); //sb.AppendFormat("<TextBlock.RenderTransform><RotateTransform Angle=\"90\" CenterX=\"{0}\" CenterY=\"{1}\"/></TextBlock.RenderTransform>", // r2.Width, r2.Height); } sb.Append("</TextBlock>"); sb.Append("</Canvas>"); }
override internal void RunPage(Pages pgs, Row row) { Report r = pgs.Report; if (IsHidden(r, row)) return; base.RunPage(pgs, row); // need to save the owner report and nest in this defintion ReportDefn saveReport = r.ReportDefinition; NeedPassword np = r.GetDataSourceReferencePassword; // get current password r.SetReportDefinition(_ReportDefn); r.Folder = _ReportDefn.ParseFolder; // folder needs to get set since the id of the report is used by the cache r.GetDataSourceReferencePassword = np; DataSourcesDefn saveDS = r.ParentConnections; if (this.MergeTransactions) r.ParentConnections = saveReport.DataSourcesDefn; else r.ParentConnections = null; r.SubreportDataRetrievalTriggerEvent(); bool bRows = true; if (_Parameters == null) { // When no parameters we only retrieve data once SubreportWorkClass wc = r.Cache.Get(this, "report") as SubreportWorkClass; if (wc == null) { // run report first time; bRows = r.RunGetData(null); if (!r.IsSubreportDataRetrievalDefined) // if use has defined subreportdataretrieval they might set data r.Cache.Add(this, "report", new SubreportWorkClass(bRows)); // so we can't cache } else bRows = wc.bRows; } else { SetSubreportParameters(r, row); // apply the parameters bRows = r.RunGetData(null); } SetPageLeft(r); // Set the Left attribute since this will be the margin for this report SetPagePositionBegin(pgs); float yOffset; if (bRows) // Only run subreport if have a row in some Dataset { // // Run the subreport -- this is the major effort in creating the display objects in the page // r.ReportDefinition.Body.RunPage(pgs); // create a the subreport items yOffset = pgs.CurrentPage.YOffset; } else { // Handle NoRows message string msg; if (this.NoRows != null) msg = this.NoRows.EvaluateString(pgs.Report, null); else msg = null; if (msg != null) { PageText pt = new PageText(msg); SetPagePositionAndStyle(pgs.Report, pt, null); if (pt.SI.BackgroundImage != null) pt.SI.BackgroundImage.H = pt.H; // and in the background image pgs.CurrentPage.AddObject(pt); yOffset = pt.Y + pt.H; } else yOffset = pgs.CurrentPage.YOffset; } r.SetReportDefinition(saveReport); // restore the current report r.ParentConnections = saveDS; // restore the data connnections SetPagePositionEnd(pgs, yOffset); }
private void DrawString(PageText pt, Cairo.Context g, Cairo.Rectangle r) { StyleInfo si = pt.SI; string s = pt.Text; g.Save(); layout = Pango.CairoHelper.CreateLayout(g); // Font drawFont = null; // StringFormat drawFormat = null; // Brush drawBrush = null; // STYLE // System.Drawing.FontStyle fs = 0; // if (si.FontStyle == FontStyleEnum.Italic) // fs |= System.Drawing.FontStyle.Italic; //Pango fonts are scaled to 72dpi, Windows fonts uses 96dpi float fontsize = (si.FontSize * 72 / 96); var font = Pango.FontDescription.FromString(string.Format("{0} {1}", si.GetFontFamily().Name, fontsize * PixelsX(1))); if (si.FontStyle == FontStyleEnum.Italic) font.Style = Pango.Style.Italic; // // switch (si.TextDecoration) // { // case TextDecorationEnum.Underline: // fs |= System.Drawing.FontStyle.Underline; // break; // case TextDecorationEnum.LineThrough: // fs |= System.Drawing.FontStyle.Strikeout; // break; // case TextDecorationEnum.Overline: // case TextDecorationEnum.None: // break; // } // WEIGHT // switch (si.FontWeight) // { // case FontWeightEnum.Bold: // case FontWeightEnum.Bolder: // case FontWeightEnum.W500: // case FontWeightEnum.W600: // case FontWeightEnum.W700: // case FontWeightEnum.W800: // case FontWeightEnum.W900: // fs |= System.Drawing.FontStyle.Bold; // break; // default: // break; // } // try // { // drawFont = new Font(si.GetFontFamily(), si.FontSize, fs); // si.FontSize already in points // } // catch (ArgumentException) // { // drawFont = new Font("Arial", si.FontSize, fs); // if this fails we'll let the error pass thru // } //font.AbsoluteSize = (int)(PixelsX (si.FontSize)); switch (si.FontWeight) { case FontWeightEnum.Bold: case FontWeightEnum.Bolder: case FontWeightEnum.W500: case FontWeightEnum.W600: case FontWeightEnum.W700: case FontWeightEnum.W800: case FontWeightEnum.W900: font.Weight = Pango.Weight.Bold; break; } Pango.FontDescription oldfont = layout.FontDescription; layout.FontDescription = font; // ALIGNMENT // drawFormat = new StringFormat(); // switch (si.TextAlign) // { // case TextAlignEnum.Right: // drawFormat.Alignment = StringAlignment.Far; // break; // case TextAlignEnum.Center: // drawFormat.Alignment = StringAlignment.Center; // break; // case TextAlignEnum.Left: // default: // drawFormat.Alignment = StringAlignment.Near; // break; // } switch (si.TextAlign) { case TextAlignEnum.Right: layout.Alignment = Pango.Alignment.Right; break; case TextAlignEnum.Center: layout.Alignment = Pango.Alignment.Center; break; case TextAlignEnum.Left: default: layout.Alignment = Pango.Alignment.Left; break; } layout.Width = Pango.Units.FromPixels((int)(r.Width - si.PaddingLeft - si.PaddingRight - 2)); // layout.Width = (int)Pango.Units.FromPixels((int)r.Width); layout.SetText(s); // if (pt.SI.WritingMode == WritingModeEnum.tb_rl) // { // drawFormat.FormatFlags |= StringFormatFlags.DirectionRightToLeft; // drawFormat.FormatFlags |= StringFormatFlags.DirectionVertical; // } // switch (si.VerticalAlign) // { // case VerticalAlignEnum.Bottom: // drawFormat.LineAlignment = StringAlignment.Far; // break; // case VerticalAlignEnum.Middle: // drawFormat.LineAlignment = StringAlignment.Center; // break; // case VerticalAlignEnum.Top: // default: // drawFormat.LineAlignment = StringAlignment.Near; // break; // } // Pango.Rectangle logical; Pango.Rectangle ink; layout.GetExtents(out ink, out logical); double height = logical.Height / Pango.Scale.PangoScale; double y = 0; switch (si.VerticalAlign) { case VerticalAlignEnum.Top: y = r.Y + si.PaddingTop; break; case VerticalAlignEnum.Middle: y = r.Y + (r.Height - height) / 2; break; case VerticalAlignEnum.Bottom: y = r.Y + (r.Height - height) - si.PaddingBottom; break; } // draw the background DrawBackground(g, r, si); // adjust drawing rectangle based on padding // Cairo.Rectangle r2 = new Cairo.Rectangle(r.X + si.PaddingLeft, // r.Y + si.PaddingTop, // r.Width - si.PaddingLeft - si.PaddingRight, // r.Height - si.PaddingTop - si.PaddingBottom); Cairo.Rectangle box = new Cairo.Rectangle( r.X + si.PaddingLeft + 1, y, r.Width, r.Height); //drawBrush = new SolidBrush(si.Color); g.Color = si.Color.ToCairoColor(); // if (pt.NoClip) // request not to clip text // { // g.DrawString(pt.Text, drawFont, drawBrush, new PointF(r.Left, r.Top), drawFormat); // //HighlightString(g, pt, new RectangleF(r.Left, r.Top, float.MaxValue, float.MaxValue),drawFont, drawFormat); // } // else // { // g.DrawString(pt.Text, drawFont, drawBrush, r2, drawFormat); // //HighlightString(g, pt, r2, drawFont, drawFormat); // } g.MoveTo(box.X, box.Y); Pango.CairoHelper.ShowLayout(g, layout); layout.FontDescription = oldfont; g.Restore(); }
internal bool AnyRowsPage(Pages pgs, Rows data) { if (data != null && data.Data != null && data.Data.Count > 0) return true; string msg; if (this.NoRows != null) msg = this.NoRows.EvaluateString(pgs.Report, null); else msg = null; if (msg == null) return false; // OK we have a message we need to put out RunPageRegionBegin(pgs); // still perform page break if needed PageText pt = new PageText(msg); SetPagePositionAndStyle(pgs.Report, pt, null); if (pt.SI.BackgroundImage != null) pt.SI.BackgroundImage.H = pt.H; // and in the background image pgs.CurrentPage.AddObject(pt); RunPageRegionEnd(pgs); // perform end page break if needed return false; }
protected internal override void AddText(PageText pt, Pages pgs) { BaseFont bf; float width = pt.W; float height = pt.H; float[] tw; string[] sa = Measurement.MeasureString(pt, pgs.G, out tw); string face = iFontNameNormalize(pt.SI.FontFamily); string fontname = ""; bool fonttype1 = true; var folder = FontFolder; //Call to determine folder and set value of _dejavuFonts; if (face == "Times-Roman") { if (pt.SI.IsFontBold() && pt.SI.FontStyle == FontStyleEnum.Italic) { //OSX if (IsOSX) { face = "TimesNewRomanPS-BoldItalicMT"; fontname = "Times New Roman Bold Italic.ttf"; } else { face = _dejavuFonts ? "DejaVu Serif Condensed Bold Italic" : "Times-BoldItalic"; fontname = (_dejavuFonts ? "DejaVuSerifCondensed-BoldItalic.ttf" : "timesbi.ttf"); } } else if (pt.SI.IsFontBold()) { //OSX if (IsOSX) { face = "TimesNewRomanPS-BoldMT"; fontname = "Times New Roman Bold.ttf"; } else { face = _dejavuFonts ? "DejaVu Serif Condensed Bold" : "Times-Bold"; fontname = (_dejavuFonts ? "DejaVuSerifCondensed-Bold.ttf" : "timesbd.ttf"); } } else if (pt.SI.FontStyle == FontStyleEnum.Italic) { //OSX if (IsOSX) { face = "TimesNewRomanPS-ItalicMT"; fontname = "Times New Roman Italic.ttf"; } else { face = _dejavuFonts ? "DejaVu Serif Condensed Italic" : "Times-Italic"; fontname = (_dejavuFonts ? "DejaVuSerifCondensed-Italic.ttf" : "timesi.ttf"); } } else { //OSX if (IsOSX) { face = "TimesNewRomanPSMT"; fontname = "Times New Roman.ttf"; } else { face = _dejavuFonts ? "DejaVu Serif Condensed" : face; fontname = (_dejavuFonts ? "DejaVuSerifCondensed.ttf" : "times.ttf"); } } fonttype1 = false; } else if (face == "Arial") { if (pt.SI.IsFontBold() && pt.SI.FontStyle == FontStyleEnum.Italic) { //OSX if (IsOSX) { face = "Arial BoldItalicMT"; fontname = "Arial Bold Italic.ttf"; } else { face = _dejavuFonts ? "DejaVu Sans Condensed Bold Oblique" : "Arial-BoldItalic"; fontname = (_dejavuFonts ? "DejaVuSansCondensed-BoldOblique.ttf" : "arialbi.ttf"); } } else if (pt.SI.IsFontBold()) { //OSX if (IsOSX) { face = "Arial-BoldMT"; fontname = "Arial Bold.ttf"; } else { face = _dejavuFonts ? "DejaVu Sans Condensed Bold" : "Arial-Bold"; fontname = (_dejavuFonts ? "DejaVuSansCondensed-Bold.ttf" : "arialbd.ttf"); } } else if (pt.SI.FontStyle == FontStyleEnum.Italic) { //OSX if (IsOSX) { face = "Arial-ItalicMT"; fontname = "Arial Italic.ttf"; } else { face = _dejavuFonts ? "DejaVu Sans Condensed Oblique" : "Arial-Italic"; fontname = (_dejavuFonts ? "DejaVuSansCondensed-Oblique.ttf" : "ariali.ttf"); } } else { //OSX if (IsOSX) { face = "ArialMT"; fontname = "Arial.ttf"; } else { face = _dejavuFonts ? "DejaVu Sans Condensed" : face; fontname = (_dejavuFonts ? "DejaVuSansCondensed.ttf" : "arial.ttf"); } } fonttype1 = false; } else if (face == "Courier New") { if (pt.SI.IsFontBold() && pt.SI.FontStyle == FontStyleEnum.Italic) { //OSX if (IsOSX) { face = "CourierNewPS-BoldItalicMT"; fontname = "Courier New Bold Italic.ttf"; } else { face = _dejavuFonts ? "DejaVu Sans Mono Bold Oblique" : "Courier New-BoldItalic"; fontname = (_dejavuFonts ? "DejaVuSansMono-BoldOblique.ttf" : "courbi.ttf"); } } else if (pt.SI.IsFontBold()) { //OSX if (IsOSX) { face = "CourierNewPS-BoldMT"; fontname = "Courier New Bold.ttf"; } else { face = _dejavuFonts ? "DejaVu Sans Mono Bold" : "Courier New-Bold"; fontname = (_dejavuFonts ? "DejaVuSansMono-Oblique.ttf" : "courbd.ttf"); } } else if (pt.SI.FontStyle == FontStyleEnum.Italic) { //OSX if (IsOSX) { face = "CourierNewPS-ItalicMT"; fontname = "Courier New Italic.ttf"; } else { face = _dejavuFonts ? "DejaVu Sans Mono Oblique" : "Courier New-Italic"; fontname = (_dejavuFonts ? "DejaVuSansMono-Oblique.ttf" : "couri.ttf"); } } else { //OSX if (IsOSX) { face = "CourierNewPSMT"; fontname = "Courier New.ttf"; } else { face = _dejavuFonts ? "DejaVu Sans Mono" : face; fontname = (_dejavuFonts ? "DejaVuSansMono.ttf" : "cour.ttf"); } } fonttype1 = false; } else { if (pt.SI.IsFontBold() && pt.SI.FontStyle == FontStyleEnum.Italic) // bold and italic? face = face + "-BoldOblique"; else if (pt.SI.IsFontBold()) // just bold? face = face + "-Bold"; else if (pt.SI.FontStyle == FontStyleEnum.Italic) face = face + "-Oblique"; fonttype1 = true; } //Get index of fontname in List font name int indexbf = _baseFontsName.FindIndex(delegate (string _fontname) { return _fontname == face; }); //If not found then add new BaseFont if (indexbf == -1) { _baseFontsName.Add(face); if (fonttype1) { bf = BaseFont.CreateFont(face, BaseFont.WINANSI, BaseFont.NOT_EMBEDDED); } else { string path = System.IO.Path.Combine(folder, fontname); bf = BaseFont.CreateFont(path, BaseFont.IDENTITY_H, BaseFont.EMBEDDED); } _baseFonts.Add(bf); } else //Get from List { bf = _baseFonts[indexbf]; } // Loop thru the lines of text for (int i = 0; i < sa.Length; i++) { string text = sa[i]; float textwidth = tw[i]; // Calculate the x positino float startX = pt.X + pt.SI.PaddingLeft; // TODO: handle tb_rl float startY = pt.Y + pt.SI.PaddingTop + (i * pt.SI.FontSize); // TODO: handle tb_rl int align = 0; if (pt.SI.WritingMode == WritingModeEnum.lr_tb) { // TODO: not sure what alignment means with tb_lr so I'll leave it out for now switch (pt.SI.TextAlign) { case TextAlignEnum.Center: if (width > 0) { startX = pt.X + pt.SI.PaddingLeft + (width - pt.SI.PaddingLeft - pt.SI.PaddingRight) / 2 - textwidth / 2; align = Element.ALIGN_CENTER; } break; case TextAlignEnum.Right: if (width > 0) { startX = pt.X + width - textwidth - pt.SI.PaddingRight; align = Element.ALIGN_RIGHT; } break; case TextAlignEnum.Left: default: align = Element.ALIGN_LEFT; break; } // Calculate the y position switch (pt.SI.VerticalAlign) { case VerticalAlignEnum.Middle: if (height <= 0) break; // calculate the middle of the region startY = pt.Y + pt.SI.PaddingTop + (height - pt.SI.PaddingTop - pt.SI.PaddingBottom) / 2 - pt.SI.FontSize / 2; // now go up or down depending on which line if (sa.Length == 1) break; if (sa.Length % 2 == 0) // even number { startY = startY - ((sa.Length / 2 - i) * pt.SI.FontSize) + pt.SI.FontSize / 2; } else { startY = startY - ((sa.Length / 2 - i) * pt.SI.FontSize); } break; case VerticalAlignEnum.Bottom: if (height <= 0) break; startY = pt.Y + height - pt.SI.PaddingBottom - (pt.SI.FontSize * (sa.Length - i)); break; case VerticalAlignEnum.Top: default: break; } } else { //25072008 GJL - Move x in a little - it draws to close to the edge of the rectangle (25% of the font size seems to work!) and Center or right align vertical text startX += pt.SI.FontSize / 4; switch (pt.SI.TextAlign) { case TextAlignEnum.Center: if (height > 0) startY = pt.Y + pt.SI.PaddingLeft + (height - pt.SI.PaddingLeft - pt.SI.PaddingRight) / 2 - textwidth / 2; break; case TextAlignEnum.Right: if (width > 0) startY = pt.Y + height - textwidth - pt.SI.PaddingRight; break; case TextAlignEnum.Left: default: break; } } // Draw background rectangle if needed (only put out on the first line, since we do whole rectangle) if (!pt.SI.BackgroundColor.IsEmpty && height > 0 && width > 0 && i == 0) { // background color, height and width are specified iAddFillRect(pt.X, pt.Y, width, height, pt.SI.BackgroundColor); } // Set the clipping path, (Itext have no clip) if (height > 0 && width > 0) { _contentByte.SetRGBColorFill(pt.SI.Color.R, pt.SI.Color.G, pt.SI.Color.B); if (pt.SI.WritingMode == WritingModeEnum.lr_tb) { //If textline after measure with word break can fit just simple show Text if (width >= textwidth) { _contentByte.BeginText(); _contentByte.SetFontAndSize(bf, pt.SI.FontSize); _contentByte.SetTextMatrix(startX, (PageSize.yHeight - startY - pt.SI.FontSize)); _contentByte.ShowText(text); _contentByte.EndText(); } else { //else use Column text to wrap or clip (wrap: for example a text like an URL so word break is not working here, itextsharp ColumnText do the work for us) ColumnText ct = new ColumnText(_contentByte); Phrase myPhrase = new Phrase(text, new iTextSharp.text.Font(bf, pt.SI.FontSize)); ct.SetSimpleColumn(myPhrase, pt.X + pt.SI.PaddingLeft, PageSize.yHeight - startY, pt.X + width - pt.SI.PaddingRight, PageSize.yHeight - pt.Y - pt.SI.PaddingBottom - height, 10f, align); ct.Go(); } } else { //Not checked double rads = -283.0 / 180.0; double radsCos = Math.Cos(rads); double radsSin = Math.Sin(rads); _contentByte.BeginText(); _contentByte.SetFontAndSize(bf, pt.SI.FontSize); _contentByte.SetTextMatrix((float)radsCos, (float)radsSin, (float)-radsSin, (float)radsCos, startX, PageSize.yHeight - startY); _contentByte.ShowText(text); _contentByte.EndText(); } //add URL if (pt.HyperLink != null) _pdfDocument.Add(new Annotation(pt.X, PageSize.yHeight - (pt.Y + height), width + pt.X, PageSize.yHeight - pt.Y, pt.HyperLink)); //add tooltip if (pt.Tooltip != null) _pdfDocument.Add(new Annotation(pt.X, PageSize.yHeight - (pt.Y + height), width +pt.X, PageSize.yHeight - pt.Y,pt.Tooltip)); } // Handle underlining etc. float maxX; switch (pt.SI.TextDecoration) { case TextDecorationEnum.Underline: maxX = width > 0 ? Math.Min(pt.X + width, startX + textwidth) : startX + textwidth; AddLine(startX, startY + pt.SI.FontSize + 1, maxX, startY + pt.SI.FontSize + 1, 1, pt.SI.Color, BorderStyleEnum.Solid); break; case TextDecorationEnum.LineThrough: maxX = width > 0 ? Math.Min(pt.X + width, startX + textwidth) : startX + textwidth; AddLine(startX, startY + (pt.SI.FontSize / 2) + 1, maxX, startY + (pt.SI.FontSize / 2) + 1, 1, pt.SI.Color, BorderStyleEnum.Solid); break; case TextDecorationEnum.Overline: maxX = width > 0 ? Math.Min(pt.X + width, startX + textwidth) : startX + textwidth; AddLine(startX, startY + 1, maxX, startY + 1, 1, pt.SI.Color, BorderStyleEnum.Solid); break; case TextDecorationEnum.None: default: break; } } iAddBorder(pt.SI, pt.X, pt.Y, height, width); // add any required border return; }
private string[] MeasureString(PageText pt, Graphics g, out float[] width) { StyleInfo si = pt.SI; string s = pt.Text; Font drawFont=null; StringFormat drawFormat=null; SizeF ms; string[] sa=null; width=null; try { // STYLE System.Drawing.FontStyle fs = 0; if (si.FontStyle == FontStyleEnum.Italic) fs |= System.Drawing.FontStyle.Italic; // WEIGHT switch (si.FontWeight) { case FontWeightEnum.Bold: case FontWeightEnum.Bolder: case FontWeightEnum.W500: case FontWeightEnum.W600: case FontWeightEnum.W700: case FontWeightEnum.W800: case FontWeightEnum.W900: fs |= System.Drawing.FontStyle.Bold; break; default: break; } drawFont = new Font(StyleInfo.GetFontFamily(si.FontFamilyFull), si.FontSize, fs); drawFormat = new StringFormat(); drawFormat.Alignment = StringAlignment.Near; // Measure string // pt.NoClip indicates that this was generated by PageTextHtml Build. It has already word wrapped. if (pt.NoClip || pt.SI.WritingMode == WritingModeEnum.tb_rl) // TODO: support multiple lines for vertical text { ms = MeasureString(s, g, drawFont, drawFormat); width = new float[1]; width[0] = RSize.PointsFromPixels(g, ms.Width); // convert to points from pixels sa = new string[1]; sa[0] = s; return sa; } // handle multiple lines; // 1) split the string into the forced line breaks (ie "\n and \r") // 2) foreach of the forced line breaks; break these into words and recombine s = s.Replace("\r\n", "\n"); // don't want this to result in double lines string[] flines = s.Split(lineBreak); List<string> lines = new List<string>(); List<float> lineWidths = new List<float>(); // remove the size reserved for left and right padding float ptWidth = pt.W - pt.SI.PaddingLeft - pt.SI.PaddingRight; if (ptWidth <= 0) ptWidth = 1; foreach (string tfl in flines) { string fl; if (tfl.Length > 0 && tfl[tfl.Length-1] == ' ') fl = tfl.TrimEnd(' '); else fl = tfl; // Check if entire string fits into a line ms = MeasureString(fl, g, drawFont, drawFormat); float tw = RSize.PointsFromPixels(g, ms.Width); if (tw <= ptWidth) { // line fits don't need to break it down further lines.Add(fl); lineWidths.Add(tw); continue; } // Line too long; need to break into multiple lines // 1) break line into parts; then build up again keeping track of word positions string[] parts = fl.Split(wordBreak); // this is the maximum split of lines StringBuilder sb = new StringBuilder(fl.Length); CharacterRange[] cra = new CharacterRange[parts.Length]; for (int i = 0; i < parts.Length; i++) { int sc = sb.Length; // starting character sb.Append(parts[i]); // endding character if (i != parts.Length - 1) // last item doesn't need blank sb.Append(" "); int ec = sb.Length; CharacterRange cr = new CharacterRange(sc, ec - sc); cra[i] = cr; // add to character array } // 2) Measure the word locations within the line string wfl = sb.ToString(); WordStartFinish[] wordLocations = MeasureString(wfl, g, drawFont, drawFormat, cra); if (wordLocations == null) continue; // 3) Loop thru creating new lines as needed int startLoc = 0; CharacterRange crs = cra[startLoc]; CharacterRange cre = cra[startLoc]; float cwidth = wordLocations[0].end; // length of the first float bwidth = wordLocations[0].start; // characters need a little extra on start string ts; bool bLine = true; for (int i=1; i < cra.Length; i++) { cwidth = wordLocations[i].end - wordLocations[startLoc].start + bwidth; if (cwidth > ptWidth) { // time for a new line cre = cra[i-1]; ts = wfl.Substring(crs.First, cre.First + cre.Length - crs.First); lines.Add(ts); lineWidths.Add(wordLocations[i-1].end - wordLocations[startLoc].start + bwidth); // Find the first non-blank character of the next line while (i < cra.Length && cra[i].Length == 1 && fl[cra[i].First] == ' ') { i++; } if (i < cra.Length) // any lines left? { // yes, continue on startLoc = i; crs = cre = cra[startLoc]; cwidth = wordLocations[i].end - wordLocations[startLoc].start + bwidth; } else // no, we can stop bLine = false; // bwidth = wordLocations[startLoc].start - wordLocations[startLoc - 1].end; } else cre = cra[i]; } if (bLine) { ts = fl.Substring(crs.First, cre.First + cre.Length - crs.First); lines.Add(ts); lineWidths.Add(cwidth); } } // create the final array from the Lists string[] la = lines.ToArray(); width = lineWidths.ToArray(); return la; } finally { if (drawFont != null) drawFont.Dispose(); if (drawFormat != null) drawFont.Dispose(); } }
private void DoInstructions(Font f, StringFormat sf, Brush br, Single recX, Single recY, Single recWidth, Single recHeight, String Text) { Color Col = Color.Black; if (br.GetType().Name.Equals("SolidBrush")) { SolidBrush sb = (SolidBrush)br; Col = sb.Color; } PageText pt = new PageText(Text); pt.X = X + recX * SCALEFACTOR; pt.Y = Y + recY * SCALEFACTOR; pt.W = recWidth * SCALEFACTOR; pt.H = recHeight * SCALEFACTOR; StyleInfo SI = new StyleInfo(); SI.Color = Col; SI.Direction = DirectionEnum.LTR; SI.FontFamily = f.Name; SI.FontSize = f.Size * SCALEFACTOR; if (f.Italic) {SI.FontStyle = FontStyleEnum.Italic;} if (f.Bold) { SI.FontWeight = FontWeightEnum.Bold; } if (f.Underline) { SI.TextDecoration = TextDecorationEnum.Underline; } if (sf.LineAlignment == StringAlignment.Center) { SI.TextAlign = TextAlignEnum.Center; } else if (sf.LineAlignment == StringAlignment.Far) { SI.TextAlign = TextAlignEnum.Right; } if (sf.Alignment == StringAlignment.Center) { SI.VerticalAlign = VerticalAlignEnum.Middle; } else if (sf.Alignment == StringAlignment.Far) { SI.VerticalAlign = VerticalAlignEnum.Bottom; } if ((sf.FormatFlags & StringFormatFlags.DirectionVertical) == StringFormatFlags.DirectionVertical) { SI.WritingMode = WritingModeEnum.tb_rl; } else { SI.WritingMode = WritingModeEnum.lr_tb; } pt.SI = SI; items.Add(pt); //r = Math.Round((r / 255), 3); //g = Math.Round((g / 255), 3); //b = Math.Round((b / 255), 3); //string pdfFont = fonts.GetPdfFont(f.Name); ////need a graphics object... //Bitmap bm = new Bitmap(1, 1); //Graphics gr = Graphics.FromImage(bm); //Font scaleFont = new Font(f.Name, (f.Size * ScaleY) * 1.5f, f.Style, f.Unit); //SizeF TextSize = gr.MeasureString(Text.Substring(0, Text.Length), scaleFont, (int)(recWidth * ScaleX), sf); //float textwidth = TextSize.Width; //float textHeight = TextSize.Height; //float startX = X + recX * ScaleX; //float startY = Y + Height - recY * ScaleY - (scaleFont.Size); //if ((sf.FormatFlags & StringFormatFlags.DirectionVertical) != StringFormatFlags.DirectionVertical) //{ // if (sf.LineAlignment == StringAlignment.Center) // { // startX = (startX + (recWidth * ScaleX) / 2) - (textwidth / 4); // } // else if (sf.LineAlignment == StringAlignment.Far) // { // startX = (startX + recWidth * ScaleX) - (textwidth / 1.8f); // } //} //else //{ // startX += textwidth / 4; // if (sf.LineAlignment == StringAlignment.Center) // { // startY = (startY - (recHeight * ScaleY) / 2) + (textHeight / 4); // } // else if (sf.LineAlignment == StringAlignment.Far) // { // startY = (startY - recHeight * ScaleY) + (textHeight / 1.8f); // } //} //Lines.Append("\r\nq\t"); //string newtext = PdfUtility.UTF16StringQuoter(Text); //if ((sf.FormatFlags & StringFormatFlags.DirectionVertical) != StringFormatFlags.DirectionVertical) //{ // Lines.AppendFormat(System.Globalization.NumberFormatInfo.InvariantInfo, // "\r\nBT/{0} {1} Tf\t{5} {6} {7} rg\t{2} {3} Td \t({4}) Tj\tET\tQ\t", // pdfFont, scaleFont.SizeInPoints, startX, startY, newtext, r, g, b); //} //else //{ // double rads = -283.0 / 180.0; // double radsCos = Math.Cos(rads); // double radsSin = Math.Sin(rads); // Lines.AppendFormat(System.Globalization.NumberFormatInfo.InvariantInfo, // "\r\nBT/{0} {1} Tf\t{5} {6} {7} rg\t{8} {9} {10} {11} {2} {3} Tm \t({4}) Tj\tET\tQ\t", // pdfFont, scaleFont.SizeInPoints, startX, startY, newtext, r, g, b, // radsCos, radsSin, -radsSin, radsCos); //} }
private void HighlightString(Graphics g, PageText dtext, RectangleF r, Font f, StringFormat sf) { if (_HighlightText == null || _HighlightText.Length == 0) return; // nothing to highlight bool bhighlightItem = dtext == _HighlightItem || (_HighlightItem != null && dtext.HtmlParent == _HighlightItem); if (!(_HighlightAll || bhighlightItem)) return; // not highlighting all and not on current highlight item string hlt = _HighlightCaseSensitive ? _HighlightText : _HighlightText.ToLower(); string text = _HighlightCaseSensitive ? dtext.Text : dtext.Text.ToLower(); if (text.IndexOf(hlt) < 0) return; // string not in text StringFormat sf2 = null; try { // Create a CharacterRange array with the highlight location and length // Handle multiple occurences of text List<CharacterRange> rangel = new List<CharacterRange>(); int loc = text.IndexOf(hlt); int hlen = hlt.Length; int len = text.Length; while (loc >= 0) { rangel.Add(new CharacterRange(loc, hlen)); if (loc + hlen < len) // out of range of text loc = text.IndexOf(hlt, loc + hlen); else loc = -1; } if (rangel.Count <= 0) // we should have gotten one; but return; CharacterRange[] ranges = rangel.ToArray(); // Construct a new StringFormat object. sf2 = sf.Clone() as StringFormat; // Set the ranges on the StringFormat object. sf2.SetMeasurableCharacterRanges(ranges); // Get the Regions to highlight by calling the // MeasureCharacterRanges method. if (r.Width <= 0 || r.Height <= 0) { SizeF ts = g.MeasureString(dtext.Text, f); r.Height = ts.Height; r.Width = ts.Width; } Region[] charRegion = g.MeasureCharacterRanges(dtext.Text, f, r, sf2); // Fill in the region using a semi-transparent color to highlight foreach (Region rg in charRegion) { Color hl = bhighlightItem ? _HighlightItemColor : _HighlightAllColor; g.FillRegion(new SolidBrush(Color.FromArgb(50, hl)), rg); } } catch { } // if highlighting fails we don't care; need to continue finally { if (sf2 != null) sf2.Dispose(); } }
override internal void RunPage(Pages pgs, Row row) { Report r = pgs.Report; TextboxRuntime tbr = TextboxRuntime.GetTextboxRuntime(r, this); tbr.RunCount++; // Increment the run count bool bHidden = IsHidden(r, row); SetPagePositionBegin(pgs); string t; if (bHidden) { t = ""; } else { t = RunText(r, row); // get the text } bool bDup = RunTextIsDuplicate(tbr, t, pgs.CurrentPage); if (bDup) { if (!(this.IsTableOrMatrixCell(r))) // don't put out anything if not in Table or Matrix { bHidden = true; } t = ""; // still need to put out the cell } PageText pt; PageTextHtml pth = null; if (IsHtml(r, row)) { pt = pth = new PageTextHtml(t); } else { pt = new PageText(t); } SetPagePositionAndStyle(r, pt, row); if (this.CanGrow && tbr.RunHeight == 0) // when textbox is in a DataRegion this will already be called { this.RunTextCalcHeight(r, pgs.G, row, pt is PageTextHtml? pt as PageTextHtml: null); } pt.H = Math.Max(pt.H, tbr.RunHeight); // reset height if (pt.SI.BackgroundImage != null) { pt.SI.BackgroundImage.H = pt.H; // and in the background image } pt.CanGrow = this.CanGrow; // check TextAlign: if General then correct based on data type if (pt.SI.TextAlign == TextAlignEnum.General) { if (DataType.IsNumeric(this.Value.GetTypeCode())) { pt.SI.TextAlign = TextAlignEnum.Right; } } // Hidden objects don't affect the current page? if (!bHidden) { // Force page break if it doesn't fit on a page if (this.IsInBody && // Only force page when object directly in body pgs.CurrentPage.YOffset + pt.Y + pt.H >= pgs.BottomOfPage && // running off end of page !pgs.CurrentPage.IsEmpty()) // if page is already empty don't force new { // force page break if it doesn't fit on the page pgs.NextOrNew(); pgs.CurrentPage.YOffset = OwnerReport.TopOfPage; if (this.YParents != null) { pt.Y = 0; } } Page p = pgs.CurrentPage; RecordPageReference(r, p, row); // save information for late page header/footer references p.AddObject(pt); if (!bDup) { tbr.PreviousText = t; // previous text displayed tbr.PreviousPage = p; // page previous text was shown on } } SetPagePositionEnd(pgs, pt.Y + pt.H); if (pth != null) { pth.Reset(); } if (this.CanGrow && !Value.IsConstant()) { tbr.RunHeight = 0; // need to recalculate } }