/// <summary> /// This method measures (or formats and typesets) a paragraph of text. /// </summary> /// <param name="paragraph"> This parameter references the paragraph to measure. </param> /// <param name="region"> This parameter contains the region to measure the paragraph within. </param> /// <param name="obstructions"> This parameter references floating obstructions that text will flow around. </param> /// <returns> This method returns the final measured text metrics. </returns> public ITextMetrics Measure( Paragraph paragraph, Rectangle region, params Rectangle[] obstructions) { Contract.Requires(paragraph != null); _TextAnalyzer.BeginAnalysis(paragraph.Text, paragraph.Culture); foreach(TextRun run in paragraph.Runs) { _TextAnalyzer.SetCulture(run.TextRange, run.Culture); _TextAnalyzer.SetNumberSubstitution(run.TextRange, null); } _TextAnalyzer.Analyze(_Aggregator); foreach(TextRun run in paragraph.Runs) { _Aggregator.SetCulture(run.TextRange, run.Culture); _Aggregator.SetFamily(run.TextRange, run.Family); _Aggregator.SetFeatures(run.TextRange, run.Features); _Aggregator.SetInline(run.TextRange, run.Inline, run.HAlignment, run.VAlignment); _Aggregator.SetPointSize(run.TextRange, run.PointSize); _Aggregator.SetStretch(run.TextRange, run.Stretch); _Aggregator.SetStyle(run.TextRange, run.Style); _Aggregator.SetWeight(run.TextRange, run.Weight); } _Shaper.Shape(_AggregatorSink); _Typesetter.Typeset(_ShaperSink, paragraph, region, obstructions); _Formatter.Format(_TypesetterSink); return new ParagraphMetrics(paragraph, _FormatterSink, _GeometryCache); }
internal ParagraphMetrics( Paragraph paragraph, FormatterSink formattedData, TextGeometryCache geometryCache) { Contract.Requires(paragraph != null); Contract.Requires(formattedData != null); Contract.Requires(geometryCache != null); _Paragraph = paragraph; _Leading = formattedData.Leading; _LayoutRegion = formattedData.LayoutRegion; _BaselineOffset = formattedData.BaselineOffset; _Clusters = formattedData.Clusters.ToArray(); _ClusterBidiLevels = new byte[formattedData.Clusters.Count]; _Outlines = CreateOutlineList(formattedData, geometryCache, out _ClusterBidiLevels); // create the text index to cluster index transformation table _TextToCluster = new int[formattedData.FullText.Length]; for(int i = 0; i < _Clusters.Length; ++i) { foreach(int characterIndex in _Clusters[i].Characters) { _TextToCluster[characterIndex] = i; } } // determine the region that encompasses all formatted clusters float left = float.MaxValue; float top = float.MaxValue; float right = float.MinValue; float bottom = float.MinValue; for(int i = 0; i < _Clusters.Length; ++i) { left = Math.Min(left, _Clusters[i].Region.Left); top = Math.Min(top, _Clusters[i].Region.Top); right = Math.Max(right, _Clusters[i].Region.Right); bottom = Math.Max(bottom, _Clusters[i].Region.Bottom); } _TextRegion = Rectangle.FromEdges(left, top, right, bottom); // determine the ranges of each line _LineListBuilder.Clear(); int lastLine = 0; IndexedRange range = IndexedRange.Empty; for(int i = 0; i < formattedData.Runs.Count; ++i) { if(formattedData.Runs[i].LineNumber > lastLine) { _LineListBuilder.Add(ToTextRange(range)); range = new IndexedRange(formattedData.Runs[i].Clusters.StartIndex, 0); lastLine = formattedData.Runs[i].LineNumber; } range = range.Extend(formattedData.Runs[i].Clusters.Length); } if(range.Length > 0) { _LineListBuilder.Add(ToTextRange(range)); } _Lines = new LineCollection(_LineListBuilder); // build a collection of regions mapping to text indexes _RegionListBuilder.Clear(); for(int i = 0; i < paragraph.Text.Length; ++i) { _RegionListBuilder.Add(_Clusters[_TextToCluster[i]].Region); } _Regions = new RegionCollection(_RegionListBuilder); }
public void Begin( ITypesetText outputSink, Rectangle layoutRegion, IShapedText inputSink) { Contract.Requires(outputSink != null); Contract.Requires(inputSink != null); Contract.Requires(Paragraph == null); _Figures.Clear(); _Paragraph = inputSink.Paragraph; }