X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=pdf2swf%2Fspline.cc;fp=pdf2swf%2Fspline.cc;h=0000000000000000000000000000000000000000;hb=6dea5761ff73bf30cf08f8cfed637f4ad12a93a5;hp=096122717469a500919fad58aa4ea0389ce4a6fe;hpb=78d2e3234f739a655ee371b3dcde94b4f59ed087;p=swftools.git diff --git a/pdf2swf/spline.cc b/pdf2swf/spline.cc deleted file mode 100644 index 0961227..0000000 --- a/pdf2swf/spline.cc +++ /dev/null @@ -1,411 +0,0 @@ -/* spline.cc - Routine to convert cubic splines into quadratic ones. - - Part of the swftools package. - - Copyright (c) 2001,2002,2003 Matthias Kramm - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -#include -#include -#include -#include "spline.h" - -static int solve(double a,double b,double c, double*dd) -{ - double det=b*b-4*a*c; - int pos = 0; - if(det<0) return 0; // we don't do imaginary. not today. - if(det==0) { // unlikely, but we have to deal with it. - dd[0]=-b/2*a; - return (dd[0]>0 && dd[0]<1); - } - - dd[pos]=(-b+sqrt(det))/(2*a); - if(dd[pos]>0 && dd[pos]<1) - pos++; - dd[pos]=(-b-sqrt(det))/(2*a); - if(dd[pos]>0 && dd[pos]<1) - pos++; - return pos; -} - -struct plotxy splinepos(struct plotxy p0, struct plotxy p1, struct plotxy p2, struct plotxy p3, double d) { - struct plotxy p; - p.x = (p0.x * d*d*d + p1.x * 3*(1-d)*d*d + p2.x * 3*(1-d)*(1-d)*d + p3.x * (1-d)*(1-d)*(1-d)); - p.y = (p0.y * d*d*d + p1.y * 3*(1-d)*d*d + p2.y * 3*(1-d)*(1-d)*d + p3.y * (1-d)*(1-d)*(1-d)); - return p; -} - -inline double plotxy_dist(struct plotxy a, struct plotxy b) -{ - double dx = a.x - b.x; - double dy = a.y - b.y; - return sqrt(dx*dx+dy*dy); -} - - -int wp(double p0,double p1,double p2,double p3,double*dd) -{ - double div= (6*p0-18*p1+18*p2-6*p3); - if(!div) return 0; - dd[0] = -(6*p1-12*p2+6*p3)/div; - return (dd[0]>0 && dd[0]<1); -} - -int approximate(struct plotxy p0, struct plotxy p1, struct plotxy p2, struct plotxy p3, struct qspline*q) -{ - double roots[12]; - int pos = 0; - int s,t; - struct plotxy myxy[12]; - struct plotxy last; - // the parameters for the solve function are the 1st deviation of a cubic spline - roots[pos] = 0;pos++; - pos += solve(3*p0.x-9*p1.x+9*p2.x-3*p3.x, 6*p1.x-12*p2.x+6*p3.x,3*p2.x-3*p3.x, &roots[pos]); - pos += solve(3*p0.y-9*p1.y+9*p2.y-3*p3.y, 6*p1.y-12*p2.y+6*p3.y,3*p2.y-3*p3.y, &roots[pos]); - pos += wp(p0.x,p1.x,p2.x,p3.x,&roots[pos]); - pos += wp(p0.x,p1.x,p2.x,p3.x,&roots[pos]); - roots[pos] = 1;pos++; - - // bubblesort - fast enough for 4-6 parameters - for(s=0;sroots[t]) - { - double tmp=roots[s]; - roots[s]=roots[t]; - roots[t]=tmp; - } - for(t=0;t0.01 || t==pos-1) - { - s++; - last=myxy[t]; - } - } - pos = s; - - // try 1:curve through 3 points, using the middle of the cubic spline. - for(t=0;tend.x + s->start.x)/2; - mid.y = (s->end.y + s->start.y)/2; - dir.x = s->control.x - mid.x; - dir.y = s->control.y - mid.y; - s->control.x = mid.x + 2*dir.x; - s->control.y = mid.y + 2*dir.y; -} - -int approximate2(struct cspline*s, struct qspline*q, double quality, double start, double end); - -void check(struct cspline*s, struct qspline*q, int num) -{ - int t; - plotxy p = s->start; - for(t=0;t 0.005) { - printf("--\n"); - exit(1); - } - p = q[t].end; - } - if(plotxy_dist(p, s->end) > 0.005) { - printf("--\n"); - exit(1); - } -} - -int cspline_approximate(struct cspline*s, struct qspline*q, double quality, approximate_method method) -{ - if(method==0) { - return approximate(s->start, s->control1, s->control2, s->end, q); - } else { - return approximate2(s, q, quality, 0.0, 1.0); - } -} -inline plotxy cspline_getpoint(cspline*s, double t) -{ - plotxy p; - p.x= s->end.x*t*t*t + 3*s->control2.x*t*t*(1-t) - + 3*s->control1.x*t*(1-t)*(1-t) + s->start.x*(1-t)*(1-t)*(1-t); - p.y= s->end.y*t*t*t + 3*s->control2.y*t*t*(1-t) - + 3*s->control1.y*t*(1-t)*(1-t) + s->start.y*(1-t)*(1-t)*(1-t); - return p; -} -plotxy cspline_getderivative(cspline*s, double t) -{ - plotxy d; - d.x = s->end.x*(3*t*t) + 3*s->control2.x*(2*t-3*t*t) + - 3*s->control1.x*(1-4*t+3*t*t) + s->start.x*(-3+6*t-3*t*t); - d.y = s->end.y*(3*t*t) + 3*s->control2.y*(2*t-3*t*t) + - 3*s->control1.y*(1-4*t+3*t*t) + s->start.y*(-3+6*t-3*t*t); - return d; -} -plotxy cspline_getderivative2(cspline*s, double t) -{ - plotxy d; - d.x = s->end.x*(6*t) + 3*s->control2.x*(2-6*t) + - 3*s->control1.x*(-4+6*t) + s->start.x*(6-6*t); - d.y = s->end.y*(6*t) + 3*s->control2.y*(2-6*t) + - 3*s->control1.y*(-4+6*t) + s->start.y*(6-6*t); - return d; -} -plotxy cspline_getderivative3(cspline*s, double t) -{ - plotxy d; - d.x = 6*s->end.x - 18*s->control2.x + 18*s->control1.x - 6*s->start.x; - d.y = 6*s->end.y - 18*s->control2.y + 18*s->control1.y - 6*s->start.y; - return d; -} -void cspline_getequalspacedpoints(cspline*s, float**p, int*num, double dist) -{ - plotxy d,next; - double t = 0; - int end = 0; - int pos = 0; - float*positions = (float*)malloc(1048576); - do - { - if(t>=1.0) { - t = 1.0; - end = 1; - } - - plotxy d = cspline_getderivative(s, t); - plotxy d2 = cspline_getderivative2(s, t); - - double dl = sqrt(d.x*d.x+d.y*d.y); - double dl2 = sqrt(d2.x*d2.x+d2.y*d2.y); - - double rdl = dist/dl; - - if(rdl>1.0-t) - rdl = 1.0-t; - - plotxy p = cspline_getpoint(s, t); - while(plotxy_dist(cspline_getpoint(s, t+rdl), p) > dist) { - /* we were ask to divide the spline into dist long fragments, - but for the value we estimated even the geometric distance - is bigger than 'dist'. Approximate a better value. - */ - rdl = rdl*0.9; - } - - positions[pos] = t; - t+=rdl; - pos++; - } - while(!end); - *num = pos; - *p = positions; -} - -plotxy qspline_getpoint(qspline*s, double t) -{ - plotxy p; - p.x= s->end.x*t*t + 2*s->control.x*t*(1-t) + s->start.x*(1-t)*(1-t); - p.y= s->end.y*t*t + 2*s->control.y*t*(1-t) + s->start.y*(1-t)*(1-t); - return p; -} -plotxy qspline_getderivative(qspline*s, double t) -{ - plotxy p; - p.x= s->end.x*2*t + 2*s->control.x*(1-2*t) + s->start.x*(-2+2*t); - p.y= s->end.y*2*t + 2*s->control.y*(1-2*t) + s->start.y*(-2+2*t); - return p; -} -plotxy qspline_getderivative2(qspline*s, double t) -{ - plotxy p; - p.x= s->end.x*2 + 2*s->control.x*(-2) + s->start.x*(2); - p.y= s->end.y*2 + 2*s->control.y*(-2) + s->start.y*(2); - return p; -} -double qspline_getlength(qspline*s) -{ - double t = 0; - int end = 0; - double len; - plotxy last = qspline_getpoint(s, 0.0); - do { - if(t>=1.0) { - t = 1.0; - end = 1; - } - plotxy d2 = qspline_getderivative2(s, t); - double dl2 = sqrt(d2.x*d2.x+d2.y*d2.y); - double rdl = 1.0/dl2; - if(rdl>0.01) - rdl = 0.01; - t+=rdl; - plotxy here = qspline_getpoint(s, t); - len += plotxy_dist(last, here); - last = here; - } - while(!end); - return len; -} -void qsplines_getequalspacedpoints(qspline**s, int num, float**p, int*pnum, double acc) -{ -/* int t; - float r[128]; - for(t=0;t=1.0) { - t = 1.0; - end = 1; - } - - plotxy d = qspline_getderivative(s, t); - double dl = sqrt(d.x*d.x+d.y*d.y); - double rdl = acc/dl; - - if(rdl>acc) - rdl = acc; - - positions[pos] = t; - t+=rdl; - pos++; - } - while(!end); - *pnum = pos; - *p = positions; -} - - -#define TANGENTS - -int approximate2(struct cspline*s, struct qspline*q, double quality, double start, double end) -{ - int num=0; - plotxy qr1,qr2,cr1,cr2; - double dist1,dist2; - int t; - int recurse = 0; - int probes = 15; - qspline test; - test.start = cspline_getpoint(s, start); - test.control = cspline_getpoint(s, (start+end)/2); - test.end = cspline_getpoint(s, end); - fixcp(&test); - -#ifdef TANGENTS - if(start< 0.5) { - test.control = cspline_getderivative(s, start); - test.control.x *= (end-start)/2; - test.control.y *= (end-start)/2; - test.control.x += test.start.x; - test.control.y += test.start.y; - } else { - test.control = cspline_getderivative(s, end); - test.control.x *= -(end-start)/2; - test.control.y *= -(end-start)/2; - test.control.x += test.end.x; - test.control.y += test.end.y; - } -#endif - - for(t=0;tquality) { - recurse=1;break; - } - qr2 = qspline_getpoint(&test, (1-pos)); - cr2 = cspline_getpoint(s, start+(1-pos)*(end-start)); - dist2 = plotxy_dist(qr2, cr2); - if(dist2>quality) { - recurse=1;break; - } - } - - if(recurse && (end-start)>1.0/120) { - /* quality is too bad, split it up recursively */ - num += approximate2(s, q, quality, start, (start+end)/2); - q+=num; - num += approximate2(s, q, quality, (start+end)/2, end); - return num; - } else { - *q = test; - return 1; - } -} -