Drawing on Pages

Draw text, lines, and rectangles directly onto existing PDF pages using the PDFium-backed drawing API. Unlike stamps (which composite a separate PDF), drawing methods modify the page content stream in place - ideal for adding approval marks, highlight boxes, borders, and annotations that need precise pixel-level placement.

Coordinate System

PDF uses a coordinate system where:

  • The origin (0, 0) is at the bottom-left corner of the page.
  • The X axis increases to the right.
  • The Y axis increases upward.
  • All measurements are in PDF points (1 point = 1/72 inch).
Paper SizeWidth (points)Height (points)
A4 Portrait595842
A4 Landscape842595
US Letter Portrait612792
US Letter Landscape792612
US Legal Portrait6121008

Bottom-left origin. This is the standard PDF coordinate convention. A point at (50, 800) on an A4 page is 50 points from the left edge and 800 points from the bottom - which places it near the top of the page. If you are used to screen coordinates (origin at top-left), remember that y = pageHeight - desiredDistanceFromTop.

Drawing Text

Place text at an exact position on a specific page:

PdfEditor.Open("form.pdf")
    .DrawText(
        pageIndex: 0,
        text: "Approved",
        x: 400,
        y: 50,
        fontSize: 18,
        fontName: "Helvetica",
        r: 0, g: 128, b: 0)
    .Save("form-approved.pdf");

DrawText Parameters

ParameterTypeDefaultDescription
pageIndexint-Zero-based page index.
textstring-The text to draw.
xfloat-X coordinate in PDF points (from left edge).
yfloat-Y coordinate in PDF points (from bottom edge).
fontSizefloat12Font size in points.
fontNamestring"Helvetica"A standard PDF font name (see table below).
rbyte0Red component (0-255).
gbyte0Green component (0-255).
bbyte0Blue component (0-255).

Standard PDF Fonts

These fonts are built into every PDF viewer and do not require embedding:

Font NameStyle
HelveticaSans-serif (default)
Helvetica-BoldSans-serif bold
Helvetica-ObliqueSans-serif italic
Helvetica-BoldObliqueSans-serif bold italic
Times-RomanSerif
Times-BoldSerif bold
Times-ItalicSerif italic
Times-BoldItalicSerif bold italic
CourierMonospace
Courier-BoldMonospace bold
Courier-ObliqueMonospace italic
Courier-BoldObliqueMonospace bold italic
SymbolSymbol characters
ZapfDingbatsDingbats / ornaments

Drawing Lines

Draw a straight line between two points on a page:

PdfEditor.Open("document.pdf")
    .DrawLine(
        pageIndex: 0,
        x1: 50, y1: 750,
        x2: 545, y2: 750,
        strokeWidth: 2,
        r: 0, g: 0, b: 0)
    .Save("document-with-line.pdf");

DrawLine Parameters

ParameterTypeDefaultDescription
pageIndexint-Zero-based page index.
x1float-Starting X coordinate.
y1float-Starting Y coordinate.
x2float-Ending X coordinate.
y2float-Ending Y coordinate.
strokeWidthfloat1Line thickness in points.
rbyte0Red component (0-255).
gbyte0Green component (0-255).
bbyte0Blue component (0-255).

Drawing Rectangles

Draw a rectangle with an optional fill colour:

// Stroke only (no fill)
PdfEditor.Open("form.pdf")
    .DrawRectangle(
        pageIndex: 0,
        x: 50, y: 700,
        width: 200, height: 30,
        strokeWidth: 1,
        strokeR: 255, strokeG: 0, strokeB: 0)
    .Save("form-highlighted.pdf");
// Filled rectangle with semi-transparent yellow
PdfEditor.Open("report.pdf")
    .DrawRectangle(
        pageIndex: 0,
        x: 50, y: 700,
        width: 495, height: 30,
        strokeWidth: 0,
        strokeR: 0, strokeG: 0, strokeB: 0,
        fillR: 255, fillG: 255, fillB: 0,
        fillAlpha: 80)
    .Save("report-highlighted.pdf");

DrawRectangle Parameters

ParameterTypeDefaultDescription
pageIndexint-Zero-based page index.
xfloat-X of the bottom-left corner.
yfloat-Y of the bottom-left corner.
widthfloat-Rectangle width in points.
heightfloat-Rectangle height in points.
strokeWidthfloat1Border thickness. Use 0 for no border.
strokeR, strokeG, strokeBbyte0Stroke colour (RGB 0-255).
fillRint-1Fill red component. Pass -1 for no fill.
fillG, fillBint0Fill green and blue components (ignored when fillR is -1).
fillAlphabyte255Fill alpha (0 = transparent, 255 = opaque).

No-fill mode. When fillR is -1, the rectangle is stroke-only with no fill. Set fillR to 0 or higher to enable filling.

Practical Examples

Approval Stamp Box

Draw a bordered box with approval text inside it, placed in the bottom-right corner of the first page:

float boxX = 400, boxY = 30;
float boxW = 160, boxH = 50;

PdfEditor.Open("contract.pdf")
    // Green border rectangle
    .DrawRectangle(0, boxX, boxY, boxW, boxH,
        strokeWidth: 2,
        strokeR: 0, strokeG: 128, strokeB: 0,
        fillR: 240, fillG: 255, fillB: 240, fillAlpha: 200)
    // "APPROVED" text
    .DrawText(0, "APPROVED", boxX + 15, boxY + 28,
        fontSize: 18, fontName: "Helvetica-Bold",
        r: 0, g: 128, b: 0)
    // Date line
    .DrawText(0, $"{DateTime.Now:yyyy-MM-dd}", boxX + 15, boxY + 10,
        fontSize: 10, fontName: "Helvetica",
        r: 80, g: 80, b: 80)
    .Save("contract-approved.pdf");

Page Border

Draw a border around the entire page content area (50-point margin on an A4 page):

float margin = 50;
float pageW = 595, pageH = 842;

PdfEditor.Open("report.pdf")
    .DrawRectangle(0,
        x: margin, y: margin,
        width: pageW - 2 * margin,
        height: pageH - 2 * margin,
        strokeWidth: 1,
        strokeR: 180, strokeG: 180, strokeB: 180)
    .Save("report-bordered.pdf");

Highlight Box Over a Region

Draw a semi-transparent yellow box to highlight a specific area:

PdfEditor.Open("document.pdf")
    .DrawRectangle(0,
        x: 72, y: 500,
        width: 300, height: 20,
        strokeWidth: 0,
        strokeR: 0, strokeG: 0, strokeB: 0,
        fillR: 255, fillG: 255, fillB: 0,
        fillAlpha: 64)
    .Save("document-highlighted.pdf");

Separator Lines Between Sections

PdfEditor.Open("report.pdf")
    // Thin grey line across the page at y=600
    .DrawLine(0, x1: 50, y1: 600, x2: 545, y2: 600,
        strokeWidth: 0.5f, r: 180, g: 180, b: 180)
    // Thicker coloured line at y=400
    .DrawLine(0, x1: 50, y1: 400, x2: 545, y2: 400,
        strokeWidth: 2, r: 0, g: 102, b: 204)
    .Save("report-with-dividers.pdf");

Drawing on Multiple Pages

Draw a footer line and page label on every page of a document:

using var inspector = PdfiumDocument.Load(File.ReadAllBytes("manual.pdf"));
int pageCount = inspector.PageCount;
inspector.Dispose();

var editor = PdfEditor.Open("manual.pdf");

for (int i = 0; i < pageCount; i++)
{
    // Footer line
    editor.DrawLine(i,
        x1: 50, y1: 40,
        x2: 545, y2: 40,
        strokeWidth: 0.5f,
        r: 150, g: 150, b: 150);

    // Page number text
    editor.DrawText(i, $"Page {i + 1} of {pageCount}",
        x: 480, y: 25,
        fontSize: 9,
        fontName: "Helvetica",
        r: 120, g: 120, b: 120);
}

editor.Save("manual-with-footers.pdf");

Redaction-Style Black Box

Cover a region with an opaque black rectangle (for visual redaction when formal redaction is not needed):

PdfEditor.Open("report.pdf")
    .DrawRectangle(0,
        x: 200, y: 710,
        width: 180, height: 14,
        strokeWidth: 0,
        strokeR: 0, strokeG: 0, strokeB: 0,
        fillR: 0, fillG: 0, fillB: 0, fillAlpha: 255)
    .Save("report-redacted.pdf");

True redaction. Drawing a black box over text is not true redaction - the original text remains in the PDF's content stream and can be extracted. For proper content removal, use PdfEditor.RedactText() or PdfEditor.RedactArea() instead.

Drawing vs Stamping

FeatureDrawing APIStamp API
Precision placementExact X/Y coordinatesAlignment-based (Start/Center/End)
Per-page controlTargets a specific pageApplies to all pages
TypographyStandard PDF fonts onlyFull layout engine (any font)
ShapesLines, rectanglesText and images only
MechanismModifies page content streamGenerates overlay PDF + qpdf merge
Best forApproval marks, borders, highlightsWatermarks, logos, branding

Next Steps