예제 #1
0
        protected override void OnRender(DrawingContext drawingContext)
        {
            base.OnRender(drawingContext);
            Rect rect = new Rect(0.0, 0.0, base.ActualWidth, base.ActualHeight);
            JapaneseTextSource source = new JapaneseTextSource();

            source.Text = this.Text;
            JapaneseTextParagraphProperties textParagraphProperties = this.MakeTextProperties();

            source.JapaneseTextRunProperties = (JapaneseTextRunProperties)textParagraphProperties.DefaultTextRunProperties;
            source.IsVarticalWriting         = textParagraphProperties.IsVerticalWriting;
            if (textParagraphProperties.DefaultTextRunProperties.BackgroundBrush != null)
            {
                drawingContext.DrawRectangle(textParagraphProperties.DefaultTextRunProperties.BackgroundBrush, null, rect);
            }
            Rect   paddingRect = new Rect(this.Padding.Left, this.Padding.Top, Math.Max(0.0, base.ActualWidth - this.Padding.Left - this.Padding.Right), Math.Max(0.0, base.ActualHeight - this.Padding.Top - this.Padding.Bottom));
            Point  center      = new Point((paddingRect.Left + paddingRect.Right) / 2.0, (paddingRect.Top + paddingRect.Bottom) / 2.0);
            Point  startPosition;
            double paragraphWidth;

            if (textParagraphProperties.IsVerticalWriting)
            {
                Point     origin      = paddingRect.TopRight;
                Transform transOrigin = new RotateTransform(-90.0, center.X, center.Y);
                startPosition  = transOrigin.Transform(origin);
                paragraphWidth = Math.Abs(paddingRect.Height);
                Transform trans = new RotateTransform(90.0, center.X, center.Y);
                drawingContext.PushTransform(trans);
            }
            else
            {
                startPosition  = paddingRect.TopLeft;
                paragraphWidth = Math.Abs(paddingRect.Width);
            }
            startPosition.Y += textParagraphProperties.JapaneseTextRunProperties.FontRenderingEmSize;
            int           textStorePosition = 0;
            Point         linePosition      = startPosition;
            TextFormatter formatter         = TextFormatter.Create();

            while (textStorePosition < source.Text.Length)
            {
                using (TextLine textLine = formatter.FormatLine(source, textStorePosition, paragraphWidth, textParagraphProperties, null))
                {
                    foreach (IndexedGlyphRun indexedrun in textLine.GetIndexedGlyphRuns())
                    {
                        if (textParagraphProperties.IsVerticalWriting)
                        {
                            source.UniscribeIndexedGlyphRun(indexedrun);
                            Rect runRect;
                            if (source.GlyphCount != 0 && source.Glyphs[0] != 0)
                            {
                                Point ansiLinePosition = linePosition;
                                ansiLinePosition.Y -= textParagraphProperties.JapaneseTextRunProperties.FontRenderingEmSize / 2.0;
                                runRect             = this.DrawIndexedGlyphRun(drawingContext, indexedrun, ansiLinePosition, source, true);
                            }
                            else
                            {
                                Point ansiLinePosition = linePosition;
                                ansiLinePosition.Y -= textParagraphProperties.JapaneseTextRunProperties.FontRenderingEmSize / 10.0;
                                runRect             = this.DrawIndexedGlyphRun(drawingContext, indexedrun, ansiLinePosition, source, false);
                            }
                            linePosition.X += runRect.Width;
                        }
                        else
                        {
                            Rect runRect = this.DrawIndexedGlyphRun(drawingContext, indexedrun, linePosition, source, false);
                            linePosition.X += runRect.Width;
                        }
                    }
                    textStorePosition += textLine.Length;
                    linePosition.X     = startPosition.X;
                    linePosition.Y    += textLine.Height;
                }
            }
            if (textParagraphProperties.IsVerticalWriting)
            {
                drawingContext.Pop();
            }
        }
        private void Render(Point location, string colour)
        {
            int  textStorePosition = 0;
            bool flipped;

            Position = location;
            if (ParentAtom == null)
            {
                flipped = false;
            }
            else
            {
                flipped = Flipped;
            }

            var textStore = new FunctionalGroupTextSource(ParentGroup, colour, flipped);

            //main textformatter - this does the writing of the visual
            using (TextFormatter textFormatter = TextFormatter.Create())
            {
                //set up the default paragraph properties
                var paraprops = new FunctionalGroupTextSource.GenericTextParagraphProperties(
                    FlowDirection.LeftToRight,
                    TextAlignment.Left,
                    true,
                    false,
                    new LabelTextRunProperties(colour),
                    TextWrapping.NoWrap,
                    GlyphText.SymbolSize,
                    0d);

                var    anchorRuns   = textStore.Runs.Where(f => f.IsAnchor);
                string anchorString = string.Empty;
                foreach (var run in anchorRuns)
                {
                    anchorString += run.Text;
                }

                using (TextLine myTextLine =
                           textFormatter.FormatLine(textStore, textStorePosition, 999, paraprops, null))
                {
                    IList <TextBounds> textBounds;
                    Rect firstRect = Rect.Empty;
                    if (!Flipped) //isolate them at the beginning
                    {
                        textBounds = myTextLine.GetTextBounds(0, anchorString.Length);
                    }
                    else
                    {
                        //isolate them at the end
                        var start = myTextLine.Length - 1 - anchorString.Length;
                        textBounds = myTextLine.GetTextBounds(start, anchorString.Length);
                    }

                    //add all the bounds together
                    foreach (TextBounds anchorBound in textBounds)
                    {
                        firstRect.Union(anchorBound.Rectangle);
                    }

                    //center will be position close to the origin 0,0
                    Point center = new Point((firstRect.Left + firstRect.Right) / 2,
                                             (firstRect.Top + firstRect.Bottom) / 2);

                    //the displacement vector will be added to each relative coordinate for the glyph run
                    var displacementVector = location - center;

                    //locus is where the text line is drawn
                    var locus = new Point(0, 0) + displacementVector;

                    textBounds = myTextLine.GetTextBounds(0, 999);
                    var obb = textBounds[0].Rectangle;

                    //draw the line of text
                    using (DrawingContext dc = RenderOpen())
                    {
                        myTextLine.Draw(dc, locus, InvertAxes.None);
#if DEBUG
#if SHOWBOUNDS
                        obb.Offset(new Vector(locus.X, locus.Y));
                        dc.DrawRectangle(null, new Pen(new SolidColorBrush(Colors.BlueViolet), 1.0), obb);
#endif
#endif
                        var          glyphRuns     = myTextLine.GetIndexedGlyphRuns();
                        List <Point> outline       = new List <Point>();
                        double       advanceWidths = 0d;

                        //build up the convex hull from each glyph
                        //you need to add in the advance widths for each
                        //glyph run as they are traversed,
                        //to the outline
                        foreach (IndexedGlyphRun igr in glyphRuns)
                        {
                            var originalRun = textStore.GetTextRun(igr.TextSourceCharacterIndex);
                            var currentRun  = igr.GlyphRun;
                            //need to work out how much the current run has been offset from the baseline
                            var runBounds =
                                myTextLine.GetTextBounds(igr.TextSourceCharacterIndex, igr.TextSourceLength);
                            //get the bounding rect
                            var rect = runBounds[0].TextRunBounds[0].Rectangle;

                            //it's relative to the baseline
                            //adjust it
                            rect.Offset(new Vector(locus.X, locus.Y));
                            var rectCopy = rect;
#if DEBUG
#if SHOWBOUNDS
                            dc.DrawRectangle(null, new Pen(new SolidColorBrush(Colors.DarkOrange), 1.0), rect);
#endif
#endif
                            var runOutline = GlyphUtils.GetOutline(currentRun);
                            //need to see if the run has been super or sub-scripted
                            var variants = originalRun.Properties.TypographyProperties.Variants;

                            if (variants == FontVariants.Subscript || variants == FontVariants.Superscript)
                            {
                                //simply union in the rect -it's easier!
                                outline.AddRange(new[]
                                {
                                    rectCopy.BottomLeft, rectCopy.BottomRight, rectCopy.TopLeft,
                                    rectCopy.TopRight
                                });
                            }
                            else
                            {
                                //add in the points from the convex hull
                                for (int i = 0; i < runOutline.Count; i++)
                                {
                                    var point = runOutline[i] + displacementVector +
                                                new Vector(0.0, myTextLine.Baseline);
                                    point.X      += advanceWidths;
                                    runOutline[i] = point;
                                }

                                outline.AddRange(runOutline);
                            }

                            advanceWidths += currentRun.AdvanceWidths.Sum();
                        }

                        _sortedOutline = (from Point p in outline
                                          orderby p.X ascending, p.Y descending
                                          select p).ToList();

                        Hull = Geometry <Point> .GetHull(_sortedOutline, p => p);

                        // Diag: Show Hulls or Atom centres
#if DEBUG
#if SHOWHULLS
                        dc.DrawGeometry(null, new Pen(Brushes.GreenYellow, thickness: 1), HullGeometry);
#endif
#if SHOWATOMCENTRES
                        dc.DrawEllipse(Brushes.Red, null, ParentAtom.Position, 5, 5);
#endif
#endif
                        // End Diag
                        dc.Close();
                    }
                }
            }
        }
