Skip to content
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

Negative margins causing a line break with inline elements #2476

Closed
eddturtle opened this issue Jun 21, 2021 · 7 comments · Fixed by #2499
Closed

Negative margins causing a line break with inline elements #2476

eddturtle opened this issue Jun 21, 2021 · 7 comments · Fixed by #2499

Comments

@eddturtle
Copy link
Contributor

Applying a negative margin on an element breaks the text to a new line after the inline element.

The HTML:

<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
</head>
<body>
  
  <p style="margin-left:-30px;">the garage dated 22<sup>nd</sup> March 2013. This would appear to have been the work that has been carried out by your Seller. Outline Planning</p>

</body>
</html>

Screenshot 2021-06-21 at 15-01-50 0 pdf issue - 0pdfissue pdf
Screenshot 2021-06-21 at 14-59-35 dompdf Debugging Helper

Would expect "March" to appear next to, and to the right of, the "nd" superscript.

We've tried this using: https://eclecticgeek.com/dompdf/debug.php running Dompdf v1.0.2 and v0.8.3 and they both show this issue happening.

On our local machines, if we set the margin left to -17px then it didn't work, but -16px did (this could be something on our setup though). Probably un-important, but transform: translateX(-30px); caused the same issue to happen.

I've tried looking at the code (would happily put together a PR, but can't find the right bit). The best I could come up with would be the positioner isn't positioning the 2nd line correctly? Any help would be amazing!

@Mellthas
Copy link
Member

Had a look at the code handling inline elements a while ago, and yes, I think the positioner is forcing line breaks where it shouldn't. I have some work on this lying around that I need to review again; when I find some time I will post a PR. Though I cannot guarantee that it fixes this particular bug.

@bsweeney bsweeney added this to the 1.0.3 milestone Jun 21, 2021
@gweithio
Copy link

@Mellthas Would you be in the position to create a gist (or here) of the fix? Would be much great if you could!

@Mellthas
Copy link
Member

I have posted #2497. It is mostly concerned with fixing issues around page breaks, and although it contains a few fixes related to line breaks, it unfortunately does not fix the issue here. Maybe the changes can help in finding a solution. The most important parts of the changes are in d210663.

@Mellthas
Copy link
Member

The issue here does not seem to be related to the negative margin, actually. It seems it depends on the space available for the text. I can reproduce the issue with style="width: 700pt; instead of the negative margin on the p element (with a page size of A4).

@Mellthas
Copy link
Member

Mellthas commented Jul 28, 2021

The following HTML makes the issue more visible:

<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
</head>
<style>
  @page {
    size: 400pt 300pt;
    margin: 50pt;
  }
</style>
<body>

<p style="width: 350pt;">
Lorem ipsum dolor sit amet, consectetur adipisici elit, sed eiusmod tempor
incidunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis
nostrud exercitation ullamco laboris <b>nisi</b> ut aliquid ex ea commodi consequat.
Quis aute iure reprehenderit in voluptate velit esse cillum dolore eu fugiat
nulla pariatur. Excepteur sint obcaecat cupiditat non proident, sunt in culpa
qui officia deserunt mollit anim id est laborum.
</p>

</body>
</html>

issue-2476

The single inline frame messes up the following line layout. If you take it out, the layout works properly. The issue only appears if the width of the paragraph is larger than the page width within the margins, by virtue of an explicit width or negative margins, as reported initially. In trying to debug this I have come thus far, maybe someone can pick up from there:

  • When a line break for the text portion after the inline frame is decided, the available width, mainly the width of the containing block, is reported properly.
    // Determine the available width
    $line_width = $this->_frame->get_containing_block("w");
    $current_line_width = $current_line->left + $current_line->w + $current_line->right;
    $available_width = $line_width - $current_line_width;
  • But when reflow happens, and the frame is added to the current line, the containing block reports a smaller width – presumably the width between the page margins – and the text that was calculated to fit onto the current line before is now moved to the next line.
    $add_line = $this->_layout_line();
    if ($block) {
    $block->add_frame_to_line($frame);

    $line = $this->_line_boxes[$this->_cl];
    if ($line->left + $line->w + $line->right + $w > $this->get_containing_block("w")) {
    $this->add_line();
    }

Mellthas added a commit to Mellthas/dompdf that referenced this issue Jul 28, 2021
The block must check its own content-box width, not the content-box
width of its containing block when placing child frames.

Fixes dompdf#2476.
@Mellthas
Copy link
Member

I think I found the culprit, but it would be nice if someone could double-check the logic in PR #2499.

@eddturtle
Copy link
Contributor Author

Thanks for the notes/work above - the code change looks like it fixes our scenario (above) and makes sense 👍

Mellthas added a commit to Mellthas/dompdf that referenced this issue Jul 29, 2021
Mellthas added a commit to Mellthas/dompdf that referenced this issue Jul 29, 2021
Mellthas added a commit to Mellthas/dompdf that referenced this issue Jul 29, 2021
The block must check its own content-box width, not the content-box
width of its containing block when placing child frames.

Fixes dompdf#2476.
@bsweeney bsweeney linked a pull request Aug 24, 2021 that will close this issue
bsweeney pushed a commit that referenced this issue Sep 11, 2021
The block must check its own content-box width, not the content-box
width of its containing block when placing child frames.

Fixes #2476.
liam-milbel added a commit to Milestone-Belanova/dompdf that referenced this issue Sep 16, 2021
* Moving the PDF version to a `const`

* Remove unused import

* Coding standards: Enable more PSR-2 rules

Enable rules which should be uncontroversial and easy to fix.

* Apply coding-standards changes to files

* Travis: Also check tests dir for coding standards

* Update IMagick version check logic

fixes dompdf#1296

* Fix scoping issue for IMagick version check

* fix Trying to access array offset on value of type null (dompdf#2227)

* fix Trying to access array offset on value of type null

* space

* fix css selector issue

* Fall back to decimals for roman numerals, if out of range

Consistent with how web browsers do it.

See https://en.wikipedia.org/wiki/Roman_numerals#Standard_form

* Stylesheet: Rename and document `_image` method for clarity

* Stylesheet: Make `resolve_url` public to reduce code duplication

* FontMetrics: Fix text-width calculations when using different backends

Fixes issue dompdf#2403.

* FontMetrics: Use direct access for protected properties

* Extend tests for resolving URLs in stylesheets

Without `$sheet->set_base_path(__DIR__)`, the stylesheet location would
be the location of phpunit.

* Fix instantiating CPDF Adapter without Dompdf

* Avoid offset error in CPDF line trasparency logic

related to dompdf#2227

* Use strict comparison in CPDF transparency logic

* Stylesheet: Improve return-value check

* Remove temporary file created when caching an image. (dompdf#2411)

* Remove temporary file created when caching an image.
dompdf#2377

* move unlink() to exception catch block

* Fix text-width calulation with letter spacing (dompdf#2414)

* Consistent doc for `get_text_width` arguments

To clear up the confusion about whether word and char spacing can be
float.

* CPDF: Fix text-width calulation with letter spacing

The letter spacing was counted twice for every space character.

* PDFLib: Fix text-width calculation with letter spacing

See discussion in dompdf#2414.

* Use OS-indepenent file path for unit test

* BlockFrameReflower: Always resolve `auto` widths

* Fix undefined variable (dompdf#2466)

* Bump version to 0.8.6

* Reset version string to commit hash

* Bump version to 1.0.1

* Reset version string to commit hash

* Bump version to 1.0.2

* Reset version string to commit hash

* Fix undefined variable

* Fix indentation

* Fix undefined variable

* Update src/FontMetrics.php

* Update src/FontMetrics.php

Co-authored-by: Brian Sweeney <brian@eclecticgeek.com>

* Add support for `page-break-before/-after` on table rows

pr dompdf#2512:

* Fix some typos

* Update documentation text for `_page_break_allowed`

Mainly to clear up a few unclear points that have changed. The comment
about table headers does not apply anymore.

* Add support for `page-break-before/-after` on table rows

Caveat: `page-break-after: always` does not work if the row is the last
of its table row group. I want to keep things simple now; this might be
better fixed in a proper rework of the page-break-properties handling,
e.g. by properly propagating the property values as per
https://www.w3.org/TR/css-break-3/#break-propagation.

Fixes dompdf#329

* BlockFrameReflower: Fixes to height calculations (dompdf#2511)

Brings the code closer to the spec:
* Always resolve `auto` heights
* Apply `min-/max-height` independently of the `overflow` property
value
* `min-height` overrules `max-height` (swapping removed)

* Prevent case exception in text renderer (dompdf#2423)

In case of " auto " width is throws an error as following and breaks the PDF render.
ErrorException: A non-numeric value encountered in /Path_To_Project/vendor/dompdf/dompdf/src/Renderer/Text.php:158

type casting the $width to float will prevent the ErrorException

* Resolve auto margins in more cases (dompdf#2531)

Fixes dompdf#1482

* Properly skip checking for page breaks on empty text nodes (dompdf#2506)

Before, page breaks before empty text nodes were not allowed, but they
were still checked; and as they report their line height as the space
needed, they could force a page break, which then would continue to
search backwards in the tree for an element that allowed a page break
(even though it would fit on the current page).

Based on work in dompdf#1356
Fixes dompdf#2468

* Fix table column widths after page break (dompdf#2502)

Node attributes are always string, so when a table was laid out, and
then a page break occurred before the table at a later point, `$colspan`
and `$rowspan` would always be string values and fail the checks below,
most notably the check where the minimum column width is set, so that
all columns received `0` minimum width.

Fixes dompdf#2395

* Add support for any inline-positioned frames in text alignment

This notably adds support for inline-block.

Fixes dompdf#1761

* Fix `justify` text alignment with letter spacing

The old logic seemed to correct for wrong text-width calculation
involving letter spacing when using the CPDF backend. With the fix in
dompdf#2414 this is no longer needed.

* Improve support for relative positioning

* Move handling of relative positioning to after the reflow process, so
that it does not affect layout.
* Handle `right` and `bottom` properties plus `auto` values (except for
RTL language support, which is an easy FIXME).
* As a side-effet, this adds support for relative positioning on inline
and inline-block elements.

Fixes dompdf#516

* Fix logic error in `add_frame_to_line` function

The block must check its own content-box width, not the content-box
width of its containing block when placing child frames.

Fixes dompdf#2476.

* Apply line shift to justified lines with break

* Tweak Style border/outline method color handling

fixes dompdf#2367

* BlockFrameReflower: Fix handling of `100%` width

The condition is wrong, as an `auto` width can resolve to more than
100% if the minimum width of the content is larger.

* BlockFrameReflower: Remove swapping of `min-/max-width`

Per spec, `min-width` overrules `max-width`.

https://www.w3.org/TR/CSS21/visudet.html#min-max-widths

* Remove erroneous ‘degenerate’ case handling in `get_min_max_width`

If the frame has no children, it might still have a fixed width set.

Fixes dompdf#2366

* Small code cleanups (dompdf#2547)

* Clean up `get_margin_height/width` functions

For simplicity, return a `float` value consistently.
The `get_break_margins` method was unused.

* TextReflower: Small cleanup for `get_min_max_width`

Also, add type declarations to `_collapse_white_space`.

* Clean up `split` method signatures

Consistent argument names and more type declarations.

Co-authored-by: Thomas Landauer <thomas@landauer.at>
Co-authored-by: Till Berger <till@mellthas.de>
Co-authored-by: Brian Sweeney <brian@eclecticgeek.com>
Co-authored-by: Edwin Manuel Cerrón Angeles <xerron.angels@gmail.com>
Co-authored-by: Ion Bazan <ion.bazan@gmail.com>
Co-authored-by: bradbulger <1234634+bradbulger@users.noreply.github.com>
Co-authored-by: Jáchym Toušek <enumag@gmail.com>
Co-authored-by: Madi <mudasser.ismail@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants