Skip to content

Commit e46e332

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

1 file changed

Lines changed: 74 additions & 81 deletions

File tree

Meter.c

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

250+
#if 0 /* Unused code */
250251
static size_t GraphMeterMode_valueCellIndex(unsigned int graphHeight, bool isPercentChart, int deltaExp, unsigned int y, unsigned int* scaleFactor, unsigned int* increment) {
251252
assert(deltaExp >= 0);
252253
assert(deltaExp < UINT16_WIDTH);
@@ -825,9 +826,9 @@ static void GraphMeterMode_computeColors(Meter* this, const GraphDrawContext* co
825826
}
826827
}
827828
}
829+
#endif /* End of unused code */
828830

829831
static void GraphMeterMode_recordNewValue(Meter* this, const GraphDrawContext* context) {
830-
uint8_t maxItems = context->maxItems;
831832
bool isPercentChart = context->isPercentChart;
832833
size_t nCellsPerValue = context->nCellsPerValue;
833834
if (!nCellsPerValue)
@@ -847,15 +848,23 @@ static void GraphMeterMode_recordNewValue(Meter* this, const GraphDrawContext* c
847848
valueStart = &valueStart[(nValues - 1) * nCellsPerValue];
848849

849850
// Compute "sum" and "total"
850-
double sum = Meter_computeSum(this);
851-
assert(sum >= 0.0);
852-
assert(sum <= DBL_MAX);
853-
double total;
851+
double total = 0.0;
854852
int scaleExp = 0;
855853
if (isPercentChart) {
856-
total = MAXIMUM(this->total, sum);
854+
assert(this->total >= 0.0);
855+
total = this->total;
856+
valueStart[0].scaleExp = (int16_t)scaleExp;
857857
} else {
858-
(void) frexp(sum, &scaleExp);
858+
if (isPositive(this->values[0]))
859+
total = this->values[0];
860+
861+
if (this->curItems > 1 && isgreater(this->values[1], total))
862+
total = this->values[1];
863+
864+
if (total > DBL_MAX)
865+
total = DBL_MAX;
866+
867+
(void) frexp(total, &scaleExp);
859868
if (scaleExp < 0) {
860869
scaleExp = 0;
861870
}
@@ -871,47 +880,22 @@ static void GraphMeterMode_recordNewValue(Meter* this, const GraphDrawContext* c
871880

872881
assert(graphHeight <= UINT16_MAX / 8);
873882
double maxDots = (double)(int32_t)(graphHeight * 8);
874-
int numDots = (int) ceil((sum / total) * maxDots);
875-
assert(numDots >= 0);
876-
if (sum > 0.0 && numDots <= 0) {
877-
numDots = 1; // Division of (sum / total) underflows
878-
}
879-
880-
if (maxItems == 1) {
881-
assert(numDots <= UINT16_MAX);
882-
valueStart[isPercentChart ? 0 : 1].numDots = (uint16_t)numDots;
883-
return;
884-
}
885-
886-
// Clear cells
887-
unsigned int y = ((unsigned int)numDots + 8 - 1) / 8; // Round up
888-
size_t i = GraphMeterMode_valueCellIndex(graphHeight, isPercentChart, 0, y, NULL, NULL);
889-
if (i < nCellsPerValue) {
890-
memset(&valueStart[i], 0, (nCellsPerValue - i) * sizeof(*valueStart));
891-
}
892-
893-
if (sum <= 0.0)
894-
return;
895-
896-
int deltaExp = 0;
897-
double scaledTotal = total;
898-
while (true) {
899-
numDots = (int) ceil((sum / scaledTotal) * maxDots);
900-
if (numDots <= 0) {
901-
numDots = 1; // Division of (sum / scaledTotal) underflows
902-
}
903-
904-
GraphMeterMode_computeColors(this, context, valueStart, deltaExp, scaledTotal, (unsigned int)numDots);
905-
906-
if (isPercentChart || !(scaledTotal < DBL_MAX) || (1U << deltaExp) >= graphHeight) {
907-
break;
883+
for (uint8_t i = 0; i < 2; i++) {
884+
double value = 0.0;
885+
if (i < this->curItems && isPositive(this->values[i]))
886+
value = this->values[i];
887+
888+
if (value > total)
889+
value = total;
890+
891+
int numDots = (int) ceil((value / total) * maxDots);
892+
assert(numDots >= 0);
893+
if (value > 0.0 && numDots <= 0) {
894+
numDots = 1; // Division of (value / total) underflows
908895
}
909896

910-
deltaExp++;
911-
scaledTotal *= 2.0;
912-
if (scaledTotal > DBL_MAX) {
913-
scaledTotal = DBL_MAX;
914-
}
897+
assert(numDots <= UINT16_MAX);
898+
valueStart[1 + i].numDots = (uint16_t)numDots;
915899
}
916900
}
917901

@@ -931,6 +915,7 @@ static void GraphMeterMode_printScale(int exponent) {
931915
}
932916
}
933917

918+
#if 0 /* Unused code */
934919
static uint8_t GraphMeterMode_scaleCellDetails(uint8_t details, unsigned int scaleFactor) {
935920
// Only the "top cell" of a record may need scaling like this; the cell does
936921
// not use the special meaning of bit 4.
@@ -958,6 +943,7 @@ static uint8_t GraphMeterMode_scaleCellDetails(uint8_t details, unsigned int sca
958943
}
959944
return 0x00;
960945
}
946+
#endif /* End of unused code */
961947

962948
static int GraphMeterMode_lookupCell(const Meter* this, const GraphDrawContext* context, int scaleExp, size_t valueIndex, unsigned int y, uint8_t* details) {
963949
unsigned int graphHeight = (unsigned int)this->h;
@@ -984,50 +970,59 @@ static int GraphMeterMode_lookupCell(const Meter* this, const GraphDrawContext*
984970
int deltaExp = isPercentChart ? 0 : scaleExp - valueStart[0].scaleExp;
985971
assert(deltaExp >= 0);
986972

987-
if (maxItems == 1) {
988-
unsigned int numDots = valueStart[isPercentChart ? 0 : 1].numDots;
973+
unsigned int numDots = valueStart[1].numDots;
974+
if (numDots >= 1) {
975+
if (deltaExp + 1 < UINT16_WIDTH) {
976+
numDots = ((numDots - 1) >> (deltaExp + 1)) + 1;
977+
} else {
978+
numDots = 1;
979+
}
980+
}
981+
unsigned int blanksAtEnd = graphHeight * 4 - numDots;
989982

990-
if (numDots < 1)
991-
goto cellIsEmpty;
983+
numDots = valueStart[2].numDots;
984+
if (numDots >= 1) {
985+
if (deltaExp + 1 < UINT16_WIDTH) {
986+
numDots = ((numDots - 1) >> (deltaExp + 1)) + 1;
987+
} else {
988+
numDots = 1;
989+
}
990+
}
991+
unsigned int blanksAtStart = graphHeight * 4 - numDots;
992992

993-
// Scale according to exponent difference. Round up.
994-
numDots = deltaExp < UINT16_WIDTH ? ((numDots - 1) >> deltaExp) : 0;
995-
numDots++;
993+
if (graphHeight - 1 - y < blanksAtEnd / 8)
994+
goto cellIsEmpty;
995+
if (y < blanksAtStart / 8)
996+
goto cellIsEmpty;
996997

997-
if (y > (numDots - 1) / 8)
998-
goto cellIsEmpty;
998+
if (y * 2 == graphHeight - 1 && !(valueStart[1].numDots || valueStart[2].numDots))
999+
goto cellIsEmpty;
9991000

1001+
if (maxItems <= 1 || y * 2 > graphHeight - 1) {
10001002
itemIndex = 0;
1001-
*details = 0xFF;
1002-
if (y == (numDots - 1) / 8) {
1003-
const uint8_t dotAlignment = 2;
1004-
unsigned int blanksAtTopCell = (8 - 1 - (numDots - 1) % 8) / dotAlignment * dotAlignment;
1005-
*details <<= blanksAtTopCell;
1006-
}
1003+
} else if (y * 2 < graphHeight - 1) {
1004+
itemIndex = 1;
10071005
} else {
1008-
int deltaExpArg = deltaExp >= UINT16_WIDTH ? UINT16_WIDTH - 1 : deltaExp;
1009-
1010-
unsigned int scaleFactor;
1011-
size_t i = GraphMeterMode_valueCellIndex(graphHeight, isPercentChart, deltaExpArg, y, &scaleFactor, NULL);
1012-
if (i >= nCellsPerValue)
1013-
goto cellIsEmpty;
1006+
itemIndex = valueStart[1].numDots >= valueStart[2].numDots ? 0 : 1;
1007+
}
10141008

1015-
if (deltaExp >= UINT16_WIDTH) {
1016-
// Any "scaleFactor" value greater than 8 behaves the same as 8 for the
1017-
// "scaleCellDetails" function.
1018-
scaleFactor = 8;
1009+
if (y * 2 == graphHeight - 1 && valueStart[1].numDots > 8 && valueStart[2].numDots > 8) {
1010+
*details = valueStart[1].numDots >= valueStart[2].numDots ? 0x0F : 0xF0;
1011+
} else {
1012+
*details = 0xFF;
1013+
const uint8_t dotAlignment = 2;
1014+
if (y == blanksAtStart / 8) {
1015+
blanksAtStart = (blanksAtStart % 8) / dotAlignment * dotAlignment;
1016+
*details >>= blanksAtStart;
1017+
}
1018+
if ((graphHeight - 1 - y) == blanksAtEnd / 8) {
1019+
blanksAtEnd = (blanksAtEnd % 8) / dotAlignment * dotAlignment;
1020+
*details = (uint8_t)((*details >> blanksAtEnd) << blanksAtEnd);
10191021
}
1020-
1021-
const GraphDataCell* cell = &valueStart[i];
1022-
itemIndex = cell->c.itemNum - 1;
1023-
*details = GraphMeterMode_scaleCellDetails(cell->c.details, scaleFactor);
10241022
}
10251023
/* fallthrough */
10261024

10271025
cellIsEmpty:
1028-
if (y == 0)
1029-
*details |= 0xC0;
1030-
10311026
if (itemIndex == (uint8_t)-1)
10321027
return BAR_SHADOW;
10331028

@@ -1125,9 +1120,7 @@ static void GraphMeterMode_draw(Meter* this, int x, int y, int w) {
11251120

11261121
uint8_t maxItems = Meter_maxItems(this);
11271122
bool isPercentChart = Meter_isPercentChart(this);
1128-
size_t nCellsPerValue = maxItems <= 1 ? maxItems : graphHeight;
1129-
if (!isPercentChart)
1130-
nCellsPerValue *= 2;
1123+
size_t nCellsPerValue = maxItems < 1 ? maxItems : 3;
11311124

11321125
GraphDrawContext context = {
11331126
.maxItems = maxItems,

0 commit comments

Comments
 (0)