Utility and Helper Classes

Utility and Helper Classes

Utility and Helper Classes

This guide shows how to use the small, focused helper classes that Aspose.PDF FOSS for .NET ships for common low-level tasks: integer math used by security primitives, regex search configuration, PostScript function evaluation, external font discovery, vector sub-path extraction, physical text measurement, buffered content-stream edits, large in-memory streams, and library version reporting. These classes are not entry points on their own, but they back higher-level document, text, and rendering operations throughout the API.


Integer math helpers

MathExtensions is a small static helper used internally by the library’s security primitives, but it is available for general use whenever you need a modulo operation that always returns a non-negative result.

// Unlike the C# % operator, Mod never returns a negative value.
int wrapped = MathExtensions.Mod(-3, 5); // 2

Regex search configuration

RegexManager is a static class that configures the regular-expression engine used by text search operations such as TextFragmentAbsorber. Set MatchTimeout to bound how long a pattern is allowed to run, and enable NonBacktracking to use the non-backtracking regex engine for performance-sensitive searches.

using var doc = Document.Open(pdfBytes);

// Guard against runaway regex patterns.
RegexManager.MatchTimeout = TimeSpan.FromSeconds(5);
RegexManager.NonBacktracking = true;

var absorber = new TextFragmentAbsorber(@"\d{3}-\d{4}", true);
doc.Pages[1].Accept(absorber);

Evaluating PostScript functions

PostScriptEvaluator is a static class that evaluates Type 4 PDF functions (PDF32000 §7.10.5) — PostScript calculator programs embedded in a PDF, such as those used in some color-space and shading definitions.

double[] inputs = { 0.5 };

// Evaluate a PostScript calculator program against the input array.
var outputs = PostScriptEvaluator.Evaluate("{ 2 mul }", inputs);

External font search paths

ExternalFontCache manages the folders searched for external (non-embedded) TrueType/OpenType faces during rendering and conversion. Use Instance to reach the singleton, GetDefaultFontsFolders to inspect the built-in search locations, and SetFontsFolders to add or replace them.

var cache = ExternalFontCache.Instance;
var defaultFolders = cache.GetDefaultFontsFolders();

// reset: false appends to the existing search paths instead of replacing them.
cache.SetFontsFolders(new[] { @"C:\Fonts\Custom" }, reset: false);

Extracting vector sub-paths

GraphicsAbsorber visits a page and extracts its painted vector sub-paths as SubPath elements, each carrying its own page-space bounding Rectangle. This is useful for inspecting or measuring vector artwork without parsing the content stream by hand.

using var doc = Document.Open(pdfBytes);

var absorber = new GraphicsAbsorber();
absorber.Visit(doc.Pages[1]);

Console.WriteLine($"Elements found: {absorber.Elements.Count}");

foreach (var element in absorber.Elements)
{
    if (element is SubPath subPath)
    {
        Rectangle bounds = subPath.Rectangle;
        Console.WriteLine($"Sub-path bounds: [{bounds.LLX}, {bounds.LLY}, {bounds.URX}, {bounds.URY}]");
    }
}

Physical text segment measurement

PhysicalTextSegment is the page-space projection of an absorbed TextSegment. Reach it through TextSegment.PhysicalSegment to measure a run of characters or read its resolved TextState.

using var doc = Document.Open(pdfBytes);

var absorber = new TextFragmentAbsorber();
doc.Pages[1].Accept(absorber);

foreach (TextFragment fragment in absorber.TextFragments)
{
    foreach (TextSegment segment in fragment.Segments)
    {
        PhysicalTextSegment physical = segment.PhysicalSegment;
        var width = physical.MeasureSegment(segment.StartCharIndex, segment.EndCharIndex, true);
        TextState state = physical.TextState;
    }
}

Buffering content-stream edits

ContentsAppender, reached through Page.ContentsAppender, buffers operators to prepend or append to a page’s content stream and commits them in one pass with UpdateData.

using var doc = Document.Open(pdfBytes);

Page page = doc.Pages[1];
page.ContentsAppender.AppendToBegin(new GSave());
page.ContentsAppender.AppendToEnd(new GRestore());
page.ContentsAppender.UpdateData();

Large in-memory streams

OptimizedMemoryStream is a growable in-memory stream that can exceed the 2 GB single-array limit of MemoryStream by storing data in fixed-size chunks. It derives from Stream, so it supports the usual read, write, and seek operations.

