svgdotjs / svg.js

The lightweight library for manipulating and animating SVG
https://svgjs.dev
Other
11.04k stars 1.07k forks source link

Font to Path #456

Closed villanus closed 8 years ago

villanus commented 8 years ago

I just ran across your svg.textmorph.js plugin and wanted to make the following question / request. I am trying to wrap my head around this, since chrome has dropped support for SVG Fonts.

Our Challenge. We are using SVG.js to create SVGs which are later cut as stickers using adobe illustrator. The biggest challenge has been working with fonts. Right now we are working on getting around this by using PHP to turn a text string into an SVG path. This causes a http request on every text change, and requires us to load external svgs. This works, but its ugly because it requires PHP and so many server calls.

Feature request. It would be great if SVG.js could load svg fonts and convert them to paths. I see that that is a feature of the svg.textmorph.js but I wish we could take it a little further and part of svg.js with the following features:

  1. Convert the whole string to a single path, or set of paths when letters dont overlap
  2. The ability to adjust Kerning (spacing between letters)
  3. The ability to have the text path auto fit a parent bbox or container
  4. The ability to justify (right, left, center, full)

This would be an extremely useful feature for something like headings, or custom shirt printing. So it would be very similar to fittext.js except it would be SVG paths.

The drawback is that the text is not accessible for screen readers, but since most of us will be using this for dynamic text, it should not be an issue.

Looking forward to your feedback!

Fuzzyma commented 8 years ago

Drawing text from an svg font will certainly not become a core future. But a plugin is always possible. I was thinking about a plugin for font-import when I wrote the textmorphing extension. I came to a point where I was wondering which types I should support. In the plugin I read an svg-font but pulled the needed information into a data structure which remined me of typeface.js. So I thought if it would be worth to just use this structure instead and only build a svg-font to typeface converter (which are for sure already out there in the web). Thats why I finally didnt do it because I found no specification about typeface.

To your numbers:

  1. I think thats possible. We just have to close the path ourselves and glue the path from the next glyph BUT you have to adjust every single coordinate which could be a problem since you have to scale them accordingly, too. Messy on second thought! Also textmorphing would morph the whole path and not letter by letter...
  2. In case we just build a typeface interpreter and a font-to-typeface-converter it would be no problem to alter the typeface object before using it which includes kerning, too
  3. Should work (only with point 1), but the path would be drawn in a wrong size forst before it is adjusted to the box because you dont know which factor you need, to scale a single glyph.
  4. Something the rendered should take care about. Its just math. What does full mean btw?
villanus commented 8 years ago

Thanks!!!

I am working a a more detailed write up because I think a text plugin would be extremely useful. The full justification would adjust the kerning of a string to make it fit a complete box.

Lets say you have the string "WELCOME" and with 0 Letter spacing (kerning) the string is 100px wide. And lets assume that the text is in a box which is 150px wide.

I am not a programmer, so please excuse my limited knowledge, but the more I think about it the easier this all seems if we made it a bit simpler by:

  1. Using SVG font loaded for glyphs
  2. Adjusting the spacing between letters (kerning)
  3. Welding all overlapping paths, and then grouping all the paths.

Then the resulting group can be centered, left justified, right justified, and for full justification you could just play with the kerning to make it fit your needs.

The welding feature is important, specially if you stroke the text. If you have a fancy font (something which looks cursive), then without welding overlapping paths, the strokes will mess up the text.

The welding function might be useful as a core feature of SVG.js. If two paths overlap, and are the same exact color, a user might want to weld them into a single path. This is easy to do in illustrator, not sure how it works in Javascript =)

Quick side note, Are you or any developers you can recommend available for a small freelance project using SVG.js?

Thanks

villanus commented 8 years ago

Thank you for the detailed answer. =)

I was not familiar with typeface.js, but it looks to me as the project is dead. At a minimum I think it would be worthwhile to have a 1st class Type pluing for SVG.js. Working with Type is extremely hard, and SVG can solve a lot of issues.

In this long email I wanted ot give more detail on the matter, but I also wanted to pre-face it with how we are planning on using SVG.js to give you a real life use case outside of the browser.

Our Use of SVG.js

I wanted to give you some background on what we are trying to use svg.js for. Our use case is a little different than the traditional one where SVG's are used as an alternative to bitmap images for web consumption. I assume that we are not the only ones with this specific use case, and am hoping we can use SVG.js as the foundation of the project we are trying to have developed. I myself am more of a designer (not a coder) so please excuse my limited knowledge of what is possible. =)

My partner forming a sign printing startup. What is normal in our industry is to use Adobe Illustrator for the production of signs, t-shirts, and other print graphics. In the case of signs, vectors are essential, because the items are not printed, but rather cut from sheets of colored vinyl. The machinery (plotter), actually traces the paths from a vector and cuts out the final result.

For our project our goal is to create two tools:

Back End Tool

The first tool is a simple back end interface which will accepts "SVGs" as products. In this tool we hope to accomplish the following:

  1. Upload or Cut & Paste SVG Code generated by Illustrator
  2. Clean the Illustrator SVG by removing Doctype and Comments
  3. Centering the SVG (Horizontal & Vertical) within a 1000px by 1000px space
  4. Allowing us define groups (what we call layers) and then clicking on certian paths will move them to the selected layer. This is our way of re-organizing an svg. Here is a link to a fiddle with the end result. https://jsfiddle.net/pymg38o7/1/
  5. The ability to define multiple text boxes where users can later input their own text input, font choices and text options. https://jsfiddle.net/pymg38o7/2/
  6. Other backend options (meta data, print size options, pricing, etc)

Front End Tool (Public Site)

With the svgs formatted and ready for use. The front end site will just present the desired svg (1 per product) and then let the user choose colors for layers and fonts / colors / text string per text box. With the 2nd JS Filddle example above The user would choose color for Layer1 (I SHOOT), Layer2 (RAW). The User would also choose Color, Font and Text for whatever they want in the text box.

The Problem with Fonts in SVG (Outside Browser)

Using fonts (such as google fonts) with SVG works great for web consumption, but breaks down once the SVG is opened outside the browser (Illustrator, Corel, Inkscape).

Here are a few problems which commonly occur:

Our Incomeplete Solution

To overcome the problem with how fonts are rendered in 3rd party applications we are generating svg paths using this PHP Script: https://github.com/kartsims/easysvg. The script simply takes an SVG font, text string, and then generates an SVG Path. The path is no longer text, but works well for our uses. The disadvantage is that for each time the suer changes fonts, or text string we do a server round trip. This seems like an expensive way to accomplish our goals. The advantage is the resulting SVG loads perfectly in Illustrator (What you see is what you get)

Text Plugin Wishlist

  1. Ability to use SVG Fonts (your example handles this)
  2. Kerning (Letter Spacing) Between Letters
  3. Weld Function - Convert overlapping paths into a single path
  4. Groupoing - Group the whole text element into its own group
  5. Aligning - Center | Left | Right
  6. Fitting - Fit height of bounding box, fit width of bounding box, fit best (will make the text fit within box, best use)
  7. Arcing - Having the text follow an arc (up or down)
Fuzzyma commented 8 years ago
  1. Jep - thats no problem
  2. I differentiate Kerning and Letter Spacing. While kerning adjusts the default space between 2 letters (e.g. Ya) to look smoother, Letter Spacing adjusts the space between all letters with a factor or fixed value. Letter spacing should be no problem. Kerning is done in my plugin already.
  3. Welding is not possible in javascript/svg - at least I cant imagine a way on how to accomplish that on an easy way. I saw a post saying, that you just have to combine the d-attributes of both paths but I dont know how this would work. Some tests would be needed
  4. Well - that should be really no problem^^
  5. check
  6. You cant calcualte the dimensions of a path before it is drawn. No problems to fit one dimenson with one redraw but both dimensions may need more redraws
  7. Its no problem to place a letter at a specific spot of a path - since arcs are allowed in paths this should be no problem. However if you use a path different from an arc I dont know how to get the specific tangent of that point to rotate the letter properly.

I am very busy right now - however you can mail me with my github mail

villanus commented 8 years ago

Firstly, thank you for the quick reply and the great news. Is this something you might include as its own plugin or part of the core features?

3 Welding.

I dont know how important this would be to others in the community. The closest thing I could find was a source forge project which did the opposite of welding. They call the project "clipper". It seems pretty neat, but all of its features are far above my head. https://sourceforge.net/projects/jsclipper/

7 Text on Path (arc)

I think the most common use case for this would be a simple arc, but maybe others, or yourself would want more? I dont know how this would work with alignment, or making the text full fit the complete arc. For example if you have a circle path (full arc) and want to put the words SVG JS IS AWESOME, it could go all the way around, or start at a certain position?

Offline Messaging. We are still a while away from getting everything figured out on our project. Right now its mainly at the research phase. Over the next few weeks or month I am going to write up a healthy spec, and maybe do my part by putting in some psuedo code and the UI portion in CSS. Maybe after that is all done, you can look at what we are trying to do, and see if we can contract your services to do the coding work correctly. Also on a side note, are there any JS frameworks which play nice with SVG? Not a big fan of Angular, but I really like the way vue.js, react and knockout work. For me things have never gotten past Jquery =). Just wanted to pick your brain on that.

Thank you again!!!

Frank

Fuzzyma commented 8 years ago

The jsclipper is working with polygons and not with paths which is a huge difference. However - we should check if that is really needed in order to make things work.

There is heavy math included when you want to find the tangent from a beziere curve. Simple shapes would be the easy part here. Its also not that easy to make the text autofit a path. You would have to calculate the length of your text based on the glyphs you have (kerning included). I think thats something which just needs testing. For simplicity the text would always start at the start from the path when it should go the whole way round.

I myself have no knowledge about librarays which works super well with svg.js. Neither it should create any problems using it. Just try it ;)

Fuzzyma commented 8 years ago

@villanus I consider this as solved for now. If still task is still open dont hesistate to contact me.