public static GlyphUtils.GlyphInfo GetGlyphsAndInfo(string symbolText, float pixelsPerDip, out GlyphRun hydrogenGlyphRun, Point point, GlyphTypeface glyphTypeFace, double symbolSize) { //measure the H atom first var glyphInfo = GlyphUtils.GetGlyphs(symbolText, glyphTypeFace, symbolSize); hydrogenGlyphRun = GlyphUtils.GetGlyphRun(glyphInfo, glyphTypeFace, symbolSize, pixelsPerDip, point); //work out exactly how much we should offset from the center to get to the bottom left return(glyphInfo); }
public void MeasureAtBottomLeft(Point bottomLeft, float PixelsPerDip) { GlyphInfo = GlyphUtils.GetGlyphsAndInfo(Text, PixelsPerDip, out GlyphRun groupGlyphRun, bottomLeft, _glyphTypeface, TypeSize); TextRun = groupGlyphRun; TextMetrics = new AtomTextMetrics { BoundingBox = groupGlyphRun.GetBoundingBox(bottomLeft), Geocenter = bottomLeft, TotalBoundingBox = groupGlyphRun.GetBoundingBox(bottomLeft), FlattenedPath = GlyphUtils.GetOutline(TextRun), OffsetVector = new Vector(0.0d, 0.0d) }; }
public void MeasureAtCenter(Point center) { GlyphInfo = GlyphUtils.GetGlyphsAndInfo(Text, PixelsPerDip, out GlyphRun groupGlyphRun, center, _glyphTypeface, TypeSize); //compensate the main offset vector for any descenders Vector mainOffset = GlyphUtils.GetOffsetVector(groupGlyphRun, TypeSize) + new Vector(0.0, -MaxBaselineOffset); var bb = groupGlyphRun.GetBoundingBox(center + mainOffset); Vector textFormatterOffset = new Vector(mainOffset.X, -FirstBearing(groupGlyphRun) - bb.Height / 2); TextRun = groupGlyphRun; TextMetrics = new AtomTextMetrics { BoundingBox = bb, Geocenter = center, TotalBoundingBox = groupGlyphRun.GetBoundingBox(center + mainOffset), OffsetVector = mainOffset, TextFormatterOffset = textFormatterOffset }; }
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(); } } } }
public void DrawAtBottomLeft(Point bottomLeft, DrawingContext dc) { GlyphInfo = GlyphUtils.GetGlyphsAndInfo(Text, PixelsPerDip, out GlyphRun groupGlyphRun, bottomLeft, _glyphTypeface, TypeSize); dc.DrawGlyphRun(Fill, groupGlyphRun); TextRun = groupGlyphRun; }