예제 #3
0
        public static void HandleLine2(TextLine?myTextLine,
                                       Point linePosition, int lineNo, int textStorePosition,
                                       object?change,
                                       ILineInfo2Base?curLineInfo = null, BTree <TextRunInfo>?btRuns = null, Action <CharInfo, ILineInfo2Base>?takeChar = null)
        {
            var curPos           = linePosition;
            var indexedGlyphRuns = myTextLine?.GetIndexedGlyphRuns();

            // var z = new List<TextRunInfo>();

            // btRuns?.DescendGreaterThan(new TextRunInfo(null, textStorePosition - 1),
            // info =>
            // {
            // z.Add(info);
            // return info.Value < textStorePosition + length;
            // });

            // using (var enum2 = z.GetEnumerator())
            {
                // var moveNext2 = enum2.MoveNext();
                var lineCharIndex = 0;
                var xOrigin       = linePosition.X + myTextLine !.Start;
                if (indexedGlyphRuns == null)
                {
                    return;
                }
                var lineRun = 0;
                foreach (var glyphRunC in indexedGlyphRuns)
                {
                    var gl         = glyphRunC.GlyphRun;
                    var advanceSum = gl.AdvanceWidths.Sum();
                    for (var i = 0; i < gl.Characters.Count; i++)
                    {
                        var i0             = gl.ClusterMap?[i] ?? i;
                        var glAdvanceWidth = gl.AdvanceWidths[i0];
                        var glCharacter    = gl.Characters[i];
                        var glCaretStop    = gl.CaretStops?[i0];
                        var glyphIndex     = gl.GlyphIndices[i0];

                        var storePosition = textStorePosition + lineCharIndex;
                        // Trace.WriteLine("char line " + lineNo + "[" + storePosition + "]: " + glCharacter);

                        var ci = new CharInfo(lineNo, storePosition, lineCharIndex, i,
                                              glCharacter, glAdvanceWidth,
                                              glCaretStop, xOrigin, linePosition.Y, gl.GlyphTypeface.Height * gl.FontRenderingEmSize, gl.ComputeAlignmentBox(),
                                              gl.BaselineOrigin, glyphIndex, gl.GlyphTypeface, gl.FontRenderingEmSize, lineRun);
                        takeChar !(ci, curLineInfo !);

                        lineCharIndex++;
                        xOrigin += glAdvanceWidth;
                    }

                    lineRun++;
                    // var item = new Rect(curPos, new Size(advanceSum, myTextLine.Height));
                    // if (!moveNext2)
                    // {w
                    //     var sb = new StringBuilder();
                    //     for (var c = curCharInfoNode; c != null; c = c.Next) sb.Append(c.Value.Character);
                    //
                    //     throw new CodeControlException("enumerator empty " + sb);
                    // }

                    // if (prevTri?.TextRun != null && prevTri != null && offset < prevTri.Value + prevTri.TextRun.Length)
                    // {
                    //     prevTri.Rect.Union(item);
                    // }
                    // else
                    // {
                    //     var textRunInfo = new TextRunInfo(offset);
                    //     var tri = btRuns?.Get(textRunInfo);
                    //     if (tri == null)
                    //     {
                    //         var sb = new StringBuilder();
                    //         for (var c = curCharInfoNode; c != null; c = c.Next) sb.Append(c.Value.Character);
                    //         throw new CodeControlException("Unable to find entry for " + offset);
                    //     }
                    //
                    //     tri.Rect = item;
                    //
                    //     rectBtree?.ReplaceOrInsert(new RectInfo(tri.Rect, offset, tri.TextRun));
                    //
                    //     prevTri = tri;
                    // }

                    curPos.X += advanceSum;
                }
            }

#pragma warning disable 8601
#pragma warning restore 8601
        }