Proper bounds checking for line break positions.

Closes #2037.
This commit is contained in:
Hermann Kraus 2013-10-12 02:34:07 +02:00
parent a2ca02c751
commit 5d291dae7d
7 changed files with 109 additions and 10 deletions

View file

@ -95,7 +95,7 @@ void text_layout::break_line(text_line_ptr line, double wrap_width, unsigned tex
breakitr->setText(text); breakitr->setText(text);
double current_line_length = 0; double current_line_length = 0;
unsigned last_break_position = 0; unsigned last_break_position = line->first_char();
for (unsigned i=line->first_char(); i<line->last_char(); i++) for (unsigned i=line->first_char(); i<line->last_char(); i++)
{ {
//TODO: character_spacing //TODO: character_spacing
@ -109,11 +109,8 @@ void text_layout::break_line(text_line_ptr line, double wrap_width, unsigned tex
unsigned break_position = wrap_before ? breakitr->preceding(i) : breakitr->following(i); unsigned break_position = wrap_before ? breakitr->preceding(i) : breakitr->following(i);
/* Break iterator operates on the whole string, while we only look at one line. So we need to /* following() returns a break position after the last word. So DONE should only be returned
* clamp break values. */ * when calling preceding. */
if (break_position < line->first_char()) break_position = line->first_char();
if (break_position > line->last_char()) break_position = line->last_char();
if (break_position <= last_break_position || break_position == BreakIterator::DONE) if (break_position <= last_break_position || break_position == BreakIterator::DONE)
{ {
//A single word is longer than the maximum line width. //A single word is longer than the maximum line width.
@ -125,6 +122,11 @@ void text_layout::break_line(text_line_ptr line, double wrap_width, unsigned tex
MAPNIK_LOG_WARN(text_layout) << "Unexpected result in break_line. Trying to recover...\n"; MAPNIK_LOG_WARN(text_layout) << "Unexpected result in break_line. Trying to recover...\n";
} }
} }
/* Break iterator operates on the whole string, while we only look at one line. So we need to
* clamp break values. */
if (break_position < line->first_char()) break_position = line->first_char();
if (break_position > line->last_char()) break_position = line->last_char();
text_line_ptr new_line = boost::make_shared<text_line>(last_break_position, break_position); text_line_ptr new_line = boost::make_shared<text_line>(last_break_position, break_position);
clear_cluster_widths(last_break_position, break_position); clear_cluster_widths(last_break_position, break_position);
shape_text(new_line); shape_text(new_line);
@ -133,7 +135,7 @@ void text_layout::break_line(text_line_ptr line, double wrap_width, unsigned tex
i = break_position - 1; i = break_position - 1;
current_line_length = 0; current_line_length = 0;
} }
if (last_break_position == 0) if (last_break_position == line->first_char())
{ {
//No line breaks => no reshaping required //No line breaks => no reshaping required
add_line(line); add_line(line);

View file

@ -0,0 +1,87 @@
{
"keys": [
"",
"7",
"3",
"4",
"8"
],
"data": {},
"grid": [
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ! !!!!!!!!!! ",
" ## #### $$ $$$$ !!!! ! !!! ",
" ###### $$$$$$ ! %% % ",
" # $ !!! % % %%%%%% ",
" ## # $$ $ ",
" # $ !!!! %%%%% %%%% ",
" # ## ## $ $$ $$ !! !! %%% %% ",
" ## # ## $$ $ $$ ! ! % % ",
" ! !!! % %%% ",
" ### # $$$ $ ",
" !!!! % %% % %%%%% ",
" ### # $$$ $ !!!! % %% % %%%% ",
" #### $$$$ ",
" !!!!!! ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" ",
" "
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

View file

@ -10,11 +10,21 @@
</Layer> </Layer>
<Style name="My Style"> <Style name="My Style">
<Rule> <Rule>
<PointSymbolizer/> <Filter>[nr] = 3</Filter>
<TextSymbolizer wrap-width="20" face-name="DejaVu Sans Book" size="9" wrap-before="true">"abcdef&#10;ghijkl&#10;mnopq&#10;stuv&#10;wxyz"</TextSymbolizer>
</Rule> </Rule>
<Rule> <Rule>
<Filter>[nr] = 5</Filter> <Filter>[nr] = 4</Filter>
<TextSymbolizer wrap-width="20" face-name="DejaVu Sans Book" size="9" allow-overlap="true">"xxxxxx&#10;xxxxxx"</TextSymbolizer> <TextSymbolizer wrap-width="20" face-name="DejaVu Sans Book" size="9" wrap-before="false">"abcdef&#10;ghijkl&#10;mnopq&#10;stuv&#10;wxyz"</TextSymbolizer>
</Rule> </Rule>
<Rule>
<Filter>[nr] = 7</Filter>
<TextSymbolizer wrap-width="30" face-name="DejaVu Sans Book" size="9" wrap-before="true">"Some test text with&#10;forced&#10;line breaks"</TextSymbolizer>
</Rule>
<Rule>
<Filter>[nr] = 8</Filter>
<TextSymbolizer wrap-width="30" face-name="DejaVu Sans Book" size="9" wrap-before="false">"Some test text with&#10;forced&#10;line breaks"</TextSymbolizer>
</Rule>
</Style> </Style>
</Map> </Map>