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);
|
||||
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
|
||||
face_ptr face = *(face_set->begin());
|
||||
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);
|
||||
if (tmp.glyph_index == 0) continue; // Skip unknown characters
|
||||
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.face = face;
|
||||
tmp.format = text_item.format;
|
||||
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.update_max_char_height(face->get_char_height());
|
||||
|
|
|
@ -67,6 +67,7 @@ public:
|
|||
double get_char_height() const;
|
||||
|
||||
bool set_character_sizes(double size);
|
||||
bool set_unscaled_character_sizes();
|
||||
|
||||
void glyph_dimensions(glyph_info &glyph) const;
|
||||
|
||||
|
@ -88,6 +89,7 @@ public:
|
|||
|
||||
void add(face_ptr face);
|
||||
void set_character_sizes(double size);
|
||||
void set_unscaled_character_sizes();
|
||||
|
||||
unsigned size() const { return faces_.size(); }
|
||||
iterator begin() { return faces_.begin(); }
|
||||
|
|
|
@ -42,25 +42,43 @@ struct glyph_info
|
|||
: glyph_index(0),
|
||||
face(nullptr),
|
||||
char_index(0),
|
||||
width(0.0),
|
||||
ymin(0.0),
|
||||
ymax(0.0),
|
||||
line_height(0.0),
|
||||
unscaled_ymin(0.0),
|
||||
unscaled_ymax(0.0),
|
||||
unscaled_width(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(),
|
||||
format() {}
|
||||
glyph_index_t glyph_index;
|
||||
face_ptr face;
|
||||
// Position in the string of all characters i.e. before itemizing
|
||||
unsigned char_index;
|
||||
double width;
|
||||
double ymin;
|
||||
double ymax;
|
||||
double unscaled_ymin;
|
||||
double unscaled_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 spacing, but not additional user defined spacing
|
||||
double line_height;
|
||||
double unscaled_line_height;
|
||||
double scale_multiplier;
|
||||
pixel_position offset;
|
||||
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
|
||||
|
|
|
@ -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);
|
||||
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();
|
||||
for (; face_itr != face_end; ++face_itr)
|
||||
{
|
||||
|
@ -105,10 +105,11 @@ static void shape_text(text_line & line,
|
|||
tmp.face = face;
|
||||
tmp.format = text_item.format;
|
||||
face->glyph_dimensions(tmp);
|
||||
//tmp.width = positions[i].x_advance / 64.0; //Overwrite default width with better value provided by HarfBuzz
|
||||
tmp.width = positions[i].x_advance >> 6;
|
||||
tmp.scale_multiplier = (size / face->get_face()->units_per_EM);
|
||||
//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);
|
||||
width_map[glyphs[i].cluster] += tmp.width;
|
||||
width_map[glyphs[i].cluster] += tmp.advance();
|
||||
line.add_glyph(tmp, scale_factor);
|
||||
}
|
||||
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);
|
||||
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)
|
||||
{
|
||||
UBiDi *bidi = ubidi_openSized(length, 0, &err);
|
||||
|
@ -105,7 +105,8 @@ static void shape_text(text_line & line,
|
|||
tmp.face = face;
|
||||
tmp.format = text_item.format;
|
||||
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);
|
||||
++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);
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
//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_Done_Glyph(image);
|
||||
|
||||
glyph.ymin = glyph_bbox.yMin; //pixels!
|
||||
glyph.ymax = glyph_bbox.yMax;
|
||||
glyph.line_height = face_->size->metrics.height/64.0;
|
||||
// TODO: we round to integers for now to maintain
|
||||
// back compatibility with Mapnik 2.x
|
||||
//glyph.width = face_->glyph->advance.x/64.0;
|
||||
glyph.width = face_->glyph->advance.x >> 6;
|
||||
glyph.unscaled_ymin = glyph_bbox.yMin;
|
||||
glyph.unscaled_ymax = glyph_bbox.yMax;
|
||||
|
||||
glyph.unscaled_width = glyph_bbox.xMax - glyph_bbox.xMin;
|
||||
glyph.unscaled_height = glyph_bbox.yMax - glyph_bbox.yMin;
|
||||
glyph.unscaled_advance = face_->glyph->advance.x;
|
||||
|
||||
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));
|
||||
}
|
||||
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
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
|
||||
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.x = pos.x + char_height/2.0*rot.sin;
|
||||
|
||||
cluster_offset.x += rot.cos * glyph.width;
|
||||
cluster_offset.y -= rot.sin * glyph.width;
|
||||
cluster_offset.x += rot.cos * glyph.advance();
|
||||
cluster_offset.y -= rot.sin * glyph.advance();
|
||||
|
||||
box2d<double> bbox = get_bbox(layout, glyph, pos, rot);
|
||||
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)!
|
||||
*/
|
||||
double width = layout.cluster_width(glyph.char_index);
|
||||
if (glyph.width <= 0) width = -width;
|
||||
if (glyph.advance() <= 0) width = -width;
|
||||
pixel_position tmp, tmp2;
|
||||
tmp.set(0, glyph.ymax);
|
||||
tmp.set(0, glyph.ymax());
|
||||
tmp = tmp.rotate(rot);
|
||||
tmp2.set(width, glyph.ymax);
|
||||
tmp2.set(width, glyph.ymax());
|
||||
tmp2 = tmp2.rotate(rot);
|
||||
box2d<double> bbox(tmp.x, -tmp.y,
|
||||
tmp2.x, -tmp2.y);
|
||||
tmp.set(width, glyph.ymin);
|
||||
tmp.set(width, glyph.ymin());
|
||||
tmp = tmp.rotate(rot);
|
||||
bbox.expand_to_include(tmp.x, -tmp.y);
|
||||
tmp.set(0, glyph.ymin);
|
||||
tmp.set(0, glyph.ymin());
|
||||
tmp = tmp.rotate(rot);
|
||||
bbox.expand_to_include(tmp.x, -tmp.y);
|
||||
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_)
|
||||
{
|
||||
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())
|
||||
{
|
||||
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.
|
||||
width_ += glyph.width + glyphs_.back().format->character_spacing * scale_factor_;
|
||||
width_ += advance + glyphs_.back().format->character_spacing * scale_factor_;
|
||||
}
|
||||
glyphs_.push_back(glyph);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue