[paint] Add bitmap width/height to paint_image callback

Such that we can add raw data as well.
This commit is contained in:
Behdad Esfahbod 2022-12-22 12:16:55 -07:00
parent eef47f2379
commit c5f903872f
9 changed files with 75 additions and 36 deletions

View File

@ -81,14 +81,15 @@ struct SmallGlyphMetrics
return_trace (c->check_struct (this));
}
void get_extents (hb_font_t *font, hb_glyph_extents_t *extents) const
void get_extents (hb_font_t *font, hb_glyph_extents_t *extents, bool scale) const
{
extents->x_bearing = bearingX;
extents->y_bearing = bearingY;
extents->width = width;
extents->height = -static_cast<int> (height);
font->scale_glyph_extents (extents);
if (scale)
font->scale_glyph_extents (extents);
}
HBUINT8 height;
@ -310,7 +311,7 @@ struct IndexSubtable
}
}
bool get_extents (hb_glyph_extents_t *extents HB_UNUSED) const
bool get_extents (hb_glyph_extents_t *extents HB_UNUSED, bool scale HB_UNUSED) const
{
switch (u.header.indexFormat)
{
@ -507,8 +508,8 @@ struct IndexSubtableRecord
return num_missing;
}
bool get_extents (hb_glyph_extents_t *extents, const void *base) const
{ return (base+offsetToSubtable).get_extents (extents); }
bool get_extents (hb_glyph_extents_t *extents, const void *base, bool scale) const
{ return (base+offsetToSubtable).get_extents (extents, scale); }
bool get_image_data (unsigned int gid,
const void *base,
@ -836,7 +837,7 @@ struct CBDT
}
bool
get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const
get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents, bool scale = true) const
{
const void *base;
const BitmapSizeTable &strike = this->cblc->choose_strike (font);
@ -844,7 +845,7 @@ struct CBDT
if (!subtable_record || !strike.ppemX || !strike.ppemY)
return false;
if (subtable_record->get_extents (extents, base))
if (subtable_record->get_extents (extents, base, scale))
return true;
unsigned int image_offset = 0, image_length = 0, image_format = 0;
@ -861,26 +862,29 @@ struct CBDT
if (unlikely (image_length < GlyphBitmapDataFormat17::min_size))
return false;
auto &glyphFormat17 = StructAtOffset<GlyphBitmapDataFormat17> (this->cbdt, image_offset);
glyphFormat17.glyphMetrics.get_extents (font, extents);
glyphFormat17.glyphMetrics.get_extents (font, extents, scale);
break;
}
case 18: {
if (unlikely (image_length < GlyphBitmapDataFormat18::min_size))
return false;
auto &glyphFormat18 = StructAtOffset<GlyphBitmapDataFormat18> (this->cbdt, image_offset);
glyphFormat18.glyphMetrics.get_extents (font, extents);
glyphFormat18.glyphMetrics.get_extents (font, extents, scale);
break;
}
default: return false; /* TODO: Support other image formats. */
}
/* Convert to font units. */
float x_scale = upem / (float) strike.ppemX;
float y_scale = upem / (float) strike.ppemY;
extents->x_bearing = roundf (extents->x_bearing * x_scale);
extents->y_bearing = roundf (extents->y_bearing * y_scale);
extents->width = roundf (extents->width * x_scale);
extents->height = roundf (extents->height * y_scale);
if (scale)
{
float x_scale = upem / (float) strike.ppemX;
float y_scale = upem / (float) strike.ppemY;
extents->x_bearing = roundf (extents->x_bearing * x_scale);
extents->y_bearing = roundf (extents->y_bearing * y_scale);
extents->width = roundf (extents->width * x_scale);
extents->height = roundf (extents->height * y_scale);
}
return true;
}
@ -940,6 +944,7 @@ struct CBDT
bool paint_glyph (hb_font_t *font, hb_codepoint_t glyph, hb_paint_funcs_t *funcs, void *data) const
{
hb_glyph_extents_t extents;
hb_glyph_extents_t pixel_extents;
hb_blob_t *blob = reference_png (font, glyph);
if (unlikely (blob == hb_blob_get_empty ()))
@ -948,7 +953,15 @@ struct CBDT
if (unlikely (!hb_font_get_glyph_extents (font, glyph, &extents)))
return false;
funcs->image (data, blob, HB_PAINT_IMAGE_FORMAT_PNG, font->slant_xy, &extents);
if (unlikely (!get_extents (font, glyph, &pixel_extents, false)))
return false;
funcs->image (data,
blob,
pixel_extents.width, -pixel_extents.height,
HB_PAINT_IMAGE_FORMAT_PNG,
font->slant_xy,
&extents);
hb_blob_destroy (blob);
return true;

View File

@ -214,10 +214,11 @@ struct sbix
bool get_extents (hb_font_t *font,
hb_codepoint_t glyph,
hb_glyph_extents_t *extents) const
hb_glyph_extents_t *extents,
bool scale = true) const
{
/* We only support PNG right now, and following function checks type. */
return get_png_extents (font, glyph, extents);
return get_png_extents (font, glyph, extents, scale);
}
hb_blob_t *reference_png (hb_font_t *font,
@ -241,6 +242,7 @@ struct sbix
unsigned int strike_ppem = 0;
hb_blob_t *blob = reference_png (font, glyph, &x_offset, &y_offset, &strike_ppem);
hb_glyph_extents_t extents;
hb_glyph_extents_t pixel_extents;
if (blob == hb_blob_get_empty ())
return false;
@ -248,7 +250,15 @@ struct sbix
if (!hb_font_get_glyph_extents (font, glyph, &extents))
return false;
funcs->image (data, blob, HB_PAINT_IMAGE_FORMAT_PNG, font->slant_xy, &extents);
if (unlikely (!get_extents (font, glyph, &pixel_extents, false)))
return false;
funcs->image (data,
blob,
pixel_extents.width, -pixel_extents.height,
HB_PAINT_IMAGE_FORMAT_PNG,
font->slant_xy,
&extents);
hb_blob_destroy (blob);
return true;
@ -308,7 +318,8 @@ struct sbix
bool get_png_extents (hb_font_t *font,
hb_codepoint_t glyph,
hb_glyph_extents_t *extents) const
hb_glyph_extents_t *extents,
bool scale = true) const
{
/* Following code is safe to call even without data.
* But faster to short-circuit. */
@ -333,7 +344,7 @@ struct sbix
extents->height = -1 * png.IHDR.height;
/* Convert to font units. */
if (strike_ppem)
if (strike_ppem && scale)
{
float scale = font->face->get_upem () / (float) strike_ppem;
extents->x_bearing = roundf (extents->x_bearing * scale);
@ -341,15 +352,9 @@ struct sbix
extents->width = roundf (extents->width * scale);
extents->height = roundf (extents->height * scale);
}
else
{
extents->x_bearing = extents->x_bearing;
extents->y_bearing = extents->y_bearing;
extents->width = extents->width;
extents->height = extents->height;
}
font->scale_glyph_extents (extents);
if (scale)
font->scale_glyph_extents (extents);
hb_blob_destroy (blob);

View File

@ -103,7 +103,12 @@ struct SVG
if (blob == hb_blob_get_empty ())
return false;
funcs->image (data, blob, HB_PAINT_IMAGE_FORMAT_SVG, font->slant_xy, nullptr);
funcs->image (data,
blob,
0, 0,
HB_PAINT_IMAGE_FORMAT_SVG,
font->slant_xy,
nullptr);
hb_blob_destroy (blob);
return true;

View File

@ -77,6 +77,8 @@ hb_paint_color_nil (hb_paint_funcs_t *funcs, void *paint_data,
static void
hb_paint_image_nil (hb_paint_funcs_t *funcs, void *paint_data,
hb_blob_t *image,
unsigned int width,
unsigned int height,
hb_tag_t format,
float slant_xy,
hb_glyph_extents_t *extents,

View File

@ -243,9 +243,11 @@ typedef void (*hb_paint_color_func_t) (hb_paint_funcs_t *funcs,
* @funcs: paint functions object
* @paint_data: The data accompanying the paint functions in hb_font_paint_glyph()
* @image: the image data
* @width: width of the raster image in pixels
* @height: height of the raster image in pixels
* @format: the image format as a tag
* @slant: the synthetic slant of the font
* @extents: (nullable): glyph extents
* @slant: the synthetic slant ratio to be applied to the image during rendering
* @extents: (nullable): glyph extents for desired rendering
* @user_data: User data pointer passed to hb_paint_funcs_set_image_func()
*
* A virtual method for the #hb_paint_funcs_t to paint the
@ -264,6 +266,8 @@ typedef void (*hb_paint_color_func_t) (hb_paint_funcs_t *funcs,
typedef void (*hb_paint_image_func_t) (hb_paint_funcs_t *funcs,
void *paint_data,
hb_blob_t *image,
unsigned int width,
unsigned int height,
hb_tag_t format,
float slant,
hb_glyph_extents_t *extents,

View File

@ -99,11 +99,12 @@ struct hb_paint_funcs_t
!user_data ? nullptr : user_data->color); }
void image (void *paint_data,
hb_blob_t *image,
unsigned width, unsigned height,
hb_tag_t format,
float slant,
hb_glyph_extents_t *extents)
{ func.image (this, paint_data,
image, format, slant, extents,
image, width, height, format, slant, extents,
!user_data ? nullptr : user_data->image); }
void linear_gradient (void *paint_data,
hb_color_line_t *color_line,

View File

@ -99,6 +99,8 @@ read_blob (void *closure,
void
hb_cairo_paint_glyph_image (cairo_t *cr,
hb_blob_t *blob,
unsigned width,
unsigned height,
hb_tag_t format,
float slant,
hb_glyph_extents_t *extents)
@ -111,8 +113,11 @@ hb_cairo_paint_glyph_image (cairo_t *cr,
r.blob = blob;
r.offset = 0;
cairo_surface_t *surface = cairo_image_surface_create_from_png_stream (read_blob, &r);
int width = cairo_image_surface_get_width (surface);
int height = cairo_image_surface_get_width (surface);
/* For PNG, width,height can be unreliable, as is the case for NotoColorEmoji :(.
* Just pull them out of the surface. */
width = cairo_image_surface_get_width (surface);
height = cairo_image_surface_get_width (surface);
cairo_pattern_t *pattern = cairo_pattern_create_for_surface (surface);
cairo_pattern_set_extend (pattern, CAIRO_EXTEND_PAD);

View File

@ -72,6 +72,8 @@ hb_paint_composite_mode_to_cairo (hb_paint_composite_mode_t mode)
void hb_cairo_paint_glyph_image (cairo_t *cr,
hb_blob_t *blob,
unsigned width,
unsigned height,
hb_tag_t format,
float slant,
hb_glyph_extents_t *extents);

View File

@ -221,6 +221,8 @@ static void
paint_image (hb_paint_funcs_t *funcs,
void *paint_data,
hb_blob_t *blob,
unsigned width,
unsigned height,
hb_tag_t format,
float slant,
hb_glyph_extents_t *extents,
@ -228,7 +230,7 @@ paint_image (hb_paint_funcs_t *funcs,
{
cairo_t *cr = (cairo_t *)paint_data;
hb_cairo_paint_glyph_image (cr, blob, format, slant, extents);
hb_cairo_paint_glyph_image (cr, blob, width, height, format, slant, extents);
}
static void