/* Draws box around plot and plot labels */ static void write_box(FILE * out) { fprintf(out, "newpath\n"); MOVETO(x_low, y_low); LINETO(x_high, y_low); LINETO(x_high, y_high); LINETO(x_low, y_high); fprintf(out, "closepath\n"); fprintf(out, "0 setgray\n"); fprintf(out, "1 setlinewidth\n"); fprintf(out, "stroke\n\n"); fprintf(out, "/Helvetica findfont\n"); fprintf(out, "12 scalefont setfont\n"); write_axis_units(out, 0); write_axis_units(out, 1); }
void QLCDNumberPrivate::drawSegment(const QPoint &pos, char segmentNo, QPainter &p, int segLen, bool erase) { Q_Q(QLCDNumber); QPoint ppt; QPoint pt = pos; int width = segLen/5; const QPalette &pal = q->palette(); QColor lightColor,darkColor,fgColor; if (erase){ lightColor = pal.color(q->backgroundRole()); darkColor = lightColor; fgColor = lightColor; } else { lightColor = pal.light().color(); darkColor = pal.dark().color(); fgColor = pal.color(q->foregroundRole()); } #define LINETO(X,Y) addPoint(a, QPoint(pt.x() + (X),pt.y() + (Y))) #define LIGHT #define DARK if (fill) { QPolygon a(0); //The following is an exact copy of the switch below. //don't make any changes here switch (segmentNo) { case 0 : ppt = pt; LIGHT; LINETO(segLen - 1,0); DARK; LINETO(segLen - width - 1,width); LINETO(width,width); LINETO(0,0); break; case 1 : pt += QPoint(0 , 1); ppt = pt; LIGHT; LINETO(width,width); DARK; LINETO(width,segLen - width/2 - 2); LINETO(0,segLen - 2); LIGHT; LINETO(0,0); break; case 2 : pt += QPoint(segLen - 1 , 1); ppt = pt; DARK; LINETO(0,segLen - 2); LINETO(-width,segLen - width/2 - 2); LIGHT; LINETO(-width,width); LINETO(0,0); break; case 3 : pt += QPoint(0 , segLen); ppt = pt; LIGHT; LINETO(width,-width/2); LINETO(segLen - width - 1,-width/2); LINETO(segLen - 1,0); DARK; if (width & 1) { // adjust for integer division error LINETO(segLen - width - 3,width/2 + 1); LINETO(width + 2,width/2 + 1); } else { LINETO(segLen - width - 1,width/2); LINETO(width,width/2); } LINETO(0,0); break; case 4 : pt += QPoint(0 , segLen + 1); ppt = pt; LIGHT; LINETO(width,width/2); DARK; LINETO(width,segLen - width - 2); LINETO(0,segLen - 2); LIGHT; LINETO(0,0); break; case 5 : pt += QPoint(segLen - 1 , segLen + 1); ppt = pt; DARK; LINETO(0,segLen - 2); LINETO(-width,segLen - width - 2); LIGHT; LINETO(-width,width/2); LINETO(0,0); break; case 6 : pt += QPoint(0 , segLen*2); ppt = pt; LIGHT; LINETO(width,-width); LINETO(segLen - width - 1,-width); LINETO(segLen - 1,0); DARK; LINETO(0,0); break; case 7 : if (smallPoint) // if smallpoint place'.' between other digits pt += QPoint(segLen + width/2 , segLen*2); else pt += QPoint(segLen/2 , segLen*2); ppt = pt; DARK; LINETO(width,0); LINETO(width,-width); LIGHT; LINETO(0,-width); LINETO(0,0); break; case 8 : pt += QPoint(segLen/2 - width/2 + 1 , segLen/2 + width); ppt = pt; DARK; LINETO(width,0); LINETO(width,-width); LIGHT; LINETO(0,-width); LINETO(0,0); break; case 9 : pt += QPoint(segLen/2 - width/2 + 1 , 3*segLen/2 + width); ppt = pt; DARK; LINETO(width,0); LINETO(width,-width); LIGHT; LINETO(0,-width); LINETO(0,0); break; default : qWarning("QLCDNumber::drawSegment: (%s) Illegal segment id: %d\n", q->objectName().toLocal8Bit().constData(), segmentNo); } // End exact copy p.setPen(Qt::NoPen); p.setBrush(fgColor); p.drawPolygon(a); p.setBrush(Qt::NoBrush); pt = pos; } #undef LINETO #undef LIGHT #undef DARK #define LINETO(X,Y) p.drawLine(ppt.x(), ppt.y(), pt.x()+(X), pt.y()+(Y)); \ ppt = QPoint(pt.x()+(X), pt.y()+(Y)) #define LIGHT p.setPen(lightColor) #define DARK p.setPen(darkColor) if (shadow) switch (segmentNo) { case 0 : ppt = pt; LIGHT; LINETO(segLen - 1,0); DARK; LINETO(segLen - width - 1,width); LINETO(width,width); LINETO(0,0); break; case 1 : pt += QPoint(0,1); ppt = pt; LIGHT; LINETO(width,width); DARK; LINETO(width,segLen - width/2 - 2); LINETO(0,segLen - 2); LIGHT; LINETO(0,0); break; case 2 : pt += QPoint(segLen - 1 , 1); ppt = pt; DARK; LINETO(0,segLen - 2); LINETO(-width,segLen - width/2 - 2); LIGHT; LINETO(-width,width); LINETO(0,0); break; case 3 : pt += QPoint(0 , segLen); ppt = pt; LIGHT; LINETO(width,-width/2); LINETO(segLen - width - 1,-width/2); LINETO(segLen - 1,0); DARK; if (width & 1) { // adjust for integer division error LINETO(segLen - width - 3,width/2 + 1); LINETO(width + 2,width/2 + 1); } else { LINETO(segLen - width - 1,width/2); LINETO(width,width/2); } LINETO(0,0); break; case 4 : pt += QPoint(0 , segLen + 1); ppt = pt; LIGHT; LINETO(width,width/2); DARK; LINETO(width,segLen - width - 2); LINETO(0,segLen - 2); LIGHT; LINETO(0,0); break; case 5 : pt += QPoint(segLen - 1 , segLen + 1); ppt = pt; DARK; LINETO(0,segLen - 2); LINETO(-width,segLen - width - 2); LIGHT; LINETO(-width,width/2); LINETO(0,0); break; case 6 : pt += QPoint(0 , segLen*2); ppt = pt; LIGHT; LINETO(width,-width); LINETO(segLen - width - 1,-width); LINETO(segLen - 1,0); DARK; LINETO(0,0); break; case 7 : if (smallPoint) // if smallpoint place'.' between other digits pt += QPoint(segLen + width/2 , segLen*2); else pt += QPoint(segLen/2 , segLen*2); ppt = pt; DARK; LINETO(width,0); LINETO(width,-width); LIGHT; LINETO(0,-width); LINETO(0,0); break; case 8 : pt += QPoint(segLen/2 - width/2 + 1 , segLen/2 + width); ppt = pt; DARK; LINETO(width,0); LINETO(width,-width); LIGHT; LINETO(0,-width); LINETO(0,0); break; case 9 : pt += QPoint(segLen/2 - width/2 + 1 , 3*segLen/2 + width); ppt = pt; DARK; LINETO(width,0); LINETO(width,-width); LIGHT; LINETO(0,-width); LINETO(0,0); break; default : qWarning("QLCDNumber::drawSegment: (%s) Illegal segment id: %d\n", q->objectName().toLocal8Bit().constData(), segmentNo); } #undef LINETO #undef LIGHT #undef DARK }
/* Note: * This is just a sample piece of code that shows how to use some structs - * it may not even run. */ #include <geos.h> static const graphicStr myString = { MOVEPENTO (0,0), LINETO(100,100), RECTANGLETO(50,50), NEWPATTERN(3), FRAME_RECTO(50,50), PEN_X_DELTA(10), PEN_Y_DELTA(10), PEN_XY_DELTA(10,10), GSTR_END }; int main (void) { GraphicsString(&myString); }
void QLCDNumber::drawSegment( const QPoint &pos, char segmentNo, QPainter &p, int segLen, bool erase ) { QPoint pt = pos; int width = segLen/5; const QColorGroup & g = colorGroup(); QColor lightColor,darkColor,fgColor; if ( erase ){ lightColor = backgroundColor(); darkColor = lightColor; fgColor = lightColor; } else { lightColor = g.light(); darkColor = g.dark(); fgColor = g.foreground(); } #define LINETO(X,Y) addPoint( a, QPoint(pt.x() + (X),pt.y() + (Y))) #define LIGHT #define DARK if ( fill ) { QPointArray a(0); //The following is an exact copy of the switch below. //don't make any changes here switch ( segmentNo ) { case 0 : p.moveTo(pt); LIGHT; LINETO(segLen - 1,0); DARK; LINETO(segLen - width - 1,width); LINETO(width,width); LINETO(0,0); break; case 1 : pt += QPoint(0 , 1); p.moveTo(pt); LIGHT; LINETO(width,width); DARK; LINETO(width,segLen - width/2 - 2); LINETO(0,segLen - 2); LIGHT; LINETO(0,0); break; case 2 : pt += QPoint(segLen - 1 , 1); p.moveTo(pt); DARK; LINETO(0,segLen - 2); LINETO(-width,segLen - width/2 - 2); LIGHT; LINETO(-width,width); LINETO(0,0); break; case 3 : pt += QPoint(0 , segLen); p.moveTo(pt); LIGHT; LINETO(width,-width/2); LINETO(segLen - width - 1,-width/2); LINETO(segLen - 1,0); DARK; if (width & 1) { // adjust for integer division error LINETO(segLen - width - 3,width/2 + 1); LINETO(width + 2,width/2 + 1); } else { LINETO(segLen - width - 1,width/2); LINETO(width,width/2); } LINETO(0,0); break; case 4 : pt += QPoint(0 , segLen + 1); p.moveTo(pt); LIGHT; LINETO(width,width/2); DARK; LINETO(width,segLen - width - 2); LINETO(0,segLen - 2); LIGHT; LINETO(0,0); break; case 5 : pt += QPoint(segLen - 1 , segLen + 1); p.moveTo(pt); DARK; LINETO(0,segLen - 2); LINETO(-width,segLen - width - 2); LIGHT; LINETO(-width,width/2); LINETO(0,0); break; case 6 : pt += QPoint(0 , segLen*2); p.moveTo(pt); LIGHT; LINETO(width,-width); LINETO(segLen - width - 1,-width); LINETO(segLen - 1,0); DARK; LINETO(0,0); break; case 7 : if ( smallPoint ) // if smallpoint place'.' between other digits pt += QPoint(segLen + width/2 , segLen*2); else pt += QPoint(segLen/2 , segLen*2); p.moveTo(pt); DARK; LINETO(width,0); LINETO(width,-width); LIGHT; LINETO(0,-width); LINETO(0,0); break; case 8 : pt += QPoint(segLen/2 - width/2 + 1 , segLen/2 + width); p.moveTo(pt); DARK; LINETO(width,0); LINETO(width,-width); LIGHT; LINETO(0,-width); LINETO(0,0); break; case 9 : pt += QPoint(segLen/2 - width/2 + 1 , 3*segLen/2 + width); p.moveTo(pt); DARK; LINETO(width,0); LINETO(width,-width); LIGHT; LINETO(0,-width); LINETO(0,0); break; #if defined(CHECK_RANGE) default : qWarning( "QLCDNumber::drawSegment: (%s) Internal error." " Illegal segment id: %d\n", name( "unnamed" ), segmentNo ); #endif } // End exact copy p.setPen( fgColor ); p.setBrush( fgColor ); p.drawPolygon( a ); p.setBrush( NoBrush ); pt = pos; } #undef LINETO #undef LIGHT #undef DARK #define LINETO(X,Y) p.lineTo(QPoint(pt.x() + (X),pt.y() + (Y))) #define LIGHT p.setPen(lightColor) #define DARK p.setPen(darkColor) if ( shadow ) switch ( segmentNo ) { case 0 : p.moveTo(pt); LIGHT; LINETO(segLen - 1,0); DARK; LINETO(segLen - width - 1,width); LINETO(width,width); LINETO(0,0); break; case 1 : pt += QPoint(0,1); p.moveTo(pt); LIGHT; LINETO(width,width); DARK; LINETO(width,segLen - width/2 - 2); LINETO(0,segLen - 2); LIGHT; LINETO(0,0); break; case 2 : pt += QPoint(segLen - 1 , 1); p.moveTo(pt); DARK; LINETO(0,segLen - 2); LINETO(-width,segLen - width/2 - 2); LIGHT; LINETO(-width,width); LINETO(0,0); break; case 3 : pt += QPoint(0 , segLen); p.moveTo(pt); LIGHT; LINETO(width,-width/2); LINETO(segLen - width - 1,-width/2); LINETO(segLen - 1,0); DARK; if (width & 1) { // adjust for integer division error LINETO(segLen - width - 3,width/2 + 1); LINETO(width + 2,width/2 + 1); } else { LINETO(segLen - width - 1,width/2); LINETO(width,width/2); } LINETO(0,0); break; case 4 : pt += QPoint(0 , segLen + 1); p.moveTo(pt); LIGHT; LINETO(width,width/2); DARK; LINETO(width,segLen - width - 2); LINETO(0,segLen - 2); LIGHT; LINETO(0,0); break; case 5 : pt += QPoint(segLen - 1 , segLen + 1); p.moveTo(pt); DARK; LINETO(0,segLen - 2); LINETO(-width,segLen - width - 2); LIGHT; LINETO(-width,width/2); LINETO(0,0); break; case 6 : pt += QPoint(0 , segLen*2); p.moveTo(pt); LIGHT; LINETO(width,-width); LINETO(segLen - width - 1,-width); LINETO(segLen - 1,0); DARK; LINETO(0,0); break; case 7 : if ( smallPoint ) // if smallpoint place'.' between other digits pt += QPoint(segLen + width/2 , segLen*2); else pt += QPoint(segLen/2 , segLen*2); p.moveTo(pt); DARK; LINETO(width,0); LINETO(width,-width); LIGHT; LINETO(0,-width); LINETO(0,0); break; case 8 : pt += QPoint(segLen/2 - width/2 + 1 , segLen/2 + width); p.moveTo(pt); DARK; LINETO(width,0); LINETO(width,-width); LIGHT; LINETO(0,-width); LINETO(0,0); break; case 9 : pt += QPoint(segLen/2 - width/2 + 1 , 3*segLen/2 + width); p.moveTo(pt); DARK; LINETO(width,0); LINETO(width,-width); LIGHT; LINETO(0,-width); LINETO(0,0); break; #if defined(CHECK_RANGE) default : qWarning( "QLCDNumber::drawSegment: (%s) Internal error." " Illegal segment id: %d\n", name( "unnamed" ), segmentNo ); #endif } #undef LINETO #undef LIGHT #undef DARK }
/* Plotting procedure. * X-axis is segmented according to 'delta' distance, that is distance between * consecutive x's (x_i to x_{i + 1} distance). Infinity and NaN checks are * performed and corresponding action is taken to prevent mess. * Infinity case is handled by computing intersect with plot-box. NaNs * are not plotted at all. * Adaptive smoothing is performed at the end of plot loop. */ static void plot(FILE * out, parsed_expr p) { double delta = (x_high - x_low) / SMOOTHNESS; double x_1 = x_low; double x_2 = x_low + delta; double y_1 = evaluate(p, x_1); double y_2 = evaluate(p, x_2); double old_x; double old_y; /* if y-value out of box, compute intersection of line with box */ double x_intersect; int last_out = 1, last_nan = 0; int SMOOTHNESS_LVL = MAX_SMOOTHNESS_LVL; /* Transformation of real number coordinates to plot box coordinates. * Plot is in lanscape mode, real x-coordinates are mappend to plot * y-coordinate and vice versa. * Plot y-coordinates are flipped vertically */ #define COORD_X(x) (((x) - x_low) * scale_x + LLY + BLANK) #define COORD_Y(y) (URX - BLANK - (((y) - y_low) * scale_y)) /* Redefine postscript lineto and moveto commands, such that there is * no need to take care of coordinate transformations. * x and y coordinates are swapped here. */ #define LINETO(x, y) fprintf(out, "%.3f %.3f lineto\n", \ COORD_Y(y), COORD_X(x)) #define MOVETO(x, y) fprintf(out, "%.3f %.3f moveto\n", \ COORD_Y(y), COORD_X(x)) /* find intersection with y-boundary */ #define INTERSECT(boundary) (x_1 + ((boundary) - y_1) * \ (x_2 - x_1) / (y_2 - y_1)); if (y_1 < y_low) y_1 = y_low; else if (y_1 > y_high) y_1 = y_high; else last_out = 0; /* New path exclusively for function plot */ fprintf(out, "newpath\n"); if (!IS_NAN(y_1)) MOVETO(x_1, y_1); else last_nan = 1; old_x = x_1; old_y = y_1; /* plotting loop */ while (x_2 <= x_high) { if (IS_NAN(y_2)) last_nan = 1; /* next point is in bounding box, thus can be plotted */ else if (y_low <= y_2 && y_2 <= y_high) { /* handle case where last point was NaN */ if (last_nan) { MOVETO(x_2, y_2); last_nan = 0; /* handle case where last point was out of box, * find intersections with box. Next line will start * from this point */ } else if (last_out) { /* point is too high or too low? */ if (y_2 > y_1) { x_intersect = INTERSECT(y_low); if (IS_NAN(x_intersect)) x_intersect = x_1; MOVETO(x_intersect, y_low); } else { x_intersect = INTERSECT(y_high); if (IS_NAN(x_intersect)) x_intersect = x_1; MOVETO(x_intersect, y_high); } } /* Draw a valid line. This plots most of the lines. */ LINETO(x_2, y_2); last_out = 0; /* case where next point is out of the box */ } else { /* if last point was in the box, stroke a line to the intersection * with y-boundary */ if (!last_out && !last_nan) { if (y_2 > y_1) { x_intersect = INTERSECT(y_high); if (IS_NAN(x_intersect)) x_intersect = x_1; LINETO(x_intersect, y_high); } else { x_intersect = INTERSECT(y_low); if (IS_NAN(x_intersect)) x_intersect = x_1; LINETO(x_intersect, y_low); } } last_out = 1; } /** smoothing procedure **/ /* SLOPE_JUMP is numerically evaluated second derivative, that is * difference of first derivatives. Expression is simplified algebraically */ #define SLOPE_JUMP (y_2 - y_1 - ((y_1 - old_y)*(x_2 - x_1))/(x_1 - old_x)) #define TOO_SHARP() (fabs(SLOPE_JUMP) > THRESHOLD) #define TOO_SMOOTH() (fabs(SLOPE_JUMP) < THRESHOLD / 4) old_x = x_1; old_y = y_1; x_1 = x_2; y_1 = y_2; x_2 = x_1 + delta; y_2 = evaluate(p, x_2); /* If the plot is too sharp or too smooth, * find appropriate smoothness lvl * by increasing/decreasing smoothness until right one is found. */ if (TOO_SHARP()) { while (SMOOTHNESS_LVL < MAX_SMOOTHNESS_LVL && TOO_SHARP()) { delta /= 2; x_2 = x_1 + delta; y_2 = evaluate(p, x_2); SMOOTHNESS_LVL++; } } else { while (SMOOTHNESS_LVL > 0 && TOO_SMOOTH()) { delta *= 2; x_2 = x_1 + delta; y_2 = evaluate(p, x_2); SMOOTHNESS_LVL--; } } /* make sure the last point is on the right boundary */ if (x_1 < x_high && x_1 + delta > x_high) { x_2 = x_high; y_2 = evaluate(p, x_2); } } /* stroke the path */ fprintf(out, "%s setrgbcolor\n", PLOT_COLOR); fprintf(out, "0.5 setlinewidth\n"); fprintf(out, "stroke\n\n\n"); }