/// <summary>
        ///   This method retrieves the geometry for a formatted cluster.
        /// </summary>
        /// <param name="clusterIndex"> This parameter indicates the formatted cluster index. </param>
        /// <param name="bidiLevel"> This parameter indicates the bidi level of the cluster. </param>
        /// <param name="font"> This parameter references the font for the cluster. </param>
        /// <param name="input"> This parameter references the formatted text output. </param>
        /// <returns> This method returns the geometry for the formatted cluster if available; otherwise, this method returns <c>null</c>. </returns>
        public Geometry Retrieve(int clusterIndex, byte bidiLevel, FontHandle font, FormatterSink input)
        {
            Contract.Requires(clusterIndex >= 0);
            Contract.Requires(font != null);
            Contract.Requires(input != null);

            FormattedCluster cluster = input.Clusters[clusterIndex];

            ResizeInternalBuffers(cluster.Glyphs.Length);

            int index = 0;

            foreach(int itemIndex in cluster.Glyphs)
            {
                _GlyphAdvances[index] = cluster.Region.Width;

                _GlyphIndices[index] = input.Glyphs[itemIndex].Index;
                _GlyphOffsets[index] = input.Glyphs[itemIndex].Offset;

                ++index;
            }

            TextGeometryKey key;

            key.Advances = _GlyphAdvances;
            key.Indices = _GlyphIndices;
            key.Offsets = _GlyphOffsets;

            Dictionary<TextGeometryKey, Geometry> cacheForFont;

            if(_Cache.TryGetValue(font, out cacheForFont))
            {
                Geometry result;

                if(cacheForFont.TryGetValue(key, out result))
                {
                    return result;
                }
            }
            else
            {
                cacheForFont = new Dictionary<TextGeometryKey, Geometry>();

                _Cache.Add(font, cacheForFont);
            }

            Geometry geometry = _Sink.CreateGeometry(key, bidiLevel, font);

            TextGeometryKey newKey;

            newKey.Advances = (float[])key.Advances.Clone();
            newKey.Indices = (short[])key.Indices.Clone();
            newKey.Offsets = (GlyphOffset[])key.Offsets.Clone();

            cacheForFont.Add(newKey, geometry);

            return geometry;
        }
Exemple #2
0
        public TextPipeline(FontDevice fontDevice)
        {
            Contract.Requires(fontDevice != null);

            _FontDevice = fontDevice;

            _TextAnalyzer = new Analyzer(_FontDevice.Factory);
            _AggregatorSink = new AggregatorSink();
            _Aggregator = new Aggregator(_AggregatorSink);
            _ShaperSink = new ShaperSink();
            _Shaper = new Shaper(_FontDevice, _ShaperSink);
            _FormatterSink = new FormatterSink();
            _Formatter = new Formatter(_FormatterSink);
            _TypesetterSink = new TypesetterSink();
            _Typesetter = new Typesetter(_TypesetterSink);
            _GeometryCache = new TextGeometryCache();
        }
Exemple #3
0
        /// <summary>
        ///   This constructor links a new instance of this class to an output sink.
        /// </summary>
        /// <param name="outputSink"> This parameter references the output sink. </param>
        public Formatter(FormatterSink outputSink)
        {
            Contract.Requires(outputSink != null);

            _OutputSink = outputSink;
        }
        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);
        }
        /// <summary>
        ///   This method creates an outline collection.
        /// </summary>
        /// <param name="formattedData"> This parameter references the formatted input sink. </param>
        /// <param name="geometryCache"> This parameter references the text geometry cache. </param>
        /// <param name="clusterBidiLevels"> This parameter references the cluster bidi levels. </param>
        /// <returns> This method returns a new outline collection containing an outline for each formatted cluster. </returns>
        private static OutlineCollection CreateOutlineList(
			FormatterSink formattedData, TextGeometryCache geometryCache, out byte[] clusterBidiLevels)
        {
            _OutlineListBuilder.Clear();

            clusterBidiLevels = new byte[formattedData.Clusters.Count];

            int geometryClusterIndex = 0;

            for(int i = 0; i < formattedData.Runs.Count; ++i)
            {
                FormattedRun run = formattedData.Runs[i];

                FontFace face = run.Font.ResolveFace();

                float emSize = face.Metrics.Ascent + face.Metrics.Descent;

                float baseline = face.Metrics.Ascent / emSize;

                foreach(int clusterIndex in run.Clusters)
                {
                    Geometry geometry = geometryCache.Retrieve(
                        clusterIndex, run.BidiLevel, run.Font, formattedData);

                    _OutlineListBuilder.Add(new Outline(geometry, run.EmSize, baseline));

                    clusterBidiLevels[geometryClusterIndex] = run.BidiLevel;

                    geometryClusterIndex++;
                }
            }

            return new OutlineCollection(_OutlineListBuilder);
        }