Create text on line ViewControl

Product: SDK .NET

Product Version:11.3

Please give a brief summary of your issue:
(Think of this as an email subject)
I’m trying to create angled measurement text on a line in PDFTron using a custom appearance stream. However, the behavior is inconsistent—sometimes the text appears, and sometimes it doesn’t. I’m using the code below to create the text annotation at an angle.

When I tried using Annot.Type.e_Unknown, the text wasn’t visible at all, so I switched to using FreeText. But with FreeText, the text always renders in black, ignoring the color I set via the appearance stream.

Also, when I call textAnnot.RefreshAppearance() after setting the annotation, I intermittently get this exception: " System.AccessViolationException: 'Attempted to read or write protected memory. This is often an indication that other memory is corrupt."
Here’s the function I’m using to create the text on the line. Could someone please:

  • Suggest the proper way to create rotated/angled text at a specific position,

  • Ensure that the color is respected (not defaulting to black), and

  • Help avoid the AccessViolationException when refreshing the appearance?

    public Annot CreateTextLineAnnot(CustomPDFViewCtrl viewCtrl, pdftron.PDF.PDFDoc doc, pdftron.PDF.Page currentPage, PointF? startPt, PointF? endPt, double dimension,
    int pageNumber, System.Drawing.Color textColor)
    {
    if (!startPt.HasValue || !endPt.HasValue)
    return null;

      int pageNum = viewCtrl.GetCurrentPage();
      var rotation = currentPage.GetRotation();
      double rotationDeg = pdftron.PDF.Page.RotationToDegree(rotation);
      double rotationRad = rotationDeg * Math.PI / 180;
    
      // Text formatting properties
      string fontName = "";
      float fontSize = 0;
      bool roundUpToInt = false;
      int decimalPlaces = 3;
      bool showLabel = false;
      float offsetX = 0, offsetY = 5; // Default vertical offset if not specified
    
      // Get text properties from global settings
      GlobalVariable.CurrentFontSettingsData.GetTextProperties(out fontName, out fontSize, out roundUpToInt, out showLabel, out decimalPlaces, out offsetX, out offsetY);
    
      // Format the measurement text
      string labelText = roundUpToInt
          ? CommonUtil.FormatUtils.RoundToInt(dimension)
          : CommonUtil.FormatUtils.RoundToDecimal(dimension, decimalPlaces);
    
      if (fontSize < 1)
          fontSize = CommonConstants.DEFAULT_TEXT_SIZE_PDF;
    
      // Create a point for the center of the line
      PointF lineCenter = new PointF((startPt.Value.X + endPt.Value.X) / 2, (startPt.Value.Y + endPt.Value.Y) / 2);
    
      // Calculate line properties
      double dx = endPt.Value.X - startPt.Value.X;
      double dy = endPt.Value.Y - startPt.Value.Y;
      double lineAngle = Math.Atan2(dy, dx);
    
      // Determine text offset perpendicular to the line (90 degrees)
      double perpAngle = lineAngle - Math.PI / 2; // Perpendicular angle (90 degrees counterclockwise)
      float textOffsetDistance = Math.Max(fontSize * 0.7f, offsetY); // Distance above the line
    
      using (ElementWriter writer = new ElementWriter())
      using (ElementBuilder builder = new ElementBuilder())
      {
          writer.Begin(doc);
    
          // Only create the text (since line is already created in DrawTemporaryLine)
          pdftron.PDF.Font font = pdftron.PDF.Font.Create(doc, pdftron.PDF.Font.StandardType1Font.e_helvetica);
          
          Element element = builder.CreateTextBegin(font, fontSize);
          writer.WriteElement(element);
    
          Element textRun = builder.CreateTextRun(labelText);
          var gs = textRun.GetGState();
          gs.SetFillColorSpace(ColorSpace.CreateDeviceRGB());
          gs.SetFillColor(new ColorPt(textColor.R / 255.0, textColor.G / 255.0, textColor.B / 255.0));
    
          // Get text dimensions to center it
          textRun.UpdateTextMetrics();
          double textWidth = textRun.GetTextLength();
    
          // Position text at center of line with perpendicular offset
          float textPosX = lineCenter.X + (float)(Math.Cos(perpAngle) * textOffsetDistance);
          float textPosY = lineCenter.Y + (float)(Math.Sin(perpAngle) * textOffsetDistance);
    
          // Create transformation matrix for text orientation
          pdftron.Common.Matrix2D textTransform = new pdftron.Common.Matrix2D();
    
          // Option 1: Text aligned with line direction
          // Manually create rotation matrix components
          double cosAngle = Math.Cos(lineAngle);
          double sinAngle = Math.Sin(lineAngle);
    
          // First translate to center text horizontally relative to origin
          pdftron.Common.Matrix2D translateCenter = new pdftron.Common.Matrix2D(1, 0, 0, 1, -textWidth / 2, 0);
    
          // Then create rotation matrix
          pdftron.Common.Matrix2D rotation1 = new pdftron.Common.Matrix2D(cosAngle, sinAngle, -sinAngle, cosAngle, 0, 0);
    
          // Finally translate to target position
          pdftron.Common.Matrix2D translatePos = new pdftron.Common.Matrix2D(1, 0, 0, 1, textPosX, textPosY);
    
          // Concatenate transforms in correct order: translate → rotate → translate
          textTransform = translateCenter * rotation1 * translatePos;
    
          // Option 2: Horizontal text (uncomment to use)
          // double horizontalOffset = textWidth / 2;
          // textTransform.Translate(textPosX - horizontalOffset, textPosY);
    
          textRun.GetGState().SetTransform(textTransform);
          writer.WriteElement(textRun);
          writer.WriteElement(builder.CreateTextEnd());
    
          double buffer = fontSize * 1.2; // Small buffer around text           
          pdftron.PDF.Rect bbox = new pdftron.PDF.Rect(
              textPosX - textWidth / 2 - buffer,
              textPosY - fontSize / 2 - buffer,
              textPosX + textWidth / 2 + buffer,
              textPosY + fontSize / 2 + buffer
          );
    
          Obj appStream = writer.End();
    
          // Create text annotation (FreeText would be ideal, but we'll use a custom annotation)
          Annot textAnnot = Annot.Create(doc, Annot.Type.e_FreeText, bbox);
          textAnnot.SetAppearance(appStream);
          textAnnot.SetContents(labelText);           
          // Remove the default border (set width to 0)
          Annot.BorderStyle borderStyle = new Annot.BorderStyle(Annot.BorderStyle.Style.e_solid, 0);
          textAnnot.SetBorderStyle(borderStyle);          
          currentPage.AnnotPushBack(textAnnot);
          return textAnnot;
      }
    

    }
    Any suggestions or best practices would be greatly appreciated!
    Please describe your issue and provide steps to reproduce it:
    (The more descriptive your answer, the faster we are able to help you)

Please provide a link to a minimal sample where the issue is reproducible:

1 Like

Hello, I’m AiRon, an automated tech support bot :robot: While you wait for one of our customer support representatives, I can help you with your question.


It seems you’re experiencing issues with creating angled measurement text on a PDF using Apryse’s PDFTron SDK. The problems include inconsistent rendering of the text, the text color defaulting to black, and an AccessViolationException when calling RefreshAppearance().

Some things you can try:

  • Ensure you are using the correct method to create a rotated text annotation. Consider using a FreeText annotation with a custom appearance stream to manage rotation and styling.

  • When setting the text color, double-check that the GState object is correctly configured with the desired color space and color values.

  • To prevent the AccessViolationException, ensure that all objects and resources are properly managed and disposed of, especially when interacting with unmanaged resources.

  • Verify that the transformation matrix is properly set and applied to the text element to ensure correct positioning and rotation.

  • Check for any potential race conditions or threading issues that might affect memory access during appearance refresh.



Here are some resources that might help you:


Hopefully, this helps you solve your problem while you wait for a human to get back to you.

1 Like

Before we go down the road of editing the default appearance, it would first be important to establish if the existing API to add text works for you or not.

Please see this forum post and let me know how it works for you (and if it doesn’t please elaborate).

1 Like

Consider if i want to change the font color, text size, text offset position and font is there any API for that?

1 Like

The PDF standard supports

Text Off Set
Font Color
Text Size

However, not aware of any PDF viewers actually supporting customizing Text Color and Text Size, not Adobe, nor any other major vendors.

So if you adjust Font Color and Text Size, and anyone later on adjusts the annotation, those customizations would be lost.

But if they are important for you then yes you would have to either make your own stream, or better yet, modify the default appearance. You could follow the examples in the forum post below to change the GState of any text to be the color you want. Adjusting the font size though would be much more complicated since it could overlap the line, or even be clipped by the annotation bounding box.

Why is setting color and size important for your users (especially considering Adobe doesn’t support this)?

2 Likes

Since we are using it for measurement the text size becomes small on zoom out.