public static void DrawGlyphRun(this DrawingContext drawingContext, Brush foreground, GlyphRun glyphRun,
            Point position, HorizontalAlignment horizontalAlignment, VerticalAlignment verticalAlignment)
        {
            var boundingBox = glyphRun.ComputeInkBoundingBox();

            switch (horizontalAlignment)
            {
                case HorizontalAlignment.Center:
                    position.X -= boundingBox.Width / 2d;
                    break;
                case HorizontalAlignment.Right:
                    position.X -= boundingBox.Width;
                    break;
                default:
                    break;
            }

            switch (verticalAlignment)
            {
                case VerticalAlignment.Center:
                    position.Y -= boundingBox.Height / 2d;
                    break;
                case VerticalAlignment.Bottom:
                    position.Y -= boundingBox.Height;
                    break;
                default:
                    break;
            }

            drawingContext.PushTransform(new TranslateTransform(position.X - boundingBox.X, position.Y - boundingBox.Y));
            drawingContext.DrawGlyphRun(foreground, glyphRun);
            drawingContext.Pop();
        }
Exemple #2
0
        public unsafe void DrawGlyphRun(Brush brush, GlyphRun run)
        {
            gl.PushMatrix();
            Geometry geo = run.GetGeometry();

            fixed (TextureCoordinate* texCoords = run.FontCoords)
            {
                gl.Enable(gl.GL_BLEND);
                gl.ActiveTexture(gl.GL_TEXTURE1);
                gl.ClientActiveTexture(gl.GL_TEXTURE1);
                gl.EnableClientState(gl.GL_TEXTURE_COORD_ARRAY);
                gl.Enable(gl.GL_TEXTURE_2D);
                gl.BindTexture(gl.GL_TEXTURE_2D, run.Font.mySource.myName);
                gl.TexCoordPointer(2, gl.GL_FLOAT, 0, (IntPtr)texCoords);
                gl.ActiveTexture(gl.GL_TEXTURE0);
                gl.ClientActiveTexture(gl.GL_TEXTURE0);

                DrawGeometry(brush, null, geo);

                gl.ActiveTexture(gl.GL_TEXTURE1);
                gl.Disable(gl.GL_TEXTURE_2D);
                gl.ActiveTexture(gl.GL_TEXTURE0);
                gl.Disable(gl.GL_BLEND);
            }

            gl.PopMatrix();
        }
        public static ImageSource ToFontAwesomeIcon(this string text, Brush foreBrush, FontStyle fontStyle, FontWeight fontWeight, FontStretch fontStretch)
        {
            var fontFamily = new FontFamily("/GitWorkItems;component/Resources/#FontAwesome");
            if (fontFamily != null && !String.IsNullOrEmpty(text))
            {
                //premier essai, on charge la police directement
                Typeface typeface = new Typeface(fontFamily, fontStyle, fontWeight, fontStretch);

                GlyphTypeface glyphTypeface;
                if (!typeface.TryGetGlyphTypeface(out glyphTypeface))
                {
                    //si ça ne fonctionne pas (et pour le mode design dans certains cas) on ajoute l'uri pack://application
                    typeface = new Typeface(new FontFamily(new Uri("pack://application:,,,"), fontFamily.Source), fontStyle, fontWeight, fontStretch);
                    if (!typeface.TryGetGlyphTypeface(out glyphTypeface))
                        throw new InvalidOperationException("No glyphtypeface found");
                }

                //détermination des indices/tailles des caractères dans la police
                ushort[] glyphIndexes = new ushort[text.Length];
                double[] advanceWidths = new double[text.Length];

                for (int n = 0; n < text.Length; n++)
                {
                    ushort glyphIndex;
                    try
                    {
                        glyphIndex = glyphTypeface.CharacterToGlyphMap[text[n]];

                    }
                    catch (Exception)
                    {
                        glyphIndex = 42;
                    }
                    glyphIndexes[n] = glyphIndex;

                    double width = glyphTypeface.AdvanceWidths[glyphIndex] * 1.0;
                    advanceWidths[n] = width;
                }

                try
                {

                    //création de l'objet DrawingImage (compatible avec Imagesource) à partir d'un glyphrun
                    GlyphRun gr = new GlyphRun(glyphTypeface, 0, false, 1.0, glyphIndexes,
                                                                         new Point(0, 0), advanceWidths, null, null, null, null, null, null);

                    GlyphRunDrawing glyphRunDrawing = new GlyphRunDrawing(foreBrush, gr);
                    return new DrawingImage(glyphRunDrawing);
                }
                catch (Exception ex)
                {
                    // ReSharper disable LocalizableElement
                    Console.WriteLine("Error in generating Glyphrun : " + ex.Message);
                    // ReSharper restore LocalizableElement
                }
            }
            return null;
        }
Exemple #4
0
        protected override Size MeasureOverride(Size constraint)
        {
            if (Content == null)
                return Size.Empty;

            if (myRun == null)
                myRun = new GlyphRun(Content.ToString(), myFont, myTextAlignment);

            return new Size(myRun.Width, myRun.Height);
        }
Exemple #5
0
 /// <summary>
 /// Internal constructor. 
 /// </summary>
 internal IndexedGlyphRun(
     int      textSourceCharacterIndex,
     int      textSourceCharacterLength,
     GlyphRun glyphRun
     )
 {
     _textSourceCharacterIndex  = textSourceCharacterIndex;
     _length                    = textSourceCharacterLength;
     _glyphRun                  = glyphRun;            
 }
Exemple #6
0
 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);
 }
        public HexEditorBlock(GeometryCollection hexGeos, GeometryCollection ascciGeos)
        {
            m_Run = HexEditor.CreateGlyphRun(new Typeface(FontFamily, FontStyle, FontWeight, FontStretch), "0", FontSize, new Point(0, FontSize));

            Unloaded += HexEditorTextBlock_Unloaded;
            Loaded += HexEditorTextBlock_Loaded;
            Width = 50;
            Height = 50;
            m_HexGeo = hexGeos;
            m_AsciiGeo = ascciGeos;
        }
        public override IText AddText(string text, double fontSize, SolidColorBrush brush)
        {
            if (cachedTypeface == null) {
                var t = CreateTypeface();
                if (!t.TryGetGlyphTypeface(out cachedTypeface))
                    throw new NotSupportedException();
            }

            ushort[] glyphIndexes = new ushort[text.Length];
            double[] advanceWidths = new double[text.Length];

            double totalWidth = 0;
            for (int n = 0; n < text.Length; n++) {
                ushort glyphIndex;
                cachedTypeface.CharacterToGlyphMap.TryGetValue(text[n], out glyphIndex);
                glyphIndexes[n] = glyphIndex;
                double width = cachedTypeface.AdvanceWidths[glyphIndex] * fontSize;
                advanceWidths[n] = width;
                totalWidth += width;
            }

            GlyphRun run = new GlyphRun(cachedTypeface,
                                        bidiLevel: 0,
                                        isSideways: false,
                                        renderingEmSize: fontSize,
                                        glyphIndices: glyphIndexes,
                                        baselineOrigin: new Point(0, Math.Round(cachedTypeface.Baseline * fontSize)),
                                        advanceWidths: advanceWidths,
                                        glyphOffsets: null,
                                        characters: null,
                                        deviceFontName: null,
                                        clusterMap: null,
                                        caretStops: null,
                                        language: null);
            MyText myText = new MyText { run = run, parent = this, brush = brush };
            texts.Add(myText);
            return myText;
        }
        /// <summary> 
        ///
        /// </summary> 
        /// <param name="glyphRun"></param> 
        public GlyphsSerializer(GlyphRun glyphRun)
        { 
            if (glyphRun == null)
            {
                throw new ArgumentNullException("glyphRun");
            } 

            _glyphTypeface = glyphRun.GlyphTypeface; 
            _milToEm = EmScaleFactor / glyphRun.FontRenderingEmSize; 

            _sideways = glyphRun.IsSideways; 

            _characters = glyphRun.Characters;
            _caretStops = glyphRun.CaretStops;
 
            // the first value in the cluster map can be non-zero, in which case it's applied as an offset to all
            // subsequent entries in the cluster map 
            _clusters = glyphRun.ClusterMap; 
            if (_clusters != null)
                _glyphClusterInitialOffset = _clusters[0]; 

            _indices = glyphRun.GlyphIndices;
            _advances = glyphRun.AdvanceWidths;
            _offsets = glyphRun.GlyphOffsets; 

            // "100,50,,0;".Length is a capacity estimate for an individual glyph 
            _glyphStringBuider = new StringBuilder(10); 

            // string length * _glyphStringBuider.Capacity is an estimate for the whole string 
            _indicesStringBuider = new StringBuilder(
                Math.Max(
                    (_characters == null ? 0 : _characters.Count),
                    _indices.Count 
                )
                * _glyphStringBuider.Capacity 
            ); 
        }
