Ejemplo n.º 1
0
void drvIDRAW::print_coords()
{
	unsigned int pathelts = numberOfElementsInPath();
	bool closed;				// True if shape is closed
	bool curved;				// True if shape is curved
	const Point *firstpoint;	// First and last points in shape
	const Point *lastpoint;
	unsigned int totalpoints;	// Total number of points in shape
	const Point dummypoint(-123.456f, -789.101112f);	// Used to help eliminate duplicates

	unsigned int i, j;

	// First, try to figure out what type of shape we have
	closed = false;
	curved = false;
	for (i = 0; i < pathelts; i++) {
		if (pathElement(i).getType() == curveto)
			curved = true;
		else if (pathElement(i).getType() == closepath)
			closed = true;
	}
	const Point **pointlist = new const Point *[pathelts * 3];	// List of points
	 	// Allocate a conservative amount
	assert(pointlist != NIL);
	firstpoint = NIL;
	lastpoint = &dummypoint;
	totalpoints = 0;
	for (i = 0; i < pathelts; i++) {
		const basedrawingelement & pelt = pathElement(i);

		if ((pelt.getType() == moveto || pelt.getType() == lineto) &&
			!(pelt.getPoint(0) == *lastpoint))
			lastpoint = pointlist[totalpoints++] = &pelt.getPoint(0);
		else if (pelt.getType() == curveto)
			for (j = 0; j < 3; j++)
				lastpoint = pointlist[totalpoints++] = &pelt.getPoint(j);
	}
	if (totalpoints) {
		firstpoint = pointlist[0];
		if (firstpoint->x_ == lastpoint->x_ && firstpoint->y_ == lastpoint->y_)
			closed = true;

		// Find points on the curve for curved lines
		if (curved) {
			const unsigned int pt_per_cp = 5;	// PostScript points per control point
			const unsigned int min_innerpoints = 2;	// Minimum # of points to add
			unsigned int innerpoints;	// Number of points to add
			unsigned int newtotalpoints = 0;	// Number of points in curve

			// ASSUMPTION: Curve is moveto+curveto+curveto+curveto+...
			// List of points on curve
			const Point **newpointlist = new const Point *[pathelts * 3000 / pt_per_cp];	// Allocate a conservative amount
			assert(newpointlist != NIL);
			for (i = 0; i < totalpoints - 3; i += 3) {
				const float x0 = pointlist[i]->x_;
				const float y0 = pointlist[i]->y_;
				const float x1 = pointlist[i + 1]->x_;
				const float y1 = pointlist[i + 1]->y_;
				const float x2 = pointlist[i + 2]->x_;
				const float y2 = pointlist[i + 2]->y_;
				const float x3 = pointlist[i + 3]->x_;
				const float y3 = pointlist[i + 3]->y_;
				const float cx = (x1 - x0) * 3;
				const float cy = (y1 - y0) * 3;
				const float bx = (x2 - x1) * 3 - cx;
				const float by = (y2 - y1) * 3 - cy;
				const float ax = x3 - x0 - cx - bx;
				const float ay = y3 - y0 - cy - by;
				

				// Longer lines get more control points
				innerpoints =(unsigned int) (
							pythagoras((y1 - y0),(x1 - x0) ) + 
							pythagoras((y2 - y1),(x2 - x1) ) + 
							pythagoras((y3 - y2),(x3 - x2) ) ) / pt_per_cp;
				if (innerpoints < min_innerpoints)
					innerpoints = min_innerpoints;

				// Add points to the list
				ADDPOINT(x0, y0);
				for (j = 1; j <= innerpoints; j++) {
					const float t = (float) j / (float) innerpoints;
					const float newx = (((ax * t) + bx) * t + cx) * t + x0;
					const float newy = (((ay * t) + by) * t + cy) * t + y0;
					ADDPOINT(newx, newy);
				}
				ADDPOINT(x3, y3);
			}

			delete[]pointlist;
			pointlist = newpointlist;
			totalpoints = newtotalpoints;
		}
		// Straight lines, not closed
		if (!closed && !curved) {
			if (totalpoints == 2) {	// Special case for single line
				print_header("Line");
				outf << "%I" << endl;
				outf << iscale(firstpoint->x_) << ' ' << iscale(firstpoint->y_) << ' ';
				outf << iscale(lastpoint->x_) << ' ' << iscale(lastpoint->y_) << ' ';
				outf << "Line" << endl;
				outf << "%I 1" << endl;
				outf << "End" << endl << endl;
			} else {			// Otherwise, output a multiline
				print_header("MLine");	// (Should have a special case for Rect)
				outf << "%I " << totalpoints << endl;
				for (i = 0; i < totalpoints; i++) {
					outf << iscale(pointlist[i]->x_) << ' ';
					outf << iscale(pointlist[i]->y_) << endl;
				}
				outf << totalpoints << " MLine" << endl;
				outf << "%I 1" << endl;
				outf << "End" << endl << endl;
			}
		}
		// Straight lines, closed */
		if (closed && !curved) {
			unsigned int numpoints;

			numpoints = totalpoints == 1 ? 1 : totalpoints - 1;
			print_header("Poly");	// Output a polygon
			outf << "%I " << numpoints << endl;
			for (i = 0; i < numpoints; i++) {
				outf << iscale(pointlist[i]->x_) << ' ';
				outf << iscale(pointlist[i]->y_) << endl;
			}
			outf << numpoints << " Poly" << endl;
			outf << "End" << endl << endl;
		}
		// Curved lines, not closed
		if (!closed && curved) {
			print_header("BSpl");	// Output a B-spline
			outf << "%I " << totalpoints << endl;
			for (i = 0; i < totalpoints; i++) {
				outf << iscale(pointlist[i]->x_) << ' ';
				outf << iscale(pointlist[i]->y_) << endl;
			}
			outf << totalpoints << " BSpl" << endl;
			outf << "%I 1" << endl;
			outf << "End" << endl << endl;
		}
		// Curved lines, closed
		if (closed && curved) {
			unsigned int numpoints;

			numpoints = totalpoints == 1 ? 1 : totalpoints - 1;
			print_header("CBSpl");	// Output a closed B-spline
			outf << "%I " << numpoints << endl;
			for (i = 0; i < numpoints; i++) {
				outf << iscale(pointlist[i]->x_) << ' ';
				outf << iscale(pointlist[i]->y_) << endl;
			}
			outf << numpoints << " CBSpl" << endl;
			outf << "End" << endl << endl;
		}
		if (curved) {
			//
			// in this case we have created the pointlist newly with Points on the heap
			//
			if (pointlist)
				for (unsigned int pindex = 0; pindex < totalpoints; pindex++) {
					//cout << "pindex / totalpoints " << pindex  << " " << totalpoints << " " << pointlist[pindex]->x_ << " " << pointlist[pindex]->y_ << " " << pointlist[pindex]<< endl;
#if defined (_MSC_VER) && (_MSC_VER < 1100)
					// MSVC < 6 needs cast here
					delete (Point *)	(pointlist[pindex]);	
#else
					delete				(pointlist[pindex]);	
#endif
				}

		}
	}
	delete[]pointlist;
}
Ejemplo n.º 2
0
PyObject* compute_path_bbox( PyObject* self, PyObject* args )
{
    PyObject* pobj;
    PyObject* plist = NULL;
    PyObject* cacheobj = NULL;
    int i;
    int size;
    PyObject* item;

    int cset = 0;    // is there a current point?
    double sx, sy;   // start of subpath
    double cx, cy;   // current point
    
    double c[8];
    int j, k;
    double *xy;

    int empty = 1;
    double minx, maxx, miny, maxy;

    if ( !PyArg_ParseTuple( args, "O", &pobj ) )
	return NULL;

    cacheobj = PyObject_GetAttrString( pobj, "_bbox" );
    if ( cacheobj && cacheobj != Py_None )
    {
	Py_INCREF( cacheobj );
    }
    else
    {
	plist = PyObject_GetAttrString( pobj, "raw" );
	if ( plist == NULL || !PyList_Check( plist ) )
	{
	    Py_XDECREF( plist );
	    PyErr_SetString( DrawError, "bad path object" );
	    return NULL;
	}

	size = PyList_Size( plist );
	
	for ( i = 0; i < size; ++i )
	{
	    item = PyList_GetItem( plist, i );

#define ADDPOINT(x,y)  {if(empty){empty=0;minx=maxx=(x);miny=maxy=(y);}else{ if((x)<minx)minx=(x);else if((x)>maxx)maxx=(x); if((y)<miny)miny=(y);else if((y)>maxy)maxy=(y);}}

	    
	    switch( PyInt_AsLong( PyList_GetItem( item, 0 ) ) )
	    {
	      case S_CLOSE:
		ADDPOINT( sx, sy );
		cset = 0;
		break;

	      case S_MOVE:
		sx = cx = PyFloat_AsDouble( PyList_GetItem( item, 1 ) );
		sy = cy = PyFloat_AsDouble( PyList_GetItem( item, 2 ) );
		cset = 1;
		break;

	      case S_LINE:
		ADDPOINT( cx, cy );
		cx = PyFloat_AsDouble( PyList_GetItem( item, 1 ) );
		cy = PyFloat_AsDouble( PyList_GetItem( item, 2 ) );
		ADDPOINT( cx, cy );
		break;

	      case S_CURVE:
		c[0] = cx;
		c[1] = cy;
		for ( j = 0; j < 6; ++j )
		    c[j+2] = PyFloat_AsDouble( PyList_GetItem( item, j+1 ) );
		cx = c[6];
		cy = c[7];
	    
		xy = bezier_points( &k, 4, c, 0.001, 0 );
		for ( j = 0; j < k; ++j )
		    ADDPOINT( xy[j*2], xy[j*2+1] );
		break;

	      case S_QCURVE:
		c[0] = cx;
		c[1] = cy;
		for ( j = 0; j < 4; ++j )
		    c[j+2] = PyFloat_AsDouble( PyList_GetItem( item, j+1 ) );
		cx = c[4];
		cy = c[5];

		xy = bezier_points( &k, 3, c, 0.001, 0 );
		for ( j = 0; j < k; ++j )
		    ADDPOINT( xy[j*2], xy[j*2+1] );
		break;
	    }
	}

	cacheobj = Py_BuildValue( "dddd", minx, miny, maxx, maxy );
	PyObject_SetAttrString( pobj, "_bbox", cacheobj );
    }

    Py_XDECREF( plist );

    Py_INCREF( Py_None );
    return cacheobj;
}