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

[Feature request] Provide a way to use custom fonts and ship a default icon font #522

Open
jbsarrodie opened this issue Sep 3, 2019 · 22 comments

Comments

@jbsarrodie
Copy link
Member

I often use FontAwesome icons in Archi to produce better looking diagrams. This used to be a bit difficult in the past, but this has been simplified a lot with the new version of the FontAwesome OFT/TTF which now use ligatures to make it as easy as writing frogto get a frog icon:

The only issue is that this requires to install the font on every computer running Archi, which is, most of the time, not possible.

It seems that it is possible in JAVA to load a font and make it available to the applicationwithout having to install it in the OS. This would be a great solution in Archi.

I can see several ways of doing it:

  • Ship FontAwsome by default in Archi so anyone using Archi can use it
  • Add a configuration option inside preferences to select font(s) files to load when Archi starts. This would allow users to configure Archi (or create pre-configured packaged) to use needed fonts.

Note: it is easy to create a custom font nowadays, so we could imagine creating an ArchiMate font containing official notation icons, and use it in Archi (instead of code based version as now).

@Phillipus
Copy link
Member

Phillipus commented Sep 7, 2019

Not sure if this is possible if SWT handles loading fonts differently than AWT? Will investigate...

@Phillipus
Copy link
Member

Phillipus commented Sep 10, 2019

I can install a FA font like this:

Display.getDefault().loadFont("Font Awesome 5 Free-Regular-400.otf");

It works.

@Phillipus
Copy link
Member

Add a configuration option inside preferences to select font(s) files to load when Archi starts

Why not set a user fonts folder and Archi scans it when starting for files ending with "OTF" or "TTF"?

@jbsarrodie
Copy link
Member Author

It works.

Great !

Why not set a user fonts folder and Archi scans it when starting for files ending with "OTF" or "TTF"?

Yes, that was the idea. My only concerns/question is: do we ship FontAwsome (or any similar "icon" font) by default with Archi?

Pro: this would allow users to easily add icons inside ArchiMate views and be sure that anybody would see the same thing with plain Archi.
Cons: we create a dependancy that we might not want. Maybe a better optioin would be to have our "AwesomeArchi" Font in which we'll include choosen icons (but then we have to create and manage it)

@jbsarrodie
Copy link
Member Author

For reference, here is a list (that I'll update) of known icon fonts:

icomoon seems really interresting as it allows anyone to compose its own font, set its name and define ligatures. In 2min I was able to create "AwesomeArchi" font:
image

@Phillipus
Copy link
Member

Note - The ligature icon does not export when exporting a diagram as SVG image from Archi.

@Phillipus
Copy link
Member

If the main idea is to use FA then we should only focus on shipping it with Archi and forget the general font path setting. In most other cases a user will install fonts in the OS themselves.

Things to consider:

  • Licencing and redistribution
  • Getting locked into a dependency ("Cons: we create a dependency that we might not want. ")
  • Exporting to SVG image

Maybe a better option would be to have our "AwesomeArchi" Font in which we'll include chosen icons (but then we have to create and manage it)

We could do a POC with just one icon replacing an existing figure icon (before we create the whole 60 icon set ;-))

@Phillipus
Copy link
Member

BTW...

memory

@jbsarrodie
Copy link
Member Author

BTW...

;-) A good friend of mine explained me how to make it visible (who said "easter egg"?)

If the main idea is to use FA then we should only focus on shipping it with Archi and forget the general font path setting. In most other cases a user will install fonts in the OS themselves.

The main idea is twofold:

  • Provide a default/builtin way to use icons from a known set (not going to change at every release) that people can safely rely on.
  • Provide a way for power users to create portable versions of Archi which include some custom fonts (could be in fact icon fonts but also "corporate" fonts). Nowadays in big companies, users have less and less rights on their computer (e.g. in my case: can't install a software, can't install a font, can't use a usb key...)

@Phillipus
Copy link
Member

So let's try a POC with one icon and see how that works in Archi UI and exporting images.

@jbsarrodie
Copy link
Member Author

So let's try a POC with one icon and see how that works in Archi UI and exporting images.

I have better than that! Here is a font created with icomoon which contains most icons from FontAwesome: Archi-FontAwesome-v1.0.zip

I've set the name of the font to "Archi-FontAwesome" so that it doesn't conflict with potentially already installed fonts. In addition, starting with Archi makes sure it is on the top of the list.

The ZIP file contains the font but also a demo page allowing users to see them and easily get the associated ligature.

@Phillipus
Copy link
Member

Provide a default/builtin way to use icons from a known set (not going to change at every release) that people can safely rely on.

How do you reference one icon by a character code to use as an icon instead of the Draw2D code one we have now? (ligature doesn't export in SVG image)

@jbsarrodie
Copy link
Member Author

How do you reference one icon by a character code to use as an icon instead of the Draw2D code one we have now? (ligature doesn't export in SVG image)

For this we have to use the character code. You can find it in the "demo.html" page included with the ZIP (under each icon you have the hexa code on the left and the actual character on the right).

BWT, just to make it clear and avoid misunderstanding: this issue is not about using a font instead of some code to draw figure's icon, simply about helping people use an icon font anywhere they want (labels, notes...). As it is already possible for people to do so, they should already experiment the SVG issue, so I don't consider this a regression but a known "limitation". If we decide to use a font to draw figure's icon (and I'm going to create an issue for this), then we have to take care of SVG rendering and thus have to use character code instead of ligature.

@jbsarrodie jbsarrodie changed the title [Feature request] Ship FontAwesome with Archi [Feature request] Provide a way to use custom fonts and ship a default icon font Sep 13, 2019
@jbsarrodie
Copy link
Member Author

BTW - Doing some research, I discovered this small tool: WinFontsForAll. It can run without admin rights and will make any font usable without prior installation (I've just tested it on a "locked" computer and it works). So this is a potential workaround for users under windows.

So, this doesn't impact my first requirement:

Provide a default/builtin way to use icons from a known set (not going to change at every release) that people can safely rely on.

But this can lead us to challenge the second:

Provide a way for power users to create portable versions of Archi which include some custom fonts (could be in fact icon fonts but also "corporate" fonts). Nowadays in big companies, users have less and less rights on their computer (e.g. in my case: can't install a software, can't install a font, can't use a usb key...)

The use-case behind is to let people create more attractive views using better fonts and icons. Of course, a model should render the same way on all workstations in a team.

I can see 3 different ways to address it:

  1. People use Archi as it is now, and in addition use fonts installed on their system or loaded through tools like WinFontsForAll.
    • Pros: Nothing to implement in Archi, and users can do it already (as proven by my test)
    • Cons: in order for a model to be viewed on another workstation, users have to make sure the right fonts are either installed or loaded through 3rd party tool
    • Workaround: Create a packaged version of Archi that comes with fonts and utilities that must be ran outside Archi
  2. Archi provide an easy way to add register fonts (user defined font folder). That's the scope of this issue.
    • Pros: Small impact on Archi. Users simply have to put the needed fonts into the right folder. It becomes easier for a packaged version of Archi to include such fonts which will be accessible without requiring to run an external tool
    • Cons: Users still have to share the fonts with their models
  3. Archi provides a way to embed fonts into a model (like images are).
    • Pros: Users can share their models without any troubles. Could also be useful for any font (not just icons)
    • Cons: Where do we stop? There is no way to tell if a font is native on an OS or not, so for a model to be really "portable" then we should embed all fonts used (text and icon)!

@jbsarrodie
Copy link
Member Author

Some update...

Archi provide an easy way to add register fonts (user defined font folder). That's the scope of this issue.

I now think the best way to do this is for me to create a custom plugin. This will provide more freedom for people who need it without adding yet another feature to Archi itself.

I expect to share a first version of such plugin next week.

@Phillipus
Copy link
Member

OK, I'm ready to help with that. :-)

@jbsarrodie
Copy link
Member Author

And forgot to add another good icon to the list Numberpile. It works through ligatures, so you simply wrote something like (2) to get the number 2 in a circle. It basically allows to create this kind of things to better explain the flow of data:
image

Of course, this works with the help of other features like:

  • Hide the label of the relationship (BTW, we should now rename the option "Show Label" instead of "Show Name")
  • Define a label which is independant from the name of the concept. This is needed because the number to show makes sens only in the context of one view, not every views.
  • Some scripting to generate a table or legend which provide the name and documentation for each number.

@Phillipus
Copy link
Member

we should now rename the option "Show Label" instead of "Show Name"

866d61e

@jbsarrodie
Copy link
Member Author

we should now rename the option "Show Label" instead of "Show Name"

866d61e

image

@Phillipus
Copy link
Member

We work fast around here, anticipating everything... ;-)

@jbsarrodie
Copy link
Member Author

OK, I'm ready to help with that. :-)

Well...

I've just created a new plugin in https://github.com/archi-contribs/fontloader-plugin

I've tried to load a font (through a local, hard coded path for the moment) in the Activator class but this doesn't work: I can get the DIsplay but when I try to load the font I get this error. It seems that this doesn't work in an Activator. Is there any other extension point I could use to load the font ?

!MESSAGE An error occurred while automatically activating bundle org.archicontribs.fontloader (51).
!STACK 0
org.osgi.framework.BundleException: Exception in org.archicontribs.fontloader.FontLoaderPlugin.start() of bundle org.archicontribs.fontloader.
	at org.eclipse.osgi.internal.framework.BundleContextImpl.startActivator(BundleContextImpl.java:863)
	at org.eclipse.osgi.internal.framework.BundleContextImpl.start(BundleContextImpl.java:791)
	at org.eclipse.osgi.internal.framework.EquinoxBundle.startWorker0(EquinoxBundle.java:1015)
	at org.eclipse.osgi.internal.framework.EquinoxBundle$EquinoxModule.startWorker(EquinoxBundle.java:365)
	at org.eclipse.osgi.container.Module.doStart(Module.java:603)
	at org.eclipse.osgi.container.Module.start(Module.java:467)
	at org.eclipse.osgi.framework.util.SecureAction.start(SecureAction.java:493)
	at org.eclipse.osgi.internal.hooks.EclipseLazyStarter.postFindLocalClass(EclipseLazyStarter.java:117)
	at org.eclipse.osgi.internal.loader.classpath.ClasspathManager.findLocalClass(ClasspathManager.java:571)
	at org.eclipse.osgi.internal.loader.ModuleClassLoader.findLocalClass(ModuleClassLoader.java:330)
	at org.eclipse.osgi.internal.loader.BundleLoader.findLocalClass(BundleLoader.java:398)
	at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:476)
	at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:425)
	at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:417)
	at org.eclipse.osgi.internal.loader.ModuleClassLoader.loadClass(ModuleClassLoader.java:155)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
	at org.eclipse.osgi.internal.framework.EquinoxBundle.loadClass(EquinoxBundle.java:620)
	at org.eclipse.core.internal.registry.osgi.RegistryStrategyOSGI.createExecutableExtension(RegistryStrategyOSGI.java:196)
	at org.eclipse.core.internal.registry.ExtensionRegistry.createExecutableExtension(ExtensionRegistry.java:934)
	at org.eclipse.core.internal.registry.ConfigurationElement.createExecutableExtension(ConfigurationElement.java:246)
	at org.eclipse.core.internal.registry.ConfigurationElementHandle.createExecutableExtension(ConfigurationElementHandle.java:63)
	at org.eclipse.ui.internal.WorkbenchPlugin.lambda$0(WorkbenchPlugin.java:286)
	at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:55)
	at org.eclipse.ui.internal.WorkbenchPlugin.createExtension(WorkbenchPlugin.java:284)
	at org.eclipse.ui.internal.EarlyStartupRunnable.run(EarlyStartupRunnable.java:55)
	at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:45)
	at org.eclipse.ui.internal.Workbench$40.run(Workbench.java:2711)
	at org.eclipse.core.internal.jobs.Worker.run(Worker.java:63)
Caused by: org.eclipse.swt.SWTException: Invalid thread access
	at org.eclipse.swt.SWT.error(SWT.java:4711)
	at org.eclipse.swt.SWT.error(SWT.java:4626)
	at org.eclipse.swt.SWT.error(SWT.java:4597)
	at org.eclipse.swt.widgets.Display.error(Display.java:1434)
	at org.eclipse.swt.widgets.Display.checkDevice(Display.java:929)
	at org.eclipse.swt.graphics.Device.loadFont(Device.java:869)
	at org.archicontribs.fontloader.FontLoaderPlugin.start(FontLoaderPlugin.java:46)
	at org.eclipse.osgi.internal.framework.BundleContextImpl$3.run(BundleContextImpl.java:842)
	at org.eclipse.osgi.internal.framework.BundleContextImpl$3.run(BundleContextImpl.java:1)
	at java.base/java.security.AccessController.doPrivileged(Native Method)
	at org.eclipse.osgi.internal.framework.BundleContextImpl.startActivator(BundleContextImpl.java:834)
	... 27 more
Root exception:
org.eclipse.swt.SWTException: Invalid thread access
	at org.eclipse.swt.SWT.error(SWT.java:4711)
	at org.eclipse.swt.SWT.error(SWT.java:4626)
	at org.eclipse.swt.SWT.error(SWT.java:4597)
	at org.eclipse.swt.widgets.Display.error(Display.java:1434)
	at org.eclipse.swt.widgets.Display.checkDevice(Display.java:929)
	at org.eclipse.swt.graphics.Device.loadFont(Device.java:869)
	at org.archicontribs.fontloader.FontLoaderPlugin.start(FontLoaderPlugin.java:46)
	at org.eclipse.osgi.internal.framework.BundleContextImpl$3.run(BundleContextImpl.java:842)
	at org.eclipse.osgi.internal.framework.BundleContextImpl$3.run(BundleContextImpl.java:1)
	at java.base/java.security.AccessController.doPrivileged(Native Method)
	at org.eclipse.osgi.internal.framework.BundleContextImpl.startActivator(BundleContextImpl.java:834)
	at org.eclipse.osgi.internal.framework.BundleContextImpl.start(BundleContextImpl.java:791)
	at org.eclipse.osgi.internal.framework.EquinoxBundle.startWorker0(EquinoxBundle.java:1015)
	at org.eclipse.osgi.internal.framework.EquinoxBundle$EquinoxModule.startWorker(EquinoxBundle.java:365)
	at org.eclipse.osgi.container.Module.doStart(Module.java:603)
	at org.eclipse.osgi.container.Module.start(Module.java:467)
	at org.eclipse.osgi.framework.util.SecureAction.start(SecureAction.java:493)
	at org.eclipse.osgi.internal.hooks.EclipseLazyStarter.postFindLocalClass(EclipseLazyStarter.java:117)
	at org.eclipse.osgi.internal.loader.classpath.ClasspathManager.findLocalClass(ClasspathManager.java:571)
	at org.eclipse.osgi.internal.loader.ModuleClassLoader.findLocalClass(ModuleClassLoader.java:330)
	at org.eclipse.osgi.internal.loader.BundleLoader.findLocalClass(BundleLoader.java:398)
	at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:476)
	at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:425)
	at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:417)
	at org.eclipse.osgi.internal.loader.ModuleClassLoader.loadClass(ModuleClassLoader.java:155)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
	at org.eclipse.osgi.internal.framework.EquinoxBundle.loadClass(EquinoxBundle.java:620)
	at org.eclipse.core.internal.registry.osgi.RegistryStrategyOSGI.createExecutableExtension(RegistryStrategyOSGI.java:196)
	at org.eclipse.core.internal.registry.ExtensionRegistry.createExecutableExtension(ExtensionRegistry.java:934)
	at org.eclipse.core.internal.registry.ConfigurationElement.createExecutableExtension(ConfigurationElement.java:246)
	at org.eclipse.core.internal.registry.ConfigurationElementHandle.createExecutableExtension(ConfigurationElementHandle.java:63)
	at org.eclipse.ui.internal.WorkbenchPlugin.lambda$0(WorkbenchPlugin.java:286)
	at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:55)
	at org.eclipse.ui.internal.WorkbenchPlugin.createExtension(WorkbenchPlugin.java:284)
	at org.eclipse.ui.internal.EarlyStartupRunnable.run(EarlyStartupRunnable.java:55)
	at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:45)
	at org.eclipse.ui.internal.Workbench$40.run(Workbench.java:2711)
	at org.eclipse.core.internal.jobs.Worker.run(Worker.java:63)

@Phillipus
Copy link
Member

I've just created a new plugin in https://github.com/archi-contribs/fontloader-plugin

I'm on it. Let's track this on that issue tracker...

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

No branches or pull requests

2 participants