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

GlyphSerializer rounding fix #7545

Merged
merged 2 commits into from
Apr 3, 2023

Conversation

miloush
Copy link
Contributor

@miloush miloush commented Feb 16, 2023

Fixes #7499

Related: #6295

Description

Previous rounding strategy

  1. did not calculate the error according to XPS specification
  2. updated error with shaping value when font value is used by the client

The PR fixes 1. by keeping track of total advance width (desired and rounded) and 2. by using the font advance width when no value is output to XPS.

Customer Impact

Customers not taking this fix will see either gaps or overlapped characters when producing XPS with text. See #7499 for an example.

Regression

Yes. Introduced by #6295 trying to fix #6525. This PR addresses both issues.

Testing

Tested manually using repro projects for #6525 and #7499.

image

Risk

Same risks as with #6295. This PR changes relative positioning of glyphs in a GlyphRun to match the bounding box, so it should not cause reflow of documents.

Microsoft Reviewers: Open in CodeFlow

@miloush miloush requested a review from a team as a code owner February 16, 2023 14:38
@ghost ghost assigned miloush Feb 16, 2023
@ghost ghost added the PR metadata: Label to tag PRs, to facilitate with triage label Feb 16, 2023
@ghost ghost requested review from dipeshmsft and singhashish-wpf February 16, 2023 14:38
@ghost ghost added the Community Contribution A label for all community Contributions label Feb 16, 2023
@miloush
Copy link
Contributor Author

miloush commented Feb 16, 2023

@campeters try this

@campeters
Copy link

This works for my test cases. Thank you so much!

Copy link

@campeters campeters left a comment

Choose a reason for hiding this comment

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

When initializing the doubles should we set them to 0.0? Either for style convention or prevent the compiler from needing to do the implicit conversion from int to double?

Also, I was able to get the same result using only a single double to aggregate the error.... the other changes to your logic are what fixed the problem. This works for me:

        // advance width
        // #7499 Advance width needs to be specified if it differs from what is in the font tables. [ECMA-388 O5.5]
        // Most commonly it differs after shaping, e.g. when kerning is applied. (Ex. 12-15)
        // XPS supports floating point values, but in the interest of file size, we want to specify integers.

        double shapingAdvance = _advances[glyph] * _milToEm;
        double fontAdvance = _sideways ? _glyphTypeface.AdvanceHeights[fontIndex] : _glyphTypeface.AdvanceWidths[fontIndex];

        // To minimize rounding errors, we keep track of the unrounded advance total as required by [M5.6].
        int roundedShapingAdvance = (int)Math.Round(_idealAdvanceDelta + shapingAdvance);
        int roundedFontAdvance = (int)Math.Round(fontAdvance);

        if (roundedShapingAdvance != roundedFontAdvance)
        {
            _glyphStringBuider.Append(roundedShapingAdvance.ToString(CultureInfo.InvariantCulture));
            _idealAdvanceDelta += (shapingAdvance - roundedShapingAdvance);
        }
        else
        {
            // when the value comes from the font tables, the specification does not mandate clients to do any rounding
        }

@miloush
Copy link
Contributor Author

miloush commented Feb 18, 2023

I was able to get the same result using only a single double to aggregate the error

Yes that was the approach of the original fix. However, the XPS specification puts a hard requirement on keeping the total and subtracting the sum of advance to avoid error accumulation.

@singhashish-wpf
Copy link
Member

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@campeters
Copy link

@dipeshmsft @singhashish-wpf - Thanks for the help on this. Would you be able to share any details on when we will see this fix in a public release?

@dipeshmsft
Copy link
Member

Thanks @miloush . Looks good to me. We will take it up for the next test pass. As far as I remember, we may need to make some changes in the test code as well. I am on it.

@campeters
Copy link

Thanks @miloush . Looks good to me. We will take it up for the next test pass. As far as I remember, we may need to make some changes in the test code as well. I am on it.

@dipeshmsft - Is this something that will be merged into a dotnet 6 maintenance release as well?

@wstaelens
Copy link
Contributor

Thanks @miloush . Looks good to me. We will take it up for the next test pass. As far as I remember, we may need to make some changes in the test code as well. I am on it.

@dipeshmsft - Is this something that will be merged into a dotnet 6 maintenance release as well?

yes @dipeshmsft , how can we get this fix? our customers experience also this XPS issue.

@dipeshmsft
Copy link
Member

@campeters @wstaelens, we will be taking this PR for the next round of test pass and once that is complete, we will take this PR for upcoming .NET servicing releases.

@wstaelens
Copy link
Contributor

@campeters @wstaelens, we will be taking this PR for the next round of test pass and once that is complete, we will take this PR for upcoming .NET servicing releases.

@dipeshmsft great! just so that I can inform our customers: are we talking about days, weeks or months?

@dipeshmsft
Copy link
Member

@wstaelens, I will get back on this, once the test pass is complete.

@wstaelens
Copy link
Contributor

@wstaelens, I will get back on this, once the test pass is complete.

will this be in regular Windows Updates for customers or OOB?

@dipeshmsft
Copy link
Member

The fix causing regression was not included in .NET Framework, so it will not be present in either. This fix will be shipped with .NET SDK servicing release.

@dipeshmsft
Copy link
Member

/backport to release/7.0

@singhashish-wpf
Copy link
Member

/backport to release/7.0

1 similar comment
@singhashish-wpf
Copy link
Member

/backport to release/7.0

@github-actions
Copy link

Started backporting to release/7.0: https://github.com/dotnet/wpf/actions/runs/4687438204

@wstaelens
Copy link
Contributor

@singhashish-wpf I guess this will be backported to 6.0 also, as this is Long term release (and our products affected are not yet on .net 7)

@dipeshmsft
Copy link
Member

@wstaelens, yes this will be backported to 6.0 also.

@dipeshmsft
Copy link
Member

/backport to release/6.0

@github-actions
Copy link

Started backporting to release/6.0: https://github.com/dotnet/wpf/actions/runs/4695602743

@miloush miloush deleted the GlyphRunSerializer-Rounding branch April 17, 2023 08:29
@ghost ghost locked as resolved and limited conversation to collaborators May 17, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Community Contribution A label for all community Contributions PR metadata: Label to tag PRs, to facilitate with triage
Projects
None yet
5 participants