@@ -36,6 +36,7 @@ in the source distribution for its full text.
36
36
#define DEFAULT_GRAPH_HEIGHT 4 /* Unit: rows (lines) */
37
37
#define MAX_GRAPH_HEIGHT 8191 /* == (int)(UINT16_MAX / 8) */
38
38
39
+ #if 0 /* Unused code */
39
40
typedef struct GraphColorCell_ {
40
41
/* Meter item number for the cell's color. Item numbers [1, 255] correspond
41
42
to array indices [0, 254] respectively. 0 means no color for the cell. */
@@ -46,11 +47,11 @@ typedef struct GraphColorCell_ {
46
47
specially. See the code of the "printCellDetails" function. */
47
48
uint8_t details ;
48
49
} GraphColorCell ;
50
+ #endif /* End of unused code */
49
51
50
52
typedef union GraphDataCell_ {
51
53
int16_t scaleExp ;
52
54
uint16_t numDots ;
53
- GraphColorCell c ;
54
55
} GraphDataCell ;
55
56
56
57
typedef struct GraphDrawContext_ {
@@ -255,6 +256,7 @@ static void GraphMeterMode_reallocateGraphBuffer(Meter* this, const GraphDrawCon
255
256
data -> nValues = nValues ;
256
257
}
257
258
259
+ #if 0 /* Unused code */
258
260
static inline size_t GraphMeterMode_valueCellIndex (unsigned int h , bool isPercentChart , int deltaExp , unsigned int y , unsigned int * scaleFactor , unsigned int * increment ) {
259
261
assert (deltaExp >= 0 );
260
262
assert (deltaExp < UINT16_WIDTH );
@@ -830,9 +832,9 @@ static void GraphMeterMode_computeColors(Meter* this, const GraphDrawContext* co
830
832
}
831
833
}
832
834
}
835
+ #endif /* End of unused code */
833
836
834
837
static void GraphMeterMode_recordNewValue (Meter * this , const GraphDrawContext * context ) {
835
- uint8_t maxItems = context -> maxItems ;
836
838
bool isPercentChart = context -> isPercentChart ;
837
839
size_t nCellsPerValue = context -> nCellsPerValue ;
838
840
if (!nCellsPerValue )
@@ -851,23 +853,23 @@ static void GraphMeterMode_recordNewValue(Meter* this, const GraphDrawContext* c
851
853
valueStart = (GraphDataCell * )data -> buffer ;
852
854
valueStart = & valueStart [(nValues - 1 ) * nCellsPerValue ];
853
855
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
-
862
856
// "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 );
864
870
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.
869
871
int scaleExp = 0 ;
870
- (void )frexp (sum , & scaleExp );
872
+ (void )frexp (total , & scaleExp );
871
873
scaleExp = MAXIMUM (0 , scaleExp );
872
874
873
875
// It's safe to assume "scaleExp" never overflows when IEEE 754
@@ -882,57 +884,26 @@ static void GraphMeterMode_recordNewValue(Meter* this, const GraphDrawContext* c
882
884
// Prevent overflow from "this->total" or ldexp().
883
885
total = MINIMUM (DBL_MAX , total );
884
886
885
- // The total number of dots that we would draw for this record
886
887
assert (h <= UINT16_MAX / 8 );
887
888
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
+ }
894
903
}
895
- }
896
904
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 ) {
900
905
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 ;
936
907
}
937
908
}
938
909
@@ -952,6 +923,7 @@ static void GraphMeterMode_printScale(int exponent) {
952
923
}
953
924
}
954
925
926
+ #if 0 /* Unused code */
955
927
static uint8_t GraphMeterMode_scaleCellDetails (uint8_t details , unsigned int scaleFactor ) {
956
928
// This scaling routine is only used on the "top cell" of a record.
957
929
// (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
981
953
}
982
954
return 0x00 ;
983
955
}
956
+ #endif /* End of unused code */
984
957
985
958
static int GraphMeterMode_lookupCell (const Meter * this , const GraphDrawContext * context , int scaleExp , size_t valueIndex , unsigned int y , uint8_t * details ) {
986
959
unsigned int h = (unsigned int )this -> h ;
@@ -1007,50 +980,59 @@ static int GraphMeterMode_lookupCell(const Meter* this, const GraphDrawContext*
1007
980
int deltaExp = isPercentChart ? 0 : scaleExp - valueStart [0 ].scaleExp ;
1008
981
assert (deltaExp >= 0 );
1009
982
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 ;
1012
992
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 ;
1015
1002
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 ;
1019
1007
1020
- if (y > ( numDots - 1 ) / 8 )
1021
- goto cellIsEmpty ;
1008
+ if (y * 2 == h - 1 && !( valueStart [ 1 ]. numDots || valueStart [ 2 ]. numDots ) )
1009
+ goto cellIsEmpty ;
1022
1010
1011
+ if (maxItems <= 1 || y * 2 > h - 1 ) {
1023
1012
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 ;
1030
1015
} 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
+ }
1037
1018
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 );
1042
1031
}
1043
-
1044
- const GraphDataCell * cell = & valueStart [i ];
1045
- itemIndex = cell -> c .itemNum - 1 ;
1046
- * details = GraphMeterMode_scaleCellDetails (cell -> c .details , scaleFactor );
1047
1032
}
1048
1033
/* fallthrough */
1049
1034
1050
1035
cellIsEmpty :
1051
- if (y == 0 )
1052
- * details |= 0xC0 ;
1053
-
1054
1036
if (itemIndex == (uint8_t )-1 )
1055
1037
return BAR_SHADOW ;
1056
1038
0 commit comments