%D \module %D [ file=mp-spec.mpii, %D version=1999.6.26, %D title=\CONTEXT\ \METAPOST\ graphics, %D subtitle=special extensions, %D author=Hans Hagen, %D date=\currentdate, %D copyright={PRAGMA / Hans Hagen \& Ton Otten}] %C %C This module is part of the \CONTEXT\ macro||package and is %C therefore copyrighted by \PRAGMA. See licen-en.pdf for %C details. % Spot colors are not handled by mptopdf ! % let graycolor = numeric ; % let greycolor = numeric ; % let withanycolor = withcolor ; % rgbcolor red ; red := (1,0,0) ; % rgbcolor green ; green := (0,1,0) ; % rgbcolor blue ; blue := (0,0,1) ; % cmykcolor cyan ; cyan := (1,0,0,0) ; % cmykcolor magenta ; magenta := (0,1,0,0) ; % cmykcolor yellow ; yellow := (0,0,1,0) ; % graycolor black ; black := 0 ; % (0) ; % graycolor white ; white := 1 ; % (1) ; % primarydef p withcolor c = % p withanycolor (c) % enddef ; % fill fullcircle scaled 10cm withcolor cyan ; % fill fullcircle scaled 7cm withcolor red ; % fill fullcircle scaled 4cm withcolor white ; % (r,g,b) => cmyk : r=123 g= 1 b=hash % => spot : r=123 g= 2 b=hash % => transparent rgb : r=123 g= 3 b=hash % => transparent cmyk : r=123 g= 4 b=hash % => transparent spot : r=123 g= 5 b=hash % => rest : r=123 g=n>10 b=whatever %D This module is rather preliminary and subjected to %D changes. Here we closely cooperates with the \METAPOST\ %D to \PDF\ converter module built in \CONTEXT\ and provides %D for instance shading. More information can be found in %D type {supp-mpe.tex}. if known context_spec : endinput ; fi ; boolean context_spec ; context_spec := true ; numeric _special_counter_ ; _special_counter_ := 0 ; numeric _color_counter_ ; _color_counter_ := 11 ; % < 10 reserved numeric _special_signal_ ; _special_signal_ := 123 ; numeric _special_div_ ; _special_div_ := 1000 ; %D When set to \type {true}, shading will be supported. Some %D day I will also write an additional directive. boolean _inline_specials_ ; _inline_specials_ := false ; %D Because we want to output only those specials that are %D actually used in a figure, we need a bit complicated %D bookkeeping and collection of specials. At the cost of some %D obscurity, we now have rather efficient resources. string _global_specials_ ; _global_specials_ := "" ; string _local_specials_ ; _local_specials_ := "" ; % vardef add_special_signal = % write the version number % if (length _global_specials_>0) or (length _local_specials_ >0) : % special ("%%MetaPostSpecials: 1.0 " & decimal _special_signal_ ) ; % fi ; % enddef ; % % After some reported problems at the \CONTEXT\ mailing list, % Taco's came up with: % TH: \quotation {Ok, got it. There is a bug in mp-spec.mp (inside metafun). % Because of a wrapping number, it fails to recognize the fact that there % are embedded specials at all.} The corrected definition is: vardef add_special_signal = % write the version number if (length _global_specials_ <> 0) or (length _local_specials_ <> 0) : special ("%%MetaPostSpecials: 2.0 " & decimal _special_signal_ & " " & decimal _special_div_) ; fi ; enddef ; % \quotation {It now tests for \quote {not equal to zero} instead of % \quote {larger than zero}: because of all the included files, the % string \type {_local_specials_} becomes longer than the maximum number % \quote {length} can return, so it returns -32768 instead, and that is % of course less than zero.} vardef add_extra_specials = scantokens _global_specials_ ; scantokens _local_specials_ ; enddef ; vardef reset_extra_specials = % only local ones _local_specials_ := "" ; enddef ; boolean insidefigure ; insidefigure := false ; % todo: alleen als special gebruikt flush extra_beginfig := " insidefigure := true ; " & " reset_extra_specials ; " & extra_beginfig & " ; " ; extra_endfig := " ; " & " add_special_signal ; " & extra_endfig & " add_extra_specials ; " & " reset_extra_specials ; " & " insidefigure := false ; " ; def set_extra_special (expr s) = if insidefigure : _local_specials_ := _local_specials_ & s ; else : _global_specials_ := _global_specials_ & s ; fi enddef ; def flush_special (expr typ, siz, dat) = _special_counter_ := _special_counter_ + 1 ; if _inline_specials_ : set_extra_special ( "special " & "(" & ditto & dat & " " & decimal _special_counter_ & " " & decimal typ & " " & decimal siz & " special" & ditto & ");" ) ; else : set_extra_special ( "special " & "(" & ditto & "%%MetaPostSpecial: " & decimal siz & " " & dat & " " & decimal _special_counter_ & " " & decimal typ & ditto & ");" ) ; fi ; enddef ; %D The next hack is needed in case you use a version of %D \METAPOST\ that does not provide you the means to configure %D the buffer size. Patrick Gundlach suggested to use arrays %D in this case. boolean bufferhack ; bufferhack := false ; % true ; if bufferhack : string _global_specials_[] ; numeric _nof_global_specials_ ; string _local_specials_[] ; numeric _nof_local_specials_ ; _nof_global_specials_ := _nof_local_specials_ := 0 ; vardef add_special_signal = % write the version number if (_nof_global_specials_>0) or (_nof_local_specials_>0) : special ("%%MetaPostSpecials: 1.0 " & decimal _special_signal_ ) ; fi ; enddef ; vardef add_extra_specials = for i=1 upto _nof_global_specials_ : scantokens _global_specials_[i] ; endfor; for i=1 upto _nof_local_specials_ : scantokens _local_specials_[i] ; endfor; enddef ; vardef reset_extra_specials = string _local_specials_[] ; _nof_local_specials_ := 0 ; enddef ; def set_extra_special (expr s) = if insidefigure : _local_specials_[incr(_nof_local_specials_)] := s ; else : _global_specials_[incr(_nof_global_specials_)] := s ; fi enddef ; fi ; %D So far for this hack. %D Shade allocation. newinternal shadefactor ; shadefactor := 1 ; pair shadeoffset ; shadeoffset := origin ; % vardef define_linear_shade (expr a, b, ca, cb) = % flush_special(30, 15, "0 1 " & decimal shadefactor & " " & % dddecimal ca & " " & ddecimal (a shifted shadeoffset) & " " & % dddecimal cb & " " & ddecimal (b shifted shadeoffset) ) ; % _special_counter_ % enddef ; % vardef define_circular_shade (expr a, b, ra, rb, ca, cb) = % flush_special(31, 17, "0 1 " & decimal shadefactor & " " & % dddecimal ca & " " & ddecimal (a shifted shadeoffset) & " " & decimal ra & " " & % dddecimal cb & " " & ddecimal (b shifted shadeoffset) & " " & decimal rb ) ; % _special_counter_ % enddef ; % these tests are not yet robust for new gray/cmyk features; % % - we need to get rid of cmykcolor() and vardef _is_cmyk_(expr c) = (redpart c = _special_signal_/_special_div_) and (greenpart c = 1/_special_div_) enddef ; vardef _is_spot_(expr c) = (redpart c = _special_signal_/_special_div_) and (greenpart c = 2/_special_div_) enddef ; vardef _is_gray_(expr c) = (redpart c = greenpart c) and (greenpart c = bluepart c) enddef ; numeric mp_shade_version ; mp_shade_version := 2 ; % more colors, needs new backend vardef define_linear_shade (expr a, b, ca, cb) = save cmyk_a, cmyk_b ; boolean cmyk_a, cmyk_b ; save gray_a, gray_b ; boolean gray_a, gray_b ; cmyk_a := _is_cmyk_(ca) ; gray_a := _is_gray_(ca) ; cmyk_b := _is_cmyk_(cb) ; gray_b := _is_gray_(cb) ; if (mp_shade_version > 1) and cmyk_a and cmyk_b : flush_special(32, 17, "0 1 " & decimal shadefactor & " " & cmykcolorpattern[bluepart ca] & " " & ddecimal (a shifted shadeoffset) & " " & cmykcolorpattern[bluepart cb] & " " & ddecimal (b shifted shadeoffset) ) ; elseif (mp_shade_version > 1) and cmyk_a and gray_b : save cg ; color cg ; cg := cmyk(0,0,0,1-greenpart cb) ; flush_special(32, 17, "0 1 " & decimal shadefactor & " " & cmykcolorpattern[bluepart ca] & " " & ddecimal (a shifted shadeoffset) & " " & cmykcolorpattern[bluepart cg] & " " & ddecimal (b shifted shadeoffset) ) ; elseif (mp_shade_version > 1) and gray_a and cmyk_b : save cg ; color cg ; cg := cmyk(0,0,0,1-greenpart ca) ; flush_special(32, 17, "0 1 " & decimal shadefactor & " " & cmykcolorpattern[bluepart cg] & " " & ddecimal (a shifted shadeoffset) & " " & cmykcolorpattern[bluepart cb] & " " & ddecimal (b shifted shadeoffset) ) ; elseif (mp_shade_version > 1) and _is_spot_(ca) and _is_spot_(cb) : flush_special(34, 17, "0 1 " & decimal shadefactor & " " & spotcolorpattern[bluepart ca] & " " & ddecimal (a shifted shadeoffset) & " " & spotcolorpattern[bluepart cb] & " " & ddecimal (b shifted shadeoffset) ) ; else : flush_special(30, 15, "0 1 " & decimal shadefactor & " " & dddecimal ca & " " & ddecimal (a shifted shadeoffset) & " " & dddecimal cb & " " & ddecimal (b shifted shadeoffset) ) ; fi ; _special_counter_ enddef ; vardef define_circular_shade (expr a, b, ra, rb, ca, cb) = save cmyk_a, cmyk_b ; boolean cmyk_a, cmyk_b ; save gray_a, gray_b ; boolean gray_a, gray_b ; cmyk_a := _is_cmyk_(ca) ; gray_a := _is_gray_(ca) ; cmyk_b := _is_cmyk_(cb) ; gray_b := _is_gray_(cb) ; if (mp_shade_version > 1) and cmyk_a and cmyk_b : flush_special(33, 19, "0 1 " & decimal shadefactor & " " & cmykcolorpattern[bluepart ca] & " " & ddecimal (a shifted shadeoffset) & " " & decimal ra & " " & cmykcolorpattern[bluepart cb] & " " & ddecimal (b shifted shadeoffset) & " " & decimal rb ) ; elseif (mp_shade_version > 1) and cmyk_a and gray_b : save cg ; color cg ; cg := cmyk(0,0,0,1-greenpart cb) ; flush_special(33, 19, "0 1 " & decimal shadefactor & " " & cmykcolorpattern[bluepart ca] & " " & ddecimal (a shifted shadeoffset) & " " & decimal ra & " " & cmykcolorpattern[bluepart cg] & " " & ddecimal (b shifted shadeoffset) & " " & decimal rb ) ; elseif (mp_shade_version > 1) and gray_a and cmyk_b : save cg ; color cg ; cg := cmyk(0,0,0,1-greenpart ca) ; flush_special(33, 19, "0 1 " & decimal shadefactor & " " & cmykcolorpattern[bluepart cg] & " " & ddecimal (a shifted shadeoffset) & " " & decimal ra & " " & cmykcolorpattern[bluepart cb] & " " & ddecimal (b shifted shadeoffset) & " " & decimal rb ) ; elseif (mp_shade_version > 1) and _is_spot_(ca) and _is_spot_(cb) : flush_special(35, 19, "0 1 " & decimal shadefactor & " " & spotcolorpattern[bluepart ca] & " " & ddecimal (a shifted shadeoffset) & " " & decimal ra & " " & spotcolorpattern[bluepart cb] & " " & ddecimal (b shifted shadeoffset) & " " & decimal rb ) ; else : flush_special(31, 17, "0 1 " & decimal shadefactor & " " & dddecimal ca & " " & ddecimal (a shifted shadeoffset) & " " & decimal ra & " " & dddecimal cb & " " & ddecimal (b shifted shadeoffset) & " " & decimal rb ) ; fi ; _special_counter_ enddef ; %D A few predefined shading macros. boolean trace_shades ; trace_shades := false ; % if (n=1) : a := llcorner p ; b := urcorner p ; % elseif (n=2) : a := llcorner p ; b := ulcorner p ; % elseif (n=3) : a := lrcorner p ; b := ulcorner p ; % else : a := llcorner p ; b := lrcorner p ; % fi ; def set_linear_vector (suffix a,b)(expr p,n) = if (n=1) : a := llcorner p ; b := urcorner p ; elseif (n=2) : a := lrcorner p ; b := ulcorner p ; elseif (n=3) : a := urcorner p ; b := llcorner p ; elseif (n=4) : a := ulcorner p ; b := lrcorner p ; elseif (n=5) : a := .5[ulcorner p,llcorner p] ; b := .5[urcorner p,lrcorner p] ; elseif (n=6) : a := .5[llcorner p,lrcorner p] ; b := .5[ulcorner p,urcorner p] ; elseif (n=7) : a := .5[lrcorner p,urcorner p] ; b := .5[llcorner p,ulcorner p] ; elseif (n=8) : a := .5[urcorner p,ulcorner p] ; b := .5[lrcorner p,llcorner p] ; else : a := .5[ulcorner p,llcorner p] ; b := .5[urcorner p,lrcorner p] ; fi ; enddef ; def set_circular_vector (suffix ab, r)(expr p,n) = if (n=1) : ab := llcorner p ; elseif (n=2) : ab := lrcorner p ; elseif (n=3) : ab := urcorner p ; elseif (n=4) : ab := ulcorner p ; else : ab := center p ; r := .5r ; fi ; enddef ; def linear_shade (expr p, n, ca, cb) = begingroup ; save a, b, sh ; pair a, b ; set_linear_vector(a,b)(p,n) ; fill p withshade define_linear_shade (a,b,ca,cb) ; if trace_shades : drawarrow a -- b withpen pencircle scaled 1pt withcolor .5white ; fi ; endgroup ; enddef ; def circular_shade (expr p, n, ca, cb) = begingroup ; save ab, r ; pair ab ; numeric r ; r := (xpart lrcorner p - xpart llcorner p) ++ (ypart urcorner p - ypart lrcorner p) ; set_circular_vector(ab,r)(p,n) ; fill p withshade define_circular_shade(ab,ab,0,r,ca,cb) ; if trace_shades : drawarrow ab -- ab shifted (0,r) withpen pencircle scaled 1pt withcolor .5white ; fi ; endgroup ; enddef ; vardef predefined_linear_shade (expr p, n, ca, cb) = save a, b, sh ; pair a, b ; set_linear_vector(a,b)(p,n) ; define_linear_shade (a,b,ca,cb) enddef ; vardef predefined_circular_shade (expr p, n, ca, cb) = save ab, r ; pair ab ; numeric r ; r := (xpart lrcorner p - xpart llcorner p) ++ (ypart urcorner p - ypart lrcorner p) ; set_circular_vector(ab,r)(p,n) ; define_circular_shade(ab,ab,0,r,ca,cb) enddef ; %D Since a \type {fill p withshade s} syntax looks better %D than some macro, we implement a new primary. primarydef p withshade sc = % == p withcolor shadecolor(sh) hide (_color_counter_ := _color_counter_ + 1) p withcolor (_special_signal_/_special_div_,_color_counter_/_special_div_,sc/_special_div_) enddef ; vardef shadecolor(expr sc) = hide (_color_counter_ := _color_counter_ + 1) (_special_signal_/_special_div_,_color_counter_/_special_div_,sc/_special_div_) enddef ; %D Figure inclusion. %numeric cef ; cef := 0 ; def externalfigure primary filename = doexternalfigure (filename) enddef ; def doexternalfigure (expr filename) text transformation = begingroup ; save p, t ; picture p ; transform t ; p := nullpicture ; t := identity transformation ; flush_special(10, 9, dddecimal (xxpart t, yxpart t, xypart t) & " " & dddecimal (yypart t, xpart t, ypart t) & " " & filename) ; addto p contour unitsquare scaled 0 ; setbounds p to unitsquare transformed t ; _color_counter_ := _color_counter_ + 1 ; draw p withcolor (_special_signal_/_special_div_,_color_counter_/_special_div_,_special_counter_/_special_div_) ; endgroup ; enddef ; %D Experimental: %numeric currenthyperlink ; currenthyperlink := 0 ; def hyperlink primary t = dohyperlink(t) enddef ; def hyperpath primary t = dohyperpath(t) enddef ; def dohyperlink (expr destination) text transformation = begingroup ; save somepath ; path somepath ; somepath := fullsquare transformation ; dohyperpath(destination) somepath ; endgroup ; enddef ; def dohyperpath (expr destination) expr somepath = begingroup ; flush_special(20, 7, ddecimal (xpart llcorner somepath, ypart llcorner somepath) & " " & ddecimal (xpart urcorner somepath, ypart urcorner somepath) & " " & destination) ; _color_counter_ := _color_counter_ + 1 ; fill boundingbox unitsquare scaled 0 withcolor (_special_signal_/_special_div_,_color_counter_/_special_div_,_special_counter_/_special_div_) ; endgroup ; enddef ; % \setupinteraction[state=start] % \setupcolors [state=start] % % Hello There! \blank % % \startMPcode % pickup pencircle scaled 5 ; % draw fullcircle scaled 4cm withcolor red ; % hyperpath "nextpage" boundingbox currentpicture ; % draw origin withcolor blue ; % \stopMPcode % % \blank Does it work or not? % % \startMPcode % pickup pencircle scaled 5 ; % draw fullcircle scaled 4cm withcolor red ; % hyperpath "nextpage" fullcircle scaled 4cm ; % draw origin withcolor blue ; % draw fullcircle scaled 4cm shifted (1cm,1cm); % \stopMPcode % % \blank Does it work or not? \page Hello There! \blank % % \startMPcode % pickup pencircle scaled 5 ; % draw fullcircle scaled 2cm shifted (-2cm,-1cm) ; % draw fullcircle scaled 3cm shifted (2cm,1cm) withcolor red ; % draw fullcircle scaled 1cm ; % hyperlink "previouspage" scaled 3cm shifted (2cm,1cm) ; % draw origin withcolor blue ; % \stopMPcode % % \blank Does it work or not? _cmyk_counter_ := 0 ; extra_endfig := " ; resetcmykcolors ; " & extra_endfig ; def resetcmykcolors = numeric cmykcolorhash[][][][] ; enddef ; resetcmykcolors ; boolean cmykcolors ; cmykcolors := false ; % true string cmykcolorpattern[] ; % needed for transparancies vardef cmyk(expr c,m,y,k) = if cmykcolors : save ok ; boolean ok ; if unknown cmykcolorhash[c][m][y][k] : ok := false ; % not yet defined elseif cmykcolorhash[c][m][y][k] = -1 : ok := false ; % locally defined and undefined else : ok := true ; % globally already defined fi ; if not ok : % save s ; string s ; s := dddecimal (c,m,y) & " " & decimal k ; save s ; string s ; s := ddddecimal (c,m,y,k) ; _cmyk_counter_ := _cmyk_counter_ + 1 ; cmykcolorpattern[_cmyk_counter_/_special_div_] := s ; cmykcolorhash[c][m][y][k] := _cmyk_counter_ ; flush_special(1, 7, decimal _cmyk_counter_ & " " & s) ; _local_specials_ := _local_specials_ & " cmykcolorhash[" & decimal c & "][" & decimal m & "][" & decimal y & "][" & decimal k & "] := -1 ; " ; fi ; (_special_signal_/_special_div_,1/_special_div_,cmykcolorhash[c][m][y][k]/_special_div_) else : (1-c-k,1-m-k,1-y-k) fi enddef ; % newcolor truecyan, truemagenta, trueyellow ; % % truecyan = (1,0,0,0) ; % truemagenta = (0,1,0,0) ; % trueyellow = (0,0,1,0) ; %D Spot colors _spotcolor_counter_ := 0 ; _spotcolor_number_ := 0 ; extra_endfig := " ; resetspotcolors ; " & extra_endfig ; def resetspotcolors = numeric spotcolorhash[][] ; enddef ; resetspotcolors ; boolean spotcolors ; spotcolors := false ; % true string spotcolorpattern[] ; % needed for transparancies vardef spotcolor(expr p, s) = multitonecolor(p, 1, "", decimal s) enddef ; vardef multitonecolor(expr n, f, d, p) = % name fractions names factors if spotcolors : save ok, pc_tag ; boolean ok ; string pc_tag ; pc_tag := "_pct_" & n ; if not unstringed(pc_tag) : _spotcolor_number_ := _spotcolor_number_ + 1 ; setunstringed(pc_tag,_spotcolor_number_) ; fi ; pp := getunstringed(pc_tag) ; pc_tag := "_pct_"& decimal f & "_" & if d = "" : n else : d fi & "_" & p ; % check for d empty if not unstringed(pc_tag) : _spotcolor_number_ := _spotcolor_number_ + 1 ; setunstringed(pc_tag,_spotcolor_number_) ; fi ; ps := getunstringed(pc_tag) ; if unknown spotcolorhash[pp][ps] : ok := false ; % not yet defined elseif spotcolorhash[pp][ps] = -1 : ok := false ; % locally defined and undefined else : ok := true ; % globally already defined fi ; if not ok : save ss ; string ss ; ss := n & " " & decimal f & " " & if d = "" : n else : d fi & " " & p ; _spotcolor_counter_ := _spotcolor_counter_ + 1 ; spotcolorpattern[_spotcolor_counter_/_special_div_] := ss ; spotcolorhash[pp][ps] := _spotcolor_counter_ ; flush_special(2, 7, decimal _spotcolor_counter_ & " " & ss) ; _local_specials_ := _local_specials_ & "spotcolorhash["&decimal pp&"]["&decimal ps&"]:=-1;" ; fi ; (_special_signal_/_special_div_,2/_special_div_,spotcolorhash[pp][ps]/_special_div_) else : .5white fi enddef ; %D Transparency normaltransparent := 1 ; multiplytransparent := 2 ; screentransparent := 3 ; overlaytransparent := 4 ; softlighttransparent := 5 ; hardlighttransparent := 6 ; colordodgetransparent := 7 ; colorburntransparent := 8 ; darkentransparent := 9 ; lightentransparent := 10 ; differencetransparent := 11 ; exclusiontransparent := 12 ; % nottransparent := 0 ; % compatibletransparent := 99 ; % fill fullcircle scaled 10cm withcolor transparant(8,.3,red) ; vardef transparent(expr n, t, c) = save s, ss, nn, cc, is_cmyk, is_spot, ok ; string s, ss ; numeric nn ; color cc ; boolean is_cmyk, is_spot, ok ; % transparancy type if string n : if expandafter known scantokens(n&"transparent") : nn := scantokens(n&"transparent") ; else : nn := 0 ; fi else : % nn := min(n,13) nn := if n<13 : n else : nn := 0 fi ; fi ; % we need to expand the color (can be cmyk(..) or predefined) cc := c ; % expand color % check for cmyk special is_cmyk := (redpart cc = _special_signal_/_special_div_) and (greenpart cc = 1/_special_div_) ; is_spot := (redpart cc = _special_signal_/_special_div_) and (greenpart cc = 2/_special_div_) ; % build special string, fetch cmyk components s := decimal nn & " " & decimal t & " " & if is_cmyk : cmykcolorpattern[bluepart cc] elseif is_spot : spotcolorpattern[bluepart cc] else : dddecimal cc fi ; % check if this one is already used ss := cleanstring("tr_" & s) ; % we now have rather unique names, i.e. a color spec of .234 becomes % tr..._234.... and metapost gives a number overflow (parse error) % for variables like tr_12345678 which may result from many decimal % positions (imo mp bug) ss := asciistring(ss) ; % efficiency hack if expandafter unknown scantokens(ss) : ok := false ; % not yet defined elseif scantokens(ss) < 0 : ok := false ; % locally defined and undefined else : ok := true ; % globally already defined fi ; if not ok : if is_spot : flush_special(5, 8, s) ; elseif is_cmyk : flush_special(4, 8, s) ; else : flush_special(3, 7, s) ; fi ; scantokens(ss) := _special_counter_ ; _local_specials_ := _local_specials_ & "scantokens(" & ditto & ss & ditto & ") := -1 ;" ; fi ; % go ahead if is_spot : (_special_signal_/_special_div_,5/_special_div_,scantokens(ss)/_special_div_) elseif is_cmyk : (_special_signal_/_special_div_,4/_special_div_,scantokens(ss)/_special_div_) else : (_special_signal_/_special_div_,3/_special_div_,scantokens(ss)/_special_div_) fi enddef ; %D This function returns true of false, dependent on transparency. vardef is_transparent(text t) = begingroup ; save transparent ; save _c_, _b_ ; vardef transparent(expr nn, tt, cc) = _b_ := true ; cc enddef ; boolean _b_ ; _b_ := false ; color _c_ ; _c_ := t ; _b_ endgroup enddef ; % boolean _b_ ; better namespacing % color _c_ ; % vardef _transparent_(expr nn, tt, cc) = _b_ := true ; cc enddef ; % vardef is_transparent(text t) = % begingroup ; % save transparent ; % transparent := _transparent_ ; % _b_ := false ; % _c_ := t ; _b_ % endgroup % enddef ; %D This function returns the not transparent color. vardef not_transparent(text t) = begingroup ; save transparent ; vardef transparent(expr nn, tt, cc) = cc enddef ; t endgroup enddef ; %D Basic position tracking: def register (expr label, width, height, offset) = begingroup ; flush_special(50, 7, ddecimal offset & " " & decimal width & " " & decimal height & " " & label) ; endgroup ; enddef ; %D We cannot scale cmyk colors directly since this spoils %D the trigger signal (such colors are no real colors). vardef scaledcmyk(expr c,m,y,k,sf) = cmyk(sf*c,sf*m,sf*y,sf*k) enddef ; vardef scaledcmykasrgb(expr c,m,y,k,sf) = (sf*(1-c-k,1-m-k,1-y-k)) enddef ; vardef scaledrgbascmyk(expr c,m,y,k,sf) = scaledcmyk(1-c,1-m,1-y,0,sf) enddef ; vardef scaledrgb(expr r,g,b,sf) = (sf*(r,g,b)) enddef ; vardef scaledgray(expr s,sf) = (sf*(s,s,s)) enddef ; % spotcolor is already scaled % just an exercise (due to a question by Chof on the context mailing list); scaling of % 'special' colors is not possible and the next solution is incomplete (spot colors, % transparency, etc); watch the the tricky chained macro construction % vardef normalgray(expr s ) = (s,s,s) enddef ; % vardef normalrgb (expr r,g,b ) = (r,g,b) enddef ; % vardef normalcmyk(expr c,m,y,k) = if cmykcolors : save ok ; boolean ok ; if unknown cmykcolorhash[c][m][y][k] : ok := false ; elseif cmykcolorhash[c][m][y][k] = -1 : ok := false ; else : ok := true ; fi ; if not ok : save s ; string s ; s := dddecimal (c,m,y) & " " & decimal k ; _cmyk_counter_ := _cmyk_counter_ + 1 ; cmykcolorpattern[_cmyk_counter_/_special_div_] := s ; cmykcolorhash[c][m][y][k] := _cmyk_counter_ ; flush_special(1, 7, decimal _cmyk_counter_ & " " & s) ; _local_specials_ := _local_specials_ & " cmykcolorhash[" & decimal c & "][" & decimal m & "][" & decimal y & "][" & decimal k & "] := -1 ; " ; fi ; (_special_signal_/_special_div_,1/_special_div_,cmykcolorhash[c][m][y][k]/_special_div_) else : (1-c-k,1-m-k,1-y-k) fi enddef ; % vardef gray(expr s) = normalgray(s ) enddef ; % vardef rgb (expr r,g,b) = normalrgb (r,g,b ) enddef ; % vardef cmyk(expr c,m,y,k) = normalcmyk(c,m,y,k) enddef ; % numeric _scaled_color_t_ ; % color _scaled_color_c_ ; % def withscaledcolor = % hide ( % _scaled_color_t_ := 0 ; % direct % def gray(expr s) = % hide ( % _gray_s_ := s ; % _scaled_color_t_ := 1; % gray % ) % 0 % enddef ; % def rgb (expr r,g,b) = % hide ( % _rgb_r_ := r ; _rgb_g_ := g ; _rgb_b_ := b ; % _scaled_color_t_ := 2 ; % rgb % ) % 0 % enddef ; % def cmyk (expr c,m,y,k) = % hide ( % _cmyk_c_ := c ; _cmyk_m_ := m ; _cmyk_y_ := y ; _cmyk_k_ := k ; % _scaled_color_t_ := 3 ; % cmyk % ) % 0 % enddef ; ) % dowithscaledcolor % enddef ; % def dowithscaledcolor expr t = % hide ( % if color t : _scaled_color_c_ := t fi ; % vardef gray(expr s) = normalgray(s) enddef ; % vardef rgb (expr r,g,b) = normalrgb (r,g,b) enddef ; % vardef cmyk(expr c,m,y,k) = normalcmyk(c,m,y,k) enddef ; % ) % enddef ; % def by expr s = % if _scaled_color_t_ = 0 : % withcolor s*_scaled_color_c_ % elseif _scaled_color_t_ = 1 : % withcolor gray(s*_gray_s_) % elseif _scaled_color_t_ = 2 : % withcolor rgb (s*_rgb_r_, s*_rgb_g_, s*_rgb_b_) % elseif _scaled_color_t_ = 3 : % withcolor cmyk(s*_cmyk_c_, s*_cmyk_m_, s*_cmyk_y_, s*_cmyk_k_) % fi % enddef ; % fill fullcircle scaled 10cm withscaledcolor cmyk(0,0,1,0) by .5 ; % fill fullcircle scaled 8cm withscaledcolor rgb (0,0,1) by .5 ; % fill fullcircle scaled 6cm withscaledcolor gray(1) by .5 ; % fill fullcircle scaled 4cm withscaledcolor (0,1,0) by .5 ;