@@ -36,6 +36,7 @@ in the source distribution for its full text.
3636#define DEFAULT_GRAPH_HEIGHT 4 /* Unit: rows (lines) */
3737#define MAX_GRAPH_HEIGHT 8191 /* == (int)(UINT16_MAX / 8) */
3838
39+ #if 0 /* Unused code */
3940typedef struct GraphColorCell_ {
4041 /* Meter item number for the cell's color. Item numbers [1, 255] correspond
4142 to array indices [0, 254] respectively. 0 means no color for the cell. */
@@ -46,11 +47,11 @@ typedef struct GraphColorCell_ {
4647 specially. See the code of the "printCellDetails" function. */
4748 uint8_t details ;
4849} GraphColorCell ;
50+ #endif /* End of unused code */
4951
5052typedef union GraphDataCell_ {
5153 int16_t scaleExp ;
5254 uint16_t numDots ;
53- GraphColorCell c ;
5455} GraphDataCell ;
5556
5657typedef struct GraphDrawContext_ {
@@ -255,6 +256,7 @@ static void GraphMeterMode_reallocateGraphBuffer(Meter* this, const GraphDrawCon
255256 data -> nValues = nValues ;
256257}
257258
259+ #if 0 /* Unused code */
258260static inline size_t GraphMeterMode_valueCellIndex (unsigned int h , bool isPercentChart , int deltaExp , unsigned int y , unsigned int * scaleFactor , unsigned int * increment ) {
259261 assert (deltaExp >= 0 );
260262 assert (deltaExp < UINT16_WIDTH );
@@ -830,9 +832,9 @@ static void GraphMeterMode_computeColors(Meter* this, const GraphDrawContext* co
830832 }
831833 }
832834}
835+ #endif /* End of unused code */
833836
834837static void GraphMeterMode_recordNewValue (Meter * this , const GraphDrawContext * context ) {
835- uint8_t maxItems = context -> maxItems ;
836838 bool isPercentChart = context -> isPercentChart ;
837839 size_t nCellsPerValue = context -> nCellsPerValue ;
838840 if (!nCellsPerValue )
@@ -851,23 +853,23 @@ static void GraphMeterMode_recordNewValue(Meter* this, const GraphDrawContext* c
851853 valueStart = (GraphDataCell * )data -> buffer ;
852854 valueStart = & valueStart [(nValues - 1 ) * nCellsPerValue ];
853855
854- // Sum the values of all items
855- double sum = 0.0 ;
856- if (this -> curItems > 0 ) {
857- sum = Meter_computeSum (this );
858- assert (sum >= 0.0 );
859- assert (sum <= DBL_MAX );
860- }
861-
862856 // "total" refers to the value that we would draw as full in graph
863- double total = MAXIMUM (this -> total , sum );
857+ double total = 0.0 ;
858+ if (isPercentChart ) {
859+ assert (this -> total >= 0.0 );
860+ total = this -> total ;
861+ valueStart [0 ].scaleExp = 0 ;
862+ } else {
863+ if (isPositive (this -> values [0 ]))
864+ total = this -> values [0 ];
865+
866+ if (this -> curItems > 1 && isgreater (this -> values [1 ], total ))
867+ total = this -> values [1 ];
868+
869+ total = MINIMUM (DBL_MAX , total );
864870
865- if (!isPercentChart ) {
866- // Dynamic scale. "this->total" is ignored.
867- // Determine the scale and "total" that we need afterward. The "total" is
868- // the "sum" value rounded up to a power of 2.
869871 int scaleExp = 0 ;
870- (void )frexp (sum , & scaleExp );
872+ (void )frexp (total , & scaleExp );
871873 scaleExp = MAXIMUM (0 , scaleExp );
872874
873875 // It's safe to assume "scaleExp" never overflows when IEEE 754
@@ -882,57 +884,26 @@ static void GraphMeterMode_recordNewValue(Meter* this, const GraphDrawContext* c
882884 // Prevent overflow from "this->total" or ldexp().
883885 total = MINIMUM (DBL_MAX , total );
884886
885- // The total number of dots that we would draw for this record
886887 assert (h <= UINT16_MAX / 8 );
887888 double maxDots = (double )(int32_t )(h * 8 );
888- int numDots = 0 ;
889- if (total > 0.0 ) {
890- numDots = (int )ceil ((sum / total ) * maxDots );
891- assert (numDots >= 0 );
892- if (sum > 0.0 && numDots <= 0 ) {
893- numDots = 1 ; // Division of (sum / total) underflows
889+ for (uint8_t i = 0 ; i < 2 ; i ++ ) {
890+ double value = 0.0 ;
891+ if (i < this -> curItems && isPositive (this -> values [i ]))
892+ value = this -> values [i ];
893+
894+ value = MINIMUM (total , value );
895+
896+ int numDots = 0 ;
897+ if (total > 0.0 ) {
898+ numDots = (int )ceil ((value / total ) * maxDots );
899+ assert (numDots >= 0 );
900+ if (value > 0.0 && numDots <= 0 ) {
901+ numDots = 1 ; // Division of (value / total) underflows
902+ }
894903 }
895- }
896904
897- // For a one-item meter, record the number of dots in the graph data buffer
898- // and we are done.
899- if (maxItems == 1 ) {
900905 assert (numDots <= UINT16_MAX );
901- valueStart [isPercentChart ? 0 : 1 ].numDots = (uint16_t )numDots ;
902- return ;
903- }
904-
905- // For a meter of multiple items, we will precompute the colors of each cell
906- // and store them in a record. First clear the cells, which might contain
907- // data of the previous record.
908- unsigned int y = ((unsigned int )numDots + 8 - 1 ) / 8 ; // Round up
909- size_t i = GraphMeterMode_valueCellIndex (h , isPercentChart , 0 , y , NULL , NULL );
910- if (i < nCellsPerValue ) {
911- memset (& valueStart [i ], 0 , (nCellsPerValue - i ) * sizeof (* valueStart ));
912- }
913-
914- if (sum <= 0.0 ) {
915- // The record is empty. No colors needed.
916- return ;
917- }
918-
919- int deltaExp = 0 ;
920- double scaledTotal = total ;
921- assert (scaledTotal > 0.0 );
922- while (true) {
923- numDots = (int )ceil ((sum / scaledTotal ) * maxDots );
924- if (numDots <= 0 ) {
925- numDots = 1 ; // Division of (sum / scaledTotal) underflows
926- }
927-
928- GraphMeterMode_computeColors (this , context , valueStart , deltaExp , scaledTotal , (unsigned int )numDots );
929-
930- if (isPercentChart || !(scaledTotal < DBL_MAX ) || (1U << deltaExp ) >= h ) {
931- break ;
932- }
933-
934- deltaExp ++ ;
935- scaledTotal = MINIMUM (DBL_MAX , scaledTotal * 2.0 );
906+ valueStart [1 + i ].numDots = (uint16_t )numDots ;
936907 }
937908}
938909
@@ -952,6 +923,7 @@ static void GraphMeterMode_printScale(int exponent) {
952923 }
953924}
954925
926+ #if 0 /* Unused code */
955927static uint8_t GraphMeterMode_scaleCellDetails (uint8_t details , unsigned int scaleFactor ) {
956928 // This scaling routine is only used on the "top cell" of a record.
957929 // (The "top cell" never uses the special meaning of bit 4.)
@@ -981,6 +953,7 @@ static uint8_t GraphMeterMode_scaleCellDetails(uint8_t details, unsigned int sca
981953 }
982954 return 0x00 ;
983955}
956+ #endif /* End of unused code */
984957
985958static int GraphMeterMode_lookupCell (const Meter * this , const GraphDrawContext * context , int scaleExp , size_t valueIndex , unsigned int y , uint8_t * details ) {
986959 unsigned int h = (unsigned int )this -> h ;
@@ -1007,50 +980,59 @@ static int GraphMeterMode_lookupCell(const Meter* this, const GraphDrawContext*
1007980 int deltaExp = isPercentChart ? 0 : scaleExp - valueStart [0 ].scaleExp ;
1008981 assert (deltaExp >= 0 );
1009982
1010- if (maxItems == 1 ) {
1011- unsigned int numDots = valueStart [isPercentChart ? 0 : 1 ].numDots ;
983+ unsigned int numDots = valueStart [1 ].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 blanksAtEnd = h * 4 - numDots ;
1012992
1013- if (numDots < 1 )
1014- goto cellIsEmpty ;
993+ numDots = valueStart [2 ].numDots ;
994+ if (numDots >= 1 ) {
995+ if (deltaExp + 1 < UINT16_WIDTH ) {
996+ numDots = ((numDots - 1 ) >> (deltaExp + 1 )) + 1 ;
997+ } else {
998+ numDots = 1 ;
999+ }
1000+ }
1001+ unsigned int blanksAtStart = h * 4 - numDots ;
10151002
1016- // Scale according to exponent difference. Round up.
1017- numDots = deltaExp < UINT16_WIDTH ? ((numDots - 1 ) >> deltaExp ) : 0 ;
1018- numDots ++ ;
1003+ if (h - 1 - y < blanksAtEnd / 8 )
1004+ goto cellIsEmpty ;
1005+ if (y < blanksAtStart / 8 )
1006+ goto cellIsEmpty ;
10191007
1020- if (y > ( numDots - 1 ) / 8 )
1021- goto cellIsEmpty ;
1008+ if (y * 2 == h - 1 && !( valueStart [ 1 ]. numDots || valueStart [ 2 ]. numDots ) )
1009+ goto cellIsEmpty ;
10221010
1011+ if (maxItems <= 1 || y * 2 > h - 1 ) {
10231012 itemIndex = 0 ;
1024- * details = 0xFF ;
1025- if (y == (numDots - 1 ) / 8 ) {
1026- const uint8_t dotAlignment = 2 ;
1027- unsigned int blanksAtTopCell = (8 - 1 - (numDots - 1 ) % 8 ) / dotAlignment * dotAlignment ;
1028- * details <<= blanksAtTopCell ;
1029- }
1013+ } else if (y * 2 < h - 1 ) {
1014+ itemIndex = 1 ;
10301015 } else {
1031- int deltaExpArg = MINIMUM (UINT16_WIDTH - 1 , deltaExp );
1032-
1033- unsigned int scaleFactor ;
1034- size_t i = GraphMeterMode_valueCellIndex (h , isPercentChart , deltaExpArg , y , & scaleFactor , NULL );
1035- if (i >= nCellsPerValue )
1036- goto cellIsEmpty ;
1016+ itemIndex = valueStart [1 ].numDots >= valueStart [2 ].numDots ? 0 : 1 ;
1017+ }
10371018
1038- if (deltaExp >= UINT16_WIDTH ) {
1039- // Any "scaleFactor" value greater than 8 behaves the same as 8 for the
1040- // "scaleCellDetails" function.
1041- scaleFactor = 8 ;
1019+ if (y * 2 == h - 1 && valueStart [1 ].numDots > 8 && valueStart [2 ].numDots > 8 ) {
1020+ * details = valueStart [1 ].numDots >= valueStart [2 ].numDots ? 0x0F : 0xF0 ;
1021+ } else {
1022+ * details = 0xFF ;
1023+ const uint8_t dotAlignment = 2 ;
1024+ if (y == blanksAtStart / 8 ) {
1025+ blanksAtStart = (blanksAtStart % 8 ) / dotAlignment * dotAlignment ;
1026+ * details >>= blanksAtStart ;
1027+ }
1028+ if ((h - 1 - y ) == blanksAtEnd / 8 ) {
1029+ blanksAtEnd = (blanksAtEnd % 8 ) / dotAlignment * dotAlignment ;
1030+ * details = (uint8_t )((* details >> blanksAtEnd ) << blanksAtEnd );
10421031 }
1043-
1044- const GraphDataCell * cell = & valueStart [i ];
1045- itemIndex = cell -> c .itemNum - 1 ;
1046- * details = GraphMeterMode_scaleCellDetails (cell -> c .details , scaleFactor );
10471032 }
10481033 /* fallthrough */
10491034
10501035cellIsEmpty :
1051- if (y == 0 )
1052- * details |= 0xC0 ;
1053-
10541036 if (itemIndex == (uint8_t )-1 )
10551037 return BAR_SHADOW ;
10561038
0 commit comments