Skip to content

Commit 7db2107

Browse files
committed
(draft) "Positive/negative" Graph meter style
Signed-off-by: Kang-Che Sung <[email protected]>
1 parent c5f3eb8 commit 7db2107

File tree

1 file changed

+74
-81
lines changed

1 file changed

+74
-81
lines changed

Meter.c

Lines changed: 74 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,7 @@ static void GraphMeterMode_reallocateGraphBuffer(Meter* this, const GraphDrawCon
320320
data->nValues = nValues;
321321
}
322322

323+
#if 0 /* Unused code */
323324
static size_t GraphMeterMode_valueCellIndex(unsigned int graphHeight, bool isPercentChart, int deltaExp, unsigned int y, unsigned int* scaleFactor, unsigned int* increment) {
324325
assert(deltaExp >= 0);
325326
assert(deltaExp < UINT16_WIDTH);
@@ -882,9 +883,9 @@ static void GraphMeterMode_computeColors(Meter* this, const GraphDrawContext* co
882883
}
883884
}
884885
}
886+
#endif /* End of unused code */
885887

886888
static void GraphMeterMode_recordNewValue(Meter* this, const GraphDrawContext* context) {
887-
uint8_t maxItems = context->maxItems;
888889
bool isPercentChart = context->isPercentChart;
889890
size_t nCellsPerValue = context->nCellsPerValue;
890891
if (!nCellsPerValue)
@@ -901,15 +902,23 @@ static void GraphMeterMode_recordNewValue(Meter* this, const GraphDrawContext* c
901902
GraphColorCell* valueStart = &data->buffer[(nValues - 1) * nCellsPerValue];
902903

903904
// Compute "sum" and "total"
904-
double sum = Meter_computeSum(this);
905-
assert(sum >= 0.0);
906-
assert(sum <= DBL_MAX);
907-
double total;
905+
double total = 0.0;
908906
int scaleExp = 0;
909907
if (isPercentChart) {
910-
total = MAXIMUM(this->total, sum);
908+
assert(this->total >= 0.0);
909+
total = this->total;
910+
valueStart[0].scaleExp = (int16_t)scaleExp;
911911
} else {
912-
(void) frexp(sum, &scaleExp);
912+
if (isPositive(this->values[0]))
913+
total = this->values[0];
914+
915+
if (this->curItems > 1 && isgreater(this->values[1], total))
916+
total = this->values[1];
917+
918+
if (total > DBL_MAX)
919+
total = DBL_MAX;
920+
921+
(void) frexp(total, &scaleExp);
913922
if (scaleExp < 0) {
914923
scaleExp = 0;
915924
}
@@ -925,47 +934,22 @@ static void GraphMeterMode_recordNewValue(Meter* this, const GraphDrawContext* c
925934

926935
assert(graphHeight <= UINT16_MAX / 8);
927936
double maxDots = (double)(int32_t)(graphHeight * 8);
928-
int numDots = (int) ceil((sum / total) * maxDots);
929-
assert(numDots >= 0);
930-
if (sum > 0.0 && numDots <= 0) {
931-
numDots = 1; // Division of (sum / total) underflows
932-
}
933-
934-
if (maxItems == 1) {
935-
assert(numDots <= UINT16_MAX);
936-
valueStart[isPercentChart ? 0 : 1].numDots = (uint16_t)numDots;
937-
return;
938-
}
939-
940-
// Clear cells
941-
unsigned int y = ((unsigned int)numDots + 8 - 1) / 8; // Round up
942-
size_t i = GraphMeterMode_valueCellIndex(graphHeight, isPercentChart, 0, y, NULL, NULL);
943-
if (i < nCellsPerValue) {
944-
memset(&valueStart[i], 0, (nCellsPerValue - i) * sizeof(*valueStart));
945-
}
946-
947-
if (sum <= 0.0)
948-
return;
949-
950-
int deltaExp = 0;
951-
double scaledTotal = total;
952-
while (true) {
953-
numDots = (int) ceil((sum / scaledTotal) * maxDots);
954-
if (numDots <= 0) {
955-
numDots = 1; // Division of (sum / scaledTotal) underflows
956-
}
957-
958-
GraphMeterMode_computeColors(this, context, valueStart, deltaExp, scaledTotal, (unsigned int)numDots);
959-
960-
if (isPercentChart || !(scaledTotal < DBL_MAX) || (1U << deltaExp) >= graphHeight) {
961-
break;
937+
for (uint8_t i = 0; i < 2; i++) {
938+
double value = 0.0;
939+
if (i < this->curItems && isPositive(this->values[i]))
940+
value = this->values[i];
941+
942+
if (value > total)
943+
value = total;
944+
945+
int numDots = (int) ceil((value / total) * maxDots);
946+
assert(numDots >= 0);
947+
if (value > 0.0 && numDots <= 0) {
948+
numDots = 1; // Division of (value / total) underflows
962949
}
963950

964-
deltaExp++;
965-
scaledTotal *= 2.0;
966-
if (scaledTotal > DBL_MAX) {
967-
scaledTotal = DBL_MAX;
968-
}
951+
assert(numDots <= UINT16_MAX);
952+
valueStart[1 + i].numDots = (uint16_t)numDots;
969953
}
970954
}
971955

@@ -985,6 +969,7 @@ static void GraphMeterMode_printScale(int exponent) {
985969
}
986970
}
987971

972+
#if 0 /* Unused code */
988973
static uint8_t GraphMeterMode_scaleCellDetails(uint8_t details, unsigned int scaleFactor) {
989974
// Only the "top cell" of a record may need scaling like this; the cell does
990975
// not use the special meaning of bit 4.
@@ -1012,6 +997,7 @@ static uint8_t GraphMeterMode_scaleCellDetails(uint8_t details, unsigned int sca
1012997
}
1013998
return 0x00;
1014999
}
1000+
#endif /* End of unused code */
10151001

10161002
static int GraphMeterMode_lookupCell(const Meter* this, const GraphDrawContext* context, int scaleExp, size_t valueIndex, unsigned int y, uint8_t* details) {
10171003
unsigned int graphHeight = (unsigned int)this->h;
@@ -1037,50 +1023,59 @@ static int GraphMeterMode_lookupCell(const Meter* this, const GraphDrawContext*
10371023
int deltaExp = isPercentChart ? 0 : scaleExp - valueStart[0].scaleExp;
10381024
assert(deltaExp >= 0);
10391025

1040-
if (maxItems == 1) {
1041-
unsigned int numDots = valueStart[isPercentChart ? 0 : 1].numDots;
1026+
unsigned int numDots = valueStart[1].numDots;
1027+
if (numDots >= 1) {
1028+
if (deltaExp + 1 < UINT16_WIDTH) {
1029+
numDots = ((numDots - 1) >> (deltaExp + 1)) + 1;
1030+
} else {
1031+
numDots = 1;
1032+
}
1033+
}
1034+
unsigned int blanksAtEnd = graphHeight * 4 - numDots;
10421035

1043-
if (numDots < 1)
1044-
goto cellIsEmpty;
1036+
numDots = valueStart[2].numDots;
1037+
if (numDots >= 1) {
1038+
if (deltaExp + 1 < UINT16_WIDTH) {
1039+
numDots = ((numDots - 1) >> (deltaExp + 1)) + 1;
1040+
} else {
1041+
numDots = 1;
1042+
}
1043+
}
1044+
unsigned int blanksAtStart = graphHeight * 4 - numDots;
10451045

1046-
// Scale according to exponent difference. Round up.
1047-
numDots = deltaExp < UINT16_WIDTH ? ((numDots - 1) >> deltaExp) : 0;
1048-
numDots++;
1046+
if (graphHeight - 1 - y < blanksAtEnd / 8)
1047+
goto cellIsEmpty;
1048+
if (y < blanksAtStart / 8)
1049+
goto cellIsEmpty;
10491050

1050-
if (y > (numDots - 1) / 8)
1051-
goto cellIsEmpty;
1051+
if (y * 2 == graphHeight - 1 && !(valueStart[1].numDots || valueStart[2].numDots))
1052+
goto cellIsEmpty;
10521053

1054+
if (maxItems <= 1 || y * 2 > graphHeight - 1) {
10531055
itemIndex = 0;
1054-
*details = 0xFF;
1055-
if (y == (numDots - 1) / 8) {
1056-
const uint8_t dotAlignment = 2;
1057-
unsigned int blanksAtTopCell = (8 - 1 - (numDots - 1) % 8) / dotAlignment * dotAlignment;
1058-
*details <<= blanksAtTopCell;
1059-
}
1056+
} else if (y * 2 < graphHeight - 1) {
1057+
itemIndex = 1;
10601058
} else {
1061-
int deltaExpArg = deltaExp >= UINT16_WIDTH ? UINT16_WIDTH - 1 : deltaExp;
1062-
1063-
unsigned int scaleFactor;
1064-
size_t i = GraphMeterMode_valueCellIndex(graphHeight, isPercentChart, deltaExpArg, y, &scaleFactor, NULL);
1065-
if (i >= nCellsPerValue)
1066-
goto cellIsEmpty;
1059+
itemIndex = valueStart[1].numDots >= valueStart[2].numDots ? 0 : 1;
1060+
}
10671061

1068-
if (deltaExp >= UINT16_WIDTH) {
1069-
// Any "scaleFactor" value greater than 8 behaves the same as 8 for the
1070-
// "scaleCellDetails" function.
1071-
scaleFactor = 8;
1062+
if (y * 2 == graphHeight - 1 && valueStart[1].numDots > 8 && valueStart[2].numDots > 8) {
1063+
*details = valueStart[1].numDots >= valueStart[2].numDots ? 0x0F : 0xF0;
1064+
} else {
1065+
*details = 0xFF;
1066+
const uint8_t dotAlignment = 2;
1067+
if (y == blanksAtStart / 8) {
1068+
blanksAtStart = (blanksAtStart % 8) / dotAlignment * dotAlignment;
1069+
*details >>= blanksAtStart;
1070+
}
1071+
if ((graphHeight - 1 - y) == blanksAtEnd / 8) {
1072+
blanksAtEnd = (blanksAtEnd % 8) / dotAlignment * dotAlignment;
1073+
*details = (uint8_t)((*details >> blanksAtEnd) << blanksAtEnd);
10721074
}
1073-
1074-
const GraphColorCell* cell = &valueStart[i];
1075-
itemIndex = cell->c.itemNum - 1;
1076-
*details = GraphMeterMode_scaleCellDetails(cell->c.details, scaleFactor);
10771075
}
10781076
/* fallthrough */
10791077

10801078
cellIsEmpty:
1081-
if (y == 0)
1082-
*details |= 0xC0;
1083-
10841079
if (itemIndex == (uint8_t)-1)
10851080
return BAR_SHADOW;
10861081

@@ -1176,9 +1171,7 @@ static void GraphMeterMode_draw(Meter* this, int x, int y, int w) {
11761171

11771172
uint8_t maxItems = Meter_maxItems(this);
11781173
bool isPercentChart = Meter_isPercentChart(this);
1179-
size_t nCellsPerValue = maxItems <= 1 ? maxItems : graphHeight;
1180-
if (!isPercentChart)
1181-
nCellsPerValue *= 2;
1174+
size_t nCellsPerValue = maxItems < 1 ? maxItems : 3;
11821175

11831176
GraphDrawContext context = {
11841177
.maxItems = maxItems,

0 commit comments

Comments
 (0)