else
val = -1.;
change_border(render_priv, val, render_priv->state.border_y);
+ render_priv->state.bm_run_id++;
} else if (mystrcmp(&p, "ybord")) {
double val;
if (mystrtod(&p, &val))
else
val = 0.;
render_priv->state.shadow_x = val;
+ render_priv->state.bm_run_id++;
} else if (mystrcmp(&p, "yshad")) {
double val;
if (mystrtod(&p, &val))
else
val = 0.;
render_priv->state.shadow_y = val;
+ render_priv->state.bm_run_id++;
} else if (mystrcmp(&p, "fax")) {
double val;
if (mystrtod(&p, &val))
render_priv->state.blur = val;
} else
render_priv->state.blur = 0.0;
+ render_priv->state.bm_run_id++;
// ASS standard tags
} else if (mystrcmp(&p, "fsc")) {
char tp = *p++;
} else
val = -1.; // reset to default
change_border(render_priv, val, val);
+ render_priv->state.bm_run_id++;
} else if (mystrcmp(&p, "move")) {
double x1, x2, y1, y2;
long long t1, t2, delta_t, t;
change_alpha(&render_priv->state.c[3],
render_priv->state.style->BackColour, pwr);
}
+ render_priv->state.bm_run_id++;
// FIXME: simplify
} else if (mystrcmp(&p, "an")) {
int val;
val = render_priv->state.style->PrimaryColour;
ass_msg(render_priv->library, MSGL_DBG2, "color: %X", val);
change_color(&render_priv->state.c[0], val, pwr);
+ render_priv->state.bm_run_id++;
} else if ((*p >= '1') && (*p <= '4') && (++p)
&& (mystrcmp(&p, "c") || mystrcmp(&p, "a"))) {
char n = *(p - 2);
switch (cmd) {
case 'c':
change_color(render_priv->state.c + cidx, val, pwr);
+ render_priv->state.bm_run_id++;
break;
case 'a':
change_alpha(render_priv->state.c + cidx, val >> 24, pwr);
+ render_priv->state.bm_run_id++;
break;
default:
ass_msg(render_priv->library, MSGL_WARN, "Bad command: %c%c",
render_priv->state.be = val;
} else
render_priv->state.be = 0;
+ render_priv->state.bm_run_id++;
} else if (mystrcmp(&p, "b")) {
int b;
if (mystrtoi(&p, &b)) {
} else
val = 0.;
render_priv->state.shadow_x = render_priv->state.shadow_y = val;
+ render_priv->state.bm_run_id++;
} else if (mystrcmp(&p, "s")) {
int val;
if (mystrtoi(&p, &val) && val)
render_priv->state.flags |= DECO_STRIKETHROUGH;
else
render_priv->state.flags &= ~DECO_STRIKETHROUGH;
+ render_priv->state.bm_run_id++;
} else if (mystrcmp(&p, "u")) {
int val;
if (mystrtoi(&p, &val) && val)
render_priv->state.flags |= DECO_UNDERLINE;
else
render_priv->state.flags &= ~DECO_UNDERLINE;
+ render_priv->state.bm_run_id++;
} else if (mystrcmp(&p, "pbo")) {
double val = 0;
if (mystrtod(&p, &val))
bbox->xMin = bbox->xMax = bbox->yMin = bbox->yMax = 0.;
}
+/**
+ * \brief Compute the size of the target bitmap for a run of outlines.
+ * \param run first outline of the run
+ * \param len run length
+ * \param w returns target width, in pixels
+ * \param h returns target height, in pixels
+ */
+static void compute_run_size(GlyphInfo *run, size_t len, int *w, int *h)
+{
+ int i;
+ FT_BBox bbox;
+ bbox.xMin = bbox.yMin = INT_MAX;
+ bbox.xMax = bbox.yMax = INT_MIN;
+
+ for (i = 0; i < len; i++) {
+ GlyphInfo *info = run + i;
+ if (info->skip || info->symbol == 0 || info->symbol == '\n')
+ continue;
+ bbox.xMin = FFMIN(bbox.xMin, info->pos.x + info->bbox.xMin);
+ bbox.yMin = FFMIN(bbox.yMin, info->pos.y + info->bbox.yMin);
+ bbox.xMax = FFMAX(bbox.xMax, info->pos.x + info->bbox.xMax);
+ bbox.yMax = FFMAX(bbox.yMax, info->pos.y + info->bbox.yMax);
+ }
+ bbox.xMin &= ~63;
+ bbox.yMin &= ~63;
+ bbox.xMax = (bbox.xMax + 63) & ~63;
+ bbox.yMax = (bbox.yMax + 63) & ~63;
+ *w = (bbox.xMax - bbox.xMin) >> 6;
+ *h = (bbox.yMax - bbox.yMin) >> 6;
+}
+
/**
* \brief partially reset render_context to style values
* Works like {\r}: resets some style overrides
render_priv->state.effect_type = EF_NONE;
render_priv->state.effect_timing = 0;
render_priv->state.effect_skip_timing = 0;
+ render_priv->state.bm_run_id = 0;
ass_drawing_free(render_priv->state.drawing);
render_priv->state.drawing = ass_drawing_new(render_priv->library,
render_priv->ftlibrary);
double pen_shift_x;
double pen_shift_y;
int cur_line;
+ int run_offset;
TextInfo *text_info = &render_priv->text_info;
last_space = -1;
pen_shift_x = 0.;
pen_shift_y = 0.;
cur_line = 1;
+ run_offset = 0;
i = 0;
cur = text_info->glyphs + i;
text_info->lines[cur_line - 1].desc +
text_info->lines[cur_line].asc;
cur_line++;
+ run_offset++;
pen_shift_x = d6_to_double(-cur->pos.x);
pen_shift_y += height + render_priv->settings.line_spacing;
ass_msg(render_priv->library, MSGL_DBG2,
"shifting from %d to %d by (%f, %f)", i,
text_info->length - 1, pen_shift_x, pen_shift_y);
}
+ cur->bm_run_id += run_offset;
cur->pos.x += double_to_d6(pen_shift_x);
cur->pos.y += double_to_d6(pen_shift_y);
}
glyphs[text_info->length].frz = render_priv->state.frz;
glyphs[text_info->length].fax = render_priv->state.fax;
glyphs[text_info->length].fay = render_priv->state.fay;
+ glyphs[text_info->length].bm_run_id = render_priv->state.bm_run_id;
// fill bitmap hash
glyphs[text_info->length].hash_key.type = BITMAP_OUTLINE;
get_bitmap_glyph(render_priv, glyphs + i);
}
+ // Compute runs and their bboxes
+ // XXX: currently does nothing visible/functional
+ for (i = 0; i < text_info->length; i++) {
+ GlyphInfo *g = glyphs + i;
+ OutlineBitmapHashKey *key = &g->hash_key.u.outline;
+ int w, h;
+
+ // skip non-visual glyphs
+ if (g->skip || g->symbol == '\n' || g->symbol == 0)
+ continue;
+
+ // Determine run length and compute run bbox
+ int run_len = 0;
+ int cur_run = g->bm_run_id;
+ while (g->bm_run_id == cur_run && (i + run_len) < text_info->length) {
+ g++;
+ run_len++;
+ }
+ g = glyphs + i;
+ compute_run_size(g, run_len, &w, &h);
+ //printf("run_id %d len %d size %d %d\n", g->bm_run_id, run_len, w, h);
+
+ i += run_len - 1;
+ }
+
memset(event_images, 0, sizeof(*event_images));
event_images->top = device_y - text_info->lines[0].asc;
event_images->height = text_info->height;