first attempt at unscaled glyph dimensions

This commit is contained in:
Mike Morris 2014-06-11 19:56:55 -04:00
parent d0b357cab7
commit 2b843ec6a9
8 changed files with 80 additions and 38 deletions

View file

@ -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());

View file

@ -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(); }

View file

@ -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

View file

@ -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());

View file

@ -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;
} }

View file

@ -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)

View file

@ -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);

View file

@ -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);
} }