using var stream = new OptimizedMemoryStream();

byte[] buffer = System.Text.Encoding.UTF8.GetBytes("large payload");
stream.Write(buffer, 0, buffer.Length);

bool canSeek = stream.CanSeek;
byte[] allBytes = stream.ToArray();

Library version information

BuildVersionInfo is a static class exposing the library’s product name and version numbers at runtime — useful for diagnostics and support requests.

Console.WriteLine(BuildVersionInfo.Product);
Console.WriteLine(BuildVersionInfo.AssemblyVersion);
Console.WriteLine(BuildVersionInfo.FileVersion);

Tips and Best Practices

  • Set RegexManager.MatchTimeout before running searches over untrusted or user-supplied patterns to avoid catastrophic backtracking.
  • Call ExternalFontCache.SetFontsFolders with reset: true when you want to fully replace the default search paths rather than append to them.
  • Prefer OptimizedMemoryStream over MemoryStream when buffering very large documents or image data that may exceed 2 GB.
  • Always finish a batch of ContentsAppender edits with UpdateData() — buffered operators are not committed to the content stream until then.
  • GraphicsAbsorber.Elements may contain GraphicElement instances other than SubPath; check the type before casting.

Common Issues

IssueCauseFix
Regex search hangs on complex patternsNo timeout configured on RegexManagerSet RegexManager.MatchTimeout before running TextFragmentAbsorber searches
Content-stream edits from ContentsAppender don’t appear in the saved fileUpdateData() was never calledCall UpdateData() after the last AppendToBegin/AppendToEnd call
Custom fonts aren’t picked up during renderingFont folder wasn’t registered, or reset: true cleared expected defaultsCall ExternalFontCache.SetFontsFolders with the correct folder list and reset value
OutOfMemoryException when buffering very large outputMemoryStream hit its 2 GB single-array limitUse OptimizedMemoryStream, which stores data in fixed-size chunks

FAQ

Why does MathExtensions.Mod differ from the C# % operator?

MathExtensions.Mod always returns a non-negative remainder, whereas the built-in % operator can return a negative value when the dividend is negative.

How do I stop a regex-based text search from running too long?

Set RegexManager.MatchTimeout to a TimeSpan before constructing or running a TextFragmentAbsorber that uses a regex pattern.

Does SetFontsFolders replace or add to the existing search paths?

It depends on the reset argument: pass true to replace the current folder list, or false to append the new folders to it.

What does GraphicsAbsorber actually extract?

It extracts the painted vector sub-paths of a page as SubPath elements, each with a page-space bounding Rectangle, via GraphicsAbsorber.Visit.

When should I use OptimizedMemoryStream instead of MemoryStream?

When the buffered data may approach or exceed 2 GB, since MemoryStream is backed by a single array with that hard limit.


API Reference Summary

Class / MethodDescription
MathExtensions.ModNon-negative integer modulo helper used by security primitives
RegexManager.MatchTimeoutTimeout applied to regex-based text searches
RegexManager.NonBacktrackingEnables the non-backtracking regex engine
PostScriptEvaluator.EvaluateEvaluates a Type 4 PDF PostScript calculator function
ExternalFontCache.InstanceSingleton access to the external font cache
ExternalFontCache.GetDefaultFontsFoldersReturns the default external font search folders
ExternalFontCache.SetFontsFoldersAdds or replaces external font search folders
GraphicsAbsorber.VisitExtracts vector graphics elements from a page
GraphicsAbsorber.ElementsCollection of extracted GraphicElement/SubPath items
SubPath.RectanglePage-space bounding rectangle of an extracted sub-path
PhysicalTextSegment.MeasureSegmentMeasures a character range of a physical text segment
PhysicalTextSegment.TextStateResolved formatting state of a physical text segment
ContentsAppender.AppendToBeginBuffers an operator to prepend to a page’s content stream
ContentsAppender.AppendToEndBuffers an operator to append to a page’s content stream
ContentsAppender.UpdateDataCommits buffered operators to the content stream
OptimizedMemoryStreamGrowable in-memory stream beyond the 2 GB MemoryStream limit
BuildVersionInfo.ProductProduct name of the running library
BuildVersionInfo.AssemblyVersionAssembly version of the running library
BuildVersionInfo.FileVersionFile version of the running library

See Also