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

Support "inherit" in CSS rules #217

Open
alpha0010 opened this issue Jun 7, 2021 · 10 comments
Open

Support "inherit" in CSS rules #217

alpha0010 opened this issue Jun 7, 2021 · 10 comments
Labels

Comments

@alpha0010
Copy link

The top half of all symbols from a score generated with Verovio are cut off.

Expected: expected render

Actual: actual render

SVG file: thesvg.svg.zip

@BigBadaboom BigBadaboom added the bug label Jun 9, 2021
@BigBadaboom
Copy link
Owner

Thanks for the report.

I remember seeing you post this recently on Stack Overflow, and I was hoping that my library didn't have this bug. : Oh well :0

I'll take a look.

@alpha0010
Copy link
Author

If helpful to you, I determined text alignment issue appears to be related to nested tspan elements. Flattening the hierarchy resolved the issue for me. (Not particularly sure why the font size is larger though.)

    for (node in svgXml.xPath("//*[local-name()=\"text\"]")) {
      val textNodes = recurseGetTextNodes(node, emptyMap())
      if (textNodes.isEmpty()) {
        continue
      }

      for (tspan in node.elementsOfType("tspan")) {
        node.removeChild(tspan)
      }
      for (textNode in textNodes) {
        node.appendChild(textNode)
      }
    }

// [...]

  private fun recurseGetTextNodes(elem: Node, parentAttr: Map<String, String>): List<Element> {
    val children = elem.elementsOfType("tspan").toList()
    if (children.isEmpty()) {
      if (elem.textContent.isBlank()) {
        return emptyList()
      }
      val textNode = elem.ownerDocument.createElement("tspan")
      textNode.appendChild(elem.ownerDocument.createTextNode(elem.textContent))
      for ((attr, attrValue) in parentAttr) {
        textNode.setAttribute(attr, attrValue)
      }
      return listOf(textNode)
    }

    val output = mutableListOf<Element>()
    for (child in children) {
      val textNodes = recurseGetTextNodes(
        child,
        mergeTextAttributes(child, parentAttr)
      )
      output.addAll(textNodes)
    }
    return output
  }

  private fun mergeTextAttributes(
    node: Node,
    parentAttr: Map<String, String>
  ): Map<String, String> {
    val knownAttrs =
      arrayOf("x", "y", "font-family", "font-size", "font-style", "text-anchor", "class")
    val output = mutableMapOf<String, String>()
    for (attr in knownAttrs) {
      val attrValue = node.attributes.getNamedItem(attr)?.textContent ?: parentAttr[attr]
      if (attrValue != null) {
        output[attr] = attrValue
      }
    }
    return output
  }

@BigBadaboom
Copy link
Owner

Hi. Thanks for the research and the clues.

  • I assume by "text alignment issue", you mean the mis-aligned title text?

  • I'm pretty sure the font size issue is due to different fonts being used. Your SVG specifies font-family: Times;. However, Android SVG doesn't know what that font is, since Times isn't a standard Android system font. You can fix that by copying the Times font to your app's assets directory (as Times.ttf). Then add the following to your app before you render the SVG:

    SVG.registerExternalFileResolver(new SimpleAssetResolver(context.getAssets()));
    

    The test should render correctly then. Do the same for any other fonts one of your SVGs may need

  • Other than the clipped note shapes, is there anything else wrong that I am missing? I see there seems to be stuff missing from the bottom of the page. Is that actually missing, or is it just not included in your screenshot?

Paul

@alpha0010
Copy link
Author

Yes, alignment referred to the title text.

Adding the Times font did not change anything, best as I could tell. (I did add a symbolic font, which fixed the "symbol missing empty box" render issue I had with some other files.)

Oops, I just pulled it into GIMP to generate a png, without checking the results very well. Apparently this is a difficult SVG to render. Here is a better screenshot. Clipped note shapes and text alignment (and maybe font size? potentially something on my end?) are the issues I am having.

expected-render

@alpha0010
Copy link
Author

Traced down the font issue. Appears CSS styles did not propagate the font-family to the main text. Creating an explicit rule renderOptions.css(".text { font-family: Times; }") fixed that.

@alpha0010
Copy link
Author

Likely related: Kozea/CairoSVG#300

@BigBadaboom
Copy link
Owner

BigBadaboom commented Jul 21, 2021

Yes. You're right. AndroidSVG's CSS code doesn't support "inherit" yet. Mainly because - as that commenter said - it requires quite a bit of work,. And "inherit" is something that is rarely used.

Is that person's solution something that would work for you?

@alpha0010
Copy link
Author

A different renderer I was also using had no support for symbol elements. Scripting a conversion of symbols into multiple path defs, one for each different transform used of the specified symbol, resolved my issue (both for this library and the other renderer).

@alpha0010
Copy link
Author

So, I am not dealing with the problems mentioned here anymore. (Up to you if you want to close this issue or not.)

@BigBadaboom BigBadaboom changed the title Symbols truncated in render Support "inherit" in CSS rules Jul 21, 2021
@BigBadaboom
Copy link
Owner

Thanks for letting me know. I'll leave this around for now, and treat it as a feature request for "inherit" support.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants