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
Implement textLength support #160
Conversation
- `textLength` implementations differ between browsers, this uses the Firefox convention where it is applied to a `<text>` element (and _not_ to individual `<tspan>`s) - Compile time flag sets whether to use the Firefox convention of inserting a charSpace after the final character, or the Chrome convention of not doing so. Currently uses Chrome convention. - Adds a new unit test also
- If `xml:space="default"` then treats any prefixed 'space-like' characters as being a single character of length 1 when calculating charSpace - Also include the updated `tests.js` file
} | ||
if (i === tSpanCount - 1) { | ||
if (i === this.element.childNodes.length - 1) { |
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.
I think this line was originally a bug as this.element.childElementCount
(tSpanCount
) doesn't always equal this.element.childNodes.length
. Given this loop is over this.element.childNodes
, it makes sense to use the latter when checking for the last element in the array!
I think this is what is causing the tests to fail, however.
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.
I agree, this should be this.element.childNodes.length - 1
. The tests still fail, though, if I change this back to tSpanCount
. Could you investigate why? If the changes are only minor floating point differences, you may override the reference PDF files.
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.
Thanks for this PR! A couple of things:
- The
textLength
attribute is also allowed ontSpan
elements. Did you consider this? I think this is not too important for now, but if you have time you may have a look at this. - Could you add test cases with
x
andy
attributes ontSpans
? - Maybe we should add a comment to the
spec.svg
that Chrome doesn't render this file correctly. As far as I can see, Firefox does a better job.
src/nodes/text.ts
Outdated
@@ -123,8 +150,11 @@ export class TextNode extends GraphicsNode { | |||
if (xmlSpace === 'default') { | |||
if (i === 0) { | |||
trimmedText = trimLeft(trimmedText) | |||
if (originalText.match(/^[(\n\r)|(\t)| ]/)) { |
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.
I think this regex and the others should be /^[\n\r\t ]/
or even /^\s/
} | ||
if (i === tSpanCount - 1) { | ||
if (i === this.element.childNodes.length - 1) { |
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.
I agree, this should be this.element.childNodes.length - 1
. The tests still fail, though, if I change this back to tSpanCount
. Could you investigate why? If the changes are only minor floating point differences, you may override the reference PDF files.
Although the SVG spec states that it's allowed on For example, this is how the following SVG is rendered in both Firefox and Chrome:
The PR matches Firefox and it I think it would be significant additional work to also implement the Chrome behaviour. I'll add a test case that includes this example and also ones that set I'll also verify what's causing the checks to fail, there should be no changes to any elements that don't have a |
After resetting back to using
Switching back to I've also changed the regex and included a test case that sets |
It appears that my machine generates different reference PDFs to the test server... I've pushed the reference PDFs that make all tests pass, but it seems the server generates different PDFs. Could this be because I'm running Windows? I've deleted and reinstalled all node packages and still all my tests pass. Strange goings on indeed. |
6c88ddb
to
0718d6b
Compare
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.
Alright, looks good now. I updated the references on my machine, lets see if that helps.
Seems like it did... thanks for this PR :) |
Great, thanks for merging! Is there a road-map for when the next release will be made? |
I would like to coordinate this release with the next jsPDF release, which I will hopefully be able to release within the next 2-3 weeks or so. |
@Mrfence97 - thank you very much for the great work and your contribution! 'would love to see more quality PR requests. Let us know if there is a way we can say thank you and provide you with more awesome tasks ;-) |
This PR adds support for the
textLength
attribute for<text>
nodes, solving issue #69.The length is set by inserting appropriate spaces of length
charSpace
between characters. To calculatecharSpace
, the length ('default length') of the text is calculated usingmeasureTextWidth()
as iftextLength
wasn't applied.The implementation when the
<text>
node just contains plain text is straightforward. However, if<tspan>
s are present, the implementation is more complicated to account for e.g. different font sizes, as the default length must be calculated for each<tspan>
at a time and then summed. Note this means thatTextChunk
s aren't immediatelyput()
to the PDF when a new chunk starts, instead they are stored in an array so these width calculations can occur beforehand.Note
textLength
implementations differ between browsers, this PR follows the Firefox implementation:Firefox
textLength
is applied to a<text>
element and all child<tspans>
are scaled to fit within the 'global' length.dx
or an absolutex
on a<tspan>
has no impact on thecharSpace
.xml:space="default"
any space/tab/newline characters present at the very start of the text are treated as a single character when calculatingcharSpace
, but not rendered as such.Chrome (not implemented, only for reference)
textLength
is applied to individual<tspan>
s.dx
or an absolutex
impactscharSpace
as the 'default length' is increased by the dx amount.xml:space="default"
any space/tab/newline characters present are trimmed and not displayed or factored into thecharSpace
calculation.