public override void DrawText(System.Windows.Media.DrawingContext dc, double maxTop) { Typeface typeface = new Typeface((this.Parent as Run).Fontfamily); var _fontSize = (this.Parent as Run).ScriptOffset != 0 ? (this.Parent as Run).FontSize * Document.DIP : (this.Parent as Run).FontSize; Point origin = new Point(this.Left, maxTop); GlyphRun run = CreateGlyphRun(typeface, this.Text, _fontSize, origin); dc.DrawGlyphRun((Brush)(new BrushConverter().ConvertFromString((this.Parent as Run).Foreground.Color)), run); }
public override void Draw(DrawingContext drawingContext, double scale, double x, double y) { // Draw character at given position. var typeface = this.Character.Font; var glyphIndex = typeface.CharacterToGlyphMap[this.Character.Character]; var glyphRun = new GlyphRun(typeface, 0, false, this.Character.Size * scale, new ushort[] { glyphIndex }, new Point(x * scale, y * scale), new double[] { typeface.AdvanceWidths[glyphIndex] }, null, null, null, null, null, null); drawingContext.DrawGlyphRun(this.Foreground ?? Brushes.Black, glyphRun); }
protected override void OnRender(DrawingContext drawingContext) { if (myRun == null) return; Point offset = Point.Empty; float slack = Width - myRun.Width; if (myTextAlignment == TextAlignment.Right) offset.X = slack; else if (myTextAlignment == TextAlignment.Center) offset.X = slack / 2; drawingContext.PushTranslate(offset.X, offset.Y); drawingContext.DrawGlyphRun(ForeBrush, myRun); drawingContext.Pop(); }
private void _UpdateHighlightForeground(DrawingContext dc, ArrayList highlights) { foreach (FixedHighlight fh in highlights) { Brush fg = null; if (fh.HighlightType == FixedHighlightType.None) { #if NEVER // use this code if you want to see unrecognized highlights bg = Brushes.Yellow; #else continue; #endif } Glyphs g = fh.Glyphs; if (g == null) { continue; } Rect clipRect = fh.ComputeDesignRect(); if (clipRect == Rect.Empty) { continue; } GeneralTransform transform = fh.Element.TransformToAncestor(_page); Transform t = transform.AffineTransform; if (t != null) { dc.PushTransform(t); } else { dc.PushTransform(Transform.Identity); } dc.PushClip(new RectangleGeometry(clipRect)); if (fh.HighlightType == FixedHighlightType.TextSelection) { fg = SelectionHighlightInfo.ForegroundBrush; } else if (fh.HighlightType == FixedHighlightType.AnnotationHighlight) { fg = fh.ForegroundBrush; } // can add cases for new types of highlights GlyphRun gr = g.ToGlyphRun(); if (fg == null) { fg = g.Fill; } dc.PushGuidelineY1(gr.BaselineOrigin.Y); dc.PushClip(g.Clip); dc.DrawGlyphRun(fg, gr); dc.Pop(); // Glyphs clip dc.Pop(); // Guideline dc.Pop(); // clip dc.Pop(); // transform } }
public override void Draw(DrawingContext drawingContext, Point origin, InvertAxes inversion) { foreach (var entry in entries) { if (entry.Item2 == null) continue; if (entry.Item3 == entry.Item1.Length) // All whitespace, no need to render continue; var textRun = entry.Item1; var glyphRun = entry.Item2; var textProps = textRun.Properties; var newRun = Clone(glyphRun, new Point { X = origin.X + glyphRun.BaselineOrigin.X, Y = (int)(origin.Y + glyphRun.GlyphTypeface.Baseline * textProps.FontRenderingEmSize) }); if (_textFormattingMode != null) _textFormattingMode.SetValue(glyphRun, mode); var box = newRun.ComputeAlignmentBox(); if (textProps.BackgroundBrush != null) { drawingContext.DrawRectangle( textProps.BackgroundBrush, null, new Rect(origin, box.Size)); } drawingContext.DrawGlyphRun(textProps.ForegroundBrush, newRun); if (textProps.TextDecorations != null) foreach (var deco in textProps.TextDecorations) { var thickness = Math.Round(glyphRun.GlyphTypeface.UnderlineThickness * textProps.FontRenderingEmSize); var pos = glyphRun.GlyphTypeface.UnderlinePosition - glyphRun.GlyphTypeface.Baseline + glyphRun.GlyphTypeface.Height; pos = Math.Round(pos * textProps.FontRenderingEmSize) + thickness / 2; var pen = new Pen(textProps.ForegroundBrush, thickness); drawingContext.DrawLine(pen, new Point(newRun.BaselineOrigin.X, newRun.BaselineOrigin.Y + pos), new Point(newRun.BaselineOrigin.X + box.Width, newRun.BaselineOrigin.Y + pos)); } } }
private void DrawVerticalLinesText(DrawingContext dc, double initialPos, double stepSize) { double previousTextPos = initialPos; while (initialPos < MaxX) { initialPos += stepSize; System.Windows.Point p0 = new System.Windows.Point(initialPos, MinY); p0 = CurveCoordsToScreen(ref p0); p0.X = Math.Truncate(p0.X); if (Math.Abs(p0.X - previousTextPos) > 40) { p0.X = Math.Truncate(p0.X) + 0.5; // Draw the tick System.Windows.Point p1 = new System.Windows.Point(p0.X, ActualHeight); p0 = new System.Windows.Point(p0.X, ActualHeight - 3); dc.DrawLine(gridLinePen, p0, p1); p0.X = Math.Truncate(p0.X - 3); glyphs.UnicodeString = String.Format("{0:0.###}", initialPos); glyphs.OriginX = p0.X; glyphs.OriginY = 12; dc.DrawGlyphRun(textBrush, glyphs.ToGlyphRun()); previousTextPos = p0.X; } } }
protected override void OnRender(DrawingContext dc) { Brush bgBrush = Background; dc.DrawRectangle(bgBrush, null, new Rect(RenderSize)); if (Items == null) { return; } try { //long tickStart = DateTime.Now.Ticks; //パフォーマンス計測用 double selfLeft = Canvas.GetLeft(this); // Items 設定時に CreateDrawTextList を行うと、番組表に複数のタブを設定していると // 全てのタブの GlyphRun を一度に生成しようとするので、最初の表示までに多くの時間がかかる。 // 表示しようとするタブのみ GlyphRun を行うことで、最初の応答時間を削減することにする。 CreateDrawTextList(); //long tickGlyphRun = DateTime.Now.Ticks; //パフォーマンス計測用 foreach (ProgramViewItem info in Items) { dc.DrawRectangle(bgBrush, null, new Rect(info.LeftPos - selfLeft, info.TopPos, info.Width, 1)); dc.DrawRectangle(bgBrush, null, new Rect(info.LeftPos - selfLeft, info.TopPos + info.Height, info.Width, 1)); if (info.Height > 1) { dc.DrawRectangle(info.ContentColor, null, new Rect(info.LeftPos - selfLeft, info.TopPos + 0.5, info.Width - 1, info.Height - 0.5)); if (textDrawDict.ContainsKey(info)) { dc.PushClip(new RectangleGeometry(new Rect(info.LeftPos - selfLeft, info.TopPos + 0.5, info.Width - 1, info.Height - 0.5))); foreach (TextDrawItem txtinfo in textDrawDict[info]) { dc.DrawGlyphRun(txtinfo.FontColor, txtinfo.Text); } dc.Pop(); } } } // EpgViewPanel は複数に分けて Render するので、最後のパネルが Render し終わったら // 些細なメモリ節約のために cache をクリアする ItemFontNormal.ClearCache(); ItemFontTitle.ClearCache(); //パフォーマンス計測用 //long tickDraw = DateTime.Now.Ticks; //Console.Write("GlyphRun = " + Math.Round((tickGlyphRun - tickStart)/10000D).ToString() // + ", Draw = " + Math.Round((tickDraw - tickGlyphRun)/10000D).ToString() // + ", Total = " + Math.Round((tickDraw-tickStart)/10000D).ToString() + "\n"); } catch (Exception ex) { MessageBox.Show(ex.Message + "\r\n" + ex.StackTrace); } }
// draws a glyphrun including any defined highlights private void _drawGlyphRun(DrawingContext dc, GlyphRun run, Brush brush) { if (_highlights == null) { dc.DrawGlyphRun(brush, run); return; } var max = run.GlyphIndices.Count; var pos = 0; var k = 0; while (k < _highlights.Count) { var h1 = _highlights[k].Start; var h2 = h1 + _highlights[k].Length; if (h1 > pos) { _drawGlyphRun(dc, run, brush, pos, h1 - pos); } _drawGlyphRun(dc, run, _highlights[k].Foreground, h1, h2 - h1); pos = h2; k++; } if (pos < max) { _drawGlyphRun(dc, run, brush, pos, max - pos); } }
protected override void OnRender(DrawingContext dc) { dc.DrawRectangle(Background, null, new Rect(RenderSize)); this.VisualTextRenderingMode = TextRenderingMode.ClearType; this.VisualTextHintingMode = TextHintingMode.Fixed; this.UseLayoutRounding = true; if (Items == null) { return; } try { double sizeNormal = Settings.Instance.FontSize; double sizeTitle = Settings.Instance.FontSizeTitle; Brush bgBrush = Background; foreach (ProgramViewItem info in Items) { dc.DrawRectangle(bgBrush, null, new Rect(info.LeftPos, info.TopPos, info.Width, 1)); dc.DrawRectangle(bgBrush, null, new Rect(info.LeftPos, info.TopPos + info.Height, info.Width, 1)); if (info.Height > 1) { dc.DrawRectangle(info.ContentColor, null, new Rect(info.LeftPos + 0, info.TopPos + 0.5, info.Width - 1, info.Height - 0.5)); if (textDrawDict.ContainsKey(info)) { dc.PushClip(new RectangleGeometry(new Rect(info.LeftPos + 0, info.TopPos + 0.5, info.Width - 1, info.Height - 0.5))); foreach (TextDrawItem txtinfo in textDrawDict[info]) { dc.DrawGlyphRun(txtinfo.FontColor, txtinfo.Text); } dc.Pop(); } } } } catch (Exception ex) { MessageBox.Show(ex.Message + "\r\n" + ex.StackTrace); } }
protected bool RenderText(String text, DrawingContext dc, GlyphTypeface glyphType, double fontSize, double maxWidth, double maxHeight, double x, double y, ref double useHeight) { if (maxHeight < fontSize + 2) { useHeight = 0; return false; } double totalHeight = 0; string[] lineText = text.Replace("\r", "").Split('\n'); foreach (string line in lineText) { totalHeight += Math.Floor(2 + fontSize); List<ushort> glyphIndexes = new List<ushort>(); List<double> advanceWidths = new List<double>(); double totalWidth = 0; for (int n = 0; n < line.Length; n++) { ushort glyphIndex = glyphType.CharacterToGlyphMap[line[n]]; double width = glyphType.AdvanceWidths[glyphIndex] * fontSize; if (totalWidth + width > maxWidth) { if (totalHeight + fontSize > maxHeight) { //次の行無理 glyphIndex = glyphType.CharacterToGlyphMap['…']; glyphIndexes[glyphIndexes.Count - 1] = glyphIndex; advanceWidths[advanceWidths.Count - 1] = width; Point origin = new Point(x + 2, y + totalHeight); GlyphRun glyphRun = new GlyphRun(glyphType, 0, false, fontSize, glyphIndexes, origin, advanceWidths, null, null, null, null, null, null); dc.DrawGlyphRun(Brushes.Black, glyphRun); useHeight = totalHeight; return false; } else { //次の行いけるので今までの分出力 //次の行いける Point origin = new Point(x + 2, y + totalHeight); GlyphRun glyphRun = new GlyphRun(glyphType, 0, false, fontSize, glyphIndexes, origin, advanceWidths, null, null, null, null, null, null); dc.DrawGlyphRun(Brushes.Black, glyphRun); totalHeight += fontSize + 2; glyphIndexes = new List<ushort>(); advanceWidths = new List<double>(); totalWidth = 0; } } glyphIndexes.Add(glyphIndex); advanceWidths.Add(width); totalWidth += width; } if (glyphIndexes.Count > 0) { Point origin = new Point(x + 2, y + totalHeight); GlyphRun glyphRun = new GlyphRun(glyphType, 0, false, fontSize, glyphIndexes, origin, advanceWidths, null, null, null, null, null, null); dc.DrawGlyphRun(Brushes.Black, glyphRun); } //高さ確認 if (totalHeight + fontSize > maxHeight) { //これ以上は無理 useHeight = totalHeight; return false; } } useHeight = Math.Floor(totalHeight); return true; }
private static void DrawActorLabel(DrawingContext dc, CanvasData canvas, RadarObject radarObject, Brush brush) { var text = radarObject.CachedActorName; if (text == null) return; const int textSize = 12; const int charLimit = 20; if (text.Length > charLimit) text = text.Substring(0, charLimit); // FormattedText is very slow, so instead create text manually with glyphs var glyphRun = DrawingUtilities.CreateGlyphRun(text, textSize, radarObject.Point); dc.DrawGlyphRun(brush, glyphRun); }
private void DrawPointsOfInterest(DrawingContext dc, CanvasData canvas) { try { foreach (var marker in AdvDia.CurrentWorldMarkers.Where(m => m.Id >= 0 && m.Id < 200)) { dc.DrawEllipse(Brushes.Yellow, RadarResources.GridPen, marker.Position.ToCanvasPoint(), 5, 5); var textPoint = marker.Position.ToCanvasPoint(); textPoint.Y = textPoint.Y + 32; var glyphRun = DrawingUtilities.CreateGlyphRun(marker.NameHash.ToString(), 8, textPoint); dc.DrawGlyphRun(Brushes.Yellow, glyphRun); var toObjectivePen = new Pen(Brushes.Yellow, 0.2); dc.DrawLine(toObjectivePen, canvas.Center, marker.Position.ToCanvasPoint()); } } catch (Exception ex) { Logger.Debug("Exception in RadarUI.DrawPointsOfInterest(). {0} {1} {2}", ex.Message, ex.InnerException, ex); } }
internal Rect Draw( DrawingContext drawingContext, double x, double y, bool visiCodePath ) { if (Length <= 0 || this.Ghost) { return Rect.Empty; // nothing to draw } Brush foregroundBrush = TextRun.Properties.ForegroundBrush; if(visiCodePath && foregroundBrush is SolidColorBrush) { Color color = ((SolidColorBrush)foregroundBrush).Color; foregroundBrush = new SolidColorBrush(Color.FromArgb( (byte)(color.A>>2), // * 0.25 color.R, color.G, color.B )); } Rect inkBoundingBox; IList<double> displayGlyphAdvances; if (_textFormatterImp.TextFormattingMode == TextFormattingMode.Ideal) { displayGlyphAdvances = new ThousandthOfEmRealDoubles(EmSize, NominalAdvances.Length); for (int i = 0; i < displayGlyphAdvances.Count; i++) { // convert ideal glyph advance width to real width for displaying. displayGlyphAdvances[i] = _textFormatterImp.IdealToReal(NominalAdvances[i]); } } else { displayGlyphAdvances = new List<double>(NominalAdvances.Length); for (int i = 0; i < NominalAdvances.Length; i++) { // convert ideal glyph advance width to real width for displaying. displayGlyphAdvances.Add(_textFormatterImp.IdealToReal(NominalAdvances[i])); } } CharacterBufferRange charBufferRange = new CharacterBufferRange(CharBufferReference, Length); GlyphTypeface glyphTypeface = Typeface.TryGetGlyphTypeface(); Invariant.Assert(glyphTypeface != null); GlyphRun glyphRun = glyphTypeface.ComputeUnshapedGlyphRun( new Point(x, y), charBufferRange, displayGlyphAdvances, EmSize, TextRun.Properties.FontHintingEmSize, Typeface.NullFont, CultureMapper.GetSpecificCulture(TextRun.Properties.CultureInfo), null, // device font name _textFormatterImp.TextFormattingMode ); if (glyphRun != null) { inkBoundingBox = glyphRun.ComputeInkBoundingBox(); } else { inkBoundingBox = Rect.Empty; } if (!inkBoundingBox.IsEmpty) { // glyph run's ink bounding box is relative to its origin inkBoundingBox.X += glyphRun.BaselineOrigin.X; inkBoundingBox.Y += glyphRun.BaselineOrigin.Y; } if (drawingContext != null) { if (glyphRun != null) { glyphRun.EmitBackground(drawingContext, TextRun.Properties.BackgroundBrush); drawingContext.DrawGlyphRun(foregroundBrush, glyphRun); } // draw underline here if (Underline != null) { // Determine number of characters to underline. We don't underline trailing spaces // if the TrimTrailingUnderline flag is set. int underlineLength = Length; if (TrimTrailingUnderline) { while (underlineLength > 0 && IsSpace(charBufferRange[underlineLength - 1])) { --underlineLength; } } // Determine the width of the underline. double dxUnderline = 0; for (int i = 0; i < underlineLength; ++i) { dxUnderline += _textFormatterImp.IdealToReal(NominalAdvances[i]); } // We know only TextDecoration.Underline will be handled in Simple Path. double offset = -Typeface.UnderlinePosition * EmSize; double penThickness = Typeface.UnderlineThickness * EmSize; Point lineOrigin = new Point(x, y + offset); Rect underlineRect = new Rect( lineOrigin.X, lineOrigin.Y - penThickness * 0.5, dxUnderline, penThickness ); // Apply the pair of guidelines: one for baseline and another // for top edge of undelining line. Both will be snapped to pixel grid. // Guideline pairing algorithm detects the case when these two // guidelines happen to be close to one another and provides // synchronous snapping, so that the gap between baseline and // undelining line does not depend on the position of text line. drawingContext.PushGuidelineY2(y, lineOrigin.Y - penThickness * 0.5 - y); try { drawingContext.DrawRectangle( foregroundBrush, null, // pen underlineRect ); } finally { drawingContext.Pop(); } // underline pen thickness is always positive in fast path inkBoundingBox.Union( underlineRect ); } } return inkBoundingBox; }
public static void DrawText(DrawingContext dc, string text, double x, double y, double maxWidth, bool bEnableDotDotDot, SolidColorBrush colorBrush) { ushort[] glyphIndexes = null; double[] advanceWidths = null; ushort[] tempGlyphIndexes = new ushort[text.Length]; double[] tempAdvanceWidths = new double[text.Length]; double totalTextWidth = 0; double maxHeight = 0.0f; bool needDoTDotDot = false; double desiredTextWidth = maxWidth; int charIndex = 0; // Build the text info and measure the final text width for (; charIndex < text.Length; charIndex++) { ushort glyphIndex = _glyphTypeface.CharacterToGlyphMap[text[charIndex]]; tempGlyphIndexes[charIndex] = glyphIndex; double width = _glyphTypeface.AdvanceWidths[glyphIndex] * _cFontSize; tempAdvanceWidths[charIndex] = width; maxHeight = Math.Max(_glyphTypeface.AdvanceHeights[glyphIndex] * _cFontSize, maxHeight); totalTextWidth += width; if (totalTextWidth > desiredTextWidth) { //we need to clip the text since it doesn't fit the allowed width //do a second measurement pass needDoTDotDot = true; break; } } if (bEnableDotDotDot && needDoTDotDot) { ushort suffixGlyphIndex = _glyphTypeface.CharacterToGlyphMap['.']; double suffixWidth = _glyphTypeface.AdvanceWidths[suffixGlyphIndex] * _cFontSize; desiredTextWidth -= suffixWidth * 3; for (; charIndex > 0; charIndex--) { double removedCharacterWidth = tempAdvanceWidths[charIndex]; totalTextWidth -= removedCharacterWidth; if (totalTextWidth <= desiredTextWidth) { charIndex--; break; } } int finalNumCharacters = charIndex + 1 + 3; glyphIndexes = new ushort[finalNumCharacters]; advanceWidths = new double[finalNumCharacters]; Array.Copy(tempGlyphIndexes, glyphIndexes, charIndex + 1); Array.Copy(tempAdvanceWidths, advanceWidths, charIndex + 1); for (int i = charIndex + 1; i < finalNumCharacters; ++i) { glyphIndexes[i] = suffixGlyphIndex; advanceWidths[i] = suffixWidth; } } else { glyphIndexes = tempGlyphIndexes; advanceWidths = tempAdvanceWidths; } double roundedX = Math.Round(x); double roundedY = Math.Round(y + maxHeight); GlyphRun gr = new GlyphRun( _glyphTypeface, 0, // Bi-directional nesting level false, // isSideways _cFontSize, // pt size glyphIndexes, // glyphIndices new Point(roundedX, roundedY), // baselineOrigin advanceWidths, // advanceWidths null, // glyphOffsets null, // characters null, // deviceFontName null, // clusterMap null, // caretStops null); // xmlLanguage dc.DrawGlyphRun(colorBrush, gr); }
protected override void OnRender(DrawingContext drawingContext) { if (ParentMap != null) { var bounds = ParentMap.ViewportTransform.Inverse.TransformBounds(new Rect(ParentMap.RenderSize)); var start = ParentMap.MapTransform.Transform(new Point(bounds.X, bounds.Y)); var end = ParentMap.MapTransform.Transform(new Point(bounds.X + bounds.Width, bounds.Y + bounds.Height)); var minSpacing = MinLineSpacing * 360d / (Math.Pow(2d, ParentMap.ZoomLevel) * TileSource.TileSize); var spacing = LineSpacings[LineSpacings.Length - 1]; if (spacing >= minSpacing) { spacing = LineSpacings.FirstOrDefault(s => s >= minSpacing); } var labelFormat = spacing < 1d ? "{0} {1}°{2:00}'" : "{0} {1}°"; var labelStart = new Location( Math.Ceiling(start.Latitude / spacing) * spacing, Math.Ceiling(start.Longitude / spacing) * spacing); var latLabels = new List<Label>((int)((end.Latitude - labelStart.Latitude) / spacing) + 1); var lonLabels = new List<Label>((int)((end.Longitude - labelStart.Longitude) / spacing) + 1); for (var lat = labelStart.Latitude; lat <= end.Latitude; lat += spacing) { latLabels.Add(new Label(lat, CoordinateString(lat, labelFormat, "NS"))); drawingContext.DrawLine(Pen, ParentMap.LocationToViewportPoint(new Location(lat, start.Longitude)), ParentMap.LocationToViewportPoint(new Location(lat, end.Longitude))); } for (var lon = labelStart.Longitude; lon <= end.Longitude; lon += spacing) { lonLabels.Add(new Label(lon, CoordinateString(Location.NormalizeLongitude(lon), labelFormat, "EW"))); drawingContext.DrawLine(Pen, ParentMap.LocationToViewportPoint(new Location(start.Latitude, lon)), ParentMap.LocationToViewportPoint(new Location(end.Latitude, lon))); } if (Foreground != null && Foreground != Brushes.Transparent && latLabels.Count > 0 && lonLabels.Count > 0) { var latLabelOrigin = new Point(StrokeThickness / 2d + 2d, -StrokeThickness / 2d - FontSize / 4d); var lonLabelOrigin = new Point(StrokeThickness / 2d + 2d, StrokeThickness / 2d + FontSize); var transform = Matrix.Identity; transform.Rotate(ParentMap.Heading); foreach (var latLabel in latLabels) { foreach (var lonLabel in lonLabels) { GlyphRun latGlyphRun; GlyphRun lonGlyphRun; if (!glyphRuns.TryGetValue(latLabel.Text, out latGlyphRun)) { latGlyphRun = GlyphRunText.Create(latLabel.Text, Typeface, FontSize, latLabelOrigin); glyphRuns.Add(latLabel.Text, latGlyphRun); } if (!glyphRuns.TryGetValue(lonLabel.Text, out lonGlyphRun)) { lonGlyphRun = GlyphRunText.Create(lonLabel.Text, Typeface, FontSize, lonLabelOrigin); glyphRuns.Add(lonLabel.Text, lonGlyphRun); } var position = ParentMap.LocationToViewportPoint(new Location(latLabel.Position, lonLabel.Position)); drawingContext.PushTransform(new MatrixTransform( transform.M11, transform.M12, transform.M21, transform.M22, position.X, position.Y)); drawingContext.DrawGlyphRun(Foreground, latGlyphRun); drawingContext.DrawGlyphRun(Foreground, lonGlyphRun); drawingContext.Pop(); } } var removeKeys = glyphRuns.Keys.Where(k => !latLabels.Any(l => l.Text == k) && !lonLabels.Any(l => l.Text == k)); foreach (var key in removeKeys.ToList()) { glyphRuns.Remove(key); } } else { glyphRuns.Clear(); } } }
protected override void OnRender(DrawingContext drawingContext) { if (CheckGlyphRun()) { var location = outline.Bounds.Location; drawingContext.PushTransform(new TranslateTransform(-location.X, -location.Y)); drawingContext.DrawGeometry(Background, null, outline); drawingContext.DrawGlyphRun(Foreground, glyphRun); } }
protected override void OnRender(DrawingContext dc) { dc.DrawRectangle(Background, null, new Rect(RenderSize)); this.VisualTextRenderingMode = TextRenderingMode.ClearType; this.VisualTextHintingMode = TextHintingMode.Fixed; this.UseLayoutRounding = true; if (Items == null) { return; } try { double sizeNormal = Settings.Instance.FontSize; double sizeTitle = Settings.Instance.FontSizeTitle; foreach (ProgramViewItem info in Items) { dc.DrawRectangle(Brushes.DarkGray, null, new Rect(info.LeftPos, info.TopPos, info.Width, info.Height)); if (info.Height > 2) { dc.DrawRectangle(info.ContentColor, null, new Rect(info.LeftPos + 0, info.TopPos + 1, info.Width - 1, info.Height - 1)); } } foreach (TextDrawItem info in textDrawList) { dc.DrawGlyphRun(info.FontColor, info.Text); } } catch (Exception ex) { MessageBox.Show(ex.Message + "\r\n" + ex.StackTrace); } }
protected override void OnRender(DrawingContext drawingContext) { if (ParentMap != null) { var x1 = Padding.Left + StrokeThickness / 2d; var x2 = size.Width - Padding.Right - StrokeThickness / 2d; var y1 = size.Height / 2d; var y2 = size.Height - Padding.Bottom - StrokeThickness / 2d; var text = length >= 1000d ? string.Format("{0:0} km", length / 1000d) : string.Format("{0:0} m", length); drawingContext.DrawRectangle(Background ?? ParentMap.Background, null, new Rect(size)); drawingContext.DrawLine(Pen, new Point(x1, y1), new Point(x1, y2)); drawingContext.DrawLine(Pen, new Point(x2, y1), new Point(x2, y2)); drawingContext.DrawLine(Pen, new Point(x1, y2), new Point(x2, y2)); drawingContext.DrawGlyphRun(Foreground, GlyphRunText.Create(text, Typeface, FontSize), new Point(size.Width / 2d, y1 - StrokeThickness - 1d), HorizontalAlignment.Center, VerticalAlignment.Center); } }
private Rect DrawIndexedGlyphRun(DrawingContext drawingContext, IndexedGlyphRun indexedrun, Point linePosition, JapaneseTextSource source, bool isVerticalWriting) { GlyphRun run; if (isVerticalWriting) { List<double> advanceWidths = new List<double>(); int[] advance2 = source.Advance; for (int i = 0; i < advance2.Length; i++) { int advance = advance2[i]; advanceWidths.Add((double)advance); } run = new GlyphRun(indexedrun.GlyphRun.GlyphTypeface, indexedrun.GlyphRun.BidiLevel, true, indexedrun.GlyphRun.FontRenderingEmSize, source.Glyphs, linePosition, indexedrun.GlyphRun.AdvanceWidths, indexedrun.GlyphRun.GlyphOffsets, indexedrun.GlyphRun.Characters, indexedrun.GlyphRun.DeviceFontName, indexedrun.GlyphRun.ClusterMap, indexedrun.GlyphRun.CaretStops, indexedrun.GlyphRun.Language); } else { run = new GlyphRun(indexedrun.GlyphRun.GlyphTypeface, indexedrun.GlyphRun.BidiLevel, false, indexedrun.GlyphRun.FontRenderingEmSize, indexedrun.GlyphRun.GlyphIndices, linePosition, indexedrun.GlyphRun.AdvanceWidths, indexedrun.GlyphRun.GlyphOffsets, indexedrun.GlyphRun.Characters, indexedrun.GlyphRun.DeviceFontName, indexedrun.GlyphRun.ClusterMap, indexedrun.GlyphRun.CaretStops, indexedrun.GlyphRun.Language); } drawingContext.DrawGlyphRun(source.JapaneseTextRunProperties.ForegroundBrush, run); return run.ComputeAlignmentBox(); }
/// <summary> /// Draw all formatted glyphruns /// </summary> /// <returns>drawing bounding box</returns> public Rect Draw( DrawingContext drawingContext, Point currentOrigin ) { Rect inkBoundingBox = Rect.Empty; Debug.Assert(_glyphs != null); foreach (Glyphs glyphs in _glyphs) { GlyphRun glyphRun = glyphs.CreateGlyphRun(currentOrigin, _rightToLeft); Rect boundingBox; if (glyphRun != null) { boundingBox = glyphRun.ComputeInkBoundingBox(); if (drawingContext != null) { // Emit glyph run background. glyphRun.EmitBackground(drawingContext, glyphs.BackgroundBrush); drawingContext.PushGuidelineY1(currentOrigin.Y); try { drawingContext.DrawGlyphRun(glyphs.ForegroundBrush, glyphRun); } finally { drawingContext.Pop(); } } } else { boundingBox = Rect.Empty; } if (!boundingBox.IsEmpty) { // glyph run's ink bounding box is relative to its origin boundingBox.X += glyphRun.BaselineOrigin.X; boundingBox.Y += glyphRun.BaselineOrigin.Y; } // accumulate overall ink bounding box inkBoundingBox.Union(boundingBox); if (_rightToLeft) { currentOrigin.X -= glyphs.Width; } else { currentOrigin.X += glyphs.Width; } } return inkBoundingBox; }
// draws a glyphrun range using the given brush private void _drawGlyphRun(DrawingContext dc, GlyphRun run, Brush brush, int start, int len) { var max = run.GlyphIndices.Count; start = Math.Min(start, max - 1); len = Math.Min(len, max - start); if (start < 0 || len <= 0) return; var indices = new ushort[len]; var widths = new double[len]; for (int i = start, j = 0; i < start + len; i++, j++) { indices[j] = run.GlyphIndices[i]; widths[j] = run.AdvanceWidths[i]; } var origin = run.BaselineOrigin; origin.X += run.AdvanceWidths.Take(start).Sum(); var run2 = new GlyphRun(run.GlyphTypeface, run.BidiLevel, run.IsSideways, run.FontRenderingEmSize, indices, origin, widths, null, null, null, null, null, null); dc.DrawGlyphRun(brush, run2); }
protected override void OnRender(DrawingContext drawingContext) { DebugHelper.Trace(); if (glyphFace == null) { return; } else if (string.IsNullOrEmpty(_text)) { _currentColumn = 0; _currentRow = 0; MoveCaretToCurrentCell(); SetDefaultSize(); CreateDocument(new List<AphidToken>()); return; } var lexer = new AphidLexer(_text); CreateDocument(lexer.GetAllTokens()); double greatestX = 0, greatestY = 0; for (int y = 0; y < _document.Count; y++) { for (int x = 0; x < _document[y].Count; x++) { var cell = _document[y][x]; if (cell.Char == '\n') { continue; } var glyph = BuildGlyphRun(x, y, cell.Char); drawingContext.DrawGlyphRun( new SolidColorBrush(GetColor(cell.Type)), glyph); var x2 = glyph.BaselineOrigin.X + _cellWidth; if (x2 > greatestX) { greatestX = x2; } if (glyph.BaselineOrigin.Y > greatestY) { //greatestY = glyph.BaselineOrigin.Y + 20; greatestY = glyph.BaselineOrigin.Y; } } } var caretY = Canvas.GetTop(_caret) + _caret.Height; if (caretY > greatestY) { greatestY = caretY; } Width = greatestX; Height = greatestY; }
private void DrawHorizontalLinesText(DrawingContext dc, double initialPos, double stepSize) { double previousTextPos = initialPos; while (initialPos < MaxY) { initialPos += stepSize; System.Windows.Point p0 = new System.Windows.Point(MinX, initialPos); p0 = CurveCoordsToScreen(ref p0); p0.Y = Math.Truncate(p0.Y); if (Math.Abs(p0.Y - previousTextPos) > 20) { p0.Y = Math.Truncate(p0.Y) + 0.5; // Draw the tick System.Windows.Point p1 = new System.Windows.Point(0, p0.Y); p0 = new System.Windows.Point(3, p0.Y); dc.DrawLine(gridLinePen, p0, p1); p0.Y = Math.Truncate(p0.Y); glyphs.UnicodeString = String.Format("{0:0.###}", initialPos); glyphs.OriginX = 4; glyphs.OriginY = p0.Y + 5; dc.DrawGlyphRun(textBrush, glyphs.ToGlyphRun()); previousTextPos = p0.Y; } } }
//draw related methods: /// <summary> Draws the current glyph run on the specified context at the specified location. </summary> /// <param name="context"> The context to draw on. </param> protected override void OnRender(DrawingContext context) { base.OnRender(context); List<double> advanceWidths = new List<double>(); List<ushort> glyphsToDraw = new List<ushort>(); //this glyph run is set at the correct left, but its height is set at the top of the parent box //to go from that origin to the baseline origin of the box (and hence also of this glyph run), subtract Box.FrombaselineToOrigin. (again, the left coordinate is already correct) //to go from the baseline origin to the top left origin of this glyph run, add layout.Top, which is guaranteed to be at least as high as FontSize * FontConstants.Baseline Point baselineOrigin = Box.FromOriginToBaseline; //relative to coordinates used by the drawingcontext (which have the origin at the top of the parent box and left correct) double top = this.Layout.Top; Point topLeftOrigin = new Point(baselineOrigin.X, baselineOrigin.Y + top); double cumulativeWidth = 0; for (int i = 0; i < viewModel.Glyphs.Count; i++) { Point glyphOrigin = topLeftOrigin + new Vector(cumulativeWidth, 0); var glyphIndex = viewModel.Glyphs[i].Index; var markup = viewModel.Glyphs[i].Markup; double advanceWidth = GlyphRunViewModel.glyphFace.AdvanceWidths[glyphIndex] * viewModel.FontSize; advanceWidths.Add(advanceWidth); glyphsToDraw.Add(glyphIndex); if (markup.Background != null) { Size glyphSize = new Size(advanceWidth, GlyphRunViewModel.glyphFace.Height * viewModel.FontSize); Rect glyphRegion = new Rect(glyphOrigin, glyphSize); context.DrawRectangle(markup.Background, null, glyphRegion); } bool collect = i != viewModel.Glyphs.Count - 1 && markup.Foreground.Equals(viewModel.Glyphs[i + 1].Markup.Foreground); if (!collect) { GlyphRun glyphRun = new GlyphRun(GlyphRunViewModel.glyphFace, 0, false, viewModel.FontSize, glyphsToDraw, baselineOrigin, advanceWidths, null, null, null, null, null, null); context.DrawGlyphRun(markup.Foreground, glyphRun); advanceWidths = new List<double>(); glyphsToDraw = new List<ushort>(); baselineOrigin.X += cumulativeWidth + advanceWidth; } if (markup.Strikethrough != null) this.DrawStrikethrough(context, glyphOrigin, cumulativeWidth, markup.Strikethrough); if (markup.Underline != null) this.DrawUnderline(context, glyphOrigin, cumulativeWidth, markup.Underline); cumulativeWidth += advanceWidth; } Pen testPen = null;//new Pen(Brushes.Black, 1); var selectionRectangle = new Rect(topLeftOrigin, new Size(cumulativeWidth, GlyphRunViewModel.glyphFace.Height * viewModel.FontSize)); context.DrawRectangle(Brushes.Transparent, testPen, selectionRectangle);//for selection }
/// <summary> /// Draw glyph run to the drawing surface /// </summary> internal sealed override void Draw( DrawingContext drawingContext, Brush foregroundBrush, GlyphRun glyphRun ) { if (drawingContext == null) throw new ArgumentNullException("drawingContext"); glyphRun.EmitBackground(drawingContext, _properties.BackgroundBrush); drawingContext.DrawGlyphRun( foregroundBrush != null ? foregroundBrush : _properties.ForegroundBrush, glyphRun ); }
protected bool RenderText(String text, DrawingContext dc, ViewUtil.ItemFont itemFont, SolidColorBrush brush, double fontSize, double maxWidth, double maxHeight, double x, double baseline, ref double useHeight, bool nowrap = false) { if (x <= 0 || maxWidth <= 0) { useHeight = 0; return false; } double totalHeight = 0; double fontHeight = fontSize * itemFont.GlyphType.Height; string[] lineText = text.Replace("\r", "").Split('\n'); foreach (string line in lineText) { //高さ確認 if (totalHeight + fontHeight > maxHeight) { //これ以上は無理 useHeight = totalHeight; return false; } // ベースラインの位置の計算 // ビットマップフォントがかすれる問題 とりあえず整数にしておく Point origin = new Point(Math.Round(x), Math.Round(totalHeight + baseline)); //メイリオみたいに行間のあるフォントと MS P ゴシックみたいな行間のないフォントがあるので //なんとなく行間を作ってみる。 totalHeight += Math.Max(fontHeight, fontSize + 2); double totalWidth = 0; List<ushort> glyphIndexes = new List<ushort>(); List<double> advanceWidths = new List<double>(); for (int n = 0; n < line.Length; n++) { // XAML に合わせて、行頭の空白を無視する if (glyphIndexes.Count == 0 && (line[n] == ' ' || line[n] == '\x3000')) continue; //ushort glyphIndex = glyphType.CharacterToGlyphMap[line[n]]; //double width = glyphType.AdvanceWidths[glyphIndex] * fontSize; ushort glyphIndex = itemFont.GlyphIndexCache[line[n]]; if (glyphIndex == 0) { itemFont.GlyphIndexCache[line[n]] = glyphIndex = itemFont.GlyphType.CharacterToGlyphMap[line[n]]; itemFont.GlyphWidthCache[glyphIndex] = (float)itemFont.GlyphType.AdvanceWidths[glyphIndex]; } double width = itemFont.GlyphWidthCache[glyphIndex] * fontSize; if (totalWidth + width > maxWidth) { if (nowrap == true) break;//改行しない場合ここで終り if (totalWidth == 0) return false;//一文字も置けなかった(glyphIndexesなどのCount=0のまま) if (totalHeight + fontHeight > maxHeight) { //次の行無理 //glyphIndex = glyphType.CharacterToGlyphMap['…']; //double widthEllipsis = glyphType.AdvanceWidths[glyphIndex] * fontSize; glyphIndex = itemFont.GlyphType.CharacterToGlyphMap['…']; double widthEllipsis = itemFont.GlyphType.AdvanceWidths[glyphIndex] * fontSize; while (totalWidth - advanceWidths.Last() + widthEllipsis > maxWidth) { totalWidth -= advanceWidths.Last(); glyphIndexes.RemoveAt(glyphIndexes.Count-1); advanceWidths.RemoveAt(advanceWidths.Count - 1); } glyphIndexes[glyphIndexes.Count - 1] = glyphIndex; advanceWidths[advanceWidths.Count - 1] = widthEllipsis; GlyphRun glyphRun = new GlyphRun(itemFont.GlyphType, 0, false, fontSize, glyphIndexes, origin, advanceWidths, null, null, null, null, null, null); dc.DrawGlyphRun(brush, glyphRun); useHeight = totalHeight; return false; } else { //次の行いけるので今までの分出力 GlyphRun glyphRun = new GlyphRun(itemFont.GlyphType, 0, false, fontSize, glyphIndexes, origin, advanceWidths, null, null, null, null, null, null); dc.DrawGlyphRun(brush, glyphRun); origin = new Point(Math.Round(x), Math.Round(totalHeight + baseline)); totalHeight += Math.Max(fontHeight, fontSize + 2); totalWidth = 0; glyphIndexes = new List<ushort>(); advanceWidths = new List<double>(); // XAML に合わせて、行頭の空白を無視する if (line[n] == ' ' || line[n] == '\x3000') continue; } } glyphIndexes.Add(glyphIndex); advanceWidths.Add(width); totalWidth += width; } if (glyphIndexes.Count > 0) { GlyphRun glyphRun = new GlyphRun(itemFont.GlyphType, 0, false, fontSize, glyphIndexes, origin, advanceWidths, null, null, null, null, null, null); dc.DrawGlyphRun(brush, glyphRun); } } useHeight = totalHeight; return true; }
/// <summary> /// Renders GlyphRun into a drawing context /// </summary> /// <param name="context">Drawing context</param> protected override void OnRender(DrawingContext context) { if (_glyphRunProperties == null || _measurementGlyphRun == null) return; context.PushGuidelineY1(_glyphRunOrigin.Y); try { context.DrawGlyphRun(Fill, _measurementGlyphRun); } finally { context.Pop(); } }
protected override void OnRender(DrawingContext drawingContext) { foreach (MyText text in texts) { drawingContext.PushTransform(new TranslateTransform(text.Position.X, text.Position.Y)); drawingContext.DrawGlyphRun(text.brush, text.run); drawingContext.Pop(); } Dispatcher.BeginInvoke(DispatcherPriority.Input, new Action(delegate { OnFrameRendered(EventArgs.Empty); })); }