first attempt at unscaled glyph dimensions
This commit is contained in:
parent
d0b357cab7
commit
2b843ec6a9
8 changed files with 80 additions and 38 deletions
|
@ -61,7 +61,7 @@ static void shape_text(text_line & line,
|
||||||
{
|
{
|
||||||
face_set_ptr face_set = font_manager.get_face_set(text_item.format->face_name, text_item.format->fontset);
|
face_set_ptr face_set = font_manager.get_face_set(text_item.format->face_name, text_item.format->fontset);
|
||||||
double size = text_item.format->text_size * scale_factor;
|
double size = text_item.format->text_size * scale_factor;
|
||||||
face_set->set_character_sizes(size);
|
face_set->set_unscaled_character_sizes();
|
||||||
if (face_set->begin() == face_set->end()) return; // Invalid face set
|
if (face_set->begin() == face_set->end()) return; // Invalid face set
|
||||||
face_ptr face = *(face_set->begin());
|
face_ptr face = *(face_set->begin());
|
||||||
FT_Face freetype_face = face->get_face();
|
FT_Face freetype_face = face->get_face();
|
||||||
|
@ -73,12 +73,14 @@ static void shape_text(text_line & line,
|
||||||
tmp.glyph_index = FT_Get_Char_Index(freetype_face, c);
|
tmp.glyph_index = FT_Get_Char_Index(freetype_face, c);
|
||||||
if (tmp.glyph_index == 0) continue; // Skip unknown characters
|
if (tmp.glyph_index == 0) continue; // Skip unknown characters
|
||||||
tmp.char_index = i;
|
tmp.char_index = i;
|
||||||
tmp.width = 0; // Filled in by glyph_dimensions
|
tmp.unscaled_width = 0; // Filled in by glyph_dimensions
|
||||||
tmp.offset.clear();
|
tmp.offset.clear();
|
||||||
tmp.face = face;
|
tmp.face = face;
|
||||||
tmp.format = text_item.format;
|
tmp.format = text_item.format;
|
||||||
face->glyph_dimensions(tmp);
|
face->glyph_dimensions(tmp);
|
||||||
width_map[i] += tmp.width;
|
tmp.scale_multiplier = (size / face->get_face()->units_per_EM);
|
||||||
|
std::cout << tmp.unscaled_advance;
|
||||||
|
width_map[i] += tmp.advance();
|
||||||
line.add_glyph(tmp, scale_factor);
|
line.add_glyph(tmp, scale_factor);
|
||||||
}
|
}
|
||||||
line.update_max_char_height(face->get_char_height());
|
line.update_max_char_height(face->get_char_height());
|
||||||
|
|
|
@ -67,6 +67,7 @@ public:
|
||||||
double get_char_height() const;
|
double get_char_height() const;
|
||||||
|
|
||||||
bool set_character_sizes(double size);
|
bool set_character_sizes(double size);
|
||||||
|
bool set_unscaled_character_sizes();
|
||||||
|
|
||||||
void glyph_dimensions(glyph_info &glyph) const;
|
void glyph_dimensions(glyph_info &glyph) const;
|
||||||
|
|
||||||
|
@ -88,6 +89,7 @@ public:
|
||||||
|
|
||||||
void add(face_ptr face);
|
void add(face_ptr face);
|
||||||
void set_character_sizes(double size);
|
void set_character_sizes(double size);
|
||||||
|
void set_unscaled_character_sizes();
|
||||||
|
|
||||||
unsigned size() const { return faces_.size(); }
|
unsigned size() const { return faces_.size(); }
|
||||||
iterator begin() { return faces_.begin(); }
|
iterator begin() { return faces_.begin(); }
|
||||||
|
|
|
@ -42,25 +42,43 @@ struct glyph_info
|
||||||
: glyph_index(0),
|
: glyph_index(0),
|
||||||
face(nullptr),
|
face(nullptr),
|
||||||
char_index(0),
|
char_index(0),
|
||||||
width(0.0),
|
unscaled_ymin(0.0),
|
||||||
ymin(0.0),
|
unscaled_ymax(0.0),
|
||||||
ymax(0.0),
|
unscaled_width(0.0),
|
||||||
line_height(0.0),
|
unscaled_height(0.0),
|
||||||
|
unscaled_advance(0.0),
|
||||||
|
unscaled_ascender(0.0),
|
||||||
|
unscaled_descender(0.0),
|
||||||
|
unscaled_line_height(0.0),
|
||||||
|
scale_multiplier(0.0),
|
||||||
offset(),
|
offset(),
|
||||||
format() {}
|
format() {}
|
||||||
glyph_index_t glyph_index;
|
glyph_index_t glyph_index;
|
||||||
face_ptr face;
|
face_ptr face;
|
||||||
// Position in the string of all characters i.e. before itemizing
|
// Position in the string of all characters i.e. before itemizing
|
||||||
unsigned char_index;
|
unsigned char_index;
|
||||||
double width;
|
double unscaled_ymin;
|
||||||
double ymin;
|
double unscaled_ymax;
|
||||||
double ymax;
|
double unscaled_width;
|
||||||
|
double unscaled_height;
|
||||||
|
double unscaled_advance;
|
||||||
|
double unscaled_ascender;
|
||||||
|
double unscaled_descender;
|
||||||
// Line height returned by freetype, includes normal font
|
// Line height returned by freetype, includes normal font
|
||||||
// line spacing, but not additional user defined spacing
|
// line spacing, but not additional user defined spacing
|
||||||
double line_height;
|
double unscaled_line_height;
|
||||||
|
double scale_multiplier;
|
||||||
pixel_position offset;
|
pixel_position offset;
|
||||||
char_properties_ptr format;
|
char_properties_ptr format;
|
||||||
double height() const { return ymax-ymin; }
|
|
||||||
|
double ymin() const { return unscaled_ymin * scale_multiplier; }
|
||||||
|
double ymax() const { return unscaled_ymax * scale_multiplier; }
|
||||||
|
double width() const { return unscaled_width * scale_multiplier; };
|
||||||
|
double height() const { return unscaled_height * scale_multiplier; };
|
||||||
|
double advance() const { return unscaled_advance * scale_multiplier; };
|
||||||
|
double ascender() const { return unscaled_ascender * scale_multiplier; };
|
||||||
|
double descender() const { return unscaled_descender * scale_multiplier; };
|
||||||
|
double line_height() const { return unscaled_line_height * scale_multiplier; };
|
||||||
};
|
};
|
||||||
|
|
||||||
} //ns mapnik
|
} //ns mapnik
|
||||||
|
|
|
@ -63,7 +63,7 @@ static void shape_text(text_line & line,
|
||||||
{
|
{
|
||||||
face_set_ptr face_set = font_manager.get_face_set(text_item.format->face_name, text_item.format->fontset);
|
face_set_ptr face_set = font_manager.get_face_set(text_item.format->face_name, text_item.format->fontset);
|
||||||
double size = text_item.format->text_size * scale_factor;
|
double size = text_item.format->text_size * scale_factor;
|
||||||
face_set->set_character_sizes(size);
|
face_set->set_unscaled_character_sizes();
|
||||||
font_face_set::iterator face_itr = face_set->begin(), face_end = face_set->end();
|
font_face_set::iterator face_itr = face_set->begin(), face_end = face_set->end();
|
||||||
for (; face_itr != face_end; ++face_itr)
|
for (; face_itr != face_end; ++face_itr)
|
||||||
{
|
{
|
||||||
|
@ -105,10 +105,11 @@ static void shape_text(text_line & line,
|
||||||
tmp.face = face;
|
tmp.face = face;
|
||||||
tmp.format = text_item.format;
|
tmp.format = text_item.format;
|
||||||
face->glyph_dimensions(tmp);
|
face->glyph_dimensions(tmp);
|
||||||
//tmp.width = positions[i].x_advance / 64.0; //Overwrite default width with better value provided by HarfBuzz
|
tmp.scale_multiplier = (size / face->get_face()->units_per_EM);
|
||||||
tmp.width = positions[i].x_advance >> 6;
|
//Overwrite default advance with better value provided by HarfBuzz
|
||||||
|
tmp.unscaled_advance = positions[i].x_advance;
|
||||||
tmp.offset.set(positions[i].x_offset / 64.0, positions[i].y_offset / 64.0);
|
tmp.offset.set(positions[i].x_offset / 64.0, positions[i].y_offset / 64.0);
|
||||||
width_map[glyphs[i].cluster] += tmp.width;
|
width_map[glyphs[i].cluster] += tmp.advance();
|
||||||
line.add_glyph(tmp, scale_factor);
|
line.add_glyph(tmp, scale_factor);
|
||||||
}
|
}
|
||||||
line.update_max_char_height(face->get_char_height());
|
line.update_max_char_height(face->get_char_height());
|
||||||
|
|
|
@ -65,7 +65,7 @@ static void shape_text(text_line & line,
|
||||||
{
|
{
|
||||||
face_set_ptr face_set = font_manager.get_face_set(text_item.format->face_name, text_item.format->fontset);
|
face_set_ptr face_set = font_manager.get_face_set(text_item.format->face_name, text_item.format->fontset);
|
||||||
double size = text_item.format->text_size * scale_factor;
|
double size = text_item.format->text_size * scale_factor;
|
||||||
face_set->set_character_sizes(size);
|
face_set->set_unscaled_character_sizes();
|
||||||
for (auto const& face : *face_set)
|
for (auto const& face : *face_set)
|
||||||
{
|
{
|
||||||
UBiDi *bidi = ubidi_openSized(length, 0, &err);
|
UBiDi *bidi = ubidi_openSized(length, 0, &err);
|
||||||
|
@ -105,7 +105,8 @@ static void shape_text(text_line & line,
|
||||||
tmp.face = face;
|
tmp.face = face;
|
||||||
tmp.format = text_item.format;
|
tmp.format = text_item.format;
|
||||||
face->glyph_dimensions(tmp);
|
face->glyph_dimensions(tmp);
|
||||||
width_map[i] += tmp.width;
|
tmp.scale_multiplier = (size / face->get_face()->units_per_EM) / 64.0;
|
||||||
|
width_map[i] += tmp.advance();
|
||||||
line.add_glyph(tmp, scale_factor);
|
line.add_glyph(tmp, scale_factor);
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,6 +52,12 @@ bool font_face::set_character_sizes(double size)
|
||||||
return !FT_Set_Char_Size(face_,0,(FT_F26Dot6)(size * (1<<6)),0,0);
|
return !FT_Set_Char_Size(face_,0,(FT_F26Dot6)(size * (1<<6)),0,0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool font_face::set_unscaled_character_sizes()
|
||||||
|
{
|
||||||
|
char_height_ = 0.0;
|
||||||
|
return !FT_Set_Char_Size(face_,0,face_->units_per_EM,0,0);
|
||||||
|
}
|
||||||
|
|
||||||
void font_face::glyph_dimensions(glyph_info & glyph) const
|
void font_face::glyph_dimensions(glyph_info & glyph) const
|
||||||
{
|
{
|
||||||
//TODO
|
//TODO
|
||||||
|
@ -85,13 +91,16 @@ void font_face::glyph_dimensions(glyph_info & glyph) const
|
||||||
FT_Glyph_Get_CBox(image, ft_glyph_bbox_pixels, &glyph_bbox);
|
FT_Glyph_Get_CBox(image, ft_glyph_bbox_pixels, &glyph_bbox);
|
||||||
FT_Done_Glyph(image);
|
FT_Done_Glyph(image);
|
||||||
|
|
||||||
glyph.ymin = glyph_bbox.yMin; //pixels!
|
glyph.unscaled_ymin = glyph_bbox.yMin;
|
||||||
glyph.ymax = glyph_bbox.yMax;
|
glyph.unscaled_ymax = glyph_bbox.yMax;
|
||||||
glyph.line_height = face_->size->metrics.height/64.0;
|
|
||||||
// TODO: we round to integers for now to maintain
|
glyph.unscaled_width = glyph_bbox.xMax - glyph_bbox.xMin;
|
||||||
// back compatibility with Mapnik 2.x
|
glyph.unscaled_height = glyph_bbox.yMax - glyph_bbox.yMin;
|
||||||
//glyph.width = face_->glyph->advance.x/64.0;
|
glyph.unscaled_advance = face_->glyph->advance.x;
|
||||||
glyph.width = face_->glyph->advance.x >> 6;
|
|
||||||
|
glyph.unscaled_ascender = face_->size->metrics.ascender;
|
||||||
|
glyph.unscaled_descender = face_->size->metrics.descender;
|
||||||
|
glyph.unscaled_line_height = face_->size->metrics.height;
|
||||||
|
|
||||||
//TODO: dimension_cache_.insert(std::pair<unsigned, char_info>(c, dim));
|
//TODO: dimension_cache_.insert(std::pair<unsigned, char_info>(c, dim));
|
||||||
}
|
}
|
||||||
|
@ -120,6 +129,14 @@ void font_face_set::set_character_sizes(double size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void font_face_set::set_unscaled_character_sizes()
|
||||||
|
{
|
||||||
|
for (face_ptr const& face : faces_)
|
||||||
|
{
|
||||||
|
face->set_unscaled_character_sizes();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
void stroker::init(double radius)
|
void stroker::init(double radius)
|
||||||
|
|
|
@ -157,10 +157,10 @@ bool placement_finder::find_point_placement(pixel_position const& pos)
|
||||||
{
|
{
|
||||||
// place the character relative to the center of the string envelope
|
// place the character relative to the center of the string envelope
|
||||||
glyphs->push_back(glyph, (pixel_position(x, y).rotate(orientation)) + layout_offset, orientation);
|
glyphs->push_back(glyph, (pixel_position(x, y).rotate(orientation)) + layout_offset, orientation);
|
||||||
if (glyph.width)
|
if (glyph.advance())
|
||||||
{
|
{
|
||||||
//Only advance if glyph is not part of a multiple glyph sequence
|
//Only advance if glyph is not part of a multiple glyph sequence
|
||||||
x += glyph.width + glyph.format->character_spacing * scale_factor_;
|
x += glyph.advance() + glyph.format->character_spacing * scale_factor_;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -313,8 +313,8 @@ bool placement_finder::single_line_placement(vertex_cache &pp, text_upright_e or
|
||||||
pos.y = -pos.y - char_height/2.0*rot.cos;
|
pos.y = -pos.y - char_height/2.0*rot.cos;
|
||||||
pos.x = pos.x + char_height/2.0*rot.sin;
|
pos.x = pos.x + char_height/2.0*rot.sin;
|
||||||
|
|
||||||
cluster_offset.x += rot.cos * glyph.width;
|
cluster_offset.x += rot.cos * glyph.advance();
|
||||||
cluster_offset.y -= rot.sin * glyph.width;
|
cluster_offset.y -= rot.sin * glyph.advance();
|
||||||
|
|
||||||
box2d<double> bbox = get_bbox(layout, glyph, pos, rot);
|
box2d<double> bbox = get_bbox(layout, glyph, pos, rot);
|
||||||
if (collision(bbox)) return false;
|
if (collision(bbox)) return false;
|
||||||
|
@ -446,18 +446,18 @@ box2d<double> placement_finder::get_bbox(text_layout const& layout, glyph_info c
|
||||||
Add glyph offset in y direction, but not in x direction (as we use the full cluster width anyways)!
|
Add glyph offset in y direction, but not in x direction (as we use the full cluster width anyways)!
|
||||||
*/
|
*/
|
||||||
double width = layout.cluster_width(glyph.char_index);
|
double width = layout.cluster_width(glyph.char_index);
|
||||||
if (glyph.width <= 0) width = -width;
|
if (glyph.advance() <= 0) width = -width;
|
||||||
pixel_position tmp, tmp2;
|
pixel_position tmp, tmp2;
|
||||||
tmp.set(0, glyph.ymax);
|
tmp.set(0, glyph.ymax());
|
||||||
tmp = tmp.rotate(rot);
|
tmp = tmp.rotate(rot);
|
||||||
tmp2.set(width, glyph.ymax);
|
tmp2.set(width, glyph.ymax());
|
||||||
tmp2 = tmp2.rotate(rot);
|
tmp2 = tmp2.rotate(rot);
|
||||||
box2d<double> bbox(tmp.x, -tmp.y,
|
box2d<double> bbox(tmp.x, -tmp.y,
|
||||||
tmp2.x, -tmp2.y);
|
tmp2.x, -tmp2.y);
|
||||||
tmp.set(width, glyph.ymin);
|
tmp.set(width, glyph.ymin());
|
||||||
tmp = tmp.rotate(rot);
|
tmp = tmp.rotate(rot);
|
||||||
bbox.expand_to_include(tmp.x, -tmp.y);
|
bbox.expand_to_include(tmp.x, -tmp.y);
|
||||||
tmp.set(0, glyph.ymin);
|
tmp.set(0, glyph.ymin());
|
||||||
tmp = tmp.rotate(rot);
|
tmp = tmp.rotate(rot);
|
||||||
bbox.expand_to_include(tmp.x, -tmp.y);
|
bbox.expand_to_include(tmp.x, -tmp.y);
|
||||||
pixel_position pos2 = pos + pixel_position(0, glyph.offset.y).rotate(rot);
|
pixel_position pos2 = pos + pixel_position(0, glyph.offset.y).rotate(rot);
|
||||||
|
|
|
@ -36,15 +36,16 @@ text_line::text_line(unsigned first_char, unsigned last_char)
|
||||||
|
|
||||||
void text_line::add_glyph(glyph_info const& glyph, double scale_factor_)
|
void text_line::add_glyph(glyph_info const& glyph, double scale_factor_)
|
||||||
{
|
{
|
||||||
line_height_ = std::max(line_height_, glyph.line_height + glyph.format->line_spacing);
|
line_height_ = std::max(line_height_, glyph.line_height() + glyph.format->line_spacing);
|
||||||
|
double advance = glyph.advance();
|
||||||
if (glyphs_.empty())
|
if (glyphs_.empty())
|
||||||
{
|
{
|
||||||
width_ = glyph.width;
|
width_ = advance;
|
||||||
}
|
}
|
||||||
else if (glyph.width)
|
else if (advance)
|
||||||
{
|
{
|
||||||
// Only add character spacing if the character is not a zero-width part of a cluster.
|
// Only add character spacing if the character is not a zero-width part of a cluster.
|
||||||
width_ += glyph.width + glyphs_.back().format->character_spacing * scale_factor_;
|
width_ += advance + glyphs_.back().format->character_spacing * scale_factor_;
|
||||||
}
|
}
|
||||||
glyphs_.push_back(glyph);
|
glyphs_.push_back(glyph);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue