Skip to content

Commit b70e2b7

Browse files
committed
Merge branch 'feature-faster_field' into develop
2 parents 912708b + 24f0559 commit b70e2b7

10 files changed

Lines changed: 141 additions & 128 deletions

File tree

engine/src/block.cpp

Lines changed: 29 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -613,63 +613,13 @@ bool MCBlock::fit(int2 x, uint2 maxwidth, uint2& r_break_index, bool& r_break_fi
613613
else
614614
t_next_block_char = -1;
615615

616-
// If this is a text block and we fit inside maxwidth fully then check
617-
// for a break point at the end.
618-
if (getwidth(NULL, x) <= maxwidth)
619-
{
620-
uint2 t_last_char, t_break_index;
621-
if (hasunicode() && (size & 1) == 0)
622-
t_last_char = *(uint2 *)&text[index + size - 2], t_break_index = index + size - 2;
623-
else
624-
t_last_char = MCUnicodeMapFromNative(text[index + size - 1]), t_break_index = index + size - 1;
625-
626-
// If this is the last block, or we can break between this and the
627-
// next block, return the end point.
628-
if (t_next_block_char != -2)
629-
{
630-
if (t_next_block_char == -1 || MCUnicodeCanBreakBetween(t_last_char, t_next_block_char))
631-
{
632-
r_break_index = index + size;
633-
r_break_fits = true;
634-
return true;
635-
}
636-
}
637-
638-
// Compute the last possible break position in the block by looping
639-
// back over the characters;
640-
if (t_break_index > index)
641-
{
642-
do
643-
{
644-
uint2 i;
645-
i = t_break_index;
646-
647-
uint2 t_prev_char;
648-
if (hasunicode())
649-
{
650-
i -= 2;
651-
t_prev_char = *(uint2 *)&text[i];
652-
}
653-
else
654-
{
655-
i -= 1;
656-
t_prev_char = MCUnicodeMapFromNative(text[i]);
657-
}
658-
659-
if (MCUnicodeCanBreakBetween(t_prev_char, t_last_char))
660-
break;
661-
662-
t_break_index = i;
663-
664-
t_last_char = t_prev_char;
665-
}
666-
while(t_break_index > index);
667-
}
668-
669-
r_break_index = t_break_index;
670-
r_break_fits = true;
671-
return true;
672-
}
616+
// FG-2013-10-21 [[ Field speedups ]]
617+
// Previously, we used to calculate the length of the entire block here in order
618+
// to determine if splitting was required. Unfortunately, this tends to bypass
619+
// the text layout cache resulting in very slow laying out now that the "proper"
620+
// Unicode text layout APIs are in use.
621+
//
622+
// Now, all text is laid out word-at-a-time.
673623

674624
// We don't completely fit within maxwidth, so compute the last break point in
675625
// the block by measuring
@@ -700,6 +650,8 @@ bool MCBlock::fit(int2 x, uint2 maxwidth, uint2& r_break_index, bool& r_break_fi
700650

701651
// MW-2013-08-01: [[ Bug 10932 ]] Optimized loop only measuring between potential break
702652
// points, rather than char by char.
653+
bool t_whole_block;
654+
t_whole_block = false;
703655
while(i < index + size)
704656
{
705657
uint4 initial_i;
@@ -709,6 +661,8 @@ bool MCBlock::fit(int2 x, uint2 maxwidth, uint2& r_break_index, bool& r_break_fi
709661
t_can_break = false;
710662

711663
uint2 t_this_char;
664+
bool t_end_of_block;
665+
t_end_of_block = false;
712666
while(i < index + size)
713667
{
714668
t_this_char = (uint2)t_next_char;
@@ -720,14 +674,20 @@ bool MCBlock::fit(int2 x, uint2 maxwidth, uint2& r_break_index, bool& r_break_fi
720674
if (i < index + size)
721675
t_next_char = *(uint2 *)&text[i];
722676
else
723-
t_next_char = t_next_block_char;
677+
{
678+
t_next_char = t_next_block_char;
679+
t_end_of_block = true;
680+
}
724681
}
725682
else
726683
{
727684
if (i < index + size)
728685
t_next_char = (uint2)MCUnicodeMapFromNative(text[i]);
729686
else
730-
t_next_char = t_next_block_char;
687+
{
688+
t_next_char = t_next_block_char;
689+
t_end_of_block = true;
690+
}
731691
}
732692

733693
if (t_this_char == '\t' ||
@@ -768,27 +728,29 @@ bool MCBlock::fit(int2 x, uint2 maxwidth, uint2& r_break_index, bool& r_break_fi
768728
break;
769729

770730
if (t_can_break)
771-
{
772731
t_break_index = i;
773732

774-
if (twidth <= maxwidth)
775-
t_can_fit = true;
733+
if (twidth <= maxwidth)
734+
{
735+
t_can_fit = true;
736+
t_whole_block = t_end_of_block;
737+
}
776738

777-
if (twidth >= maxwidth)
778-
break;
779-
}
739+
if (twidth >= maxwidth)
740+
break;
780741
}
781742

782743
// We now have a suitable break point in t_break_index. This could be index if
783744
// there are none in the block. We now loop forward until we get to the end of
784745
// any suitable run of spaces.
785746
while(t_break_index < index + size && textisspace(&text[t_break_index]))
786747
t_break_index += indexincrement(t_break_index);
787-
748+
788749
r_break_fits = t_can_fit;
789750
r_break_index = t_break_index;
790751

791-
return false;
752+
// If we found a break, was it before the end of the block?
753+
return t_whole_block;
792754
}
793755

794756
void MCBlock::split(uint2 p_index)

engine/src/field.cpp

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,7 @@ void MCField::open()
313313
else
314314
{
315315
openparagraphs();
316-
recompute();
316+
do_recompute(false);
317317
if (vscrollbar != NULL)
318318
{
319319
MCCdata *scrollptr = getcarddata(scrolls, parentid, False);
@@ -1172,6 +1172,8 @@ void MCField::setrect(const MCRectangle &nrect)
11721172
// MW-2007-07-05: [[ Bug 2435 ]] - 'Caret' doesn't move with the field when its rect changes
11731173
if (cursoron)
11741174
replacecursor(False, False);
1175+
1176+
do_recompute(true);
11751177
}
11761178

11771179
Exec_stat MCField::getprop(uint4 parid, Properties which, MCExecPoint& ep, Boolean effective)
@@ -1964,7 +1966,7 @@ Exec_stat MCField::setprop(uint4 parid, Properties p, MCExecPoint &ep, Boolean e
19641966
}
19651967
if (dirty && opened)
19661968
{
1967-
recompute();
1969+
do_recompute(reset);
19681970
if (reset)
19691971
resetparagraphs();
19701972
hscroll(savex - textx, False);
@@ -2106,7 +2108,7 @@ void MCField::undo(Ustruct *us)
21062108
pgptr = pgptr->next();
21072109
pgptr->setselectionindex(0, 0, False, False);
21082110
flags &= ~F_VISIBLE;
2109-
recompute();
2111+
do_recompute(true);
21102112
focusedparagraph = pgptr;
21112113
updateparagraph(True, False);
21122114
flags |= F_VISIBLE;
@@ -2246,7 +2248,7 @@ void MCField::replacedata(MCCdata *&data, uint4 newid)
22462248
{
22472249
paragraphs = fdata->getparagraphs();
22482250
openparagraphs();
2249-
recompute();
2251+
do_recompute(true);
22502252

22512253
// MW-2011-08-18: [[ Layers ]] Invalidate the whole object.
22522254
layer_redrawall();
@@ -2313,7 +2315,7 @@ void MCField::resetfontindex(MCStack *oldstack)
23132315
if (opened)
23142316
{
23152317
resetparagraphs();
2316-
recompute();
2318+
do_recompute(true);
23172319
}
23182320
}
23192321

@@ -2566,6 +2568,11 @@ void MCField::setsbrects()
25662568
}
25672569

25682570
void MCField::recompute()
2571+
{
2572+
do_recompute(false);
2573+
}
2574+
2575+
void MCField::do_recompute(bool p_force_layout)
25692576
{
25702577
if (!opened)
25712578
return;
@@ -2580,7 +2587,7 @@ void MCField::recompute()
25802587
{
25812588
// MW-2012-01-25: [[ ParaStyles ]] Whether to flow or noflow is decided on a
25822589
// per-paragraph basis.
2583-
pgptr -> layout();
2590+
pgptr -> layout(p_force_layout);
25842591

25852592
uint2 ascent, descent, width;
25862593
pgptr->getmaxline(width, ascent, descent);
@@ -2872,12 +2879,12 @@ void MCField::draw(MCDC *dc, const MCRectangle& p_dirty, bool p_isolated, bool p
28722879
if (state & CS_SIZE)
28732880
{
28742881
resetparagraphs();
2875-
recompute();
2882+
do_recompute(true);
28762883
}
28772884
else if (state & CS_SELECTED && (texty != 0 || textx != 0))
28782885
{
28792886
resetparagraphs();
2880-
recompute();
2887+
do_recompute(false);
28812888
}
28822889

28832890
MCRectangle frect = getfrect();
@@ -3037,7 +3044,7 @@ IO_stat MCField::save(IO_handle stream, uint4 p_part, bool p_force_ext)
30373044

30383045
if (fdata == NULL)
30393046
resetparagraphs();
3040-
recompute();
3047+
do_recompute(false);
30413048
hscroll(savex - textx, False);
30423049
vscroll(savey - texty, False);
30433050
resetscrollbars(True);
@@ -3173,7 +3180,7 @@ bool MCField::imagechanged(MCImage *p_image, bool p_deleting)
31733180

31743181
if (t_used)
31753182
{
3176-
recompute();
3183+
do_recompute(true);
31773184
layer_redrawall();
31783185
}
31793186

engine/src/field.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,8 @@ class MCField : public MCControl
281281
static Field_translations trans_lookup(Keytranslations table[], KeySym key, uint2 modifiers);
282282
static Field_translations lookup_mac_keybinding(KeySym key, uint32_t modifiers);
283283

284+
void do_recompute(bool p_force_layout);
285+
284286
void redrawcheck(MCRectangle &drect);
285287
void resetparagraphs();
286288

engine/src/fieldf.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1609,7 +1609,7 @@ void MCField::updateparagraph(Boolean flow, Boolean all, Boolean dodraw)
16091609
oldheight = focusedparagraph->getheight(fixedheight);
16101610

16111611
// MW-2012-01-25: [[ ParaStyles ]] Get the paragraph to flow itself.
1612-
focusedparagraph -> layout();
1612+
focusedparagraph -> layout(all);
16131613
uint2 newheight = focusedparagraph->getheight(fixedheight);
16141614
if (newheight != oldheight)
16151615
{
@@ -1823,7 +1823,7 @@ void MCField::fdel(Field_translations function, const char *string, KeySym key)
18231823
}
18241824
if (oldwidth == textwidth)
18251825
{
1826-
recompute();
1826+
do_recompute(true);
18271827
// MW-2011-08-18: [[ Layers ]] Invalidate the whole object.
18281828
layer_redrawall();
18291829
}
@@ -2290,7 +2290,7 @@ void MCField::typetext(const MCString &newtext)
22902290
state |= CS_CHANGED;
22912291
if (newtext.getlength() && focusedparagraph->finsertnew(newtext, false))
22922292
{
2293-
recompute();
2293+
do_recompute(true);
22942294
int4 endindex = oldfocused + newtext.getlength();
22952295
int4 junk;
22962296
MCParagraph *newfocused = indextoparagraph(focusedparagraph, endindex, junk);

engine/src/fields.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ Exec_stat MCField::sort(MCExecPoint &ep, uint4 parid, Chunk_term type,
179179
{
180180
paragraphs = newparagraphs;
181181
resetparagraphs();
182-
recompute();
182+
do_recompute(true);
183183

184184
// MW-2011-08-18: [[ Layers ]] Invalidate the whole object.
185185
layer_redrawall();
@@ -495,7 +495,7 @@ void MCField::setparagraphs(MCParagraph *newpgptr, uint4 parid)
495495
paragraphs = newpgptr;
496496
fptr->setparagraphs(newpgptr);
497497
openparagraphs();
498-
recompute();
498+
do_recompute(true);
499499

500500
// MW-2011-08-18: [[ Layers ]] Invalidate the whole object.
501501
layer_redrawall();
@@ -722,7 +722,7 @@ Exec_stat MCField::settextindex(uint4 parid, int4 si, int4 ei, const MCString &s
722722
if (state & CS_KFOCUSED)
723723
focusedparagraph->setselectionindex(ei, ei, False, False);
724724

725-
recompute();
725+
do_recompute(true);
726726

727727
// MW-2011-08-18: [[ Layers ]] Invalidate the whole object.
728728
layer_redrawall();
@@ -1389,7 +1389,7 @@ Exec_stat MCField::settextatts(uint4 parid, Properties which, MCExecPoint& ep, M
13891389
if (opened && (parid == 0 || parid == getcard()->getid()))
13901390
{
13911391
resetparagraphs();
1392-
recompute();
1392+
do_recompute(true);
13931393
// MW-2011-08-18: [[ Layers ]] Invalidate the whole object.
13941394
layer_redrawall();
13951395
}
@@ -1682,7 +1682,7 @@ Exec_stat MCField::settextatts(uint4 parid, Properties which, MCExecPoint& ep, M
16821682
if (t_need_layout && !all)
16831683
{
16841684
// MW-2012-01-25: [[ ParaStyles ]] Ask the paragraph to reflow itself.
1685-
pgptr -> layout();
1685+
pgptr -> layout(all);
16861686
drect.height += pgptr->getheight(fixedheight);
16871687
}
16881688
}
@@ -1702,7 +1702,7 @@ Exec_stat MCField::settextatts(uint4 parid, Properties which, MCExecPoint& ep, M
17021702
{
17031703
if (all)
17041704
{
1705-
recompute();
1705+
do_recompute(true);
17061706
hscroll(savex - textx, False);
17071707
vscroll(savey - texty, False);
17081708
resetscrollbars(True);
@@ -2483,7 +2483,7 @@ void MCField::cuttext()
24832483

24842484
// MW-2012-03-16: [[ Bug 3173 ]] Make sure the width is updated and such
24852485
// so that the caret repositions itself correctly.
2486-
recompute();
2486+
do_recompute(true);
24872487
layer_redrawall();
24882488

24892489
replacecursor(True, True);

engine/src/ide.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1081,7 +1081,7 @@ static void TokenizeField(MCField *p_field, MCIdeState *p_state, Chunk_term p_ty
10811081
do
10821082
{
10831083
t_paragraph = t_paragraph -> prev();
1084-
t_paragraph -> layout();
1084+
t_paragraph -> layout(false);
10851085
}
10861086
while(t_paragraph != t_first_paragraph);
10871087

engine/src/osxfield.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -669,7 +669,7 @@ Exec_stat MCField::getparagraphmacunicodestyles(MCExecPoint& ep, MCParagraph *p_
669669

670670
// MW-2011-01-25: [[ ParaStyles ]] Ask the paragraph to reflow itself.
671671
if (opened)
672-
t_paragraph -> layout();
672+
t_paragraph -> layout(false);
673673

674674
t_paragraph = t_paragraph -> next();
675675
}

0 commit comments

Comments
 (0)