public void ResetJustifySpacing(PDFTextRenderOptions options) { _linespacingOptions = new ExtraSpacingOptions() { WordSpace = PDFUnit.Zero, CharSpace = PDFUnit.Zero, Options = options }; }
public void SetTextLeading(PDFTextRenderOptions options) { PDFUnit h; if (options.Leading.HasValue) { h = options.Leading.Value; } else if (options.Font.FontMetrics != null) { h = options.Font.FontMetrics.LineHeight; } else if (null != this.CurrentFontResource && options.Font != null && this.CurrentFontResource.FontName == options.Font.FullName) { options.Font.FontMetrics = this.CurrentFontResource.Definition.GetFontMetrics(options.Font.Size); h = options.Font.FontMetrics.LineHeight; } else { h = options.Font.Size.PointsValue * 1.2; } this.Writer.WriteOpCodeS(PDFOpCode.TxtLeading, h.RealValue); }
private System.Drawing.Font GetSystemFont(PDFTextRenderOptions options) { //if (options == null || options.Font == null) return(null); //else // return options.Font.GetSystemFont(); }
/// <summary> /// Measures all the characters on a specified string returning their size /// 6based on how many fitted in the available space. /// </summary> /// <param name="chars"></param> /// <param name="offset"></param> /// <param name="fitted"></param> /// <param name="availh">The available height in the current region</param> /// <returns></returns> private PDFSize MeasureString(PDFUnit availh, PDFUnit availw, string chars, int offset, out int fitted) { PDFSize available = new PDFSize(availw, availh); PDFTextRenderOptions opts = this.TextRenderOptions; PDFSize measured; measured = this.Context.Graphics.MeasureString(chars, offset, available, opts, out fitted); return(measured); }
private void ReleaseTextRenderOptions(PDFTextRenderOptions options, PDFRect bounds) { if (options.FillBrush != null) { options.FillBrush.ReleaseGraphics(this, bounds); } if (options.Stroke != null) { options.Stroke.ReleaseGraphics(this, bounds); } }
private double GetLineLeft(PDFSize size, PDFTextRenderOptions options) { if (options != null && options.FirstLineInset != PDFUnit.Empty) { return(options.FirstLineInset.Value.ToPoints().Value); } else { return(0.0); } }
public void SetTextSpacing(PDFTextRenderOptions options) { if (options.WordSpacing.HasValue == false) { this.ResetCustomWordSpace(); } SetTextSpacing(options.WordSpacing, options.CharacterSpacing, options.Font.Size); if (options.CharacterHScale.HasValue) { this.Writer.WriteOpCodeS(PDFOpCode.TxtHScaling, (PDFReal)options.CharacterHScale.Value * 100.0); } }
private static StringFormat GetStringFormatting(PDFTextRenderOptions options) { StringFormat format; if (options.WrapText.HasValue && options.WrapText.Value == WordWrap.Character) { format = NoWrappingCharacterFormant; } else { format = NoWrappingWordFormat; } return(format); }
public TextRenderMode SetTextRenderOptions(PDFTextRenderOptions options, PDFRect bounds) { TextRenderMode mode = TextRenderMode.NoOp; if (options == null) { throw new ArgumentNullException("options"); } if (options.FillBrush != null) { mode = TextRenderMode.Fill; options.FillBrush.SetUpGraphics(this, bounds); } if (options.Stroke != null) { if (mode == TextRenderMode.Fill) { mode = TextRenderMode.FillAndStroke; } else { mode = TextRenderMode.Stroke; } options.Stroke.SetUpGraphics(this, bounds); } if (options.Font != null) { this.SetCurrentFont(options.Font); } if (options.TextDirection.HasValue) { this.TextDirection = options.TextDirection.Value; } else { this.TextDirection = Scryber.TextDirection.LTR; } SetTextLeading(options); SetTextSpacing(options); SetTextRenderMode(mode); return(mode); }
public void SetTextLeading(PDFTextRenderOptions options) { PDFUnit h; if (options.Leading.HasValue) { h = options.Leading.Value; } else if (options.Font.FontMetrics != null) { h = options.Font.FontMetrics.LineHeight; } else { h = options.Font.Size.PointsValue * 1.2; } this.Writer.WriteOpCodeS(PDFOpCode.TxtLeading, h.RealValue); }
// // layout methods // #region public void Layout(PDFLayoutContext context, Styles.PDFStyle fullstyle) /// <summary> /// Measures and lay's out the TextComponent that this engine references. /// </summary> /// <param name="context"></param> /// <param name="fullstyle"></param> public void Layout(PDFLayoutContext context, Styles.Style fullstyle) { if (null == context) { throw new ArgumentNullException("context"); } if (null == fullstyle) { throw new ArgumentNullException("fullstyle"); } this._ctx = context; this._fullstyle = fullstyle; this._posopts = fullstyle.CreatePostionOptions(); this._textopts = fullstyle.CreateTextOptions(); if (this._posopts.PositionMode == PositionMode.Invisible) { if (context.ShouldLogDebug) { context.TraceLog.Add(TraceLevel.Debug, "Layout", "Skipping the layout of the text component " + this.TextComponent.ID + " as it is invisible"); } return; } this._frsrc = ((Document)this.TextComponent.Document).GetFontResource(this.TextRenderOptions.Font, true); this.Context.PerformanceMonitor.Begin(PerformanceMonitorType.Text_Layout); this._reader = this.TextComponent.CreateReader(context, fullstyle); if (null != this._reader) { this.ContinueLayout = true; this.DoLayoutText(); } this.Context.PerformanceMonitor.End(PerformanceMonitorType.Text_Layout); }
internal bool JustifyContent(PDFUnit total, PDFUnit current, PDFUnit available, bool all, List <PDFTextRunCharacter> runCache, ref PDFTextRenderOptions currOptions) { if (this.Runs.Count < 1) { return(false); } bool shouldJustify = all; PDFLayoutRun last = this.Runs[this.Runs.Count - 1]; if (last is PDFTextRunNewLine && (last as PDFTextRunNewLine).IsHardReturn == false) { shouldJustify = true; } if (shouldJustify) { runCache.Clear(); bool intext = (null != currOptions); //if we have text render options then even if we are the first run we can be considered as inside a text block int charCount = 0; int spaceCount = 0; PDFTextRunCharacter lastchars = null; for (int i = 0; i < this.Runs.Count; i++) { PDFLayoutRun cur = this.Runs[i]; if (cur is PDFTextRunBegin) { currOptions = ((PDFTextRunBegin)cur).TextRenderOptions; if (!intext) { intext = true; } } else if (cur is PDFTextRunCharacter && intext) { PDFTextRunCharacter chars = cur as PDFTextRunCharacter; if (!(currOptions.WordSpacing.HasValue || currOptions.CharacterSpacing.HasValue)) { AddCharactersAndSpaces(chars.Characters, ref charCount, ref spaceCount); lastchars = chars; } } else if (cur is PDFLayoutComponentRun) { lastchars = null; } } // Post process to calculate the required spacing // if we have some text in our line. if (intext && (spaceCount + charCount > 0)) { if (null != lastchars && lastchars.Characters.EndsWith(" ")) { lastchars.Characters = lastchars.Characters.Substring(0, lastchars.Characters.Length - 1); spaceCount -= 1; } double spaceToCharFactor = 10; // apply ten times more to spaces than characters. double full = (spaceCount * spaceToCharFactor) + charCount; this._linespacingOptions = new ExtraSpacingOptions() { CharSpace = available / full, WordSpace = (available / full) * spaceToCharFactor, Options = currOptions }; charCount = 0; spaceCount = 0; PDFUnit currWidth = 0; PDFUnit change = PDFUnit.Zero; for (int i = 0; i < this.Runs.Count; i++) { PDFLayoutRun cur = this.Runs[i]; if (cur is PDFTextRunBegin) { PDFTextRunBegin begin = (PDFTextRunBegin)cur; currOptions = begin.TextRenderOptions; if (i > 0) { change = (_linespacingOptions.WordSpace * spaceCount) + (_linespacingOptions.CharSpace * charCount); begin.LineInset += change; } } else if (cur is PDFTextRunCharacter) { if (!currOptions.WordSpacing.HasValue || !currOptions.CharacterSpacing.HasValue) { PDFTextRunCharacter chars = cur as PDFTextRunCharacter; int runChars = 0; int runSpaces = 0; AddCharactersAndSpaces(chars.Characters, ref runChars, ref runSpaces); charCount += runChars; spaceCount += runSpaces; chars.ExtraSpace = (_linespacingOptions.WordSpace * runSpaces) + (_linespacingOptions.CharSpace * runChars); } } else if (cur is PDFLayoutComponentRun) { if (i > 0) { PDFLayoutComponentRun comprun = (cur as PDFLayoutComponentRun); PDFRect bounds = comprun.TotalBounds; bounds.X += (_linespacingOptions.WordSpace * spaceCount) + (_linespacingOptions.CharSpace * charCount); comprun.TotalBounds = bounds; } } else if (cur is PDFTextRunNewLine) { PDFTextRunNewLine newLine = (cur as PDFTextRunNewLine); newLine.Offset = new PDFSize(newLine.Offset.Width + change, newLine.Offset.Height); } } } } return(shouldJustify); }
public void CreateTextOptionsTest() { Style target = new Style(); PDFTextRenderOptions actual = target.CreateTextOptions(); Assert.IsNull(actual.Background); Assert.IsNull(actual.FillBrush); //Default value unit for first line inset and word spacing is Zero. Assert.IsTrue(actual.FirstLineInset.HasValue); Assert.AreEqual(PDFUnit.Zero, actual.FirstLineInset.Value); Assert.IsFalse(actual.WordSpacing.HasValue); Assert.IsNull(actual.Font, "Font is not null"); Assert.IsNull(actual.Stroke); Assert.IsFalse(actual.Leading.HasValue); Assert.IsFalse(actual.WrapText.HasValue); //set the specific values target = new Style(); target.Background.Color = PDFColors.Lime; target.Background.FillStyle = Scryber.Drawing.FillType.Solid; target.Fill.Color = PDFColors.Navy; target.Fill.Style = Scryber.Drawing.FillType.Solid; target.Stroke.Color = PDFColors.Purple; target.Stroke.Width = 2; target.Stroke.LineStyle = LineType.Solid; target.Font.FontSize = 36; target.Font.FontFamily = (PDFFontSelector)"Bauhaus 92"; target.Text.WrapText = Text.WordWrap.NoWrap; target.Text.WordSpacing = 1.0F; //validate against settings actual = target.CreateTextOptions(); Assert.IsInstanceOfType(actual.Background, typeof(PDFSolidBrush)); Assert.AreEqual(PDFColors.Lime, ((PDFSolidBrush)actual.Background).Color); Assert.IsInstanceOfType(actual.FillBrush, typeof(PDFSolidBrush)); Assert.AreEqual(PDFColors.Navy, ((PDFSolidBrush)actual.FillBrush).Color); Assert.IsInstanceOfType(actual.Stroke, typeof(PDFSolidPen)); Assert.AreEqual(PDFColors.Purple, ((PDFSolidPen)actual.Stroke).Color); Assert.AreEqual((PDFUnit)2, actual.Stroke.Width); Assert.IsInstanceOfType(actual.Font, typeof(PDFFont)); Assert.AreEqual((PDFFontSelector)"Bauhaus 92", actual.Font.Selector); Assert.AreEqual((PDFUnit)36, actual.Font.Size); Assert.IsTrue(actual.WordSpacing.HasValue); Assert.AreEqual((PDFUnit)1.0, actual.WordSpacing.Value); Assert.IsTrue(actual.WrapText.HasValue); Assert.AreEqual(Text.WordWrap.NoWrap, actual.WrapText.Value); }
// // overrides // #region protected override void DoPushComponentLayout(PDFLayoutContext context, int pageIndex, PDFUnit xoffset, PDFUnit yoffset) /// <summary> /// Overrides the default behaviour to push any arrangements for the child item of this region /// </summary> /// <param name="context"></param> protected override void DoPushComponentLayout(PDFLayoutContext context, int pageIndex, PDFUnit xoffset, PDFUnit yoffset) { bool logdebug = context.ShouldLogDebug; if (logdebug) { context.TraceLog.Begin(TraceLevel.Debug, "Layout Region", "Pushing the component layout for the region " + this.ToString()); } if (!this.IsClosed) { if (logdebug) { context.TraceLog.Add(TraceLevel.Debug, PDFLayoutItem.LOG_CATEGORY, "Closing the region " + this.ToString() + " before pushing the layout"); } this.Close(); } if (this._contents == null || this.Contents.Count == 0) { if (logdebug) { context.TraceLog.Add(TraceLevel.Debug, PDFLayoutItem.LOG_CATEGORY, "The region " + this.ToString() + " is empty. Exiting the push component early."); } return; } bool applyAlignments = this.ShouldApplyAlignment(); if (applyAlignments) { VerticalAlignment v = this.VAlignment; if (v != VerticalAlignment.Top) { this.EnsureCorrectHeight(); if (logdebug) { context.TraceLog.Add(TraceLevel.Debug, PDFLayoutItem.LOG_CATEGORY, "Adjusting the vertical offset of the region " + this.ToString() + " as it is not top aligned"); } PDFUnit space = this.AvailableHeight; if (v == VerticalAlignment.Middle) { space = space / 2; } yoffset += space; } } HorizontalAlignment h = this.HAlignment; PDFTextRenderOptions options = (this.Parent as PDFLayoutBlock).FullStyle.CreateTextOptions(); List <PDFTextRunCharacter> cache = new List <PDFTextRunCharacter>(); bool lastwasapplied = false; foreach (PDFLayoutItem item in this.Contents) { PDFUnit itemXOffset = xoffset; ///Individually calculate each lines horizontal offset if (applyAlignments && h != HorizontalAlignment.Left) { PDFUnit space = this.TotalBounds.Width - item.Width; if (h == HorizontalAlignment.Justified) { if (item is PDFLayoutLine) { PDFLayoutLine line = item as PDFLayoutLine; if (logdebug) { context.TraceLog.Add(TraceLevel.Debug, PDFLayoutItem.LOG_CATEGORY, "Justifying the textual content of the line " + line.LineIndex); } bool didjustify = line.JustifyContent(this.TotalBounds.Width, item.Width, space, false, cache, ref options); if (!didjustify && lastwasapplied && null != options && !(options.WordSpacing.HasValue || options.CharacterSpacing.HasValue)) { line.ResetJustifySpacing(options); } lastwasapplied = didjustify; } space = 0; // reset space to zero as already accounted for. } else if (h == HorizontalAlignment.Center) { space = space / 2; } itemXOffset = itemXOffset + space; } item.PushComponentLayout(context, pageIndex, itemXOffset, yoffset); } if (logdebug) { context.TraceLog.End(TraceLevel.Debug, "Layout Region", "Pushed all the component layouts for the region " + this.ToString()); } }
// // ctor // #region public PDFTextRunNewLine(bool isHardReturn, PDFLayoutLine line, IPDFComponent owner) /// <summary> /// Creates a new line text run. /// </summary> /// <param name="isHardReturn"></param> /// <param name="line"></param> /// <param name="owner"></param> public PDFTextRunNewLine(bool isHardReturn, PDFLayoutLine line, PDFTextRenderOptions opts, IPDFComponent owner) : base(line, owner) { this.IsHardReturn = isHardReturn; this.TextOptions = opts; }
/// <summary> /// Measures a single line of text (no wrapping) and returns the size required, /// and the number of characters fitted into that line. Uses the current font and size. /// </summary> /// <param name="chars"></param> /// <param name="startIndex"></param> /// <param name="available"></param> /// <param name="options"></param> /// <param name="charsfitted"></param> /// <returns></returns> /// <remarks>Uses the TTFFontFile if available, otherwise will default to using the GDI+ measure, /// which is slower but supports postscript fonts</remarks> public PDFSize MeasureString(string chars, int startIndex, PDFSize available, PDFTextRenderOptions options, out int charsfitted) { PDFFontResource frsc = this.CurrentFontResource; PDFUnit fsize = this.CurrentFont.Size; if (null == frsc) { throw new InvalidOperationException("Current font has not be set on the graphics class, so strings cannot be measured"); } PDFFontDefinition defn = frsc.Definition; PDFSize measured; if (defn.CanMeasureStrings) { bool trimtoword = true; if (options.WrapText.HasValue) { if (options.WrapText == WordWrap.NoWrap) { available.Width = new PDFUnit(int.MaxValue, PageUnits.Points); } else if (options.WrapText == WordWrap.Character) { trimtoword = false; } } bool vertical = false; // Not currently supported. //inspect the spacing values - if any are set then we must use them in the calculations bool complexSpacing = false; double?wordSpace = null; double charSpace = Scryber.OpenType.TTFFile.NoCharacterSpace; double hScale = Scryber.OpenType.TTFFile.NoHorizontalScale; if (options.WordSpacing.HasValue) { complexSpacing = true; wordSpace = options.WordSpacing.Value.PointsValue; } if (options.CharacterSpacing.HasValue) { complexSpacing = true; charSpace = options.CharacterSpacing.Value.PointsValue; } if (options.CharacterHScale.HasValue) { complexSpacing = true; hScale = options.CharacterHScale.Value; } if (complexSpacing) { //TODO: Check if we can do this on the widths rather than the ttfile. measured = defn.MeasureStringWidth(chars, startIndex, fsize.PointsValue, available.Width.PointsValue, wordSpace, charSpace, hScale, vertical, trimtoword, out charsfitted); } else { //TODO: Check if we can do this on the widths rather than the ttfile. measured = defn.MeasureStringWidth(chars, startIndex, fsize.PointsValue, available.Width.PointsValue, trimtoword, out charsfitted); } if (charsfitted > 0) { this.RegisterStringUse(chars, startIndex, charsfitted); } } else { throw new NotSupportedException("The font definition cannot measure strings"); //if (startIndex > 0) // chars = chars.Substring(startIndex); //measured = this.MeasureGraphicsString(chars, available, options.WrapText.HasValue ? options.WrapText.Value : WordWrap.Auto, out charsfitted); } return(measured); }
// // ctor // public PDFTextRunBegin(PDFTextRenderOptions renderopts, PDFLayoutLine line, IPDFComponent owner) : base(line, owner) { this.TextRenderOptions = renderopts; this.Lines.Add(line); }
public PDFSize GetRequiredSizeForLayout(PDFSize available, PDFLayoutContext context, Style appliedstyle) { PDFPositionOptions pos = appliedstyle.CreatePostionOptions(); PDFTextRenderOptions opts = appliedstyle.CreateTextOptions(); PDFImageXObject xobj = this.GetImageObject(context, appliedstyle); PDFSize naturalSize = xobj.GetImageSize(); PDFUnit h; PDFUnit w; if (pos.Height.HasValue && pos.Width.HasValue) { w = pos.Width.Value; h = pos.Height.Value; } else if (pos.Width.HasValue) { w = pos.Width.Value; h = naturalSize.Height * (pos.Width.Value.PointsValue / naturalSize.Width.PointsValue); } else if (pos.Height.HasValue) { h = pos.Height.Value; w = naturalSize.Width * (pos.Height.Value.PointsValue / naturalSize.Height.PointsValue); } else if (pos.PositionMode == PositionMode.Inline) { //We dont have an explicit size //So set it to the line height. if (opts.Font != null && opts.Font.FontMetrics != null) { h = opts.Font.FontMetrics.Ascent; } else { h = opts.Font.Size * 0.75; } w = naturalSize.Width * (h.PointsValue / naturalSize.Height.PointsValue); } else //We are in a block on our own line { h = naturalSize.Height; w = naturalSize.Width; if (w > available.Width) { w = available.Width; h = naturalSize.Height * (available.Width.PointsValue / naturalSize.Width.PointsValue); if (h < naturalSize.Height * this.MinimumScaleReduction) { //exceeded our maximum - so reverting back. h = naturalSize.Height; w = naturalSize.Width; } } if (h > available.Height) { h = available.Height; w = naturalSize.Width * (available.Height.PointsValue / naturalSize.Height.PointsValue); if (w < naturalSize.Width * this.MinimumScaleReduction) { h = naturalSize.Height; w = naturalSize.Width; } } } return(new PDFSize(w, h)); }