123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310(**************************************************************************)(* *)(* Copyright (C) Johannes Kanig, Stephane Lescuyer *)(* Jean-Christophe Filliatre, Romain Bardou and Francois Bobot *)(* *)(* This software is free software; you can redistribute it and/or *)(* modify it under the terms of the GNU Library General Public *)(* License version 2.1, with the special exception on linking *)(* described in file LICENSE. *)(* *)(* This software 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. *)(* *)(**************************************************************************)letdiameter_of_a_dot=3.letdefault_line_size=1.moduleBoundingBox:sigtypepen=Spline_lib.pathtypet(** The type of the approximation *)(* val iter : (Spline.t -> unit) -> t -> unit *)valempty:t(* val create : ?base:pen -> Spline_lib.path -> t *)valof_path:?base:pen->Spline_lib.path->tvalunion:t->t->tvaltransform:Matrix.t->t->tvalbounding_box:t->Point_lib.t*Point_lib.tvalof_bounding_box:Point_lib.t*Point_lib.t->tend=struct(* A rendre plus performant ou pas*)(* le point correspond à un écart à prendre autour de la bounding box *)moduleS=Spline_libmoduleP=Point_libtypepen=S.pathtypet=(Spline.tlist*pen)list(* let iter f l = List.iter (fun (e,_) -> List.iter (fun s -> f s) e) l *)letempty=[]letcreate?(base=S.PointP.zero)=function|S.Pathp->[(p.S.pl,base)]|S.Pointp->letx=matchS.of_bounding_box(p,p)with|S.Pathp->p.S.pl|S.Point_->assertfalsein[(x,base)]letof_path=createletunionxy=List.rev_appendxylettransformtx=List.map(fun(x,f)->(List.map(Spline.transformt)x,S.transform(Matrix.remove_translationt)f))xopenPopenP.Infixletbounding_boxsl=letx_min,y_min,x_max,y_max=P.list_min_max_float(fun(e,f)->letx_min,y_min,x_max,y_max=P.list_min_max_floatSpline.precise_bounding_boxeinletpen_min,pen_max=S.bounding_boxfinletp1,p2=({x=x_min;y=y_min}+/pen_min,{x=x_max;y=y_max}+/pen_max)in(p1.x,p1.y,p2.x,p2.y))slin({x=x_min;y=y_min},{x=x_max;y=y_max})letof_bounding_boxl=create(S.of_bounding_boxl)endmoduleMP=Metapath_libmoduleP=Point_libmoduleS=BoundingBoxtypetransform=Matrix.ttypenum=floattypedash=float*numlisttypepen=transformtypecolor=Concrete_types.colortypepath=Spline_lib.pathtypeid=inttypeinteractive=|IntEmpty|IntTransformofinteractive*transform|IntClipofinteractive*path|IntOnTopofinteractive*interactive|Interofpath*idtypecommands=|Empty|Transformoftransform*commands|OnTopofcommandslist|TexofGentex.t|Stroke_pathofpath*coloroption*pen*dashoption|Fill_pathofpath*coloroption|Clipofcommands*path|ExternalImageofstring*float*transformandt={fcl:commands;fb:BoundingBox.t;fi:interactive}letcontentx=x.fclletempty={fcl=Empty;fb=S.empty;fi=IntEmpty}lettext={fcl=Text;fb=S.of_bounding_box(Gentex.bounding_boxt);fi=IntEmpty}letfill_pathpc={fcl=Fill_path(p,c);fb=S.of_pathp;fi=IntEmpty}letbase_of_penpen=Spline_lib.transformpen(MP.Approx.fullcircledefault_line_size)letstroke_pathpcpend={fcl=Stroke_path(p,c,pen,d);fb=S.of_path~base:(base_of_penpen)p;fi=IntEmpty;}letdraw_pointp=stroke_path(Spline_lib.create_pointp)None(Matrix.scalediameter_of_a_dot)Noneletclipppath={fcl=Clip(p.fcl,path);fb=S.of_pathpath;(* la bounding box d'un clip est la bounding_box du chemin fermé*)fi=IntClip(p.fi,path);}letexternalimage_dimensionfilename:float*float=letinch=Unix.open_process_in(Format.sprintf"identify -format \"%%h\\n%%w\" \"%s\""filename)intryleth=float_of_string(input_lineinch)inletw=float_of_string(input_lineinch)in(h,w)withEnd_of_file|Failure_->invalid_arg(Format.sprintf"Unknown external image %s"filename)letexternal_imagefilenamespec=letfh,fw=externalimage_dimensionfilenameinletheight,width=matchspecwith|`Exact(h,w)->(h,w)|`None->(fh,fw)|`Heighth->(h,fw/.fh*.h)|`Widthw->(fh/.fw*.w,w)|`Inside(h,w)->letw=min(h*.(fw/.fh))win(fh/.fw*.w,w)in(* TODO : width/.fw pour cairo width pour mps *)letm=Matrix.multiply(Matrix.xscaledwidth)(Matrix.yscaledheight)in{fcl=ExternalImage(filename,height,m);fb=S.of_bounding_box(P.zero,{P.x=width;y=height});fi=IntEmpty;}letinteractivepathid={fcl=Empty;fb=S.empty;fi=Inter(path,id)}letis_emptyt=t.fcl=Emptyleton_topt1t2=ifis_emptyt1thent2elseifis_emptyt2thent1else{fcl=OnTop[t1.fcl;t2.fcl];fb=S.uniont1.fbt2.fb;fi=IntOnTop(t1.fi,t2.fi);}lettransformmt={fcl=Transform(m,t.fcl);fb=S.transformmt.fb;fi=IntTransform(t.fi,m);}letshifttwh=transform(Matrix.xy_translationwh)tletbounding_boxt=S.bounding_boxt.fbletbaselinep=matchp.fclwithTextex->Gentex.get_bases_pttex|_->[]letapply_transform_cmdst=letrecauxpic=matchpicwith|Empty->Empty|OnTopl->OnTop(List.mapauxl)|Fill_path(p,c)->Fill_path(pathp,c)|Stroke_path(pa,c,pe,d)->Stroke_path(pathpa,c,pe,d)|Clip(cmds,p)->Clip(auxcmds,pathp)|Texg->Tex{gwithGentex.trans=Matrix.multiplytg.Gentex.trans}|ExternalImage(f,h,m)->ExternalImage(f,h,Matrix.multiplytm)|Transform(t',l)->Transform(Matrix.multiplyt't,l)andpathp=Spline_lib.transformtpinauxletiterft=letrecauxp=fp;matchpwith|Empty|Fill_path_|Stroke_path_|ExternalImage_|Tex_->()|OnTopl->List.iterauxl|Clip(c,_)->auxc|Transform(_,l)->auxlinaux(contentt)letapply_transformtp={pwithfcl=apply_transform_cmdstp.fcl;fb=BoundingBox.transformtp.fb;}moduleDash=structtypet=float*floatlisttypeinput_dash=Onoffloat|Offoffloatletshiftedf(x,d)=(x+.f,d)letline=(0.,[3.;3.])letdots=(0.,[0.;5.])letreconacc=function|[]->[acc]|Onf::l->on(f+.acc)l|Offf::l->acc::offflandoffacc=function|[]->[acc]|Onf::l->acc::onfl|Offf::l->off(f+.acc)landto_dash=function|[]->[]|Onf::l->onfl|Offf::l->0.::offflletpatternl=(0.,to_dashl)letscalef(x,l)=(x,List.map(funz->f*.z)l)endmodulePrint=struct(* debug printing *)openFormatletreccommandfmtc=matchcwith|Empty->pp_print_stringfmt"empty"|Stroke_path(p,_,_,_)->Spline_lib.printfmtp|Texg->Gentex.deb_printfmtg|OnTopcl->Misc.print_listMisc.newlinecommandfmtcl(*
| Transform of transform * commands
| Fill_path of path * color option
| Clip of commands * path
| ExternalImage of string * float * float
*)|_->assertfalseletpicfmtp=commandfmtp.fclend