Exemple #10
0
      // 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);
      }
Exemple #11
0
 // 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);
    }
 }
Exemple #12
0
      // builds the glyph run for the given text, possibly trimming it to fit the specified max width
      private BuildGlyphResult _buildGlyph(bool useFallbackFont, double maxWidth) {
         var font = Font;
         if (font != null && useFallbackFont) font = Font.CachedFallbackFont;
         if (VisualText.IsEmpty() || font == null || font.Size <= 0) return null;

         // get typeface metrics
         var size = font.Size;
         var glyphTypeface = font.CachedTypeface;
         var charmap = glyphTypeface.CharacterToGlyphMap;
         var widthmap = glyphTypeface.AdvanceWidths;

         // create arrays for holding the glyph indexes and advance widths of the individual text characters
         var N = VisualText.Length;
         var glyphIndexes = new ushort[N];
         var advanceWidths = new double[N];

         var ellipsisWidth = 0.0;
         var ellipsisIndex = -1;
         if (TextOverflow != TextOverflow.Ignore) {
            ellipsisWidth = 3 * widthmap[charmap['.']] * size;
         }

         var height = glyphTypeface.Height * size;
         var baseline = glyphTypeface.Baseline * size;
         var origin = new Point(0, baseline);

         // scan and measure each character until end of text or until overflow
         var overflowForward = (TextOverflowDirection == LogicalDirection.Forward);
         var width = 0.0;
         var index = (overflowForward ? 0 : N - 1);
         while (true) {
            if (overflowForward) {
               if (index >= N) break;
            } else {
               if (index < 0) break;
            }

            int c = VisualText[index];

            ushort g;
            if (charmap.ContainsKey(c)) {
               g = charmap[c];
            } else {
               if (!useFallbackFont) {
                  // character cannot be displayed with this font, try building the glyph with the fallback font
                  return _buildGlyph(true, maxWidth);
               } else {
                  // if no fallback font exists, display a '?' placeholder
                  Log.Warn("Character '{0}' (U+{1:X4}) was not found in font '{2}'", VisualText[index], (int)VisualText[index], font.Family.Source);
                  g = charmap['?'];
               }
            }

            var w = widthmap[g] * size;
            if (TextOverflow == TextOverflow.Ignore || width + w <= maxWidth - ellipsisWidth) {
               // in case there is no overflow (or we don't care about overflow), continue to accumulate the characters and their widths
               glyphIndexes[index] = g;
               advanceWidths[index] = w;
               width += w;
            } else {
               // in case of overflow, mark the position where the text should be trimmed and ellipsis added
               ellipsisIndex = index;
               if (TextOverflow == TextOverflow.WordEllipsis && ellipsisIndex > 0) {
                  // in case of trimming on word boundaries, look for the last whole word
                  Action<Regex> skipChars = pattern => {
                     for (; ellipsisIndex >= 0 && VisualText.At(ellipsisIndex).Matches(pattern); ellipsisIndex--) ;
                  };
                  skipChars(_nonWhitespace);
                  skipChars(_reWhitespace);
                  ellipsisIndex++;
               }
               break;
            }

            index += (overflowForward ? +1 : -1);
         }

         // handle overflow condition
         if (ellipsisIndex >= 0) {
            if (maxWidth < ellipsisWidth) {
               // not enough room to even display the ellipsis, so return an empty glyph
               return null;
            }

            // truncate the array of characters to display and add the ellipsis
            var g = charmap['.'];
            var w = widthmap[g] * size;

            ushort[] glyphIndexes2 = null;
            double[] advanceWidths2 = null;

            if (overflowForward) {
               glyphIndexes2 = new ushort[ellipsisIndex + 3];
               advanceWidths2 = new double[ellipsisIndex + 3];
               for (var i = 0; i < ellipsisIndex; i++) {
                  glyphIndexes2[i] = glyphIndexes[i];
                  advanceWidths2[i] = advanceWidths[i];
               }
               for (var i = ellipsisIndex; i < ellipsisIndex + 3; i++) {
                  glyphIndexes2[i] = g;
                  advanceWidths2[i] = w;
                  width += w;
               }
            } else {
               var K = Math.Max(0, N - ellipsisIndex - 1);
               glyphIndexes2 = new ushort[K + 3];
               advanceWidths2 = new double[K + 3];
               for (var i = 0; i < K; i++) {
                  glyphIndexes2[i + 3] = glyphIndexes[i + ellipsisIndex + 1];
                  advanceWidths2[i + 3] = advanceWidths[i + ellipsisIndex + 1];
               }
               for (var i = 0; i < 3; i++) {
                  glyphIndexes2[i] = g;
                  advanceWidths2[i] = w;
                  width += w;
               }
               origin.X += maxWidth - width;
            }

            glyphIndexes = glyphIndexes2;
            advanceWidths = advanceWidths2;
         }

         // create the actual glyph run
         GlyphRun glyphRun = null;
         try {
            glyphRun = new GlyphRun(glyphTypeface, 0, false, size, glyphIndexes, origin, advanceWidths, null, null, null, null, null, null);
         } catch (OverflowException) {
            // this happens when bounding area of the glyph run exceeds the maximal rendering size
            _prepareVisualText("Text too long...");
            return _buildGlyph(false, maxWidth);
         }
         return new BuildGlyphResult {
            GlyphRun = glyphRun,
            Width = width,
            Height = height,
            Baseline = baseline
         };
      }
        /// <summary>
        /// Draw a GlyphRun. 
        /// </summary> 
        /// <param name="foregroundBrush">Foreground brush to draw GlyphRun with. </param>
        /// <param name="glyphRun"> The GlyphRun to draw. </param> 
        /// <exception cref="ObjectDisposedException">
        /// This call is illegal if this object has already been closed or disposed.
        /// </exception>
        public override void DrawGlyphRun(Brush foregroundBrush, GlyphRun glyphRun) 
        {
            if (glyphRun != null) 
            { 
                // The InkBoundingBox + the Origin produce the true InkBoundingBox.
                Rect rectangle = glyphRun.ComputeInkBoundingBox(); 

                if (!rectangle.IsEmpty)
                {
                    rectangle.Offset((Vector)glyphRun.BaselineOrigin); 
                    DrawGeometry(Brushes.Black, null /* pen */, new RectangleGeometry(rectangle));
                } 
            } 
        }
        /// <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
                );
        }
