CalcSaver template, optimize TextWidget measure

This commit is contained in:
dayllenger 2017-10-18 11:16:28 +03:00
parent 1c940fcc8e
commit c074007ad2
2 changed files with 67 additions and 12 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;
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, MAX_WIDTH_UNSPECIFIED, 4, 0, textFlags);
sz = font.textSize(text, w, 4, 0, flags);
} else {
sz = font.measureMultilineText(text,maxLines,parentWidth-margins.left-margins.right-padding.left-padding.right, 4, 0, textFlags);
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) {