static VALUE pen_x(VALUE self) { SWFShape shape; Data_Get_Struct(self, struct SWFShape_s, shape); return rb_float_new(SWFShape_getPenX(shape)); }
void swfDrawStyledLineTo(SWFShape shape, double x, double y, const pGEcontext gc) { int lty = gc->lty; int lwd = gc->lwd; /* Original positions */ double x0 = SWFShape_getPenX(shape); double y0 = SWFShape_getPenY(shape); double x_next, y_next; /* Distance between (x0, y0) and (x, y) */ double dist = sqrt(pow(x - x0, 2) + pow(y - y0, 2)); unsigned char dashlist[8]; int ndash = 0; /* Length of one cycle of dashlines */ int cycle_len = 0; /* How many full cycles will we have in drawing the line? */ int ncycle = 0; /* How many pen-up and pen-down segments? */ int nseg = 0; /* Distance the pen has moved */ /* s is a temp variable */ double dist_moved = 0.0, s = 0.0; int i; /* Is the pen for next segment up or down? */ Rboolean is_down = TRUE; /* If it is a solid line */ /* NOTE: Here lty == 0 corresponds to lty = 1 in R */ if(lty == LTY_SOLID) /* LTY_SOLID == 0 */ { SWFShape_drawLineTo(shape, x, y); return; } if(lty == LTY_BLANK) /* LTY_BLANK == -1 */ { SWFShape_movePenTo(shape, x, y); return; } /* Decode texture description */ for(i = 0; i < 8 && lty & 15; i++) { dashlist[ndash++] = lty & 15; lty = lty >> 4; cycle_len += dashlist[i]; } /* Cycle length proportional to lwd */ cycle_len *= lwd; ncycle = (int) floor(dist / cycle_len); nseg = ncycle * ndash; /* Length of the last incomplete cycle */ s = dist - cycle_len * ncycle; for(i = 0; i < ndash; i++) { if(dist_moved + dashlist[i] * lwd >= s) break; dist_moved += dashlist[i] * lwd; nseg++; } dist_moved = 0.0; for(i = 0; i < nseg; i++) { dist_moved += dashlist[i % ndash] * lwd; x_next = x0 + dist_moved / dist * (x - x0); y_next = y0 + dist_moved / dist * (y - y0); if(is_down) { SWFShape_drawLineTo(shape, x_next, y_next); } else { SWFShape_movePenTo(shape, x_next, y_next); } is_down = !is_down; } if(is_down) { SWFShape_drawLineTo(shape, x, y); } else { SWFShape_movePenTo(shape, x, y); } }
static void SWF_drawStyledLineTo(SWFShape line, double x_end, double y_end, int lty) { byte dashlist[8]; int i, nlty; /* From ?par * Line types can either be specified by giving an index into a small * built-in table of line types (1 = solid, 2 = dashed, etc, see lty * above) or directly as the lengths of on/off stretches of line. This * is done with a string of an even number (up to eight) of characters, * namely non-zero (hexadecimal) digits which give the lengths in * consecutive positions in the string. For example, the string "33" * specifies three units on followed by three off and "3313" specifies * three units on followed by three off followed by one on and finally * three off. The ‘units’ here are (on most devices) proportional to lwd, * and with lwd = 1 are in pixels or points or 1/96 inch. * The five standard dash-dot line types (lty = 2:6) correspond to * c("44", "13", "1343", "73", "2262"). * * (0=blank, 1=solid (default), 2=dashed, * 3=dotted, 4=dotdash, 5=longdash, 6=twodash) */ /*Retrieve the line type pattern*/ for(i = 0; i < 8 && lty & 15 ; i++) { dashlist[i] = lty & 15; lty = lty >> 4; //if( DEBUG == TRUE ) // Rprintf("\tDash List: %d\n", dashlist[i]); } nlty = i; i = 0; if(nlty == 0){ SWFShape_drawLineTo(line, x_end, y_end); return; } /* Do the drawing of dashed line manually * this is very sucky, it sould be done for me * In my opinion, this is a huge limitation of libming. * * 1. Calculate end point of dash segment * 2a. If past end point of line, draw to end of line, end * 2b. Otherwise draw to end point of dash segment * 3. Repeat */ //Current position double x_cur = SWFShape_getPenX(line); //double y1 = GEcurrentDevice()->dev->top - SWFShape_getPenY(line); double y_cur = SWFShape_getPenY(line); //end of dash segment double x_next, y_next, ang = atan((y_end-y_cur)/(x_end-x_cur)); //distance to end of dash segment and end of line double d_dash, d_line = 10000, old_d_line; Rboolean at_line_end = FALSE; //Rprintf("x_cur=%f x_end=%f\n",x_cur,x_end); //Rprintf("y_cur=%f y_end=%f\n",y_cur,y_end); while( at_line_end == FALSE ){ while(i < nlty){ //Rprintf("INNER LOOP\n"); /* * This part is so whacked out, basically the different origins of * R and ming make drawing dashed lines REALLY confusing. This * seems to work though :). A lot of things in R graphics seem to * go this way. */ if(x_end < x_cur && y_end <= y_cur){ x_next = x_cur - (double)dashlist[i] * cos(ang); y_next = y_cur - (double)dashlist[i] * sin(ang); } if(x_end > x_cur && y_end <= y_cur){ x_next = x_cur + (double)dashlist[i] * cos(ang); y_next = y_cur + (double)dashlist[i] * sin(ang); } if(x_end < x_cur && y_end > y_cur){ x_next = x_cur - (double)dashlist[i] * cos(ang); y_next = y_cur - (double)dashlist[i] * sin(ang); } if(x_end > x_cur && y_end > y_cur){ x_next = x_cur + (double)dashlist[i] * cos(ang); y_next = y_cur + (double)dashlist[i] * sin(ang); } old_d_line = d_line; d_line = sqrt(pow(abs(x_end-x_cur),2)+pow(abs(y_end-y_cur),2)); d_dash = sqrt(pow(abs(x_next-x_cur),2)+pow(abs(y_next-y_cur),2)); //Rprintf("i=%d nlty=%d\n",i,nlty); //Rprintf("x_cur=%f x_end=%f x_next=%f\n",x_cur,x_end,x_next); //Rprintf("y_cur=%f y_end=%f y_next=%f\n",y_cur,y_end,y_next); //Rprintf("ang=%f\n",ang); //Rprintf("d_dash=%f\n",d_dash); //Rprintf("d_line=%f\n",d_line); //Rprintf("old_d_line=%f\n",old_d_line); if( (d_dash >= d_line) || old_d_line < d_line ){ //Rprintf("%s\n\n\n","Time to break"); if( (i % 2) == 0 ){ //draw to the end of the line segment SWFShape_drawLineTo(line, x_end, y_end); }else{ SWFShape_movePenTo(line, x_end, y_end); } at_line_end = TRUE; //out of main loop break; //out of inner loop } if( (i % 2) == 0 ){ //draw to the end point of the dash segment SWFShape_drawLineTo(line, x_next, y_next); //if( DEBUG == TRUE ) //Rprintf("\tDrawing dash line to: (%f,%f)\n", x_next, y_next); }else{ SWFShape_movePenTo(line, x_next, y_next); //if( DEBUG == TRUE ) //Rprintf("\tMoving dash pen to: (%f,%f)\n", x_next, y_next); } // Update coordinates x_cur = x_next; y_cur = y_next; i++; } i = 0; } }
/* ming.cには実装されていなかったけれども一応 */ EXPORT BOOL WINAPI s_getPenX(float *p1, int p2, int p3, int p4) { lstrcpy(funcname, "s_getPenX"); *p1 = SWFShape_getPenX(mhsp_shape); return 0; }