summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOleg Oshmyan <chortos@inbox.lv>2020-10-29 02:16:01 +0200
committerOleg Oshmyan <chortos@inbox.lv>2021-04-29 03:15:40 +0300
commit3f95d1701159e86b75dc49c8eaa1dfc03819bc32 (patch)
treeac2c70bb1a294b938a1c56919e00ae9fb592e58c
parent03a7c9e63bbf7e6b77631b1b291f8d95b27d890e (diff)
downloadlibass-3f95d1701159e86b75dc49c8eaa1dfc03819bc32.tar.bz2
libass-3f95d1701159e86b75dc49c8eaa1dfc03819bc32.tar.xz
Delay \fay baseline shear until last text layout step
The current code calculates the effect of \fay on advances early in retrieve_glyph, only to ignore it until reorder_text, which then partially undoes these calculations. Instead, just calculate it once, when all the necessary properties have been fully determined. The earliest point to do this would be within reorder_text, but to simplify future logic changes, delay this until all other text layout steps are done. This matches VSFilter, which applies shear after alignment. This would also have neutralized the bug that the previous commit fixed, because glyphs[0].pos.y really is always 0 until shear is applied. This also opens the door for another commit to skip glyphs that are invisible but affect layout. In addition to simplifying code and calculations, this commit fixes a bug: the current code for undoing shear assumes constant scale_x/y from the last \fay change or line break point to the next such point, producing strange, wrong positions when scale_x/y do change. This fixes https://github.com/libass/libass/issues/465.
-rw-r--r--libass/ass_render.c34
-rw-r--r--libass/ass_shaper.c5
-rw-r--r--libass/ass_shaper.h1
3 files changed, 28 insertions, 12 deletions
diff --git a/libass/ass_render.c b/libass/ass_render.c
index 3a335fa..058e0ac 100644
--- a/libass/ass_render.c
+++ b/libass/ass_render.c
@@ -2064,9 +2064,6 @@ static void retrieve_glyphs(ASS_Renderer *render_priv)
// add horizontal letter spacing
info->cluster_advance.x += info->hspacing_scaled;
-
- // add displacement for vertical shearing
- info->cluster_advance.y += (info->fay / info->scale_x * info->scale_y) * info->cluster_advance.x;
}
}
@@ -2107,23 +2104,15 @@ static void reorder_text(ASS_Renderer *render_priv)
// Reposition according to the map
ASS_Vector pen = { 0, 0 };
int lineno = 1;
- double last_pen_x = 0;
- double last_fay = 0;
for (int i = 0; i < text_info->length; i++) {
GlyphInfo *info = text_info->glyphs + cmap[i];
if (text_info->glyphs[i].linebreak) {
- pen.y -= (last_fay / info->scale_x * info->scale_y) * (pen.x - last_pen_x);
- last_pen_x = pen.x = 0;
+ pen.x = 0;
pen.y += double_to_d6(text_info->lines[lineno-1].desc);
pen.y += double_to_d6(text_info->lines[lineno].asc);
pen.y += double_to_d6(render_priv->settings.line_spacing);
lineno++;
}
- else if (last_fay != info->fay) {
- pen.y -= (last_fay / info->scale_x * info->scale_y) * (pen.x - last_pen_x);
- last_pen_x = pen.x;
- }
- last_fay = info->fay;
if (info->skip)
continue;
ASS_Vector cluster_pen = pen;
@@ -2139,6 +2128,25 @@ static void reorder_text(ASS_Renderer *render_priv)
}
}
+static void apply_baseline_shear(ASS_Renderer *render_priv)
+{
+ TextInfo *text_info = &render_priv->text_info;
+ FriBidiStrIndex *cmap = ass_shaper_get_reorder_map(render_priv->shaper);
+ int32_t shear = 0;
+ double last_fay = 0;
+ for (int i = 0; i < text_info->length; i++) {
+ GlyphInfo *info = text_info->glyphs + cmap[i];
+ if (text_info->glyphs[i].linebreak || last_fay != info->fay)
+ shear = 0;
+ last_fay = info->fay;
+ if (info->skip)
+ continue;
+ for (GlyphInfo *cur = info; cur; cur = cur->next)
+ cur->pos.y += shear;
+ shear += (info->fay / info->scale_x * info->scale_y) * info->cluster_advance.x;
+ }
+}
+
static void align_lines(ASS_Renderer *render_priv, double max_text_width)
{
TextInfo *text_info = &render_priv->text_info;
@@ -2679,6 +2687,8 @@ ass_render_event(ASS_Renderer *render_priv, ASS_Event *event,
ASS_DRect bbox;
compute_string_bbox(text_info, &bbox);
+ apply_baseline_shear(render_priv);
+
// determine device coordinates for text
double device_x = 0;
double device_y = 0;
diff --git a/libass/ass_shaper.c b/libass/ass_shaper.c
index 4665e7a..ffcb36b 100644
--- a/libass/ass_shaper.c
+++ b/libass/ass_shaper.c
@@ -1020,6 +1020,11 @@ FriBidiStrIndex *ass_shaper_reorder(ASS_Shaper *shaper, TextInfo *text_info)
return shaper->cmap;
}
+FriBidiStrIndex *ass_shaper_get_reorder_map(ASS_Shaper *shaper)
+{
+ return shaper->cmap;
+}
+
/**
* \brief Resolve a Windows font charset number to a suitable base
* direction. Generally, use LTR for compatibility with VSFilter. The
diff --git a/libass/ass_shaper.h b/libass/ass_shaper.h
index 2c4166d..70bec9a 100644
--- a/libass/ass_shaper.h
+++ b/libass/ass_shaper.h
@@ -45,6 +45,7 @@ void ass_shaper_set_bidi_brackets(ASS_Shaper *shaper, bool match_brackets);
bool ass_shaper_shape(ASS_Shaper *shaper, TextInfo *text_info);
void ass_shaper_cleanup(ASS_Shaper *shaper, TextInfo *text_info);
FriBidiStrIndex *ass_shaper_reorder(ASS_Shaper *shaper, TextInfo *text_info);
+FriBidiStrIndex *ass_shaper_get_reorder_map(ASS_Shaper *shaper);
FriBidiParType resolve_base_direction(int font_encoding);
void ass_shaper_font_data_free(ASS_ShaperFontData *priv);