/* Calculate the bounding rectangle for a string. * x and y assumed to be in INCHES. */ void textRect(double x, double y, SEXP text, int i, R_GE_gcontext *gc, double xadj, double yadj, double rot, GEDevDesc *dd, LRect *r) { /* NOTE that we must work in inches for the angles to be correct */ LLocation bl, br, tr, tl; LLocation tbl, tbr, ttr, ttl; LTransform thisLocation, thisRotation, thisJustification; LTransform tempTransform, transform; double w, h; if (isExpression(text)) { SEXP expr = VECTOR_ELT(text, i % LENGTH(text)); w = fromDeviceWidth(GEExpressionWidth(expr, gc, dd), GE_INCHES, dd); h = fromDeviceHeight(GEExpressionHeight(expr, gc, dd), GE_INCHES, dd); } else { char* string = CHAR(STRING_ELT(text, i % LENGTH(text))); w = fromDeviceWidth(GEStrWidth(string, gc, dd), GE_INCHES, dd); h = fromDeviceHeight(GEStrHeight(string, gc, dd), GE_INCHES, dd); } location(0, 0, bl); location(w, 0, br); location(w, h, tr); location(0, h, tl); translation(-xadj*w, -yadj*h, thisJustification); translation(x, y, thisLocation); if (rot != 0) rotation(rot, thisRotation); else identity(thisRotation); /* Position relative to origin of rotation THEN rotate. */ multiply(thisJustification, thisRotation, tempTransform); /* Translate to (x, y) */ multiply(tempTransform, thisLocation, transform); trans(bl, transform, tbl); trans(br, transform, tbr); trans(tr, transform, ttr); trans(tl, transform, ttl); rect(locationX(tbl), locationX(tbr), locationX(ttr), locationX(ttl), locationY(tbl), locationY(tbr), locationY(ttr), locationY(ttl), r); /* For debugging, the following prints out an R statement to draw the * bounding box */ /* Rprintf("\ngrid.lines(c(%f, %f, %f, %f, %f), c(%f, %f, %f, %f, %f), default.units=\"inches\")\n", locationX(tbl), locationX(tbr), locationX(ttr), locationX(ttl), locationX(tbl), locationY(tbl), locationY(tbr), locationY(ttr), locationY(ttl), locationY(tbl) ); */ }
static double step_computing(int k, double *px, double *py, double s1, double s2, double precision, pGEDevDesc dd) { double A_blend[4]; double xstart, ystart, xend, yend, xmid, ymid, xlength, ylength; double start_to_end_dist, devWidth, devHeight, devDiag, number_of_steps; double step, angle_cos, scal_prod, xv1, xv2, yv1, yv2, sides_length_prod; /* This function computes the step used to draw the segment (p1, p2) (xv1, yv1) : coordinates of the vector from middle to origin (xv2, yv2) : coordinates of the vector from middle to extremity */ if ((s1 == 0) && (s2 == 0)) return(1.0); /* only one step in case of linear segment */ /* compute coordinates of the origin */ if (s1>0) { if (s2<0) { positive_s1_influence(k, 0.0, s1, &A_blend[0], &A_blend[2]); negative_s2_influence(0.0, s2, &A_blend[1], &A_blend[3]); } else { positive_s1_influence(k, 0.0, s1, &A_blend[0], &A_blend[2]); positive_s2_influence(k, 0.0, s2, &A_blend[1], &A_blend[3]); } point_computing(A_blend, px, py, &xstart, &ystart); } else { xstart = px[1]; ystart = py[1]; } /* compute coordinates of the extremity */ if (s2>0) { if (s1<0) { negative_s1_influence(1.0, s1, &A_blend[0], &A_blend[2]); positive_s2_influence(k, 1.0, s2, &A_blend[1], &A_blend[3]); } else { positive_s1_influence(k, 1.0, s1, &A_blend[0], &A_blend[2]); positive_s2_influence(k, 1.0, s2, &A_blend[1], &A_blend[3]); } point_computing(A_blend, px, py, &xend, ¥d); } else { xend = px[2]; yend = py[2]; } /* compute coordinates of the middle */ if (s2>0) { if (s1<0) { negative_s1_influence(0.5, s1, &A_blend[0], &A_blend[2]); positive_s2_influence(k, 0.5, s2, &A_blend[1], &A_blend[3]); } else { positive_s1_influence(k, 0.5, s1, &A_blend[0], &A_blend[2]); positive_s2_influence(k, 0.5, s2, &A_blend[1], &A_blend[3]); } } else if (s1<0) { negative_s1_influence(0.5, s1, &A_blend[0], &A_blend[2]); negative_s2_influence(0.5, s2, &A_blend[1], &A_blend[3]); } else { positive_s1_influence(k, 0.5, s1, &A_blend[0], &A_blend[2]); negative_s2_influence(0.5, s2, &A_blend[1], &A_blend[3]); } point_computing(A_blend, px, py, &xmid, &ymid); xv1 = xstart - xmid; yv1 = ystart - ymid; xv2 = xend - xmid; yv2 = yend - ymid; scal_prod = xv1*xv2 + yv1*yv2; sides_length_prod = sqrt((xv1*xv1 + yv1*yv1)*(xv2*xv2 + yv2*yv2)); /* compute cosinus of origin-middle-extremity angle, which approximates the curve of the spline segment */ if (sides_length_prod == 0.0) angle_cos = 0.0; else angle_cos = scal_prod/sides_length_prod; xlength = xend - xstart; ylength = yend - ystart; start_to_end_dist = sqrt(xlength*xlength + ylength*ylength); /* Paul 2009-01-25 * It is possible for origin and extremity to be very remote * indeed (if the control points are located WAY off the device). * In order to avoid having ridiculously many steps, limit * the start_to_end_dist to being the length of the diagonal of the * device. */ devWidth = fromDeviceWidth(toDeviceWidth(1, GE_NDC, dd), GE_INCHES, dd)*1200; devHeight = fromDeviceHeight(toDeviceHeight(1, GE_NDC, dd), GE_INCHES, dd)*1200; devDiag = sqrt(devWidth* devWidth + devHeight*devHeight); if (start_to_end_dist > devDiag) start_to_end_dist = devDiag; /* more steps if segment's origin and extremity are remote */ number_of_steps = sqrt(start_to_end_dist)/2; /* more steps if the curve is high */ number_of_steps += (int)((1 + angle_cos)*10); if (number_of_steps == 0) step = 1; else step = precision/number_of_steps; if ((step > MAX_SPLINE_STEP) || (step == 0)) step = MAX_SPLINE_STEP; return (step); }