private double _baseGuidelineY; // the Y guideline of the text line. /// <summary> /// Construct drawing state for full text /// </summary> internal DrawingState( DrawingContext drawingContext, Point lineOrigin, MatrixTransform antiInversion, TextMetrics.FullTextLine currentLine ) { _drawingContext = drawingContext; _antiInversion = antiInversion; _currentLine = currentLine; if (antiInversion == null) { _lineOrigin = lineOrigin; } else { _vectorToLineOrigin = lineOrigin; } if (_drawingContext != null) { // LineServices draws GlyphRun and TextDecorations in multiple // callbacks and GlyphRuns may have different baselines. Pushing guideline // for each DrawGlyphRun are too costly. We optimize for the common case where // GlyphRuns and TextDecorations in the TextLine share the same baseline. _baseGuidelineY = lineOrigin.Y + currentLine.Baseline; _drawingContext.PushGuidelineY1(_baseGuidelineY); } }
/// <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(); } }
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 } }
/// <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; }
/// <summary> /// Draw a simple text line /// </summary> /// <returns>a drawing bounding box</returns> private void DrawTextLine( DrawingContext drawingContext, Point origin ) { if (_runs.Length <= 0) { _boundingBox = Rect.Empty; _statusFlags |= StatusFlags.BoundingBoxComputed; return; } int idealXRelativeToOrigin = _idealOffsetUnRounded; double y = origin.Y + Baseline; if (drawingContext != null) { drawingContext.PushGuidelineY1(y); } Rect boundingBox = Rect.Empty; try { foreach (SimpleRun run in _runs) { boundingBox.Union( run.Draw( drawingContext, _settings.Formatter.IdealToReal(idealXRelativeToOrigin) + origin.X, y, false ) ); idealXRelativeToOrigin += run.IdealWidth; } } finally { if (drawingContext != null) { drawingContext.Pop(); } } if(boundingBox.IsEmpty) { boundingBox = new Rect(Start, 0, 0, 0); } else { boundingBox.X -= origin.X; boundingBox.Y -= origin.Y; } _boundingBox = boundingBox; _statusFlags |= StatusFlags.BoundingBoxComputed; }