Use when working with page sizes, object positions, rendering dimensions, or click-to-document mapping in pdfium-render, and you need to know which unit a value is in and how to convert it. Prevents the unit-confusion bugs: treating PdfPoints as pixels, converting points to pixels without a render config, forgetting the bottom-left to top-left y-axis flip when overlaying PDF coordinates on a raster image, and the 0.8.28 bounds() return-type change. Covers PdfPoints (the 1/72 inch document unit), Pixels (the raster unit, i32), PdfPage::points_to_pixels and pixels_to_points, PdfRect versus PdfQuadPoints, and the PDF coordinate origin. Keywords: pdfium-render, coordinates, units, PdfPoints, Pixels, points_to_pixels, pixels_to_points, PdfRect, PdfQuadPoints, bounds, page size, DPI, scale, origin, y-axis flip, bounding box, "wrong size", "object in wrong place", "coordinates upside down", "image is too small", "bounds does not compile", "expected PdfRect found PdfQuadPoints", "how big is a PDF page", "convert poin
Use when working with page sizes, object positions, rendering dimensions, or click-to-document mapping in pdfium-render, and you need to know which unit a value is in and how to convert it. Prevents the unit-confusion bugs: treating PdfPoints as pixels, converting points to pixels without a render config, forgetting the bottom-left to top-left y-axis flip when overlaying PDF coordinates on a raster image, and the 0.8.28 bounds() return-type change. Covers PdfPoints (the 1/72 inch document unit), Pixels (the raster unit, i32), PdfPage::points_to_pixels and pixels_to_points, PdfRect versus PdfQuadPoints, and the PDF coordinate origin. Keywords: pdfium-render, coordinates, units, PdfPoints, Pixels, points_to_pixels, pixels_to_points, PdfRect, PdfQuadPoints, bounds, page size, DPI, scale, origin, y-axis flip, bounding box, "wrong size", "object in wrong place", "coordinates upside down", "image is too small", "bounds does not compile", "expected PdfRect found PdfQuadPoints", "how big is a PDF page", "convert points to pixels", "where did the user click".
license
MIT
compatibility
Designed for Claude Code. Requires pdfium-render 0.8,0.9.
metadata
{"author":"OpenAEC-Foundation","version":"1.0"}
pdfium-render Coordinates and Units
pdfium-render uses two coordinate systems with different units and different
origins. Mixing them is the root cause of "object in the wrong place",
"rendered image is the wrong size", and "coordinates are upside down" bugs.
This skill states which unit each value is in and how to convert correctly.
ALWAYS know which system a value belongs to before doing arithmetic with it.
NEVER add or compare a PdfPoints value to a Pixels value directly,
because they are different units with different origins.
1. PdfPoints: the Document Unit
PdfPoints is the device-independent unit of the PDF document interior. The
docs define it: "the internal coordinate system inside a PdfDocument is
measured in Points, a device-independent unit equal to 1/72 inches, roughly
0.358 mm. Points are converted to pixels when a PdfPage is rendered into a
PdfBitmap."
pubstructPdfPoints { pub value: f32 }
PdfPoints wraps a single f32 in its public value field. It carries
constants ZERO, MAX, MIN and physical-unit conversions
from_inches/from_cm/from_mm and to_inches/to_cm/to_mm. These
types return PdfPoints and stay inside PDF user space:
PdfPage::width() and height() return PdfPoints.
PdfRect and PdfQuadPoints measure their corners in PdfPoints.
A US Letter page is 612.0 x 792.0 points (8.5 x 11 inches). A4 is
595.28 x 841.89 points. ALWAYS read a page size as PdfPoints and use the
physical-unit helpers when a real-world measurement is required.
2. Pixels: the Raster Unit
Pixels is the unit of a rendered raster image. It is a plain type alias:
pubtypePixels = i32;
Pixels appear only after rendering. PdfBitmap::width() and height()
return Pixels. PdfRenderConfig builder methods (set_target_width,
set_maximum_height, the set_fixed_* family) take Pixels. A page has no
pixel size until a PdfRenderConfig decides one.
NEVER treat PdfPage::width() as a pixel count. It is points. The pixel size
is whatever the render config produces. See pdfium-syntax-rendering.
3. Converting Between Points and Pixels
Conversion is config-dependent: the same point value maps to different
pixel values depending on the render config's scale and target size. Two
PdfPage methods do the conversion, both added in 0.8.12, both requiring
a &PdfRenderConfig:
ALWAYS use the same PdfRenderConfig for conversion that you use (or will
use) to render the page. The conversion is only meaningful relative to that
config. NEVER hardcode a points-to-pixels factor such as "multiply by 72" or
"multiply by 96 / 72"; that ignores the config's scale and target dimensions
and produces values that do not match the actual bitmap.
Note: there is noPdfPoints::from_pixels constructor. Pixels become
points only through PdfPage::pixels_to_points with a config.
4. The Origin Flip
The two systems do not share an origin. This is the most common silent bug.
PDF user space (points) Raster space (pixels)
y +---------------> x
^ |
| |
| |
+---------------> x v
(0,0) bottom-left y (0,0) top-left
When PDFium renders a page to a PdfBitmap it performs this flip for
you: the rendered image looks correct. The flip becomes your responsibility
when you take a coordinate from PDF user space (an object's bounds(), a
PdfRect) and want to draw or hit-test it on the raster image with an
external library.
To map a PDF y-coordinate onto raster pixels:
raster_y_px = page_height_px - pdf_y_px
ALWAYS flip the y-axis when overlaying point-space geometry on a raster
image. NEVER assume a bounds() rectangle can be drawn directly with a
top-left-origin image library; its y values grow the opposite direction.
The x-axis does not flip.
5. PdfRect vs PdfQuadPoints
Two rectangle-like types exist, both measured in PdfPoints.
PdfRect is an axis-aligned rectangle. Its corners are named by edge:
bottom, left, top, right.
PdfQuadPoints is a quadrilateral: four independent vertices in
counter-clockwise order, (x1,y1) through (x4,y4). It can represent a
rotated box, which an axis-aligned PdfRect cannot.
Convert between them with PdfRect::to_quad_points() and
PdfQuadPoints::to_rect(). ALWAYS use to_rect() when you need a simple
axis-aligned box from a bounds() result. NEVER assume a PdfQuadPoints is
axis-aligned; a rotated text object has a slanted quadrilateral, and reading
only x1/y1 as a corner of an upright box gives the wrong region.
6. Version Traps
Item
0.8.x
0.9.x
Consequence
PdfPageObjectCommon::bounds() return
PdfRect before 0.8.28, Result<PdfQuadPoints, _> from 0.8.28
Result<PdfQuadPoints, PdfiumError>
Code reading bounds() as a PdfRect fails to compile against 0.8.28+
points_to_pixels / pixels_to_points
added 0.8.12; absent before
present
Not available on pre-0.8.12
When upgrading and the compiler reports "expected PdfRect, found
PdfQuadPoints" on a bounds() call, append .to_rect() to restore an
axis-aligned rectangle, or rework the code to handle the quadrilateral.
Decision Tree: Which Conversion
I have a value and need another unit.
Page size in a physical unit (mm, inches)
-> PdfPage::width()/height() give PdfPoints
-> PdfPoints::to_mm() / to_inches()
Object position for drawing on the rendered image
-> bounds() gives PdfQuadPoints (points)
-> .to_rect() for an axis-aligned PdfRect
-> PdfPage::points_to_pixels(x, y, &config) per corner
-> flip y : raster_y = bitmap_height - y_px
User clicked pixel (px, py) on the rendered image, need the PDF location
-> flip y back : pdf_y_px = bitmap_height - py
-> PdfPage::pixels_to_points(px, pdf_y_px, &config)
Rotated bounding box
-> keep PdfQuadPoints, do NOT collapse to PdfRect
ALWAYS / NEVER
ALWAYS know whether a value is PdfPoints or Pixels before arithmetic.
ALWAYS convert points to pixels with points_to_pixels and the actual
PdfRenderConfig; the result is config-dependent.
ALWAYS flip the y-axis when mapping point-space geometry onto a
top-left-origin raster image.
ALWAYS use PdfQuadPoints::to_rect() to get an axis-aligned box from a
bounds() result.
NEVER treat PdfPage::width()/height() as pixel counts; they are points.
NEVER hardcode a points-to-pixels multiplier; it ignores the render config.
NEVER look for PdfPoints::from_pixels; it does not exist. Use
pixels_to_points.
NEVER read a PdfQuadPoints as if it were axis-aligned.
NEVER read bounds() as a PdfRect on 0.8.28 or later.
Cross-References
pdfium-syntax-rendering : PdfRenderConfig, PdfBitmap, how target
dimensions and scale determine the pixel size.
pdfium-syntax-page-objects : PdfPageObjectCommon::bounds() and object
geometry.
pdfium-impl-page-manipulation : page boundary boxes and cropping, which
also use PdfPoints.
pdfium-core-architecture : where PdfPage and page objects sit in the
ownership tree.
Reference Files
references/methods.md : signatures of PdfPoints, Pixels, PdfRect,
PdfQuadPoints, and the PdfPage conversion methods with version notes.
references/examples.md : verified Rust code for reading sizes, converting
units, the y-axis flip, and quadrilateral handling.
references/anti-patterns.md : real unit-confusion failures with the cause
and the fix.
Sources
API names and signatures verified on 2026-05-20 via WebFetch against the
package SOURCES.md: