summaryrefslogtreecommitdiffstats
path: root/libass/ass_shaper.c
diff options
context:
space:
mode:
Diffstat (limited to 'libass/ass_shaper.c')
-rw-r--r--libass/ass_shaper.c49
1 files changed, 38 insertions, 11 deletions
diff --git a/libass/ass_shaper.c b/libass/ass_shaper.c
index f95dd58..b05a051 100644
--- a/libass/ass_shaper.c
+++ b/libass/ass_shaper.c
@@ -39,6 +39,12 @@ enum {
};
#define NUM_FEATURES 5
+enum {
+ WHOLE_TEXT_LAYOUT_OFF,
+ WHOLE_TEXT_LAYOUT_IMPLICIT,
+ WHOLE_TEXT_LAYOUT_EXPLICIT,
+};
+
struct ass_shaper {
ASS_ShapingLevel shaping_level;
@@ -62,6 +68,8 @@ struct ass_shaper {
FriBidiBracketType *btypes;
bool bidi_brackets;
#endif
+
+ char whole_text_layout;
};
struct ass_shaper_metrics_data {
@@ -895,6 +903,10 @@ void ass_shaper_find_runs(ASS_Shaper *shaper, ASS_Renderer *render_priv,
void ass_shaper_set_base_direction(ASS_Shaper *shaper, FriBidiParType dir)
{
shaper->base_direction = dir;
+
+ if (shaper->whole_text_layout != WHOLE_TEXT_LAYOUT_EXPLICIT)
+ shaper->whole_text_layout = dir == FRIBIDI_PAR_ON ?
+ WHOLE_TEXT_LAYOUT_IMPLICIT : WHOLE_TEXT_LAYOUT_OFF;
}
/**
@@ -929,6 +941,14 @@ void ass_shaper_set_bidi_brackets(ASS_Shaper *shaper, bool match_brackets)
}
#endif
+void ass_shaper_set_whole_text_layout(ASS_Shaper *shaper, bool enable)
+{
+ shaper->whole_text_layout = enable ?
+ WHOLE_TEXT_LAYOUT_EXPLICIT :
+ shaper->base_direction == FRIBIDI_PAR_ON ?
+ WHOLE_TEXT_LAYOUT_IMPLICIT : WHOLE_TEXT_LAYOUT_OFF;
+}
+
/**
* \brief Shape an event's text. Calculates directional runs and shapes them.
* \param text_info event's text
@@ -948,7 +968,8 @@ bool ass_shaper_shape(ASS_Shaper *shaper, TextInfo *text_info)
for (i = 0; i < text_info->length; i++) {
shaper->event_text[i] = glyphs[i].symbol;
// embedding levels should be calculated paragraph by paragraph
- if (glyphs[i].symbol == '\n' || i == text_info->length - 1) {
+ if (glyphs[i].symbol == '\n' || i == text_info->length - 1 ||
+ (!shaper->whole_text_layout && glyphs[i + 1].starts_new_run)) {
dir = shaper->base_direction;
fribidi_get_bidi_types(shaper->event_text + last_break,
i - last_break + 1, shaper->ctypes + last_break);
@@ -1041,17 +1062,23 @@ FriBidiStrIndex *ass_shaper_reorder(ASS_Shaper *shaper, TextInfo *text_info)
for (i = 0; i < text_info->length; i++)
shaper->cmap[i] = i;
- // Create reorder map line-by-line
- for (i = 0; i < text_info->n_lines; i++) {
- LineInfo *line = text_info->lines + i;
- FriBidiParType dir = FRIBIDI_PAR_ON;
+ // Create reorder map line-by-line or run-by-run
+ int last_break = 0;
+ GlyphInfo *glyphs = text_info->glyphs;
+ for (i = 0; i < text_info->length; i++) {
+ if (i == text_info->length - 1 || glyphs[i + 1].linebreak ||
+ (!shaper->whole_text_layout && glyphs[i + 1].starts_new_run)) {
+ FriBidiParType dir = FRIBIDI_PAR_ON;
+
+ ret = fribidi_reorder_line(0,
+ shaper->ctypes, i - last_break + 1, last_break, dir,
+ shaper->emblevels, NULL,
+ shaper->cmap);
+ if (ret == 0)
+ return NULL;
- ret = fribidi_reorder_line(0,
- shaper->ctypes + line->offset, line->len, 0, dir,
- shaper->emblevels + line->offset, NULL,
- shaper->cmap + line->offset);
- if (ret == 0)
- return NULL;
+ last_break = i + 1;
+ }
}
return shaper->cmap;