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

[JEWEL-746] Load inline markdown images using Coil3 #2924

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

obask
Copy link
Collaborator

@obask obask commented Jan 21, 2025

It supports every image as an inline node

@rock3r rock3r self-requested a review January 21, 2025 17:18
@obask obask force-pushed the images branch 3 times, most recently from b0ba3c3 to 7fdb5ac Compare January 23, 2025 15:31
@obask
Copy link
Collaborator Author

obask commented Jan 24, 2025

Screenshot 2025-01-24 at 1 19 26 PM
Screenshot 2025-01-24 at 1 19 31 PM
currently there are 2 differences with a JCEF render: JCEF renders SVG as a giant image while we keep it small(I guess it just depends on a default size parameter), and the text in build|failing is not shown for some reason...

@rock3r
Copy link
Collaborator

rock3r commented Jan 24, 2025

They look like entirely different images... Are you sure it's the same image it's being displayed, and that it's loading correctly in the first case? That to me looks like a "broken image" placeholder (which also is way too big)

SVG files have an intrinsic size declared in their root node, and any renderer should adhere to that

@obask
Copy link
Collaborator Author

obask commented Jan 24, 2025

images I posted earlier are examples of how JCEF renders my "README.md" which this is how compose shows the same things:
Screenshot 2025-01-24 at 3 27 15 PM
README.md

@rock3r
Copy link
Collaborator

rock3r commented Jan 27, 2025

I see. I had misinterpreted the original message, sorry 🙏

The first image (the broken square) has a declared size of 800x800 px, encoded as width="800px" height="800px", which browsers seem to accept but maybe the Compose renderer doesn't like, and falls back to the viewBox size of 16x16. That would explain why it's larger on JCEF.

As for the latter, I think it's because the text for whatever reason just doesn't get rendered:

<g text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
    <use x="5.5" y="2" fill="#010101" fill-opacity=".3" href="#logo" />
    <use x="5.5" y="1" fill="#fff" href="#logo" />
  <text x="40.5" y="15" fill="#010101" fill-opacity=".3">build</text>
  <text x="40.5" y="14" fill="#fff">build</text>
  <text x="83.5" y="15" fill="#010101" fill-opacity=".3">passing</text>
  <text x="83.5" y="14" fill="#fff">passing</text>
</g>

Again, possibly some unsupported value in there that Skia ignores.

That's sort of weird since Skia can interpret image sizes with units, and render text — it does in Chrome! But maybe there is some setup that is missing, or Chrome does some magic stuff. Either way, these are either CMP or Skiko bugs :)

@obask obask changed the title [JEWEL-TBD] Load markdown images using Coil3 [JEWEL-327] Load markdown images using Coil3 Jan 31, 2025
@obask obask changed the title [JEWEL-327] Load markdown images using Coil3 [JEWEL-746] Load inline markdown images using Coil3 Jan 31, 2025
@obask
Copy link
Collaborator Author

obask commented Jan 31, 2025

@obask obask marked this pull request as ready for review January 31, 2025 13:26
@obask
Copy link
Collaborator Author

obask commented Jan 31, 2025

The first image (the broken square) has a declared size of 800x800 px, encoded as width="800px" height="800px", which browsers seem to accept but maybe the Compose renderer doesn't like, and falls back to the viewBox size of 16x16. That would explain why it's larger on JCEF.

As for the latter, I think it's because the text for whatever reason just doesn't get rendered:

Again, possibly some unsupported value in there that Skia ignores.

I'm going to create a separate issue for SVG regressions. Should it go to youtrack?

@rock3r
Copy link
Collaborator

rock3r commented Jan 31, 2025

Should it go to youtrack?

Please, no. Stick with GH until further notice. You'll know together with everyone else when YT is usable. We're still waiting.

@@ -76,6 +80,7 @@ public fun Markdown(
markdownStyling: MarkdownStyling = JewelTheme.markdownStyling,
blockRenderer: MarkdownBlockRenderer = DefaultMarkdownBlockRenderer(markdownStyling),
) {
setSingletonImageLoaderFactory(::createImageLoader)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this belong here? It feels like it's init code, so having it once only (e.g., in ProvideMarkdownStyling?) would make more sense to me

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ProvideMarkdownStyling is in a different module and it's not guaranteed that a user will wrap Markdown into a style provider, so it may be confusing for debugging.
Will it attempt to invoke this code on each rerender or on each markdown usage in the app? I don't mind moving it somewhere, I just haven't figured out how exactly.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will it attempt to invoke this code on each rerender or on each markdown usage in the app?

It won't attempt to invoke, it will invoke it. That's why I'm saying it'd make more sense to do it elsewhere. I think we should even consider not using a singleton factory since users may want to use different ones; can we create one that we store in a composition local, and set it up in ProvideMarkdownStyling?

We can instruct users to use ProvideMarkdownStyling in the error message for when the composition local is not set up, like we do for other mandatory composition locals.

.build(),
contentDescription = image.title,
onSuccess = { state ->
if (knownSize.value == null) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the check needed? I'd imagine whatever we get in onSuccess we only get once anyway...

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since changing knownSize.value could trigger re rendering, it's better to be safe than end up in an infinite loop. Here is serves the goal of changing the placeholder.

@rock3r
Copy link
Collaborator

rock3r commented Feb 6, 2025

Out of curiosity, have you filed the issues for SVG rendering?

I think the size one is caused by https://github.com/coil-kt/coil/blob/main/coil-svg/src/commonMain/kotlin/coil3/svg/SvgDecoder.kt#L39 this parameter being true by default. Ideally, users should be able to override the Coil loader with one they want, but we can keep it for a follow up (it'd be nice to have an issue tracking this in our YouTrack, if you can file it).

The text one is the more baffling one. If you can look into it, maybe you can figure out what is the cause, or at least where it should happen, and file an issue for that in the right place.

@rock3r rock3r added the jewel label Feb 11, 2025
@rock3r
Copy link
Collaborator

rock3r commented Feb 11, 2025

@obask ping

@obask
Copy link
Collaborator Author

obask commented Feb 12, 2025

Out of curiosity, have you filed the issues for SVG rendering?

Thanks for doing initial investigation. I filed a tracking issue, but not the one in a coil repository yet.
https://youtrack.jetbrains.com/issue/JEWEL-762/Coil-image-rendering-issues-with-SVG

@obask obask force-pushed the images branch 3 times, most recently from 97a2f31 to 96b68a0 Compare February 12, 2025 17:14
It supports every image as an inline node;
Using built-in coroutine library and ktor2 from the platform;
Added SVG support using a coil dependency.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants