MeasureString patch

Oct 29, 2010 at 4:15 PM

I compiled trunk version 54997 to target framework SL3 but when we used silverPDF in SL3 gfx.MeasureString() always returned 0.

I tracked the issue to the class FormattedText.cs function CalculeteSize(). I did an implementation of CalculeteSize() that seems to work in both SL3 and SL4 and also is simpler than the current one (excluded use of Grid). Here it is:

In file PDFSharp4SL\!compatebleLayer\FormattedText.cs:

    // PATCH BEGIN
    private System.Windows.Size CalculeteSize()
    {
      var s = new System.Windows.Controls.StackPanel()
      {
        VerticalAlignment = System.Windows.VerticalAlignment.Center,
        HorizontalAlignment = System.Windows.HorizontalAlignment.Center
      };
      var fs = FontPool.GetFontStream(Typeface.FontFamily.Source);
      s.Children.Add(new System.Windows.Controls.TextBlock
      {
        Text = Text,
        FontSource = new FontSource(fs),
        FontSize = EmSize,
        FontFamily = Typeface.FontFamily,
        FontStretch = Typeface.FontStretch,
        FontStyle = Typeface.FontStyle,
        FontWeight = Typeface.FontWeight,
      });
      s.Measure(new System.Windows.Size(double.MaxValue, double.MaxValue));

      //var aw = s.ActualWidth;
      //var ah = s.ActualHeight;
      var aw = s.DesiredSize.Width;
      var ah = s.DesiredSize.Height;
      var size = new System.Windows.Size(aw, ah);

      //fs.Close();
      return size;
    }
    // PATCH END

I would apprecitate if you could test it and include it if it seems to work OK. Also it would be nice to have a binary release that targets SL3. We are still using VS2008 and no upgrade to VS2010 is planned so for now we are locked into SL3.

 

Mar 7, 2012 at 11:46 AM

Thanks for your code, I downloaded the latest source code but the patch you provided has not been included. Once I had included it, the demo TextLayout was working a bit better but there were two more issues I have found going up the calling chain:

In file PdfSharp.Drawing\XGraphics.cs:

    /// <summary>
    /// Measures the specified string when drawn with the specified font.
    /// </summary>
    public XSize MeasureString(string text, XFont font, XStringFormat stringFormat)
    {
      // TODO: Here comes a lot of code in the future: kerning etc...
      if (text == null)
        throw new ArgumentNullException("text");
      if (font == null)
        throw new ArgumentNullException("font");
      if (stringFormat == null)
        throw new ArgumentNullException("stringFormat");

      // BEGIN PATCH: PJANDA: fixed on 7/3/2012
      // original FormattedText formattedText = new FormattedText(text, new CultureInfo("en-us"),
      //  FlowDirection.LeftToRight, font.typeface, font.Height, new SolidColorBrush(Colors.Black));
      FormattedText formattedText = new FormattedText(text, new CultureInfo("en-us"),
        FlowDirection.LeftToRight, font.typeface, font.Size, new SolidColorBrush(Colors.Black));
      // END PATCH: PJANDA
      return new XSize(formattedText.WidthIncludingTrailingWhitespace, formattedText.Height);

#if WPF && GDI
      if (this.targetContext == XGraphicTargetContext.GDI)
      {
        XSize gdiSize = XSize.FromSizeF(this.gfx.MeasureString(text, font.RealizeGdiFont(), new PointF(0, 0), stringFormat.RealizeGdiStringFormat()));
#if DEBUG
        Debug.WriteLine(gdiSize);
#endif
        return gdiSize;
      }
      if (this.targetContext == XGraphicTargetContext.WPF)
      {
        //double h = font.Height;
        FormattedText formattedText = new FormattedText(text, new CultureInfo("en-us"),
          FlowDirection.LeftToRight, font.typeface, font.Size, System.Windows.Media.Brushes.Black);
        XSize wpfSize = new XSize(formattedText.WidthIncludingTrailingWhitespace, formattedText.Height);
#if DEBUG
        Debug.WriteLine(wpfSize);
#endif
        return wpfSize;
      }
      Debug.Assert(false);
      return XSize.Empty;
#endif
    }
In file PdfSharp.Drawing.Layout\XTextFormatter.cs:
    /// <summary>
    /// Gets or sets the font.
    /// </summary>
    public XFont Font
    {
      get { return this.font; }
      set 
      {
        if (value == null)
          throw new ArgumentNullException("font");
        this.font = value;

        this.lineSpace = font.GetHeight(this.gfx);
        this.cyAscent = lineSpace * font.cellAscent / font.cellSpace;
        this.cyDescent = lineSpace * font.cellDescent / font.cellSpace;

        // BEGIN PATCH: PJANDA: fixed on 7/3/2012
        // HACK
        // original this.spaceWidth = gfx.MeasureString("x�x", value).width;
        this.spaceWidth = gfx.MeasureString("x x", value).width;
        this.spaceWidth -= gfx.MeasureString("xx", value).width;
        // END PATCH: PJANDA
      }
    }

Hope this helps someone.

Pavel