Skip to content

Commit 64e91a4

Browse files
committed
(draft) Introduce "Graph2" meter style
Signed-off-by: Kang-Che Sung <[email protected]>
1 parent f4b4045 commit 64e91a4

File tree

3 files changed

+123
-13
lines changed

3 files changed

+123
-13
lines changed

Meter.c

Lines changed: 121 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -876,7 +876,7 @@ static void GraphMeterMode_recordNewValue(Meter* this, const GraphDrawContext* c
876876

877877
// Sum the values of all items
878878
double sum = 0.0;
879-
if (this->curItems > 0) {
879+
if (this->mode != GRAPH2_METERMODE && this->curItems > 0) {
880880
sum = Meter_computeSum(this);
881881
assert(sum >= 0.0);
882882
assert(sum <= DBL_MAX);
@@ -890,6 +890,17 @@ static void GraphMeterMode_recordNewValue(Meter* this, const GraphDrawContext* c
890890
// Dynamic scale. "this->total" is ignored.
891891
// Determine the scale and "total" that we need afterward. The "total" is
892892
// rounded up to a power of 2.
893+
894+
if (this->mode == GRAPH2_METERMODE) {
895+
// Find the greatest value in this->values array
896+
for (uint8_t i = 0; i < maxItems && i < this->curItems; i++) {
897+
if (isgreater(this->values[i], total)) {
898+
total = this->values[i];
899+
}
900+
}
901+
total = MINIMUM(DBL_MAX, total);
902+
}
903+
893904
int scaleExp = 0;
894905
(void)frexp(total, &scaleExp);
895906
scaleExp = MAXIMUM(0, scaleExp);
@@ -910,6 +921,27 @@ static void GraphMeterMode_recordNewValue(Meter* this, const GraphDrawContext* c
910921
double maxDots = (double)(int32_t)(h * 8);
911922

912923
// The total number of dots that we would draw for this record
924+
925+
if (maxItems == 1 || this->mode == GRAPH2_METERMODE) {
926+
// We just need to record the number of dots in the graph data buffer.
927+
for (uint8_t i = 0; i < maxItems; i++) {
928+
int numDots = 0;
929+
if (total > 0.0 && i < this->curItems && isPositive(this->values[i])) {
930+
double value = MINIMUM(total, this->values[i]);
931+
932+
numDots = (int)ceil((value / total) * maxDots);
933+
assert(numDots >= 0);
934+
if (numDots <= 0) {
935+
numDots = 1; // Division of (value / total) underflows
936+
}
937+
}
938+
939+
assert(numDots <= UINT16_MAX);
940+
valueStart[(isPercentChart ? 0 : 1) + i].numDots = (uint16_t)numDots;
941+
}
942+
return;
943+
}
944+
913945
int numDots = 0;
914946
if (total > 0.0) {
915947
numDots = (int)ceil((sum / total) * maxDots);
@@ -919,13 +951,6 @@ static void GraphMeterMode_recordNewValue(Meter* this, const GraphDrawContext* c
919951
}
920952
}
921953

922-
if (maxItems == 1) {
923-
// We just need to record the number of dots in the graph data buffer.
924-
assert(numDots <= UINT16_MAX);
925-
valueStart[isPercentChart ? 0 : 1].numDots = (uint16_t)numDots;
926-
return;
927-
}
928-
929954
// For a meter of multiple items, we will precompute the colors of each cell
930955
// and store them in a record. First clear the cells, which might contain
931956
// data of the previous record.
@@ -1028,6 +1053,65 @@ static int GraphMeterMode_lookupCell(const Meter* this, const GraphDrawContext*
10281053
const GraphDataCell* valueStart = (const GraphDataCell*)data->buffer;
10291054
valueStart = &valueStart[valueIndex * nCellsPerValue];
10301055

1056+
if (this->mode == GRAPH2_METERMODE) {
1057+
int deltaExp = isPercentChart ? 0 : scaleExp - valueStart[0].scaleExp;
1058+
assert(deltaExp >= 0);
1059+
1060+
unsigned int numDots = valueStart[(isPercentChart ? 0 : 1) + 0].numDots;
1061+
if (numDots >= 1) {
1062+
if (deltaExp + 1 < UINT16_WIDTH) {
1063+
numDots = ((numDots - 1) >> (deltaExp + 1)) + 1;
1064+
} else {
1065+
numDots = 1;
1066+
}
1067+
}
1068+
unsigned int blanksAtEnd = h * 4 - numDots;
1069+
1070+
numDots = valueStart[(isPercentChart ? 0 : 1) + 1].numDots;
1071+
if (numDots >= 1) {
1072+
if (deltaExp + 1 < UINT16_WIDTH) {
1073+
numDots = ((numDots - 1) >> (deltaExp + 1)) + 1;
1074+
} else {
1075+
numDots = 1;
1076+
}
1077+
}
1078+
unsigned int blanksAtStart = h * 4 - numDots;
1079+
1080+
if (h - 1 - y < blanksAtEnd / 8)
1081+
goto cellIsEmpty;
1082+
if (y < blanksAtStart / 8)
1083+
goto cellIsEmpty;
1084+
1085+
if (y * 2 == h - 1 && !(valueStart[(isPercentChart ? 0 : 1) + 0].numDots || valueStart[(isPercentChart ? 0 : 1) + 1].numDots))
1086+
goto cellIsEmpty;
1087+
1088+
if (maxItems <= 1 || y * 2 > h - 1) {
1089+
itemIndex = 0;
1090+
} else if (y * 2 < h - 1) {
1091+
itemIndex = 1;
1092+
} else {
1093+
itemIndex = valueStart[(isPercentChart ? 0 : 1) + 0].numDots >= valueStart[(isPercentChart ? 0 : 1) + 1].numDots ? 0 : 1;
1094+
}
1095+
1096+
if (y * 2 == h - 1 && valueStart[(isPercentChart ? 0 : 1) + 0].numDots > 8 && valueStart[(isPercentChart ? 0 : 1) + 1].numDots > 8) {
1097+
*details = valueStart[(isPercentChart ? 0 : 1) + 0].numDots >= valueStart[(isPercentChart ? 0 : 1) + 1].numDots ? 0x0F : 0xF0;
1098+
} else {
1099+
*details = 0xFF;
1100+
const uint8_t dotAlignment = 2;
1101+
if (y == blanksAtStart / 8) {
1102+
blanksAtStart = (blanksAtStart % 8) / dotAlignment * dotAlignment;
1103+
*details >>= blanksAtStart;
1104+
}
1105+
if ((h - 1 - y) == blanksAtEnd / 8) {
1106+
blanksAtEnd = (blanksAtEnd % 8) / dotAlignment * dotAlignment;
1107+
*details = (uint8_t)((*details >> blanksAtEnd) << blanksAtEnd);
1108+
}
1109+
}
1110+
1111+
/* fallthrough */
1112+
goto cellIsEmpty;
1113+
}
1114+
10311115
int deltaExp = 0;
10321116
if (!isPercentChart) {
10331117
// The "scaleExp" member exists only for "dynamic scale" meters (i.e.
@@ -1077,7 +1161,7 @@ static int GraphMeterMode_lookupCell(const Meter* this, const GraphDrawContext*
10771161
/* fallthrough */
10781162

10791163
cellIsEmpty:
1080-
if (y == 0)
1164+
if (this->mode != GRAPH2_METERMODE && y == 0)
10811165
*details |= 0xC0;
10821166

10831167
if (itemIndex == (uint8_t)-1)
@@ -1185,11 +1269,31 @@ static void GraphMeterMode_draw(Meter* this, int x, int y, int w) {
11851269
unsigned int h = (unsigned int)this->h;
11861270

11871271
uint8_t maxItems = Meter_maxItems(this);
1272+
if (this->mode == GRAPH2_METERMODE && maxItems > 2) {
1273+
// Items other than the first two are always hidden in "Graph2" mode.
1274+
maxItems = 2;
1275+
}
1276+
11881277
bool isPercentChart = Meter_isPercentChart(this);
11891278

1190-
size_t nCellsPerValue = maxItems <= 1 ? maxItems : h;
1191-
if (!isPercentChart)
1192-
nCellsPerValue *= 2;
1279+
size_t nCellsPerValue;
1280+
if (this->mode == GRAPH2_METERMODE) {
1281+
if (isPercentChart) {
1282+
nCellsPerValue = maxItems;
1283+
} else if (maxItems > 0) {
1284+
nCellsPerValue = 1 + maxItems;
1285+
} else {
1286+
nCellsPerValue = 0;
1287+
}
1288+
} else {
1289+
if (maxItems <= 1) {
1290+
nCellsPerValue = maxItems;
1291+
} else {
1292+
nCellsPerValue = h;
1293+
}
1294+
if (!isPercentChart)
1295+
nCellsPerValue *= 2;
1296+
}
11931297

11941298
GraphDrawContext context = {
11951299
.maxItems = maxItems,
@@ -1381,6 +1485,11 @@ static const MeterMode Meter_modes[] = {
13811485
.h = 3,
13821486
.draw = LEDMeterMode_draw,
13831487
},
1488+
[GRAPH2_METERMODE] = {
1489+
.uiName = "Graph2",
1490+
.h = DEFAULT_GRAPH_HEIGHT,
1491+
.draw = GraphMeterMode_draw,
1492+
},
13841493
};
13851494

13861495
/* Meter class and methods */

MeterMode.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ enum MeterModeId_ {
1414
TEXT_METERMODE,
1515
GRAPH_METERMODE,
1616
LED_METERMODE,
17+
GRAPH2_METERMODE /* Not default supported */,
1718
LAST_METERMODE
1819
};
1920

NetworkIOMeter.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ const MeterClass NetworkIOMeter_class = {
166166
},
167167
.updateValues = NetworkIOMeter_updateValues,
168168
.defaultMode = TEXT_METERMODE,
169-
.supportedModes = METERMODE_DEFAULT_SUPPORTED,
169+
.supportedModes = METERMODE_DEFAULT_SUPPORTED | (1 << GRAPH2_METERMODE),
170170
.maxItems = 2,
171171
.isPercentChart = false,
172172
.total = 1.0,

0 commit comments

Comments
 (0)