Exemple #15
0
        private GlyphRun BuildGlyphRun(int column, int line, char c)
        {
            var paddingTop = FontSize / 3;
            var glyphs = new GlyphRun();
            ISupportInitialize isi = glyphs;
            isi.BeginInit();
            glyphs.GlyphTypeface = glyphFace;
            glyphs.FontRenderingEmSize = FontSize;
            var chars = new[] { c };
            glyphs.Characters = chars;
            var codePoint = (int)c;
            var glyphIndex = glyphFace.CharacterToGlyphMap[codePoint];
            var glyphWidth = glyphFace.AdvanceWidths[glyphIndex];
            glyphs.GlyphIndices = new ushort[] { glyphIndex };
            glyphs.AdvanceWidths = new double[] { glyphWidth * FontSize };
            _cellWidth = glyphWidth * FontSize;
            _cellHeight = (glyphFace.Baseline * FontSize) + (paddingTop);

            glyphs.BaselineOrigin = new Point(
                glyphWidth * FontSize * column,
                (glyphFace.Baseline * FontSize * (line + 1)) + (paddingTop * line));

            isi.EndInit();

            return glyphs;
        }
 //Returns the character offset in a GlyphRun given an X position 
 private int GlyphRunHitTest(GlyphRun run, double xoffset, bool LTR)
 { 
     bool isInside;
     double distance = LTR ? xoffset - run.BaselineOrigin.X : run.BaselineOrigin.X - xoffset;
     CharacterHit hit = run.GetCaretCharacterHitFromDistance(distance, out isInside);
     return hit.FirstCharacterIndex + hit.TrailingLength; 
 }
