Skip to content

Commit a40e954

Browse files
minor text out/layout bug fix (issue #13)
1 parent 26e095e commit a40e954

File tree

1 file changed

+39
-16
lines changed

1 file changed

+39
-16
lines changed

src/canvas.cpp

Lines changed: 39 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -693,6 +693,26 @@ void kTextService::GetGlyphMetrics(const kFont &font, size_t first, size_t last,
693693
p_impl->GetGlyphMetrics(&font, first, last, metrics);
694694
}
695695

696+
// helper function to count and measure word glyphs up until specified right edge from starting x position
697+
static size_t MeasureUntil(kCanvasImpl *impl, const kFont &font, const char *text, size_t count, kScalar x, kScalar right, kScalar &actualwidth)
698+
{
699+
size_t result = 0;
700+
kScalar startx = x;
701+
for (; result < count; ++result) {
702+
kGlyphMetrics gm;
703+
size_t glyph = *text++;
704+
impl->GetGlyphMetrics(&font, glyph, glyph, &gm);
705+
706+
if ((x + gm.advance) > right) {
707+
break;
708+
}
709+
710+
x += gm.advance;
711+
}
712+
actualwidth = x - startx;
713+
return result;
714+
}
715+
696716
// helper layout callback
697717
// performs text to word split and layout of individual word blocks
698718
// each layed out word passed to provided callback function
@@ -761,25 +781,37 @@ static kSize TextLayout(
761781
while (wordbreaker.NextWord(word)) {
762782
switch (word.type) {
763783
case Word::Text: {
784+
// TODO
785+
// here might be tricky situation when the word itself bigger than
786+
// provided width to fit it in
787+
// in this case word should be broken in subwords which fit required width
788+
// propose an options for that or do it by default?
789+
// in case without doing long word break - words will fall outside
790+
// provided bounds
791+
764792
kScalar wordwidth = impl->TextSize(word.text, word.length, font).width;
793+
794+
// don't do line break if word doesn't fit and it's first word in a line
765795
breaktonextline =
766796
breaktonextline ||
767-
(multiline && (cp.x + wordwidth) > maxwidth);
797+
(multiline && cp.x > 0 && (cp.x + wordwidth) > maxwidth);
798+
768799
if (breaktonextline) {
769800
cp.x = 0;
770801
cp.y += fm.height + fm.linegap + interval;
771802
result.height = cp.y;
772803
}
773804

774805
kGlyphMetrics gm;
775-
// take word first glyph metrics
806+
// take word's first glyph metrics for adjusting left bound
776807
size_t glyph = word.text[0];
777808
impl->GetGlyphMetrics(font, glyph, glyph, &gm);
778809

779810
if ((cp.x + gm.leftbearing) < leftbound) {
780811
leftbound = cp.x + gm.leftbearing;
781812
}
782813

814+
// take word's last glyph metrics for adjusting right bound
783815
if (word.length > 1) {
784816
glyph = word.text[word.length - 1];
785817
impl->GetGlyphMetrics(font, glyph, glyph, &gm);
@@ -1283,26 +1315,17 @@ void kCanvas::Text(const kRect &rect, const char *text, int count, const kFont &
12831315
} else {
12841316
// measure word glyphs one by one while there's enough space
12851317
// to fit ellipses after word, then paint fitted glyphs of the word
1286-
size_t c = 0;
1287-
kScalar x = cp.x;
1288-
for (; c < w.count; ++c) {
1289-
kGlyphMetrics gm;
1290-
size_t glyph = w.text[c];
1291-
p_impl->GetGlyphMetrics(&font, glyph, glyph, &gm);
1292-
1293-
if ((x + gm.advance) > (rect.right - ellipseswidth)) {
1294-
break;
1295-
}
1296-
1297-
x += gm.advance;
1298-
}
1318+
kScalar fitwidth;
1319+
size_t c = MeasureUntil(p_impl, font, w.text, w.count, cp.x, rect.right - ellipseswidth, fitwidth);
12991320

13001321
p_impl->Text(cp, w.text, c, &font, &brush, kTextOrigin::Top);
1301-
cp.x = x;
1322+
cp.x += fitwidth;
13021323
}
13031324

13041325
p_impl->Text(cp, "...", 3, &font, &brush, kTextOrigin::Top);
13051326

1327+
// TODO: currently first word out of bounds will stop text output
1328+
// this seems to be layout issue, since it doesn't break long words
13061329
stopoutput = true;
13071330
break;
13081331
}

0 commit comments

Comments
 (0)