/* This file is part of tooldemo, a sample Tool plugin for Adobe Illustrator Copyright (C) 2002-5 Toby Thain, toby@telegraphics.com.au 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 "common.h" #include "SPBlocks.h" #include #include #include AIArtHandle group; AINUMBER lefth,righth,topv,bottomv; // lefth,righth,topv,bottomv define the bounding rectangle of the graph; // x (1->1000) and y (0-1) are scaled to fit that // plot_point() takes x and y ordinates in GRAPH space // and maps that coordinate to ARTWORK space // -- for the purposes of this exercise, // X axis runs logarithmically from 1 to 1000 (10^0 to 10^3) // Y axis is linear from 0.0 to 1.0 // N.B. the purpose of the macros: // TONUMBER converts a floating point argument to AINUMBER type // TOFLOAT converts a AINUMBER to floating point // the AINUMBER type ("Illustrator native" number) is AIFixedPoint (pre-v8.0) or AIReal (v8.0 and later) void plot_point(AIPOINT *p,float x,float y){ p->h = lefth + TONUMBER( TOFLOAT(righth-lefth)*log10(x)/3.0 ); p->v = bottomv + TONUMBER( TOFLOAT(topv-bottomv)*y ); } AIErr new_path(AIPathSegment *segs,long count,AIPathStyle *style){ AIArtHandle path; AIErr e; !(e = sArt->NewArt( kPathArt, kPlaceInsideOnTop, group, &path )) && !(e = sPath->SetPathSegmentCount( path, count )) && !(e = sPath->SetPathSegments( path, 0, count, segs )) && !(e = sPathStyle->SetPathStyle( path, style )); return e; } AIErr plot_graph(AIPOINT *p0,AIPOINT *p1){ AIErr e; AIPathSegment seg[4],*seg2,*s; AIPathStyle pathStyle,thinStyle,thickStyle; AIPathStyleMap pathStyleMap; float x,y; int i,exp; enum{ N_SAMPLES = 100 }; char str[32]; e = sPathStyle->GetCurrentPathStyle( &pathStyle, &pathStyleMap ); pathStyle.fillPaint = false; pathStyle.strokePaint = true; pathStyle.stroke.color.kind = kGrayColor; pathStyle.stroke.color.c.g.gray = ONECONSTANT; pathStyle.stroke.width = ONECONSTANT*.5; thinStyle = pathStyle; thinStyle.stroke.width = ONECONSTANT*.2; thickStyle = pathStyle; thickStyle.stroke.width = ONECONSTANT*1.5; if(p0->h < p1->h){ lefth = p0->h; righth = p1->h; }else{ lefth = p1->h; righth = p0->h; } if(p0->v < p1->v){ bottomv = p0->v; topv = p1->v; }else{ bottomv = p1->v; topv = p0->v; } // create enclosing group if( !(e = sArt->NewArt( kGroupArt, kPlaceAboveAll, NULL, &group )) ){ // construct horizontal gridlines for(y=0.0,i=0 ; i<11 ; i++,y+=0.1){ plot_point(&seg[0].p,1.0,y); seg[0].in = seg[0].out = seg[0].p; plot_point(&seg[1].p,1000.0,y); seg[1].in = seg[1].out = seg[1].p; if(e = new_path(seg,2,i==0 || i==10 ? &pathStyle : &thinStyle)) break; sprintf(str,"%g",y); if(e = new_text(seg[0].p.h - (righth-lefth)/20,seg[0].p.v,0.,str)) break; } // construct vertical gridlines if(!e) for(exp=1;exp<1000;exp*=10) for(i=1;i<=9;i++){ plot_point(&seg[0].p,i*exp,0.0); seg[0].in = seg[0].out = seg[0].p; plot_point(&seg[1].p,i*exp,1.0); seg[1].in = seg[1].out = seg[1].p; if(e = new_path(seg,2,i==1 ? &pathStyle : &thinStyle)) break; sprintf(str,"%d",i*exp); if(e = new_text(seg[0].p.h,seg[0].p.v-(topv-bottomv)/20,90.,str)) break; } if(!e){ plot_point(&seg[0].p,1000.0,0.0); seg[0].in = seg[0].out = seg[0].p; plot_point(&seg[1].p,1000.0,1.0); seg[1].in = seg[1].out = seg[1].p; e = new_path(seg,2,&pathStyle); } if(!e){ // plot some data if(seg2 = (AIPathSegment*)malloc(sizeof(AIPathSegment)*N_SAMPLES)){ for(i=0,s=seg2;ip,x,1./x); s->in = s->out = s->p; s->corner = true; } e = new_path(seg2,N_SAMPLES,&thickStyle); free(seg2); }else e = kSPOutOfMemoryError; // ??? is this right constant? } } return e; }