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

Adds support for 'italic' font-style when using @font-face fonts #785

Closed
wants to merge 6 commits into from
Closed

Conversation

gordyr
Copy link
Contributor

@gordyr gordyr commented Aug 7, 2013

@font-face fonts do not always offer italic versions, and if they do, they require the loading of separate font files. This means that setting fontStyle to 'italic' rarely works when using non-system fonts.

This minor patch prevents the native use of fontStyle 'italic' and instead apply's a small transform to emulate the italic style for all fonts.

This could be further improved by checking whether the fontFamily is a non system font (by simply checking through an array of defined system fonts) and only using the transform method as a fallback when needed

gordyr added 2 commits August 7, 2013 22:17
Most @font-face fonts do not support the native 'italic' declaration when rendered on a canvas.  This fix uses a small transform instead.  This could be further improved by checking if the 'fontFamily' is a non system font and only falling back to the transform method when needed.  To my eyes, however, this method looks exactly the same as the native one.
@gordyr
Copy link
Contributor Author

gordyr commented Aug 7, 2013

As a note, using @font-face fonts also breaks your underline functionality on many fonts due to the variation in font-sizes. I'm working on a quick fix right now.

@gordyr
Copy link
Contributor Author

gordyr commented Aug 8, 2013

I've just realised that this method does not cope with multiline text. Oops. My apologies. I'll leave it open for now as i' working on a solution today.

Changed where the transform was being applied.  It now happens at the line level rather than the object level.  Each line is skewed around its center point.
@gordyr
Copy link
Contributor Author

gordyr commented Aug 8, 2013

I've fixed multilne text with this pseudo italic technique by changing where the transform is applied. I've moved it into the _drawChars method so that it can be applied at line level rather than object level, while skweing each line around its center point.

@kangax
Copy link
Member

kangax commented Aug 8, 2013

I considered adding pseudo italic at one point.

But we can't do it like this, since it'll break actual @font-face -based italic rendering, and it doesn't allow you to choose.

Pseudo italic has to be a separate property (pseudoItalic? same applies to bold, so we might need pseudoBold then, or maybe pseudoFontStyle and pseudoFontWeight).

Or just a separate value: fontStyle: "pseudo-italic" and "fontWeight: pseudo-bold".

/cc @Kienz

@gordyr
Copy link
Contributor Author

gordyr commented Aug 8, 2013

Understood... In my app, what you suggest would be irrelevant but for a library such as this, it would be required.

However I don't think choosing the pseudo option is the right way to go. It would be far better for Fabric to do this in the background transparently. Attempt to use native 'italic', and if it fails, use pseudo.

This would then work as intended within my app and any other canvas based text editor that allows users to use any font from across the internet.

I have an idea. I'll give it a go.

@kangax
Copy link
Member

kangax commented Aug 8, 2013

@gordyr doing this transparently is also debatable since there's often dislike of pseudo italics. Just search for "font face avoid faux italics" :)

@gordyr
Copy link
Contributor Author

gordyr commented Aug 8, 2013

Of course an option to enable/disable pseudo would be be easy enough to implement :)

@kangax
Copy link
Member

kangax commented Aug 8, 2013

By the way, we wouldn't need this if we had support for skewing, which I was planning to add sometime in the future. It's tracked in this ticket — #726

@kangax
Copy link
Member

kangax commented Aug 8, 2013

Although skewing would work per-box, not per-line, so it probably wouldn't be very helpful after all.

@gordyr
Copy link
Contributor Author

gordyr commented Aug 8, 2013

Okay, this next commit adds transparent pseudo fallback.

It works in this manner:

Upon rendering a font for the first time we perform a check to see whether normal/bold/italic is supported by the given font family. We check by rendering an image of each font mode and comparing the base64 string returned.

This result is then stored in a new property (fontSupport).

We then also make note of the font checked so that we do not check it again. (prevFont)

When fontFamily does not equal prevFont we check again.

the values of fontSupport determine whether native or pseudo italic should be used by the renderer.

An option to turn off pseudo italic needs to be implemented as well as a fallback for Bold (Although so far every font-face font I have tried has worked perfectly)

While this may not be coded in the manner you'd like (I literally just hashed it up very quickly) It should at least give you a starting point should you feel pseudo italic is worth it.

Hope this helps!

@gordyr
Copy link
Contributor Author

gordyr commented Aug 8, 2013

As a side note I have a complete text editing system built with Fabric. You double click on a text object to enter 'editing mode', a flashing caret/cursor is then rendered onto the canvas and text becomes editable, behaving in the same way as in any wordprocessor or textbox in photoshop but all done via javascript and canvas. We have full keyboard and mouse cursor/caret control, click and drag selection etc...etc... All font widths are measured in the background so that the caret position is always correct and it works perfectly when rotating or scaling the text via the standard fabric controls, as well as skewing correctly with my pseudo italic etc.

It works beautifully and is far better than the usual hovering html textareas you tend to see.

I'm very busy at the moment but if you're interested at some point i'll get it together into a pull request. Right now its heavily tied into my application.

@kangax
Copy link
Member

kangax commented Aug 12, 2013

As a side note I have a complete text editing system built with Fabric.

It's actually coming to Fabric very soon :) Stay tuned.

@somecodemonkey
Copy link
Contributor

Not sure if this is the place to put this but until @kangax finishes and pulls this into Fabric id be interested in it @gordyr . I currently have the same thing in our application, sans italics cursor. Did you manage to implement copy and paste as well? I'm looking for a possible alternative to off screen text area hack.

@gordyr
Copy link
Contributor Author

gordyr commented Aug 13, 2013

@darbs Yes, we have full copy/paste support. I'm looking to add freeform path based text editing with bezier curve control points this week. Once this is done and well tested i'll try to pull it together into a standalone Fabric extension if Kangax hasn't merged in his own version by then.. As I said, it's currently quite heavily tied into our UI code and I'm in the process of breaking it out into it's own module anyway.

@somecodemonkey
Copy link
Contributor

Thanks i appreciate your response. Are there performance benefits of storing all the widths, my current implementation performs the same function but doesn't save the widths. It iterates through the correct row and calculates on render. Im still relatively new to this stuff so any help would be appreciated. I look forward to seeing yours or @kangax implementations.

var context = canvas.getContext("2d");
var test = {}, results = {};

var styles = ["normal", "bold", "italic"];
Copy link
Member

Choose a reason for hiding this comment

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

Indentation is off

@kangax
Copy link
Member

kangax commented Sep 11, 2013

Hey @gordyr

So I revisited this again and see few issues. Left comments. In a nutshell, I would want to just pull in standalone pseudoItalic property without adding any additional detection logic. Detection could be done on an application level. Someone might know that italic font is not supported, and so they'd like to use pseudo italic. No detection is needed in that case.

I'll close this pull request for now since I can't merge it anymore. If you can submit new one, that would be great.

Thanks!

@kangax kangax closed this Sep 11, 2013
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

Successfully merging this pull request may close these issues.

3 participants