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

Custom fonts in a jar #152

Open
smogg opened this issue Dec 6, 2017 · 10 comments
Open

Custom fonts in a jar #152

smogg opened this issue Dec 6, 2017 · 10 comments

Comments

@smogg
Copy link

smogg commented Dec 6, 2017

I'm trying to load custom fonts while running my project as packaged jar:

(g2d/g2d-register-fonts [[(-> "public/fonts/" io/resource .getPath) false]])

That doesn't seem to be working (probably cause fonts are bytestreams now?).
Does clj-pdf currently supports this (without creating temp dirs to give it an actual file or something like that?)

@yogthos
Copy link
Collaborator

yogthos commented Dec 6, 2017

The fonts are looked up relative to the filesystem by this piece of code that's called from here when the font is resolved. So, it doesn't look like there's a way to read the font directly from the jar unfortunately.

@smogg
Copy link
Author

smogg commented Dec 6, 2017

Hmm... I tracked it down to this if statement breaking the chain:

if (!file.exists() || !file.isDirectory())

It gets an url in an absolute format: file:/Users/username/project-name/target/uberjar/project-name-0.1.0-SNAPSHOT-standalone.jar!/public/fonts/

Is there something we could maybe change in this code or am I totally off? I'm not familiar with Java.

I manually inspected the .jar file and the fonts folder is at the specified path

@yogthos
Copy link
Collaborator

yogthos commented Dec 6, 2017

Yeah it should be possible to add support for reading from an input stream, however that part of the code only deals with reading the filenames. Also need to track down places where the content gets read when the font is used. I'll try take a look when I get a chance, but if you're feeling brave in the meantime I can help with a PR as well.

@smogg
Copy link
Author

smogg commented Dec 6, 2017

Sure, if you've got patience for it then I'm happy to give it a try. I'll dig deeper tomorrow. Thanks

edit: I've been busy today, I might get to it closer to the weekend.

@yogthos
Copy link
Collaborator

yogthos commented Dec 7, 2017

sounds like a plan

@smogg
Copy link
Author

smogg commented Dec 7, 2017

I think I may have misdiagnosed the problem from the beginning.
Here's what I was trying to do originally:

(g2d/g2d-register-fonts [[(-> "fonts/" io/resource .getPath) false]])

;; later when generating the pdf
[:graphics {:under true :translate [0 200]}
       (fn [g2d]
         (doto g2d
           (.setFont (java.awt.Font. "Strato" java.awt.Font/PLAIN 20))
           (.drawString "Testing Graphics" 20 160)))]

And it worked with lein run but not with java -jar ....
What I missed is the fact that I had the "Strato" font installed in the system, which is why the java.awt.Font. was able to pick it up.
I presume this is not the right way to use custom fonts with [:graphics] element?

As for other elements, ie: [:paragraph {:ttf-name "...."}], it appears to be working even from a jar.
I created an example project here https://github.com/smogg/custom-font-test
The output/ folder contains a PDF created with lein run and with java -jar ... (from outside of the project dir to make sure resources/fonts folder is not available).

When you run the test project I also print (g2d/get-font-maps), which correctly displays fonts when lein run (even tho my [:graphics] still looks like a default font) and prints empty map I run the jar.

@yogthos
Copy link
Collaborator

yogthos commented Dec 8, 2017

Ah so that's mostly good news then if it's a problem specific to the graphics element. The java.awt.Font construction looks right, but perhaps the fonts for awt have to be registered differently. You could try using:

(java.awt.Font/createFont java.awt.Font/TRUETYPE_FONT font-input-stream)

@smogg
Copy link
Author

smogg commented Dec 8, 2017

Yeah, I've came up with similar code:

    (defn graphics-env []
      (.. java.awt.GraphicsEnvironment
          getLocalGraphicsEnvironment))

    (let [font (java.awt.Font/createFont java.awt.Font/TRUETYPE_FONT (io/input-stream (io/resource "fonts/Strato-linked.ttf")))]
      (.registerFont (graphics-env) font)
      (println (.getAvailableFontFamilyNames (graphics-env )))) ;; font is available

But using it by name, later on, doesn't seem to be working. But I think we are getting closer. It's late in my timezone so I'll continue investigating tomorrow.

@smogg
Copy link
Author

smogg commented Dec 8, 2017

Ok, I feel like this is above me. I've tried a lot of things, I see fonts registered but have no idea how to use them without calling the DefaultFontMapper/insertDirectory method, which doesn't work when running from a jar. I tried creating new java.awt.Font's like above, but they don't work if not registered. I tried using FontFactory/getFont but .setFont expects java.awt.font type. I give up for now and will probably use a temp directory with g2d-register-fonts unless you have some pointers?

@yogthos
Copy link
Collaborator

yogthos commented Dec 9, 2017

I can't really think of much else that you could do here unfortunately.

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

No branches or pull requests

2 participants