Merge pull request #498 from dayllenger/optimizations

Measure & layout optimizations
This commit is contained in:
Vadim Lopatin 2017-10-19 10:12:35 +03:00 committed by GitHub
commit 513a98a332
3 changed files with 69 additions and 13 deletions

View File

@ -513,6 +513,55 @@ struct Ref(T) { // if (T is RefCountedObject)
}
/**
This struct allows to not execute some code if some variables was not changed since the last check.
Used for optimizations.
Reference types, arrays and pointers are compared by reference.
*/
struct CalcSaver(Params...) {
import std.typecons : Tuple;
Tuple!Params values;
bool check(Params args) {
bool changed;
foreach (i, arg; args) {
if (values[i] !is arg) {
values[i] = arg;
changed = true;
}
}
return changed;
}
}
///
unittest {
class A { }
CalcSaver!(uint, double[], A) saver;
uint x = 5;
double[] arr = [1, 2, 3];
A a = new A();
assert(saver.check(x, arr, a));
// values are not changing
assert(!saver.check(x, arr, a));
assert(!saver.check(x, arr, a));
assert(!saver.check(x, arr, a));
assert(!saver.check(x, arr, a));
x = 8;
arr ~= 25;
a = new A();
// values are changed
assert(saver.check(x, arr, a));
assert(!saver.check(x, arr, a));
}
//================================================================================
// some utility functions

View File

@ -115,20 +115,26 @@ class TextWidget : Widget {
return this;
}
private CalcSaver!(Font, dstring, uint, uint) _measureSaver;
override void measure(int parentWidth, int parentHeight) {
FontRef font = font();
//auto measureStart = std.datetime.Clock.currAppTick;
Point sz;
if (maxLines == 1) {
sz = font.textSize(text, MAX_WIDTH_UNSPECIFIED, 4, 0, textFlags);
} else {
sz = font.measureMultilineText(text,maxLines,parentWidth-margins.left-margins.right-padding.left-padding.right, 4, 0, textFlags);
uint w = (maxLines == 1) ? MAX_WIDTH_UNSPECIFIED :
parentWidth - margins.left - margins.right - padding.left - padding.right;
uint flags = textFlags;
// optimization: do not measure if nothing changed
if (_measureSaver.check(font.get, text, w, flags) || _needLayout) {
Point sz;
if (maxLines == 1) {
sz = font.textSize(text, w, 4, 0, flags);
} else {
sz = font.measureMultilineText(text, maxLines, w, 4, 0, flags);
}
// it's not very correct, but in such simple widget it doesn't make issues
measuredContent(SIZE_UNSPECIFIED, SIZE_UNSPECIFIED, sz.x, sz.y);
_needLayout = false;
}
//auto measureEnd = std.datetime.Clock.currAppTick;
//auto duration = measureEnd - measureStart;
//if (duration.length > 10)
// Log.d("TextWidget measureText took ", duration.length, " ticks");
measuredContent(parentWidth, parentHeight, sz.x, sz.y);
}
override void onDraw(DrawBuf buf) {

View File

@ -643,7 +643,7 @@ class FrameLayout : WidgetGroupDefaultDrawing {
applyPadding(rc);
for (int i = 0; i < _children.count; i++) {
Widget item = _children.get(i);
if (item.visibility != Visibility.Gone) {
if (item.visibility == Visibility.Visible) {
item.layout(rc);
}
}
@ -657,6 +657,7 @@ class FrameLayout : WidgetGroupDefaultDrawing {
Widget item = _children.get(i);
if (item.compareId(ID)) {
item.visibility = Visibility.Visible;
item.requestLayout();
foundWidget = item;
found = true;
} else {