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
pageIndexintZero-based page index.
textstringThe text to draw.
xfloatX coordinate in PDF points (from left edge).
yfloatY 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
pageIndexintZero-based page index.
x1floatStarting X coordinate.
y1floatStarting Y coordinate.
x2floatEnding X coordinate.
y2floatEnding 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
pageIndexintZero-based page index.
xfloatX of the bottom-left corner.
yfloatY of the bottom-left corner.
widthfloatRectangle width in points.
heightfloatRectangle 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