-
Notifications
You must be signed in to change notification settings - Fork 200
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add native text rendering to muPDF backend #1159
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,8 +8,10 @@ | |
|
||
import PIL.Image | ||
import numpy as np | ||
import logging | ||
|
||
from ezdxf.math import Vec2, BoundingBox2d | ||
from ezdxf.fonts.fonts import AbstractFont, font_manager | ||
from ezdxf.math import Vec2, BoundingBox2d, Matrix44 | ||
from ezdxf.colors import RGB | ||
from ezdxf.path import Command | ||
from ezdxf.version import __version__ | ||
|
@@ -39,6 +41,8 @@ | |
# psd does not work in PyMuPDF v1.22.3 | ||
SUPPORTED_IMAGE_FORMATS = ("png", "ppm", "pbm") | ||
|
||
logger = logging.getLogger("ezdxf") | ||
|
||
|
||
class PyMuPdfBackend(recorder.Recorder): | ||
"""This backend uses the `PyMuPdf`_ package to create PDF, PNG, PPM and PBM output. | ||
|
@@ -204,6 +208,7 @@ def __init__(self, page: layout.Page, settings: layout.Settings) -> None: | |
) | ||
self.settings = settings | ||
self._optional_content_groups: dict[str, int] = {} | ||
self._fonts: dict[str, int] = {} | ||
self._stroke_width_cache: dict[float, float] = {} | ||
self._color_cache: dict[str, tuple[float, float, float]] = {} | ||
self.page_width_in_pt = int(page.width_in_mm * MM_TO_POINTS) | ||
|
@@ -424,6 +429,46 @@ def draw_image(self, image_data: ImageData, properties: BackendProperties) -> No | |
oc=self.get_optional_content_group(properties.layer), | ||
) | ||
|
||
def register_font(self, font: AbstractFont) -> int: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess this implementation cannot handle SHX fonts. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would assume so. I wonder what autocad / other cad programs do when exporting if non-ttf fonts are used? If both exact rendering and selectable/interpretable text was desirable then invisible text could be layered on top of the baked glyphs hypothetically |
||
if font.name not in self._fonts: | ||
logger.info("registering font %s", font.name) | ||
path = font_manager.get_font_path(font.name) | ||
self._fonts[font.name] = self.page.insert_font( | ||
fontname=font.name, fontfile=path | ||
) | ||
return self._fonts[font.name] | ||
|
||
def draw_text( | ||
self, | ||
text: str, | ||
bbox: BoundingBox2d, | ||
transform: Matrix44, | ||
properties: BackendProperties, | ||
font: AbstractFont, | ||
cap_height: float, | ||
) -> None: | ||
self.register_font(font) | ||
origin = transform.origin | ||
transform = copy.deepcopy(transform) | ||
transform *= Matrix44.translate(-origin.x, -origin.y, -origin.z) | ||
transform *= Matrix44.scale(1, -1, 1) | ||
(a, b, _, c, d, _, _, _, _) = transform.get_2d_transformation() | ||
# last two entries must be 0 as translation is not allowed | ||
m = pymupdf.Matrix(a, b, c, d, 0, 0) | ||
p = pymupdf.Point(origin.x, origin.y) | ||
self.page.insert_text( | ||
origin.vec2, | ||
text, | ||
fontname=font.name, | ||
# scaling factor is empirically derived by rendering with this method | ||
# as well as the frontend at the same time. | ||
fontsize=cap_height * 1.375, | ||
render_mode=0, | ||
morph=(p, m), | ||
color=self.resolve_color(properties.color), | ||
oc=self.get_optional_content_group(properties.layer), | ||
) | ||
|
||
def configure(self, config: Configuration) -> None: | ||
self.lineweight_policy = config.lineweight_policy | ||
if config.min_lineweight: | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems to bypass the clipping stage, so text in viewports and clipped INSERTs will be draw at any time?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is clipping done in the pipeline? In which case I think you are correct, I didn't really handle clipping so I can't comment on if that would be difficult to add or not