pub struct TextItem {Show 25 fields
pub text: String,
pub x: f32,
pub y: f32,
pub width: f32,
pub height: f32,
pub rotation: f32,
pub advance_known: bool,
pub font: String,
pub font_tag: String,
pub legacy_symbol_rewrite: bool,
pub font_size: f32,
pub page: u32,
pub is_bold: bool,
pub is_italic: bool,
pub font_weight: Option<u16>,
pub bold_source: Option<BoldSource>,
pub fixed_pitch: Option<bool>,
pub fill_color: Option<[u8; 3]>,
pub stroke_color: Option<[u8; 3]>,
pub render_mode: Option<u8>,
pub is_underline: bool,
pub is_strikeout: bool,
pub item_type: ItemType,
pub mcid: Option<i64>,
pub baseline_shift: f32,
}Expand description
A text item with position information.
x, y, width, height describe the item’s axis-aligned box in PDF
points, y-up. For ordinary horizontal text the box runs from the baseline
one em upward and spans the run’s advance, which is what every consumer
historically assumed. A run shown with a rotated text matrix gets the
bounding box of its rotated glyph run instead — tall and thin for a
vertical margin stamp — and reports the angle in rotation.
§Coordinate frame
Items returned by the public position APIs (extract_text_with_positions*)
are relative to the page’s visible page box —
CropBox ∩ MediaBox when the page has a CropBox, else the MediaBox; a
CropBox that does not overlap the MediaBox is ignored, and a page without
a MediaBox is measured against US Letter (see extractor::page_box) —
with the box’s lower-left corner as the origin and y growing upward.
A renderer’s page image and the region APIs use the same box from its
top-left corner with y growing downward, so flipping y by the box
height lets items and rendered regions be intersected directly. Raw
content-stream coordinates differ whenever the CropBox or MediaBox origin
is not (0, 0). A page whose text is predominantly rotated has its frame
turned so the text reads left-to-right (PageRotation, reported by
extract_text_with_positions_and_rotations_mem) and the shift is turned
the same way; /Rotate is not applied. Inside the markdown pipeline
items stay in raw user space.
PositionFrame::Display (see
extract_text_with_positions_mem_in_frame)
reports items in the rendered page’s frame instead: the visible page box
turned clockwise by the page’s inheritable /Rotate, with the turn of a
rotated page undone, so the box and rotation describe the item as a
renderer draws it.
Fields§
§text: StringThe text content
x: f32Left edge of the item’s box, in PDF points from the visible page
box’s left edge (see the coordinate frame note on TextItem).
y: f32Bottom edge of the item’s box, in PDF points from the visible page
box’s bottom edge with y growing upward (see the coordinate frame
note on TextItem). For horizontal text this is the baseline;
descenders are not included. Image, link and form-field items carry
their rect’s bottom edge.
width: f32Horizontal extent of the box: the advance for horizontal text, the em size for a vertical run. Zero only for a horizontal run whose font carries no width information (advance unknown).
height: f32Vertical extent of the box: the rendered em size for horizontal text, the advance for a vertical run.
rotation: f32Rotation of the run’s baseline in degrees, counter-clockwise from the
page’s +x axis, normalised to [0, 360): 0 for ordinary
left-to-right text, 90 for text reading bottom-to-top (a margin
stamp rotated counter-clockwise), 270 for text reading
top-to-bottom, 180 for upside-down text. Rotation-only matrices
report exact multiples of 90; skewed matrices (deskewed OCR layers,
diagonal watermarks) report fractional angles. A reflected text
matrix has no rotation — its reading direction and its glyphs’
orientation differ by a half turn — and reports how its glyphs
stand: 0 for the mirrored-x matrix some producers paint
right-to-left text with (upright glyphs reading left), 180 for a
y-flipped one. A negative Tf size turns a run around and reads as
180. 0 for items that don’t come from a text matrix (images,
links, form fields, OCR).
On a page whose text is predominantly rotated the extractor turns
the coordinate frame so the dominant runs read as 0; upright
strays then report 270 on a counter-clockwise page and 90 on a
clockwise one.
advance_known: boolWhether the run’s advance came from font metrics. false when the
font carries no width information (or, for an ActualText span, when
the advance could not be recovered from the text matrix): the box’s
extent along the baseline is then an estimate of half an em per
painted glyph (an ActualText span counts the glyphs it covers, not its
replacement text), laid in the direction the run reads, rather than
a measurement. A
font that reports a genuine zero advance keeps true. Items that
don’t come from a text matrix (images, links, form fields, OCR)
always report true.
font: StringFont name: the /BaseFont family name (“ABCDEF+CMMI10”), which
identifies the actual face (see extractor::fonts::item_font_name
for the CID carve-out).
font_tag: StringThe raw font resource tag (“F2”, “T22”) the item’s show operator
selected. This is exactly what font carried before 1.16.0, with
the same caveats: the tag’s namespace is the enclosing page or Form
XObject’s /Resources (the same tag on another page may name a
different face), and an item merged from multiple runs keeps the
first run’s tag. Within one page it distinguishes font programs
that share a family name (two subsets of the same face keep
distinct tags), which family-keyed font cannot. Empty for items
that don’t originate from a content-stream show operator (images,
links, form fields, OCR).
legacy_symbol_rewrite: boolAt least one source character was changed by the legacy private-use symbol cleanup. This is decoding provenance, not an OCR verdict: the rewritten value must not be assumed to be an authoritative Unicode alias. Merged items retain evidence from every contributing run; later text splits conservatively retain their source run’s evidence.
font_size: f32Font size
page: u32Page number (1-indexed)
is_bold: boolWhether the font is bold: a bold word in the font name, the
FontDescriptor’s ForceBold flag or the embedded program’s bold
selection, or text filled and stroked to look heavier. With
PositionOptions::bold_from_weight it is
also true when font_weight is 600 or more.
is_italic: boolWhether the font is italic
font_weight: Option<u16>The font’s weight class on the 100..=900 scale shared by CSS
font-weight and the OS/2 usWeightClass field (400 regular, 700
bold), read from the embedded font program’s OS/2 table, else the
FontDescriptor’s /FontWeight, else a weight word in the font name
(“Light”, “Medium”, “-Md”, “Black”, “W6”). None when none of them
says, and for items that don’t come from a font (images, links, form
fields, OCR). Independent of is_bold, which stays as it was: a
medium face reports Some(500) and is_bold: false.
bold_source: Option<BoldSource>Where is_bold came from, so a caller can weigh the verdict against
font_weight: the font name, the font’s flags, the weight class or
the way the text was painted (see BoldSource). When more than one
says bold the first of them in that order is reported. None when
is_bold is false, and for items that don’t come from a font. An
item merged from several runs keeps its first run’s, like font and
font_weight.
fixed_pitch: Option<bool>Whether the font is fixed-pitch (monospaced): Some(true) when the
FontDescriptor’s FixedPitch flag or the embedded program’s post
table says so, else measured from the font’s width table — Some(true)
when at least a dozen of its glyphs share one advance, Some(false)
when two of them differ. None when the font declares nothing and no
two advances differ but fewer than a dozen share one, and for items
that don’t come from a font. Many producers write /Flags 4 whatever
the face, so the
flag is only ever read as a yes. Runs are not kept apart by it: an
item merged from several runs keeps its first run’s value, like
font and font_weight.
fill_color: Option<[u8; 3]>The fill (non-stroking) colour in force when the run was shown, as
8-bit sRGB [red, green, blue]: the colour its glyphs are filled
with in the render modes that fill (0, 2, 4, 6; see render_mode).
DeviceRGB is read as sRGB and DeviceGray as three equal components;
DeviceCMYK is converted the way the PDF specification converts it to
DeviceRGB, each of red, green and blue 1 - min(1, ink + black). An
ICCBased space is read as the device space of its component count
(1, 3 or 4) without applying the profile, and an Indexed space
(/Indexed, or its abbreviation /I) through its palette’s base
space, which may be named by another colour space resource.
Components outside their range are clamped to it, and selecting a
space with cs/CS sets the initial colour the PDF specification
gives it: black, except a four-component ICCBased space, whose
components all start at 0, which reads as white. None for any
other colour space (Separation,
DeviceN, Pattern, CalGray, CalRGB, Lab), for a colour operator whose
operands do not fit its space, and for items that don’t come from a
content-stream show operator (images, links, form fields, OCR). The
colour is graphics state: q/Q save and restore it and a Form
XObject starts with the colour it was invoked under. Runs are not
kept apart by it: an item merged from several runs keeps its first
run’s value, like font.
stroke_color: Option<[u8; 3]>The stroking colour in force when the run was shown, as 8-bit sRGB,
read like fill_color: the colour the glyph outlines are stroked
with in the render modes that stroke (1, 2, 5, 6). None when
unknown or not from a show operator, as for fill_color, and an
item merged from several runs keeps its first run’s value.
render_mode: Option<u8>The text render mode (Tr) the run was shown with, 0..=7: 0 fill,
1 stroke, 2 fill then stroke, 3 neither (invisible text, the mode OCR
text layers use), 4 to 6 as 0 to 2 while also adding the glyphs to
the clipping path, 7 clipping only. Runs in modes 3 and 7 put no
glyphs on the page, so callers can tell visible text from invisible
text by it. The mode is graphics state: it holds across text objects,
q/Q save and restore it, and a Form XObject starts with the mode
it was invoked under; a Tr whose operand is not an integer in
0..=7 is ignored, as renderers ignore it. Reporting the mode leaves
which runs are extracted exactly as before: invisible text is neither
dropped nor added because of it. None for items that don’t come
from a content-stream show operator (images, links, form fields,
OCR); an item merged from several runs keeps its first run’s value.
is_underline: boolWhether the text is underlined (drawn rule/thin rect under the
baseline — PDFs have no underline font flag, so this is detected
geometrically after extraction; see extractor::underline).
is_strikeout: boolWhether the text is struck out (drawn rule/thin rect crossing the
glyphs at mid x-height). Same geometric detection as underline,
different vertical window; see extractor::underline.
item_type: ItemTypeType of item (text, image, link)
mcid: Option<i64>Marked Content ID from the content stream’s BDC/BMC operator. Used to link this item to the PDF structure tree for tagged PDFs.
baseline_shift: f32Signed baseline offset, in points, of a superscript/subscript glyph
run from the baseline of the body text it is attached to. Zero for
normal text. Positive = raised above the anchor’s baseline
(superscript: footnote and affiliation markers, exponents), negative =
lowered (subscript: chemistry indices, math). Extraction sets it when
a short run is small relative to a tightly adjacent larger neighbor
and sits at a real baseline offset from it; a digit-only run beside a
word is instead fused into that word as Unicode super/subscript
characters (“H₂O”, “word²”) and never carries a shift. y stays the
glyph’s own baseline; TextItem::line_y gives the anchor’s.
Implementations§
Source§impl TextItem
impl TextItem
Sourcepub fn line_y(&self) -> f32
pub fn line_y(&self) -> f32
Baseline of the visual line this item belongs to: the glyphs’
baseline for normal text, the anchor’s baseline for a super/subscript
glyph run (baseline_shift below it). Line grouping compares this
instead of y so raised and lowered markers stay on their body line
and upside-down runs of different sizes share theirs.
Sourcepub fn baseline_y(&self) -> f32
pub fn baseline_y(&self) -> f32
The y of the edge the glyphs stand on or hang from: y (the box’s
bottom edge) for a run within 45° of upright, y + height (the top
edge) for one within 45° of upside-down (is_upside_down(), glyph
orientation included for reflected matrices). Exact for level runs;
for oblique ones the baseline is not horizontal and the edge is only
an approximation of it, which is what line grouping then compares.
Vertical runs return the box bottom y.
Source§impl TextItem
impl TextItem
Sourcepub fn is_horizontal(&self) -> bool
pub fn is_horizontal(&self) -> bool
Whether the run reads along the page’s x axis rather than its y
axis: rotation closer to 0/180 than to 90/270, the same
45° split the extractor uses to vote on page rotation. Layout
heuristics that reason about baselines, word gaps, and column spans
walk the x axis and assume this; rotated runs (margin stamps, chart
axis titles, rotated table headers) return false and are kept out
of them. Oblique runs (diagonal watermarks, deskewed OCR lines) are
deliberately still true: the x-axis heuristics are the closest fit
the pipeline has for them, exactly as before rotation existed, and
callers needing the precise angle read rotation directly.
Sourcepub fn is_upright(&self) -> bool
pub fn is_upright(&self) -> bool
Whether the run reads along +x: rotation within 45° of 0. The
x-ascending walks (item merging, line assembly) assume this; an
upside-down run is is_horizontal() but reads towards -x.
Sourcepub fn is_upside_down(&self) -> bool
pub fn is_upside_down(&self) -> bool
Whether the run reads towards -x: rotation within 45° of 180.
Trait Implementations§
Auto Trait Implementations§
impl Freeze for TextItem
impl RefUnwindSafe for TextItem
impl Send for TextItem
impl Sync for TextItem
impl Unpin for TextItem
impl UnsafeUnpin for TextItem
impl UnwindSafe for TextItem
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more