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

wrong export from Highcharts svg with outlined text/ #192

Open
inc198107 opened this issue Nov 11, 2021 · 13 comments
Open

wrong export from Highcharts svg with outlined text/ #192

inc198107 opened this issue Nov 11, 2021 · 13 comments
Labels
bug difficulty:medium help wanted Help with creating a proper test-case, looking up the spec, or creating a pull request.

Comments

@inc198107
Copy link

inc198107 commented Nov 11, 2021

When export from chart with outlined text (nested tSpan used) cintent is duplicated.
screenshot

after some debugging svg2pdf library i am founded cause of described bug,
it is part of code in textchunk.ts that set x coordinate of tSpan (string 111 - 112 )
image
after described changes everything works fine
screenshot after string commented

(sorry for my weak english)

Angular 10,
Highcharts 9.2.1 ,
jsPDF 2.4.0,
svg2pdf 2.2.0
Chrome 91.0.4472.124 (Official Build) (64-bit)

that used svg:

<svg version="1.1" class="highcharts-root" style="font-family:&quot;Lucida Grande&quot;, &quot;Lucida Sans Unicode&quot;, Arial, Helvetica, sans-serif;font-size:12px;" xmlns="http://www.w3.org/2000/svg" width="1431" height="646" viewBox="0 0 1431 646"> <desc>Created with Highcharts 9.1.2</desc> <defs><clipPath id="highcharts-97af60ab-ef02-e850-0b0f-90b8ffebf2a5"> <rect x="0" y="0" width="1411" height="550" fill="none"></rect> </clipPath></defs><rect fill="#ffffff" class="highcharts-background" x="0" y="0" width="1431" height="646" rx="0" ry="0"></rect><rect fill="none" class="highcharts-plot-background" x="10" y="40" width="1411" height="550"></rect><g class="highcharts-grid highcharts-xaxis-grid" data-z-index="1"></g><g class="highcharts-grid highcharts-yaxis-grid" data-z-index="1"></g><rect fill="none" class="highcharts-plot-border" data-z-index="1" x="10" y="40" width="1411" height="550"></rect><g class="highcharts-axis highcharts-xaxis" data-z-index="2"><path fill="none" class="highcharts-axis-line" data-z-index="7" d="M 10 590 L 1421 590"></path></g><g class="highcharts-axis highcharts-yaxis" data-z-index="2"><path fill="none" class="highcharts-axis-line" data-z-index="7" d="M 10 40 L 10 590"></path></g><g class="highcharts-series-group" data-z-index="3"><g class="highcharts-series highcharts-series-0 highcharts-treemap-series highcharts-color-0 highcharts-tracker" data-z-index="0.1" transform="translate(10,40) scale(1 1)" clip-path="url(#highcharts-97af60ab-ef02-e850-0b0f-90b8ffebf2a5)"><g class="highcharts-level-group-4" data-z-index="996"><rect x="-0.5" y="-0.5" width="906" height="550" fill="#7cb5ec" stroke="#e6e6e6" stroke-width="1" class="highcharts-point"></rect><rect x="905.5" y="-0.5" width="505" height="550" fill="#7cb5ec" stroke="#e6e6e6" stroke-width="1" class="highcharts-point"></rect></g><g class="highcharts-level-group-3" data-z-index="997"><rect x="-0.5" y="-0.5" width="906" height="550" fill="rgba(124,181,236,0.15)" stroke="#e6e6e6" stroke-width="1" class="highcharts-point highcharts-internal-node-interactive"></rect><rect x="905.5" y="-0.5" width="505" height="550" fill="rgba(124,181,236,0.15)" stroke="#e6e6e6" stroke-width="1" class="highcharts-point highcharts-internal-node-interactive"></rect> </g><g class="highcharts-level-group-2" data-z-index="998"><rect x="905.5" y="-0.5" width="505" height="550" fill="rgba(124,181,236,0.15)" stroke="#e6e6e6" stroke-width="1" class="highcharts-point highcharts-internal-node-interactive"></rect><rect x="-0.5" y="-0.5" width="906" height="550" fill="rgba(124,181,236,0.15)" stroke-width="1" class="highcharts-point highcharts-internal-node-interactive" data-z-index="0" stroke="#e6e6e6"></rect></g> <g class="highcharts-level-group-1" data-z-index="999"><rect x="-0.5" y="-0.5" width="906" height="550" fill="rgba(124,181,236,0.15)" stroke-width="3" class="highcharts-point highcharts-internal-node-interactive" data-z-index="0" stroke="rgb(230,230,230)"></rect> <rect x="905.5" y="-0.5" width="505" height="550" fill="rgba(124,181,236,0.15)" stroke="rgb(230,230,230)" stroke-width="3" class="highcharts-point highcharts-internal-node-interactive" data-z-index="0"></rect></g></g> <g class="highcharts-markers highcharts-series-0 highcharts-treemap-series highcharts-color-0" data-z-index="0.1" transform="translate(10,40) scale(1 1)"></g> </g><text x="716" text-anchor="middle" class="highcharts-title" data-z-index="4" style="color:#333333;font-size:18px;fill:#333333;" y="24"></text> <text x="716" text-anchor="middle" class="highcharts-subtitle" data-z-index="4" style="color:#666666;fill:#666666;" y="24"></text> <text x="10" text-anchor="start" class="highcharts-caption" data-z-index="4" style="color:#666666;fill:#666666;" y="643"></text> <g class="highcharts-data-labels highcharts-series-0 highcharts-treemap-series highcharts-color-0 highcharts-tracker" data-z-index="6" transform="translate(10,40) scale(1 1)" opacity="1"> <g class="highcharts-label highcharts-data-label highcharts-data-label-color-undefined" data-z-index="1" transform="translate(0,-9999)"><text x="5" data-z-index="1" y="16" style="color:#000000;font-size:11px;font-weight:bold;fill:#000000;"> <tspan class="highcharts-text-outline" fill="#FFFFFF" stroke="#FFFFFF" stroke-width="2px" stroke-linejoin="round" style="">-<tspan x="5" y="16">​</tspan></tspan>-</text></g> <g class="highcharts-label highcharts-data-label highcharts-data-label-color-undefined" data-z-index="1" transform="translate(1134,263)"><text x="5" data-z-index="1" y="16" style="color:#000000;font-size:11px;font-weight:bold;fill:#000000;"> <tspan class="highcharts-text-outline" fill="#FFFFFF" stroke="#FFFFFF" stroke-width="2px" stroke-linejoin="round">POWER<tspan x="5" y="16">​</tspan></tspan>POWER</text></g><g class="highcharts-label highcharts-data-label highcharts-data-label-color-undefined" data-z-index="1" transform="translate(0,-9999)" opacity="0"><text x="5" data-z-index="1" y="16" style="color:#000000;font-size:11px;font-weight:bold;fill:#000000;"><tspan class="highcharts-text-outline" fill="#FFFFFF" stroke="#FFFFFF" stroke-width="2px" stroke-linejoin="round" style="">OTHER<tspan x="5" y="16">​</tspan></tspan>OTHER</text></g><g class="highcharts-label highcharts-data-label highcharts-data-label-color-undefined" data-z-index="1" transform="translate(436,263)"><text x="5" data-z-index="1" y="16" style="color:#000000;font-size:11px;font-weight:bold;fill:#000000;"><tspan class="highcharts-text-outline" fill="#FFFFFF" stroke="#FFFFFF" stroke-width="2px" stroke-linejoin="round">GAS<tspan x="5" y="16">​</tspan></tspan>GAS</text></g></g><g class="highcharts-legend highcharts-no-tooltip" data-z-index="7" transform="translate(554,602)"><rect fill="none" class="highcharts-legend-box" rx="0" ry="0" x="0" y="0" width="322" height="29" visibility="visible"></rect><g data-z-index="1"><g><g class="highcharts-legend-item highcharts-treemap-series highcharts-color-0 highcharts-series-0" data-z-index="1" transform="translate(8,3)"><text x="21" style="color:#333333;cursor:pointer;font-size:12px;font-weight:bold;fill:#333333;" text-anchor="start" data-z-index="2" y="15">Data Set 1 Ad-hoc/UMM Count (Affected asset)</text><rect x="2" y="4" width="12" height="12" fill="#7cb5ec" rx="6" ry="6" class="highcharts-point" data-z-index="3"></rect></g></g></g></g><g class="highcharts-axis-labels highcharts-xaxis-labels" data-z-index="7"></g><g class="highcharts-axis-labels highcharts-yaxis-labels" data-z-index="7"></g><g class="highcharts-label highcharts-tooltip highcharts-color-0" style="cursor:default;white-space:nowrap;pointer-events:auto;padding:0;" data-z-index="8" transform="translate(993,-9999)" opacity="0" visibility="hidden"><path fill="none" class="highcharts-label-box highcharts-tooltip-box highcharts-shadow" d="M 3 0 L 347 0 C 350 0 350 0 350 3 L 350 72 C 350 75 350 75 347 75 L 181 75 L 175 81 L 169 75 L 3 75 C 0 75 0 75 0 72 L 0 3 C 0 0 0 0 3 0" stroke="#000000" stroke-opacity="0.049999999999999996" stroke-width="5" transform="translate(1, 1)"></path><path fill="none" class="highcharts-label-box highcharts-tooltip-box highcharts-shadow" d="M 3 0 L 347 0 C 350 0 350 0 350 3 L 350 72 C 350 75 350 75 347 75 L 181 75 L 175 81 L 169 75 L 3 75 C 0 75 0 75 0 72 L 0 3 C 0 0 0 0 3 0" stroke="#000000" stroke-opacity="0.09999999999999999" stroke-width="3" transform="translate(1, 1)"></path><path fill="none" class="highcharts-label-box highcharts-tooltip-box highcharts-shadow" d="M 3 0 L 347 0 C 350 0 350 0 350 3 L 350 72 C 350 75 350 75 347 75 L 181 75 L 175 81 L 169 75 L 3 75 C 0 75 0 75 0 72 L 0 3 C 0 0 0 0 3 0" stroke="#000000" stroke-opacity="0.15" stroke-width="1" transform="translate(1, 1)"></path><path fill="rgba(247,247,247,0.85)" class="highcharts-label-box highcharts-tooltip-box" d="M 3 0 L 347 0 C 350 0 350 0 350 3 L 350 72 C 350 75 350 75 347 75 L 181 75 L 175 81 L 169 75 L 3 75 C 0 75 0 75 0 72 L 0 3 C 0 0 0 0 3 0"></path></g><g class="bread" data-z-index="10" transform="translate(11,5)"><path fill="transparent" class="highcharts-label-box" d="M 5 0 L 64 0 C 69 0 69 0 69 5 L 69 23 C 69 28 69 28 64 28 L 5 28 C 0 28 0 28 0 23 L 0 5 C 0 0 0 0 5 0"></path><text x="5" data-z-index="1" y="17">Top Level</text></g></svg>

@HackbrettXXX
Copy link
Member

Thanks for reporting this bug. Could you reduce your SVG to only what's necessary to reproduce the bug?

@inc198107
Copy link
Author

inc198107 commented Nov 12, 2021

It is little bit hard, because svg generated by Highcharts. But problematic part is here : <text x="5" data-z-index="1" y="16" style="color:#000000;font-size:11px;font-weight:bold;fill:#000000;"> <tspan class="highcharts-text-outline" fill="#FFFFFF" stroke="#FFFFFF" stroke-width="2px" stroke-linejoin="round">POWER<tspan x="5" y="16">​</tspan></tspan>POWER</text></g><g class="highcharts-label highcharts-data-label highcharts-data-label-color-undefined" data-z-index="1" transform="translate(0,-9999)" opacity="0"><text x="5" data-z-index="1" y="16" style="color:#000000;font-size:11px;font-weight:bold;fill:#000000;"><tspan class="highcharts-text-outline" fill="#FFFFFF" stroke="#FFFFFF" stroke-width="2px" stroke-linejoin="round" style="">OTHER<tspan x="5" y="16">​</tspan></tspan>OTHER</text></g><g class="highcharts-label highcharts-data-label highcharts-data-label-color-undefined" data-z-index="1" transform="translate(436,263)"><text x="5" data-z-index="1" y="16" style="color:#000000;font-size:11px;font-weight:bold;fill:#000000;"><tspan class="highcharts-text-outline" fill="#FFFFFF" stroke="#FFFFFF" stroke-width="2px" stroke-linejoin="round">GAS<tspan x="5" y="16">​</tspan></tspan>GAS</text>

@HackbrettXXX
Copy link
Member

I've reduced it a bit further (and fixed it):

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500">
  <g>
    <text x="5" y="16" style="color:#000000;font-size:11px;font-weight:bold;fill:#000000;">
      <tspan fill="#FFFFFF" stroke="red" stroke-width="2px" stroke-linejoin="round">POWER
        <tspan x="5" y="16">​</tspan>
      </tspan>
      POWER
    </text>
  </g>
</svg>

This renders to
image

Could you create a pull request? Although we have to test the suggested fix against other text examples. I'm pretty sure, adding the text width there happens for a reason.

@HackbrettXXX HackbrettXXX added bug difficulty:medium help wanted Help with creating a proper test-case, looking up the spec, or creating a pull request. labels Nov 12, 2021
@inc198107
Copy link
Author

ok

@inc198107
Copy link
Author

Unfortunately, I don't have permission to create a new branch in your repository, so I can't make a pull request.

@HackbrettXXX
Copy link
Member

@inc198107
Copy link
Author

inc198107 commented Dec 14, 2021 via email

@karolkolodziej
Copy link

Hi!
Any updates on this issue?
Based on this issue reported in Highcharts I was able to reproduce that in your online playground as:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 150">
  <text x="5" data-z-index="1" y="16" style="color: rgb(0, 0, 0); font-size: 11px; font-weight: bold; fill: rgb(0, 0, 0);">
    <tspan class="highcharts-text-outline" fill="red" stroke="red" stroke-width="2px" stroke-linejoin="round" style="">29.9<tspan x="5" y="16">&ZeroWidthSpace;</tspan>
    </tspan>29.9
  </text>
