[justify] Document algorithm
This commit is contained in:
parent
c98bb4cf9c
commit
43dbdd9db6
|
@ -246,6 +246,9 @@ reset_buffer (hb_buffer_t *buffer,
|
||||||
* In addition, justify the shaping results such that the shaping results reach
|
* In addition, justify the shaping results such that the shaping results reach
|
||||||
* the target advance width/height, depending on the buffer direction.
|
* the target advance width/height, depending on the buffer direction.
|
||||||
*
|
*
|
||||||
|
* If the advance of the buffer shaped with hb_shape_full() is already known,
|
||||||
|
* put that in *advance. Otherwise set *advance to zero.
|
||||||
|
*
|
||||||
* This API is currently experimental and will probably change in the future.
|
* This API is currently experimental and will probably change in the future.
|
||||||
*
|
*
|
||||||
* Return value: false if all shapers failed, true otherwise
|
* Return value: false if all shapers failed, true otherwise
|
||||||
|
@ -266,6 +269,7 @@ hb_shape_justify (hb_font_t *font,
|
||||||
{
|
{
|
||||||
// TODO Negative font scales?
|
// TODO Negative font scales?
|
||||||
|
|
||||||
|
/* If default advance already matches target, nothing to do. Shape and return. */
|
||||||
if (min_target_advance <= *advance && *advance <= max_target_advance)
|
if (min_target_advance <= *advance && *advance <= max_target_advance)
|
||||||
return hb_shape_full (font, buffer,
|
return hb_shape_full (font, buffer,
|
||||||
features, num_features,
|
features, num_features,
|
||||||
|
@ -273,6 +277,8 @@ hb_shape_justify (hb_font_t *font,
|
||||||
|
|
||||||
hb_face_t *face = font->face;
|
hb_face_t *face = font->face;
|
||||||
|
|
||||||
|
/* Choose variation tag to use for justification. */
|
||||||
|
|
||||||
hb_tag_t tag = HB_TAG_NONE;
|
hb_tag_t tag = HB_TAG_NONE;
|
||||||
hb_ot_var_axis_info_t axis_info;
|
hb_ot_var_axis_info_t axis_info;
|
||||||
|
|
||||||
|
@ -288,6 +294,7 @@ hb_shape_justify (hb_font_t *font,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If no suitable variation axis found, can't justify. Just shape and return. */
|
||||||
if (!tag)
|
if (!tag)
|
||||||
{
|
{
|
||||||
if (hb_shape_full (font, buffer,
|
if (hb_shape_full (font, buffer,
|
||||||
|
@ -301,6 +308,7 @@ hb_shape_justify (hb_font_t *font,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Copy buffer text as we need it so we can shape multiple times. */
|
||||||
unsigned text_len = buffer->len;
|
unsigned text_len = buffer->len;
|
||||||
auto *text_info = (hb_glyph_info_t *) hb_malloc (text_len * sizeof (buffer->info[0]));
|
auto *text_info = (hb_glyph_info_t *) hb_malloc (text_len * sizeof (buffer->info[0]));
|
||||||
if (unlikely (text_len && !text_info))
|
if (unlikely (text_len && !text_info))
|
||||||
|
@ -308,6 +316,7 @@ hb_shape_justify (hb_font_t *font,
|
||||||
hb_memcpy (text_info, buffer->info, text_len * sizeof (buffer->info[0]));
|
hb_memcpy (text_info, buffer->info, text_len * sizeof (buffer->info[0]));
|
||||||
auto text = hb_array<const hb_glyph_info_t> (text_info, text_len);
|
auto text = hb_array<const hb_glyph_info_t> (text_info, text_len);
|
||||||
|
|
||||||
|
/* If default advance was not provided to us, calculate it. */
|
||||||
if (!*advance)
|
if (!*advance)
|
||||||
{
|
{
|
||||||
hb_font_set_variation (font, tag, axis_info.default_value);
|
hb_font_set_variation (font, tag, axis_info.default_value);
|
||||||
|
@ -318,16 +327,23 @@ hb_shape_justify (hb_font_t *font,
|
||||||
*advance = buffer_advance (buffer);
|
*advance = buffer_advance (buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If default advance already matches target, nothing to do. Shape and return.
|
||||||
|
* Do this again, in case advance was just calculated.
|
||||||
|
*/
|
||||||
if (min_target_advance <= *advance && *advance <= max_target_advance)
|
if (min_target_advance <= *advance && *advance <= max_target_advance)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
/* Prepare for running the solver. */
|
||||||
double a, b, ya, yb;
|
double a, b, ya, yb;
|
||||||
if (*advance < min_target_advance)
|
if (*advance < min_target_advance)
|
||||||
{
|
{
|
||||||
|
/* Need to expand. */
|
||||||
ya = (double) *advance;
|
ya = (double) *advance;
|
||||||
a = (double) axis_info.default_value;
|
a = (double) axis_info.default_value;
|
||||||
b = (double) axis_info.max_value;
|
b = (double) axis_info.max_value;
|
||||||
|
|
||||||
|
/* Shape buffer for maximum expansion to use as other
|
||||||
|
* starting point for the solver. */
|
||||||
hb_font_set_variation (font, tag, (float) b);
|
hb_font_set_variation (font, tag, (float) b);
|
||||||
reset_buffer (buffer, text);
|
reset_buffer (buffer, text);
|
||||||
if (!hb_shape_full (font, buffer,
|
if (!hb_shape_full (font, buffer,
|
||||||
|
@ -335,6 +351,8 @@ hb_shape_justify (hb_font_t *font,
|
||||||
shaper_list))
|
shaper_list))
|
||||||
return false;
|
return false;
|
||||||
yb = (double) buffer_advance (buffer);
|
yb = (double) buffer_advance (buffer);
|
||||||
|
/* If the maximum expansion is less than max target,
|
||||||
|
* there's nothing to solve for. Just return it. */
|
||||||
if (yb <= (double) max_target_advance)
|
if (yb <= (double) max_target_advance)
|
||||||
{
|
{
|
||||||
*advance = (float) yb;
|
*advance = (float) yb;
|
||||||
|
@ -343,10 +361,13 @@ hb_shape_justify (hb_font_t *font,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
/* Need to shrink. */
|
||||||
yb = (double) *advance;
|
yb = (double) *advance;
|
||||||
a = (double) axis_info.min_value;
|
a = (double) axis_info.min_value;
|
||||||
b = (double) axis_info.default_value;
|
b = (double) axis_info.default_value;
|
||||||
|
|
||||||
|
/* Shape buffer for maximum shrinkate to use as other
|
||||||
|
* starting point for the solver. */
|
||||||
hb_font_set_variation (font, tag, (float) a);
|
hb_font_set_variation (font, tag, (float) a);
|
||||||
reset_buffer (buffer, text);
|
reset_buffer (buffer, text);
|
||||||
if (!hb_shape_full (font, buffer,
|
if (!hb_shape_full (font, buffer,
|
||||||
|
@ -354,6 +375,8 @@ hb_shape_justify (hb_font_t *font,
|
||||||
shaper_list))
|
shaper_list))
|
||||||
return false;
|
return false;
|
||||||
ya = (double) buffer_advance (buffer);
|
ya = (double) buffer_advance (buffer);
|
||||||
|
/* If the maximum shrinkate is more than min target,
|
||||||
|
* there's nothing to solve for. Just return it. */
|
||||||
if (ya >= (double) min_target_advance)
|
if (ya >= (double) min_target_advance)
|
||||||
{
|
{
|
||||||
*advance = (float) ya;
|
*advance = (float) ya;
|
||||||
|
@ -361,6 +384,9 @@ hb_shape_justify (hb_font_t *font,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Run the solver to find a var axis value that hits
|
||||||
|
* the desired width. */
|
||||||
|
|
||||||
double epsilon = (b - a) / (1<<14);
|
double epsilon = (b - a) / (1<<14);
|
||||||
bool failed = false;
|
bool failed = false;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue