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

FontViewer: Composite Glyph Rendering #10

Open
paulushub opened this issue Nov 1, 2018 · 4 comments
Open

FontViewer: Composite Glyph Rendering #10

paulushub opened this issue Nov 1, 2018 · 4 comments

Comments

@paulushub
Copy link

First, the cast to SimpleGlyph in the following rendering codes is not correct, throwing exceptions for nested composite glyphs. Try rendering Glyph ID 126 in the font NotoSerif-Thin.ttf.

    private void paintCompositeGlyph(Graphics2D g, CompositeGlyph composite) {
      for (int i = 0; i < composite.numGlyphs(); i++) {
        int glyphIndex = composite.glyphIndex(i);
        int offset = loca.glyphOffset(glyphIndex);
        int length = loca.glyphLength(glyphIndex);
        if (length != 0) {
          SimpleGlyph simple = (SimpleGlyph) glyf.glyph(offset, length);    // <--- Here
          int deltaX = composite.argument1(i);
          int deltaY = composite.argument2(i);
          paintSimpleGlyph(g, simple, deltaX, deltaY);
        }
      }
    }

Next, checking for the nested composite glyph and calling the paintCompositeGlyph(...) recursively seems to work but rendering is incomplete and will not render the denominator in some fractional representations like 1/4 (where the 4 is not rendered in fonts like NotoSerif-Thin.ttf).
The denominator is actually rendered but clipped off the screen (it seems deltaY is very large).

What is the best way to fix the nested rendering of composite glyphs?

@rillig
Copy link
Owner

rillig commented Nov 1, 2018

Thanks for the detailed instructions.

Fixing the ClassCastException was trivial, but I wonder why the glyph for 4 is not rendered correctly. Glyph 126 is composed of glyphs 2570, 534 and 2563. When I look up the latter glyph in the glyf table, it is not rendered at all, although it is a simple glyph. I will investigate this further.

Note that I wrote the glyph renderer without actually reading the specification carefully, let alone following it word by word. It was just a quick and dirty way to see how the glyphs look approximately. You will probably find more bugs and inconsistencies if you look closely.

rillig added a commit that referenced this issue Nov 1, 2018
rillig added a commit that referenced this issue Nov 1, 2018
The internal code says that the two arguments of a composite glyph
should be interpreted as uint16, which positions the 1 of the 1/4
fraction 65536 units too far to the right.

This commit makes all simple glyphs of the frac14 visible. The 4 is
in the wrong position, which will be fixed in a follow-up commit.

Fixes part of #10.
@paulushub
Copy link
Author

Thanks for the quick response. The following seems to work, but still glyphs like 129 and 745 are partly off the view.

private void paintCompositeGlyph(Graphics2D g, CompositeGlyph composite) {
	for (int i = 0; i < composite.numGlyphs(); i++) {
		int glyphIndex = composite.glyphIndex(i);
		int offset = loca.glyphOffset(glyphIndex);
		int length = loca.glyphLength(glyphIndex);
		if (length != 0) {
			Glyph glyph = glyf.glyph(offset, length);
			int deltaX = (short) composite.argument1(i);
			int deltaY = (short) composite.argument2(i);
			if (glyph.glyphType() == Glyph.GlyphType.Simple) {
				paintSimpleGlyph(g, (SimpleGlyph) glyph, deltaX, deltaY);
			} else {
				paintCompositeGlyph(g, (CompositeGlyph) glyph, deltaX, deltaY);
			}
		}
	}
}

private void paintCompositeGlyph(Graphics2D g, CompositeGlyph composite, int offsetX, int offsetY) {
	for (int i = 0; i < composite.numGlyphs(); i++) {
		int glyphIndex = composite.glyphIndex(i);
		int offset = loca.glyphOffset(glyphIndex);
		int length = loca.glyphLength(glyphIndex);
		if (length != 0) {
			Glyph glyph = glyf.glyph(offset, length);
			int deltaX = (short) composite.argument1(i);
			int deltaY = (short) composite.argument2(i);
			if (glyph.glyphType() == Glyph.GlyphType.Simple) {
				paintSimpleGlyph(g, (SimpleGlyph) glyph, offsetX, deltaY);
			} else {
				// Cannot tell, if we will still get here!!!
				paintCompositeGlyph(g, (CompositeGlyph) glyph, deltaX, deltaY);
			}
		}
	}
}

rillig added a commit that referenced this issue Nov 2, 2018
@rillig
Copy link
Owner

rillig commented Nov 7, 2018

It'll take some time until I finish the remaining edge cases. I need to read and understand the specification first. Up to now, I did the glyph drawing by trial and error, which was probably not a too good idea. :)

@paulushub
Copy link
Author

Understood, I am also looking into it. So far, it seems the defined transforms in the glyph are not applied.

My work, I ported the library to .NET/C# and the FontViewer application was the last part I had to work on because it involves UI. The samples, testing libraries, tools, unit tests so far worked as expected within the limitations of the library.
The FontViewer issues are the remaining few I could not resolve, but I have started reading the specs too to address some of the limitations of the library and also resolve these issues.

fontviewer

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