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: