Refactor handling of pts attribute

In doing so, deprecate the `curve_obj["points"]` attribute, and fix
`PageImage.draw_line(...)`'s handling of diagonal lines.
This commit is contained in:
Jeremy Singer-Vine
2023-02-03 12:15:55 -05:00
parent bad8eea88d
commit 216bedd00a
5 changed files with 21 additions and 17 deletions
+4
View File
@@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file. The format
## [Unreleased]
### Changed
- Refactor handling of `pts` attribute and, in doing so, deprecate the `curve_obj["points"]` attribute, and fix `PageImage.draw_line(...)`'s handling of diagonal lines.
### Development Changes
- Convert `utils.py` into `utils/` submodules. Retains same interface, just an improvement in organization. ([6351d97](https://github.com/jsvine/pdfplumber/commit/6351d97))
+7 -2
View File
@@ -149,16 +149,21 @@ class PageImage:
stroke: T_color = DEFAULT_STROKE,
stroke_width: int = DEFAULT_STROKE_WIDTH,
) -> "PageImage":
# If passing a raw list of points, use those
if isinstance(points_or_obj, (tuple, list)):
points = points_or_obj
elif isinstance(points_or_obj, dict) and "points" in points_or_obj:
points = points_or_obj["points"]
# Else, use the "pts" attribute if available
elif isinstance(points_or_obj, dict) and "pts" in points_or_obj:
points = [(x, y) for x, y in points_or_obj["pts"]]
# Otherwise, just use ((x0, top), (x1, bottom))
else:
obj = points_or_obj
points = ((obj["x0"], obj["top"]), (obj["x1"], obj["bottom"]))
self.draw.line(
list(map(self._reproject, points)), fill=stroke, width=stroke_width
)
return self
def draw_lines(
+6 -11
View File
@@ -18,11 +18,8 @@ from pdfminer.layout import (
LTChar,
LTComponent,
LTContainer,
LTCurve,
LTItem,
LTLine,
LTPage,
LTRect,
LTTextContainer,
)
from pdfminer.pdfinterp import PDFPageInterpreter
@@ -196,6 +193,9 @@ class Page(Container):
self._objects: Dict[str, T_obj_list] = self.parse_objects()
return self._objects
def point2coord(self, pt: Tuple[T_num, T_num]) -> Tuple[T_num, T_num]:
return (pt[0], self.height - pt[1])
def process_object(self, obj: LTItem) -> T_obj:
kind = re.sub(lt_pat, "", obj.__class__.__name__).lower()
@@ -220,15 +220,10 @@ class Page(Container):
attr["stroking_color"] = gs.scolor
attr["non_stroking_color"] = gs.ncolor
if isinstance(obj, LTCurve) and not isinstance(obj, (LTRect, LTLine)):
if "pts" in attr:
attr["pts"] = list(map(self.point2coord, attr["pts"]))
def point2coord(pt: Tuple[T_num, T_num]) -> Tuple[T_num, T_num]:
x, y = pt
return (x, self.height - y)
attr["points"] = list(map(point2coord, obj.pts))
if attr.get("y0") is not None:
if "y0" in attr:
attr["top"] = self.height - attr["y1"]
attr["bottom"] = self.height - attr["y0"]
attr["doctop"] = self.initial_doctop + attr["top"]
+1 -1
View File
@@ -190,7 +190,7 @@ def resize_object(obj: T_obj, key: str, value: T_num) -> T_obj:
def curve_to_edges(curve: T_obj) -> T_obj_list:
point_pairs = zip(curve["points"], curve["points"][1:])
point_pairs = zip(curve["pts"], curve["pts"][1:])
return [
{
"x0": min(p0[0], p1[0]),
+3 -3
View File
@@ -70,7 +70,7 @@ class Test(unittest.TestCase):
assert c.split("\r\n")[9] == (
"char,1,45.83,58.826,656.82,674.82,117.18,117.18,135.18,12.996,"
'18.0,12.996,,,,,,TimesNewRomanPSMT,,,"(1, 0, 0, 1, 45.83, 660.69)"'
',,"(0, 0, 0)",,,18.0,,,,,Y,,1,'
',,"(0, 0, 0)",,18.0,,,,,Y,,1,'
)
io = StringIO()
@@ -125,7 +125,7 @@ class Test(unittest.TestCase):
assert res.decode("utf-8").split("\r\n")[9] == (
"char,1,45.83,58.826,656.82,674.82,117.18,117.18,135.18,12.996,"
'18.0,12.996,,,,,,TimesNewRomanPSMT,,,"(1, 0, 0, 1, 45.83, 660.69)"'
',,"(0, 0, 0)",,,18.0,,,,,Y,,1,'
',,"(0, 0, 0)",,18.0,,,,,Y,,1,'
)
def test_cli_csv_exclude(self):
@@ -147,7 +147,7 @@ class Test(unittest.TestCase):
assert res.decode("utf-8").split("\r\n")[9] == (
"char,1,45.83,58.826,656.82,674.82,117.18,117.18,135.18,12.996,"
"18.0,12.996,,,,,,TimesNewRomanPSMT,,"
',,"(0, 0, 0)",,,18.0,,,,,Y,,1,'
',,"(0, 0, 0)",,18.0,,,,,Y,,1,'
)
def test_cli_csv_include(self):