Skip to content

Support setting SplineChar width from importOutlines. #5005

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

Merged
merged 3 commits into from
May 11, 2022

Conversation

frank-trampe
Copy link
Contributor

@frank-trampe frank-trampe commented May 5, 2022

This supersedes #5004.

This set of changes allows setting SplineChar width from an imported discrete SVG file by setting the new "dimensions" flag in the Python routine SplineChar.importOutlines. Default behavior remains ignoring the SVG dimensions.

Test as follows.

frank@Luther-1:~/Projects_1/2022/Weather_Typeface_1/Samples_1$ /var/tmp/ff10/fontforge/build/bin/fontforge -lang=py -script
Copyright (c) 2000-2019. See AUTHORS for Contributors.
 License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
 with many parts BSD <http://fontforge.org/license.html>. Please read LICENSE.
 Version: 20220308
 Based on sources from 17:58 UTC 23-Jul-2019-ML-D-GDK3.
 Based on source from git with hash: 4f83172d44db72544b1bacf11b79bddf1d236647
PythonUI_Init()
copyUIMethodsToBaseTable()
Program root: /var/tmp/ff10/fontforge/build
Python 3.7.5 (default, Dec  9 2021, 17:04:37)
[GCC 8.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> font0 = fontforge.font()
>>> font0.ascent = 55
>>> font0.descent = 0
>>> char0 = font0.createChar(257)
>>> char0.importOutlines(filename="WeatherSymbol_WMO_CloudHigh_CH_1.svg",scale=False,dimensions=True)
<fontforge.glyph at 0x0x7f27eb78e4b0 U+0101 "glyph0">
>>> font0.save("font0_5.sfd")
<fontforge.font at 0x0x7f27eb78e430 "Untitled1">
>>> quit()

WeatherSymbol_WMO_CloudHigh_CH_1

…he Python bindings that sets the width of the glyph from an imported SVG.
@@ -2777,7 +2777,36 @@ return( NULL );
return( eret );
}

static Entity *SVGParseSVG(xmlNodePtr svg,int em_size,int ascent,bool scale) {
void SCDimensionFromSVG(xmlNodePtr svg, SplineChar *sc, bool vert) {
Copy link
Member

Choose a reason for hiding this comment

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

No viewBox handling needed in this change, Frank?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't know how we would map the viewBox values to glyph state.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think @ctrlcctrlv was thinking that given that the viewbox is x, y, width, height, one could consider the third and fourth values as alternate sources of width and height parameters.

Copy link
Member

Choose a reason for hiding this comment

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

Thank you, that's right.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Is there any case in which the width/height attribute would be missing or inapplicable (due to non-absolute units) and the viewBox would be useful? For what it is worth, the specification seems to suggest here that width and height are at least always present.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think values of "100%" are common, and I think I've seen elsewhere that "100%" is the implicit default for the svg element, but that could be wrong.

But yes, if the width element is a percentage or a length measure and the viewBox is present then the latter is a good source of a width dimension. That's basically what another client is going to do: treat the boundaries specified by the viewBox as the abstract dimensions of the SVG and then scale in one or both dimensions according to the length and width percentages or lengths.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I looked at an Inkscape file, since those are our most likely import candidates. Inkscape uses the user-specified page unit in the width and height fields ("8.5in" for example), with the viewBox in the user-specified drawing unit without a suffix. The patch as it is thus only works for a narrow range of inputs. But doing this right is not trivial, and I want to get what we have merged for the benefit of the weather symbols project.

Using the viewBox seems like a good fallback, but I do wonder whether we need to devote any attention to the case of one of the first two values being non-zero.

Copy link
Contributor

Choose a reason for hiding this comment

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

I believe the viewbox is x, y (starting point), width, height, so the first two values should be non-relevant for these purposes.

fontforge/svg.c Outdated
double width, height;
num = (char *) xmlGetProp(svg,(xmlChar *) "width");
if ( num!=NULL ) {
width = strtod(num,NULL);
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not necessarily against this PR as-is because particular workflows will use particular conventions and we can put the onus on the user. However, we should probably discuss this a bit.

As I understand it any of these are valid SVG width/height entries:

  • 640
  • 80%
  • 5cm

Taking the value from one of the latter cases seems like a mistake.

Taking @ctrlcctrlv's note into account as well, one could imagine using something like the following algorithm:

If "width" attribute is present
    width = strtod(num, &endptr);
    if endptr points to the end of the string (or whitespace only?)
       found = true
if not found
    check viewBox for width
    if it has one, grab it and found = True
if not found:
    Emit "dimension" flag-related warning

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agreed. Will patch.

@ronaldtse
Copy link

Thank you @frank-trampe for this -- look forward to using it in metanorma/WorldWeatherSymbols#1 !

Copy link
Contributor

@skef skef left a comment

Choose a reason for hiding this comment

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

Looks good at the functional and Python level. It would be ideal if this were also added to _ImportParamsDlg in fontforgeexe/cvimportdlg.c . Since it's another boolean it would be pretty easy to follow the model of correct_direction (copy and edit the UI group, boost some of the array lengths above it, copy and edit the GGadgetIsChecked line).

If you'd rather skip that part, though, consider this approved.

@frank-trampe
Copy link
Contributor Author

I added support to the graphical interface for the new option. I would like to add support to native scripting also, but the flag situation there is a bit of a mess.

label[k].text = (unichar_t *) _("Default Join Limit (PS/EPS/SVG):");
label[k].text_is_1byte = true;
label[k].text_in_resource = true;
gcd[k].gd.label = &label[k];
gcd[k].gd.flags = gg_visible | gg_enabled;
gcd[k++].creator = GLabelCreate;
hvarray[6][0] = &gcd[k-1];
hvarray[7][0] = &gcd[k-1];
Copy link
Contributor

Choose a reason for hiding this comment

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

I guess I didn't give these a ++ variable. Sorry!

Copy link
Contributor

@skef skef left a comment

Choose a reason for hiding this comment

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

This looks good. Any ViewBox stuff seems strictly optional, and I'm happy to review again.

@ctrlcctrlv
Copy link
Member

Just confirming it's all OK w/me too, not that my consent's needed :) only offering it as I brought up the viewBox thing.

@frank-trampe frank-trampe merged commit 566b261 into master May 11, 2022
@frank-trampe
Copy link
Contributor Author

I merged what we have. Discussion of the viewBox fallback continues.

Omnikron13 pushed a commit to Omnikron13/fontforge that referenced this pull request May 31, 2022
Add support for a "dimensions" flag in SplineChar.importOutlines in the Python bindings and in the import dialog box that sets the width of the glyph from an imported SVG. This works only for files with no units and absolute dimensions in the "width" and "height" attributes of the SVG.
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.

4 participants