Skip to content

Commit a129dc7

Browse files
committed
(draft) "Positive/negative" Graph meter style
Signed-off-by: Kang-Che Sung <explorer09@gmail.com>
1 parent 240f9e6 commit a129dc7

1 file changed

Lines changed: 76 additions & 87 deletions

File tree

Meter.c

Lines changed: 76 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,7 @@ static void GraphMeterMode_reallocateGraphBuffer(Meter* this, const GraphDrawCon
251251
data->nValues = nValues;
252252
}
253253

254+
#if 0 /* Unused code */
254255
static size_t GraphMeterMode_valueCellIndex(unsigned int graphHeight, bool isPercentChart, int deltaExp, unsigned int y, unsigned int* scaleFactor, unsigned int* increment) {
255256
assert(deltaExp >= 0);
256257
assert(deltaExp < UINT16_WIDTH);
@@ -829,9 +830,9 @@ static void GraphMeterMode_computeColors(Meter* this, const GraphDrawContext* co
829830
}
830831
}
831832
}
833+
#endif /* End of unused code */
832834

833835
static void GraphMeterMode_recordNewValue(Meter* this, const GraphDrawContext* context) {
834-
uint8_t maxItems = context->maxItems;
835836
bool isPercentChart = context->isPercentChart;
836837
size_t nCellsPerValue = context->nCellsPerValue;
837838
if (!nCellsPerValue)
@@ -851,18 +852,23 @@ static void GraphMeterMode_recordNewValue(Meter* this, const GraphDrawContext* c
851852
valueStart = &valueStart[(nValues - 1) * nCellsPerValue];
852853

853854
// Compute "sum" and "total"
854-
double sum = 0.0;
855-
if (this->curItems > 0) {
856-
sum = Meter_computeSum(this);
857-
assert(sum >= 0.0);
858-
assert(sum <= DBL_MAX);
859-
}
860-
double total;
855+
double total = 0.0;
861856
if (isPercentChart) {
862-
total = MAXIMUM(this->total, sum);
857+
assert(this->total >= 0.0);
858+
total = this->total;
859+
valueStart[0].scaleExp = 0;
863860
} else {
861+
if (isPositive(this->values[0]))
862+
total = this->values[0];
863+
864+
if (this->curItems > 1 && isgreater(this->values[1], total))
865+
total = this->values[1];
866+
867+
if (total > DBL_MAX)
868+
total = DBL_MAX;
869+
864870
int scaleExp = 0;
865-
(void)frexp(sum, &scaleExp);
871+
(void)frexp(total, &scaleExp);
866872
if (scaleExp < 0) {
867873
scaleExp = 0;
868874
}
@@ -878,51 +884,25 @@ static void GraphMeterMode_recordNewValue(Meter* this, const GraphDrawContext* c
878884

879885
assert(graphHeight <= UINT16_MAX / 8);
880886
double maxDots = (double)(int32_t)(graphHeight * 8);
881-
int numDots = 0;
882-
if (total > 0.0) {
883-
numDots = (int)ceil((sum / total) * maxDots);
884-
assert(numDots >= 0);
885-
if (sum > 0.0 && numDots <= 0) {
886-
numDots = 1; // Division of (sum / total) underflows
887+
for (uint8_t i = 0; i < 2; i++) {
888+
double value = 0.0;
889+
if (i < this->curItems && isPositive(this->values[i]))
890+
value = this->values[i];
891+
892+
if (value > total)
893+
value = total;
894+
895+
int numDots = 0;
896+
if (total > 0.0) {
897+
numDots = (int)ceil((value / total) * maxDots);
898+
assert(numDots >= 0);
899+
if (value > 0.0 && numDots <= 0) {
900+
numDots = 1; // Division of (value / total) underflows
901+
}
887902
}
888-
}
889903

890-
if (maxItems == 1) {
891904
assert(numDots <= UINT16_MAX);
892-
valueStart[isPercentChart ? 0 : 1].numDots = (uint16_t)numDots;
893-
return;
894-
}
895-
896-
// Clear cells
897-
unsigned int y = ((unsigned int)numDots + 8 - 1) / 8; // Round up
898-
size_t i = GraphMeterMode_valueCellIndex(graphHeight, isPercentChart, 0, y, NULL, NULL);
899-
if (i < nCellsPerValue) {
900-
memset(&valueStart[i], 0, (nCellsPerValue - i) * sizeof(*valueStart));
901-
}
902-
903-
if (sum <= 0.0)
904-
return;
905-
906-
int deltaExp = 0;
907-
double scaledTotal = total;
908-
assert(scaledTotal > 0.0);
909-
while (true) {
910-
numDots = (int)ceil((sum / scaledTotal) * maxDots);
911-
if (numDots <= 0) {
912-
numDots = 1; // Division of (sum / scaledTotal) underflows
913-
}
914-
915-
GraphMeterMode_computeColors(this, context, valueStart, deltaExp, scaledTotal, (unsigned int)numDots);
916-
917-
if (isPercentChart || !(scaledTotal < DBL_MAX) || (1U << deltaExp) >= graphHeight) {
918-
break;
919-
}
920-
921-
deltaExp++;
922-
scaledTotal *= 2.0;
923-
if (scaledTotal > DBL_MAX) {
924-
scaledTotal = DBL_MAX;
925-
}
905+
valueStart[1 + i].numDots = (uint16_t)numDots;
926906
}
927907
}
928908

@@ -942,6 +922,7 @@ static void GraphMeterMode_printScale(int exponent) {
942922
}
943923
}
944924

925+
#if 0 /* Unused code */
945926
static uint8_t GraphMeterMode_scaleCellDetails(uint8_t details, unsigned int scaleFactor) {
946927
// Only the "top cell" of a record may need scaling like this; the cell does
947928
// not use the special meaning of bit 4.
@@ -969,6 +950,7 @@ static uint8_t GraphMeterMode_scaleCellDetails(uint8_t details, unsigned int sca
969950
}
970951
return 0x00;
971952
}
953+
#endif /* End of unused code */
972954

973955
static int GraphMeterMode_lookupCell(const Meter* this, const GraphDrawContext* context, int scaleExp, size_t valueIndex, unsigned int y, uint8_t* details) {
974956
unsigned int graphHeight = (unsigned int)this->h;
@@ -995,50 +977,59 @@ static int GraphMeterMode_lookupCell(const Meter* this, const GraphDrawContext*
995977
int deltaExp = isPercentChart ? 0 : scaleExp - valueStart[0].scaleExp;
996978
assert(deltaExp >= 0);
997979

998-
if (maxItems == 1) {
999-
unsigned int numDots = valueStart[isPercentChart ? 0 : 1].numDots;
980+
unsigned int numDots = valueStart[1].numDots;
981+
if (numDots >= 1) {
982+
if (deltaExp + 1 < UINT16_WIDTH) {
983+
numDots = ((numDots - 1) >> (deltaExp + 1)) + 1;
984+
} else {
985+
numDots = 1;
986+
}
987+
}
988+
unsigned int blanksAtEnd = graphHeight * 4 - numDots;
1000989

1001-
if (numDots < 1)
1002-
goto cellIsEmpty;
990+
numDots = valueStart[2].numDots;
991+
if (numDots >= 1) {
992+
if (deltaExp + 1 < UINT16_WIDTH) {
993+
numDots = ((numDots - 1) >> (deltaExp + 1)) + 1;
994+
} else {
995+
numDots = 1;
996+
}
997+
}
998+
unsigned int blanksAtStart = graphHeight * 4 - numDots;
1003999

1004-
// Scale according to exponent difference. Round up.
1005-
numDots = deltaExp < UINT16_WIDTH ? ((numDots - 1) >> deltaExp) : 0;
1006-
numDots++;
1000+
if (graphHeight - 1 - y < blanksAtEnd / 8)
1001+
goto cellIsEmpty;
1002+
if (y < blanksAtStart / 8)
1003+
goto cellIsEmpty;
10071004

1008-
if (y > (numDots - 1) / 8)
1009-
goto cellIsEmpty;
1005+
if (y * 2 == graphHeight - 1 && !(valueStart[1].numDots || valueStart[2].numDots))
1006+
goto cellIsEmpty;
10101007

1008+
if (maxItems <= 1 || y * 2 > graphHeight - 1) {
10111009
itemIndex = 0;
1012-
*details = 0xFF;
1013-
if (y == (numDots - 1) / 8) {
1014-
const uint8_t dotAlignment = 2;
1015-
unsigned int blanksAtTopCell = (8 - 1 - (numDots - 1) % 8) / dotAlignment * dotAlignment;
1016-
*details <<= blanksAtTopCell;
1017-
}
1010+
} else if (y * 2 < graphHeight - 1) {
1011+
itemIndex = 1;
10181012
} else {
1019-
int deltaExpArg = deltaExp >= UINT16_WIDTH ? UINT16_WIDTH - 1 : deltaExp;
1020-
1021-
unsigned int scaleFactor;
1022-
size_t i = GraphMeterMode_valueCellIndex(graphHeight, isPercentChart, deltaExpArg, y, &scaleFactor, NULL);
1023-
if (i >= nCellsPerValue)
1024-
goto cellIsEmpty;
1013+
itemIndex = valueStart[1].numDots >= valueStart[2].numDots ? 0 : 1;
1014+
}
10251015

1026-
if (deltaExp >= UINT16_WIDTH) {
1027-
// Any "scaleFactor" value greater than 8 behaves the same as 8 for the
1028-
// "scaleCellDetails" function.
1029-
scaleFactor = 8;
1016+
if (y * 2 == graphHeight - 1 && valueStart[1].numDots > 8 && valueStart[2].numDots > 8) {
1017+
*details = valueStart[1].numDots >= valueStart[2].numDots ? 0x0F : 0xF0;
1018+
} else {
1019+
*details = 0xFF;
1020+
const uint8_t dotAlignment = 2;
1021+
if (y == blanksAtStart / 8) {
1022+
blanksAtStart = (blanksAtStart % 8) / dotAlignment * dotAlignment;
1023+
*details >>= blanksAtStart;
1024+
}
1025+
if ((graphHeight - 1 - y) == blanksAtEnd / 8) {
1026+
blanksAtEnd = (blanksAtEnd % 8) / dotAlignment * dotAlignment;
1027+
*details = (uint8_t)((*details >> blanksAtEnd) << blanksAtEnd);
10301028
}
1031-
1032-
const GraphDataCell* cell = &valueStart[i];
1033-
itemIndex = cell->c.itemNum - 1;
1034-
*details = GraphMeterMode_scaleCellDetails(cell->c.details, scaleFactor);
10351029
}
10361030
/* fallthrough */
10371031

10381032
cellIsEmpty:
1039-
if (y == 0)
1040-
*details |= 0xC0;
1041-
10421033
if (itemIndex == (uint8_t)-1)
10431034
return BAR_SHADOW;
10441035

@@ -1136,9 +1127,7 @@ static void GraphMeterMode_draw(Meter* this, int x, int y, int w) {
11361127

11371128
uint8_t maxItems = Meter_maxItems(this);
11381129
bool isPercentChart = Meter_isPercentChart(this);
1139-
size_t nCellsPerValue = maxItems <= 1 ? maxItems : graphHeight;
1140-
if (!isPercentChart)
1141-
nCellsPerValue *= 2;
1130+
size_t nCellsPerValue = maxItems < 1 ? maxItems : 3;
11421131

11431132
GraphDrawContext context = {
11441133
.maxItems = maxItems,

0 commit comments

Comments
 (0)