Exemple #17
0
 /// <summary>
 ///     DrawGlyphRun - 
 ///     Draw a GlyphRun
 /// </summary>
 /// <param name="foregroundBrush">
 ///     Foreground brush to draw the GlyphRun with.
 /// </param>
 /// <param name="glyphRun"> The GlyphRun to draw.  </param>
 public override void DrawGlyphRun(
     Brush foregroundBrush,
     GlyphRun glyphRun)
 {
     Debug.Assert(false);
 }
        /// <summary>
        /// Draw a GlyphRun.
        /// </summary>
        /// <param name="foregroundBrush">Foreground brush to draw GlyphRun with. </param>
        /// <param name="glyphRun"> The GlyphRun to draw. </param>
        /// <exception cref="ObjectDisposedException">
        /// This call is illegal if this object has already been closed or disposed.
        /// </exception>
        public override void DrawGlyphRun(Brush foregroundBrush, GlyphRun glyphRun)
        {
            if (!IsCurrentLayerNoOp && (glyphRun != null))
            {
                // The InkBoundingBox + the Origin produce the true InkBoundingBox.
                Rect rectangle = glyphRun.ComputeInkBoundingBox();

                if (!rectangle.IsEmpty)
                {
                    rectangle.Offset((Vector)glyphRun.BaselineOrigin);

                    _contains |= rectangle.Contains(_point);

                    // If we've hit, stop walking.
                    if (_contains)
                    {
                        StopWalking();
                    }
                }
            }
        }
        private double ChangeGlyphOrientation(GlyphRunDrawing glyphDrawing, 
            double baselineShiftX, double baselineShiftY, bool isLatin)
        {
            if (glyphDrawing == null)
            {
                return 0;
            }
            GlyphRun glyphRun = glyphDrawing.GlyphRun;

            GlyphRun verticalRun = new GlyphRun();
            ISupportInitialize glyphInit = verticalRun;
            glyphInit.BeginInit();

            verticalRun.IsSideways = true;

            List<double> advancedHeights = null;

            double totalHeight = 0;

            IList<UInt16> glyphIndices = glyphRun.GlyphIndices;
            int advancedCount = glyphIndices.Count;
            //{
            //    double textHeight = glyphRun.ComputeInkBoundingBox().Height + glyphRun.ComputeAlignmentBox().Height;
            //    textHeight = textHeight / 2.0d;

            //    totalHeight = advancedCount * textHeight;
            //    advancedHeights = new List<double>(advancedCount);
            //    for (int k = 0; k < advancedCount; k++)
            //    {
            //        advancedHeights.Add(textHeight);
            //    }
            //}
            advancedHeights = new List<double>(advancedCount);
            IDictionary<ushort, double> allGlyphHeights = glyphRun.GlyphTypeface.AdvanceHeights;
            double fontSize = glyphRun.FontRenderingEmSize;
            for (int k = 0; k < advancedCount; k++)
            {
                double tempValue = allGlyphHeights[glyphIndices[k]] * fontSize;
                advancedHeights.Add(tempValue);
                totalHeight += tempValue;
            }

            Point baselineOrigin = glyphRun.BaselineOrigin;
            if (isLatin)
            {
                baselineOrigin.X += baselineShiftX;
                baselineOrigin.Y += baselineShiftY;
            }

            //verticalRun.AdvanceWidths     = glyphRun.AdvanceWidths;
            verticalRun.AdvanceWidths       = advancedHeights;
            verticalRun.BaselineOrigin      = baselineOrigin;
            verticalRun.BidiLevel           = glyphRun.BidiLevel;
            verticalRun.CaretStops          = glyphRun.CaretStops;
            verticalRun.Characters          = glyphRun.Characters;
            verticalRun.ClusterMap          = glyphRun.ClusterMap;
            verticalRun.DeviceFontName      = glyphRun.DeviceFontName;
            verticalRun.FontRenderingEmSize = glyphRun.FontRenderingEmSize;
            verticalRun.GlyphIndices        = glyphRun.GlyphIndices;
            verticalRun.GlyphOffsets        = glyphRun.GlyphOffsets;
            verticalRun.GlyphTypeface       = glyphRun.GlyphTypeface;
            verticalRun.Language            = glyphRun.Language;

            glyphInit.EndInit();

            glyphDrawing.GlyphRun = verticalRun;

            return totalHeight;
        }
 /// <summary>
 ///     DrawGlyphRun - 
 ///     Draw a GlyphRun
 /// </summary>
 /// <param name="foregroundBrush">
 ///     Foreground brush to draw the GlyphRun with.
 /// </param>
 /// <param name="glyphRun"> The GlyphRun to draw.  </param>
 public override void DrawGlyphRun(
     Brush foregroundBrush,
     GlyphRun glyphRun)
 {
     _drawingContext.DrawGlyphRun(
         foregroundBrush,
         glyphRun
         );
 }
Exemple #21
0
		//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
		}
        public override void DrawGlyphRun(
            Brush foregroundBrush,
            GlyphRun glyphRun)
        {
            VerifyApiNonstructuralChange();

            if ((foregroundBrush == null) || (glyphRun == null))
            {
                return;
            }


        #if DEBUG
            MediaTrace.DrawingContextOp.Trace("DrawGlyphRun(const)");
        #endif

            unsafe
            {
                EnsureRenderData();

                // Always assume visual and drawing brushes need realization updates

                MILCMD_DRAW_GLYPH_RUN record =
                    new MILCMD_DRAW_GLYPH_RUN (
                        _renderData.AddDependentResource(foregroundBrush),
                        _renderData.AddDependentResource(glyphRun)
                        );

                // Assert that the calculated packet size is the same as the size returned by sizeof().
                Debug.Assert(sizeof(MILCMD_DRAW_GLYPH_RUN) == 8);

                _renderData.WriteDataRecord(MILCMD.MilDrawGlyphRun,
                                            (byte*)&record,
                                            8 /* sizeof(MILCMD_DRAW_GLYPH_RUN) */);
            }                           



        }
        private bool CheckGlyphRun()
        {
            if (glyphRun == null)
            {
                if (string.IsNullOrEmpty(Text))
                {
                    return false;
                }

                var typeface = new Typeface(FontFamily, FontStyle, FontWeight, FontStretch);
                GlyphTypeface glyphTypeface;

                if (!typeface.TryGetGlyphTypeface(out glyphTypeface))
                {
                    return false;
                }

                var glyphIndices = new ushort[Text.Length];
                var advanceWidths = new double[Text.Length];

                for (int i = 0; i < Text.Length; i++)
                {
                    var glyphIndex = glyphTypeface.CharacterToGlyphMap[Text[i]];
                    glyphIndices[i] = glyphIndex;
                    advanceWidths[i] = glyphTypeface.AdvanceWidths[glyphIndex] * FontSize;
                }

                glyphRun = new GlyphRun(glyphTypeface, 0, false, FontSize, glyphIndices, new Point(), advanceWidths, null, null, null, null, null, null);

                outline = glyphRun.BuildGeometry().GetWidenedPathGeometry(new Pen(null, OutlineThickness * 2d));
            }

            return true;
        }
Exemple #24
0
 protected override void OnContentChanged(object oldContent, object newContent)
 {
     base.OnContentChanged(oldContent, newContent);
     myRun = null;
     InvalidateMeasure();
 }
Exemple #25
0
        private static ImageSource CreateGlyph(string text, FontFamily fontFamily, FontStyle fontStyle, FontWeight fontWeight, FontStretch fontStretch, Brush foreBrush)
        {
            if (fontFamily != null && !string.IsNullOrEmpty(text))
            {
                var typeface = new Typeface(fontFamily, fontStyle, fontWeight, fontStretch);

                GlyphTypeface glyphTypeface;
                if (!typeface.TryGetGlyphTypeface(out glyphTypeface))
                {
                    throw Log.ErrorAndCreateException<InvalidOperationException>("No glyph type face found");
                }

                var glyphIndexes = new ushort[text.Length];
                var advanceWidths = new double[text.Length];

                for (var i = 0; i < text.Length; i++)
                {
                    ushort glyphIndex;

                    try
                    {
                        var key = text[i];

                        if (!glyphTypeface.CharacterToGlyphMap.TryGetValue(key, out glyphIndex))
                        {
                            glyphIndex = 42;
                        }
                    }
                    catch (Exception)
                    {
                        glyphIndex = 42;
                    }

                    glyphIndexes[i] = glyphIndex;

                    var width = glyphTypeface.AdvanceWidths[glyphIndex] * 1.0;
                    advanceWidths[i] = width;
                }

                try
                {
                    var glyphRun = new GlyphRun(glyphTypeface, 0, false, RenderingEmSize, glyphIndexes, new Point(0, 0), advanceWidths, null, null, null, null, null, null);
                    var glyphRunDrawing = new GlyphRunDrawing(foreBrush, glyphRun);

                    //TextOptions.SetTextRenderingMode(glyphRunDrawing, TextRenderingMode.Aliased);

                    var drawingImage = new DrawingImage(glyphRunDrawing);

                    //TextOptions.SetTextRenderingMode(drawingImage, TextRenderingMode.Aliased);

                    return drawingImage;
                }
                catch (Exception ex)
                {
                    Log.Error(ex, "Error in generating Glyphrun");
                }
            }

            return null;
        }
Exemple #26
0
 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();
 }
Exemple #27
0
        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>
 ///     DrawGlyphRun - 
 ///     Draw a GlyphRun
 /// </summary>
 /// <param name="foregroundBrush">
 ///     Foreground brush to draw the GlyphRun with.
 /// </param>
 /// <param name="glyphRun"> The GlyphRun to draw.  </param>
 public abstract void DrawGlyphRun(
     Brush foregroundBrush,
     GlyphRun glyphRun);
Exemple #29
0
		public static GlyphRun BuildGlyphRun(string text)
		{
			double fontSize = 50;
			GlyphRun glyphs = null;

			Typeface font = new Typeface("Arial");
			GlyphTypeface glyphFace;
			if (font.TryGetGlyphTypeface(out glyphFace))
			{
				glyphs = new GlyphRun();
				System.ComponentModel.ISupportInitialize isi = glyphs;
				isi.BeginInit();
				glyphs.GlyphTypeface = glyphFace;
				glyphs.FontRenderingEmSize = fontSize;

				char[] textChars = text.ToCharArray();
				glyphs.Characters = textChars;
				ushort[] glyphIndices = new ushort[textChars.Length];
				double[] advanceWidths = new double[textChars.Length];

				for (int i = 0; i < textChars.Length; ++i)
				{
					int codepoint = textChars[i];
					ushort glyphIndex = glyphFace.CharacterToGlyphMap[codepoint];
					double glyphWidth = glyphFace.AdvanceWidths[glyphIndex];

					glyphIndices[i] = glyphIndex;
					advanceWidths[i] = glyphWidth * fontSize;
				}
				glyphs.GlyphIndices = glyphIndices;
				glyphs.AdvanceWidths = advanceWidths;

				glyphs.BaselineOrigin = new Point(0, glyphFace.Baseline * fontSize);
				isi.EndInit();
			}
			return glyphs;
		}
        private static double _GetDistanceToCharacter(GlyphRun run, int charOffset)
        {
            int firstChar = charOffset, trailingLength = 0;

            int characterCount = (run.Characters == null) ? 0 : run.Characters.Count;
            if (firstChar == characterCount)
            {
                // place carat at end of previous character to make sure it works at end of line
                firstChar--;
                trailingLength = 1;
            }

            return run.GetDistanceFromCaretCharacterHit(new CharacterHit(firstChar, trailingLength));
        }