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