</svg>

image

@HackbrettXXX
Copy link
Member

There is a PR (#198), but @inc198107 hasn't responded in a while. @karolkolodziej any assistance moving the PR forward would be very welcome.

@inc198107
Copy link
Author

inc198107 commented Apr 8, 2022 via email

@karolkolodziej
Copy link

Thank you for the quick response.

A few comments on the issue and the PR:

  • There are some tests failing with this approach (replacing the calculation with currentTextX = x.
  • This approach(☝️) seems to work in our case but overall it doesn't look like a rounding/float imprecision issue it looks more like an actual error with the calculation.
  • I was able to simplify the code giving such results even more:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 150">
  <text x="8" data-z-index="1" y="16" >
    <tspan class="highcharts-text-outline" fill="red" stroke="red">29.9<tspan x="5" y="16">&ZeroWidthSpace;</tspan>
    </tspan>29.9
  </text>
</svg>
  • It seems that after this PR was introduced.
  • There is an issue with handling the &ZeroWidthSpace. There simply is no case for that in the code.

Perhaps before calculating currentTextX you should check if an element of &ZeroWidthSpace is being introduced.
Pseudocode:

if (textNodeContext === '&ZeroWidthSpace') {
   currentTextX = x
} else {
   currentTextX = x + textMeasure.width + textMeasure.length * charSpace
}

Sorry I can't help more but I'm not entirely familiar with that library and also I'm not sure how to test it...

@inc198107
Copy link
Author

inc198107 commented Apr 9, 2022 via email

@HackbrettXXX
Copy link
Member

@karolkolodziej thanks for doing the tests and for the additional insight.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug difficulty:medium help wanted Help with creating a proper test-case, looking up the spec, or creating a pull request.
Projects
None yet
Development

No branches or pull requests

3 participants