SKShaper: Support SKPaint.TextAlign property - #1910
Conversation
|
|
||
| // adjust alignment | ||
| if (paint.TextAlign != SKTextAlign.Left) { | ||
| var width = pos.Sum(p => p.XAdvance) * textSizeX; |
There was a problem hiding this comment.
This might be a huge performance hit. I think text alignment should be evaluated when the text blob is being drawn onto a canvas. Better implement this in the DrawShapedText extension method. SKTextBlob.Bounds should give you the needed Size for your calculations.
There was a problem hiding this comment.
Hi, thanks for your suggestion. I tried to implement it, but Bounds return much larger box than there is actually rendered.
For example:
SKTextBlob.Create("test", font).Bounds.Width
returns 157.3125
while
paint.MeasureText("test")
returns 67.125
According to the documentation of bounds:
/** Returns conservative bounding box. Uses SkPaint associated with each glyph to
determine glyph bounds, and unions all bounds. Returned bounds may be
larger than the bounds of all glyphs in runs.
@return conservative bounding box
*/
When diving deeper into the code of SkTextBlobBuilder, there are two functions to calculate the bounds, one is called TightRunBounds and the other ConservativeRunBounds, where ConservativeRunBounds is used for sk_textblob_builder_alloc_run_pos and sk_textblob_builder_alloc_run_pos_h, and TightRunBounds is only used for sk_textblob_builder_alloc_run (and there is a FIXME comment to not use tight run in this case too).
So it seems that bounds is pretty useless for this use case.
Another option is to use paint.MeasureText but it would not be accurate with things like Arabic text (which is the point of SKShaper)
Another option to that I can think of is to return it as part of the Result of SKShaper.Shape (last xOffset minus the starting xOffset) and than use it in DrawShapedText. What do you think?
Thanks.
There was a problem hiding this comment.
DrawPositionedText should use
SkiaSharp/binding/Binding/SKTextBlob.cs
Line 806 in fffae82
There was a problem hiding this comment.
Hmm, I think bounds is misused here and should be an out parameter. Only when a nullptr is used Skia calculates the bounds.
There was a problem hiding this comment.
It seems that bounds is an input parameter, according to documentation:
bounds defines an optional bounding box, used to suppress drawing when SkTextBlob
bounds does not intersect SkSurface bounds. If bounds is nullptr, SkTextBlob bounds
is computed from RunBuffer::pos, and RunBuffer::glyphs metrics.
Skia calculate the bounds anyway, but that parameter is just the initial value which it does SkRect.join to
https://github.com/mono/skia/blob/916a1e9721de74a05c75391f52393972ed7f736c/src/core/SkTextBlob.cpp#L514
https://github.com/mono/skia/blob/916a1e9721de74a05c75391f52393972ed7f736c/src/core/SkTextBlob.cpp#L383
At least if I am understanding the code correctly....
Anyway, the issue is the that Skia uses conservative way to calculate the bounds (probably for performance) which result in a much larger bounds than the actual bounds. (like twice as big or more in some cases), so it doesn't really help in this case.
What do you say about the current solution?
c2bfdbf to
dd0f50c
Compare
mattleibow
left a comment
There was a problem hiding this comment.
Thanks for this PR. It has been so long since I reviewed a PR on this repo 😢 Thanks for this, but I just got 1 suggestion about API/ABI compatibility.
|
/azp run SkiaSharp |
|
No pipelines are associated with this pull request. |
Description of Change
Added handling of the SKPaint.TextAlign property in SKShaper.Shape.
The width is calculated by the sum of XAdvance
Befpre;

DrawText with TextAlign = Center:
DrawShapedText with TextAlign = Center

After this PR:

DrawShapedText with TextAlign = Center
Bugs Fixed
Behavioral Changes
PR Checklist