Fix glyph widths after line breaking.

Fixes #1532.
This commit is contained in:
Hermann Kraus 2013-04-01 02:21:05 +02:00
parent 8ba49accf0
commit 74d72b9191
9 changed files with 120 additions and 3 deletions

View file

@ -108,6 +108,7 @@ private:
void break_line(text_line_ptr line, double wrap_width, unsigned text_ratio, bool wrap_before);
void shape_text(text_line_ptr line);
void add_line(text_line_ptr line);
void clear_cluster_widths(unsigned first, unsigned last);
//input
face_manager_freetype &font_manager_;
@ -115,7 +116,9 @@ private:
//processing
text_itemizer itemizer_;
/// Maps char index (UTF-16) to width. If multiple glyphs map to the same char the sum of all widths is used
/** Maps char index (UTF-16) to width. If multiple glyphs map to the same char the sum of all widths is used
note: this probably isn't the best solution. it would be better to have an object for each cluster, but
it needs to be implemented with no overhead. */
std::map<unsigned, double> width_map_;
double width_;
double height_;

View file

@ -83,7 +83,10 @@ void text_layout::break_line(text_line_ptr line, double wrap_width, unsigned tex
UErrorCode status = U_ZERO_ERROR;
BreakIterator *breakitr = BreakIterator::createLineInstance(locale, status);
//Not breaking the text if an error occurs is probably the best thing we can do.
if (!U_SUCCESS(status)) return;
if (!U_SUCCESS(status)) {
add_line(line);
return;
}
breakitr->setText(text);
unsigned current_line_length = 0;
unsigned last_break_position = 0;
@ -110,6 +113,7 @@ void text_layout::break_line(text_line_ptr line, double wrap_width, unsigned tex
}
}
text_line_ptr new_line = boost::make_shared<text_line>(last_break_position, break_position);
clear_cluster_widths(last_break_position, break_position);
shape_text(new_line);
add_line(new_line);
last_break_position = break_position;
@ -117,14 +121,22 @@ void text_layout::break_line(text_line_ptr line, double wrap_width, unsigned tex
current_line_length = 0;
}
}
if (last_break_position != line->get_last_char())
if (last_break_position == 0)
{
//No line breaks => no reshaping
add_line(line);
}
else if (last_break_position != line->get_last_char())
{
text_line_ptr new_line = boost::make_shared<text_line>(last_break_position, line->get_last_char());
clear_cluster_widths(last_break_position, line->get_last_char());
shape_text(new_line);
add_line(new_line);
}
}
void text_layout::add_line(text_line_ptr line)
{
if (lines_.empty())
@ -137,6 +149,14 @@ void text_layout::add_line(text_line_ptr line)
glyphs_count_ += line->size();
}
void text_layout::clear_cluster_widths(unsigned first, unsigned last)
{
for (int i=first; i<last; i++)
{
width_map_[i] = 0;
}
}
void text_layout::clear()
{
itemizer_.clear();

View file

@ -0,0 +1,53 @@
{
"keys": [
"",
"-63",
"-106",
"-75"
],
"data": {},
"grid": [
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ! # ",
" ",
" ",
" ",
" ",
" ",
" $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" "
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

View file

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE Map>
<!-- Minimal testcase for bug #1523. -->
<Map background-color="white" srs="+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs">
<Layer name="layer" srs="+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs">
<StyleName>My Style</StyleName>
<Datasource>
<Parameter name="type">osm</Parameter>
<Parameter name="file">../data/bug1532.osm</Parameter>
</Datasource>
</Layer>
<Style name="My Style">
<Rule>
<Filter>[wrap] = "yes" and [type] = "line"</Filter>
<LineSymbolizer stroke-width="1" stroke="red"/>
<!-- Font and size don't matter as long as text length is > wrap_width -->
<TextSymbolizer face-name="DejaVu Sans Bold" size="15" placement="line" wrap-width="35">"abcdefgh"</TextSymbolizer>
</Rule>
<Rule>
<Filter>[wrap] = "no" and [type] = "line"</Filter>
<LineSymbolizer stroke-width="1" stroke="blue"/>
<TextSymbolizer face-name="DejaVu Sans Bold" size="15" placement="line">"abcdefgh"</TextSymbolizer>
</Rule>
<Rule>
<Filter>[wrap] = "yes" and [type] = "point"</Filter>
<PointSymbolizer ignore-placement="true"/>
<TextSymbolizer face-name="DejaVu Sans Bold" size="15" placement="point" wrap-width="35">"abcdefgh"</TextSymbolizer>
</Rule>
<Rule>
<Filter>[wrap] = "no" and [type] = "point"</Filter>
<PointSymbolizer ignore-placement="true"/>
<TextSymbolizer face-name="DejaVu Sans Bold" size="15" placement="point">"abcdefgh"</TextSymbolizer>
</Rule>
</Style>
</Map>

View file

@ -74,6 +74,7 @@ text_tests = [
{'name': "rtl-point", 'sizes': [(200, 200)],'bbox':default_text_box},
{'name': "jalign-auto", 'sizes': [(200, 200)],'bbox':default_text_box},
{'name': "line-offset", 'sizes':[(900, 250)],'bbox': mapnik.Box2d(-5.192, 50.189, -5.174, 50.195)},
{'name': "text-bug1532", 'sizes':[(600, 165)]},
]
tiff_tests = [