[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
|
||||
* 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.
|
||||
*
|
||||
* Return value: false if all shapers failed, true otherwise
|
||||
|
@ -266,6 +269,7 @@ hb_shape_justify (hb_font_t *font,
|
|||
{
|
||||
// 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)
|
||||
return hb_shape_full (font, buffer,
|
||||
features, num_features,
|
||||
|
@ -273,6 +277,8 @@ hb_shape_justify (hb_font_t *font,
|
|||
|
||||
hb_face_t *face = font->face;
|
||||
|
||||
/* Choose variation tag to use for justification. */
|
||||
|
||||
hb_tag_t tag = HB_TAG_NONE;
|
||||
hb_ot_var_axis_info_t axis_info;
|
||||
|
||||
|
@ -288,6 +294,7 @@ hb_shape_justify (hb_font_t *font,
|
|||
break;
|
||||
}
|
||||
|
||||
/* If no suitable variation axis found, can't justify. Just shape and return. */
|
||||
if (!tag)
|
||||
{
|
||||
if (hb_shape_full (font, buffer,
|
||||
|
@ -301,6 +308,7 @@ hb_shape_justify (hb_font_t *font,
|
|||
return false;
|
||||
}
|
||||
|
||||
/* Copy buffer text as we need it so we can shape multiple times. */
|
||||
unsigned text_len = buffer->len;
|
||||
auto *text_info = (hb_glyph_info_t *) hb_malloc (text_len * sizeof (buffer->info[0]));
|
||||
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]));
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
/* 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)
|
||||
return true;
|
||||
|
||||
/* Prepare for running the solver. */
|
||||
double a, b, ya, yb;
|
||||
if (*advance < min_target_advance)
|
||||
{
|
||||
/* Need to expand. */
|
||||
ya = (double) *advance;
|
||||
a = (double) axis_info.default_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);
|
||||
reset_buffer (buffer, text);
|
||||
if (!hb_shape_full (font, buffer,
|
||||
|
@ -335,6 +351,8 @@ hb_shape_justify (hb_font_t *font,
|
|||
shaper_list))
|
||||
return false;
|
||||
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)
|
||||
{
|
||||
*advance = (float) yb;
|
||||
|
@ -343,10 +361,13 @@ hb_shape_justify (hb_font_t *font,
|
|||
}
|
||||
else
|
||||
{
|
||||
/* Need to shrink. */
|
||||
yb = (double) *advance;
|
||||
a = (double) axis_info.min_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);
|
||||
reset_buffer (buffer, text);
|
||||
if (!hb_shape_full (font, buffer,
|
||||
|
@ -354,6 +375,8 @@ hb_shape_justify (hb_font_t *font,
|
|||
shaper_list))
|
||||
return false;
|
||||
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)
|
||||
{
|
||||
*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);
|
||||
bool failed = false;
|
||||
|
||||
|
|
Loading…
Reference in New Issue