1if not modules then modules = { } end modules [ ' mlib-pps ' ] = {
2 version = 1 . 001 ,
3 comment = " companion to mlib-ctx.mkiv " ,
4 author = " Hans Hagen, PRAGMA-ADE, Hasselt NL " ,
5 copyright = " PRAGMA ADE / ConTeXt Development Team " ,
6 license = " see context related readme files " ,
7}
8
9local format , gmatch , match , split , gsub = string . format , string . gmatch , string . match , string . split , string . gsub
10local tonumber , type , unpack , next , select = tonumber , type , unpack , next , select
11local round , sqrt , min , max = math . round , math . sqrt , math . min , math . max
12local insert , remove , concat = table . insert , table . remove , table . concat
13local Cs , Cf , C , Cg , Ct , P , S , V , Carg = lpeg . Cs , lpeg . Cf , lpeg . C , lpeg . Cg , lpeg . Ct , lpeg . P , lpeg . S , lpeg . V , lpeg . Carg
14local lpegmatch , tsplitat , tsplitter = lpeg . match , lpeg . tsplitat , lpeg . tsplitter
15local formatters = string . formatters
16local exists , savedata = io . exists , io . savedata
17
18local mplib = mplib
19local metapost = metapost
20local lpdf = lpdf
21local context = context
22
23local implement = interfaces . implement
24local setmacro = interfaces . setmacro
25
26local texsetbox = tex . setbox
27local textakebox = tex . takebox
28local texrunlocal = tex . runlocal
29local copylist = nodes . copylist
30local flushlist = nodes . flushlist
31local setmetatableindex = table . setmetatableindex
32local sortedhash = table . sortedhash
33
34local new_hlist = nodes . pool . hlist
35
36local starttiming = statistics . starttiming
37local stoptiming = statistics . stoptiming
38
39local trace_runs = false trackers . register ( " metapost.runs " , function ( v ) trace_runs = v end )
40local trace_textexts = false trackers . register ( " metapost.textexts " , function ( v ) trace_textexts = v end )
41local trace_scripts = false trackers . register ( " metapost.scripts " , function ( v ) trace_scripts = v end )
42local trace_btexetex = false trackers . register ( " metapost.btexetex " , function ( v ) trace_btexetex = v end )
43
44local report_metapost = logs . reporter ( " metapost " )
45local report_textexts = logs . reporter ( " metapost " , " textexts " )
46local report_scripts = logs . reporter ( " metapost " , " scripts " )
47
48local colors = attributes . colors
49local defineprocesscolor = colors . defineprocesscolor
50local definespotcolor = colors . definespotcolor
51local definemultitonecolor = colors . definemultitonecolor
52local colorvalue = colors . value
53
54local transparencies = attributes . transparencies
55local registertransparency = transparencies . register
56local transparencyvalue = transparencies . value
57
58local rgbtocmyk = colors . rgbtocmyk
59local cmyktorgb = colors . cmyktorgb
60local rgbtogray = colors . rgbtogray
61local cmyktogray = colors . cmyktogray
62
63local nooutercolor = " 0 g 0 G "
64local nooutertransparency = " /Tr0 gs "
65local outercolormode = 0
66local outercolormodel = 1
67local outercolor = nooutercolor
68local outertransparency = nooutertransparency
69local innercolor = nooutercolor
70local innertransparency = nooutertransparency
71
72local pdfcolor = lpdf . color
73local pdftransparency = lpdf . transparency
74
75function metapost . setoutercolor ( mode , colormodel , colorattribute , transparencyattribute )
76
77
78 outercolormode = mode
79 outercolormodel = colormodel
80 if mode = = 1 or mode = = 3 then
81
82 outercolor = pdfcolor ( colormodel , colorattribute ) or nooutercolor
83 outertransparency = pdftransparency ( transparencyattribute ) or nooutertransparency
84 elseif mode = = 2 then
85
86 outercolor = " "
87 outertransparency = " "
88 else
89 outercolor = nooutercolor
90 outertransparency = nooutertransparency
91 end
92 innercolor = outercolor
93 innertransparency = outertransparency
94end
95
96
97
98local f_f = formatters [ " %.6N " ]
99local f_f3 = formatters [ " %.3N " ]
100local f_gray = formatters [ " %.3N g %.3N G " ]
101local f_rgb = formatters [ " %.3N %.3N %.3N rg %.3N %.3N %.3N RG " ]
102local f_cmyk = formatters [ " %.3N %.3N %.3N %.3N k %.3N %.3N %.3N %.3N K " ]
103local f_cm_b = formatters [ " q %.6N %.6N %.6N %.6N %.6N %.6N cm " ]
104local f_scn = formatters [ " %.3N " ]
105
106local f_shade = formatters [ " MpSh%s " ]
107local f_spot = formatters [ " /%s cs /%s CS %s SCN %s scn " ]
108local s_cm_e = " Q "
109
110local function checked_color_pair ( color , ... )
111 if not color then
112 return innercolor , outercolor
113 end
114 if outercolormode = = 3 then
115 innercolor = color ( ... )
116 return innercolor , innercolor
117 else
118 return color ( ... ) , outercolor
119 end
120end
121
122function metapost . colorinitializer ( )
123 innercolor = outercolor
124 innertransparency = outertransparency
125 return outercolor , outertransparency
126end
127
128
129
130local specificationsplitter = tsplitat ( " " )
131local colorsplitter = tsplitter ( " : " , tonumber )
132local domainsplitter = tsplitter ( " " , tonumber )
133local centersplitter = domainsplitter
134local coordinatesplitter = domainsplitter
135
136
137
138
139
140
141local nofshades = 0
142
143local function normalize ( ca , cb )
144 if # cb = = 1 then
145 if # ca = = 4 then
146 cb [ 1 ] , cb [ 2 ] , cb [ 3 ] , cb [ 4 ] = 0 , 0 , 0 , 1 - cb [ 1 ]
147 else
148 cb [ 1 ] , cb [ 2 ] , cb [ 3 ] = cb [ 1 ] , cb [ 1 ] , cb [ 1 ]
149 end
150 elseif # cb = = 3 then
151 if # ca = = 4 then
152 cb [ 1 ] , cb [ 2 ] , cb [ 3 ] , cb [ 4 ] = rgbtocmyk ( cb [ 1 ] , cb [ 2 ] , cb [ 3 ] )
153 else
154 cb [ 1 ] , cb [ 2 ] , cb [ 3 ] = cmyktorgb ( cb [ 1 ] , cb [ 2 ] , cb [ 3 ] , cb [ 4 ] )
155 end
156 end
157end
158
159
160local commasplitter = tsplitat ( " , " )
161
162local function checkandconvertspot ( n_a , f_a , c_a , v_a , n_b , f_b , c_b , v_b )
163
164 local name = f_shade ( nofshades )
165 local ca = lpegmatch ( commasplitter , v_a )
166 local cb = lpegmatch ( commasplitter , v_b )
167 if # ca = = 0 or # cb = = 0 then
168 return { 0 } , { 1 } , " DeviceGray " , name
169 else
170 for i = 1 , # ca do ca [ i ] = tonumber ( ca [ i ] ) or 0 end
171 for i = 1 , # cb do cb [ i ] = tonumber ( cb [ i ] ) or 1 end
172
173 return ca , cb , n_a or n_b , name
174 end
175end
176
177local function checkandconvert ( ca , cb , model )
178 local name = f_shade ( nofshades )
179 if not ca or not cb or type ( ca ) = = " string " then
180 return { 0 } , { 1 } , " DeviceGray " , name
181 else
182 if # ca > # cb then
183 normalize ( ca , cb )
184 elseif # ca < # cb then
185 normalize ( cb , ca )
186 end
187 if not model then
188 model = colors . currentnamedmodel ( )
189 end
190 if model = = " all " then
191 model = ( # ca = = 4 and " cmyk " ) or ( # ca = = 3 and " rgb " ) or " gray "
192 end
193 if model = = " rgb " then
194 if # ca = = 4 then
195 ca = { cmyktorgb ( ca [ 1 ] , ca [ 2 ] , ca [ 3 ] , ca [ 4 ] ) }
196 cb = { cmyktorgb ( cb [ 1 ] , cb [ 2 ] , cb [ 3 ] , cb [ 4 ] ) }
197 elseif # ca = = 1 then
198 local a = 1 - ca [ 1 ]
199 local b = 1 - cb [ 1 ]
200 ca = { a , a , a }
201 cb = { b , b , b }
202 end
203 return ca , cb , " DeviceRGB " , name , model
204 elseif model = = " cmyk " then
205 if # ca = = 3 then
206 ca = { rgbtocmyk ( ca [ 1 ] , ca [ 2 ] , ca [ 3 ] ) }
207 cb = { rgbtocmyk ( cb [ 1 ] , cb [ 2 ] , cb [ 3 ] ) }
208 elseif # ca = = 1 then
209 ca = { 0 , 0 , 0 , ca [ 1 ] }
210 cb = { 0 , 0 , 0 , ca [ 1 ] }
211 end
212 return ca , cb , " DeviceCMYK " , name , model
213 else
214 if # ca = = 4 then
215 ca = { cmyktogray ( ca [ 1 ] , ca [ 2 ] , ca [ 3 ] , ca [ 4 ] ) }
216 cb = { cmyktogray ( cb [ 1 ] , cb [ 2 ] , cb [ 3 ] , cb [ 4 ] ) }
217 elseif # ca = = 3 then
218 ca = { rgbtogray ( ca [ 1 ] , ca [ 2 ] , ca [ 3 ] ) }
219 cb = { rgbtogray ( cb [ 1 ] , cb [ 2 ] , cb [ 3 ] ) }
220 end
221
222 return ca , cb , " DeviceGray " , name , model
223 end
224 end
225end
226
227
228
229
230
231
232local stack = { }
233local top = nil
234local nofruns = 0
235
236local function preset ( t , k )
237
238 local v = {
239 textrial = 0 ,
240 texfinal = 0 ,
241 texslots = { } ,
242 texorder = { } ,
243 texhash = { } ,
244 }
245 t [ k ] = v
246 return v
247end
248
249local function startjob ( plugmode , kind , mpx )
250 insert ( stack , top )
251 top = {
252 textexts = { } ,
253 texstrings = { } ,
254 texregimes = { } ,
255 mapstrings = { } ,
256 mapindices = { } ,
257 mapmoves = { } ,
258 texlast = 0 ,
259 texdata = setmetatableindex ( { } , preset ) ,
260 plugmode = plugmode ,
261 extradata = mpx and metapost . getextradata ( mpx ) ,
262 }
263 if trace_runs then
264 report_metapost ( " starting %s run at level %i in %s mode " ,
265 kind , # stack + 1 , plugmode and " plug " or " normal " )
266 end
267 return top
268end
269
270local function stopjob ( )
271 if top then
272 for slot , content in next , top . textexts do
273 if content then
274 flushlist ( content )
275 if trace_textexts then
276 report_textexts ( " freeing text %s " , slot )
277 end
278 end
279 end
280 if trace_runs then
281 report_metapost ( " stopping run at level %i " , # stack + 1 )
282 end
283 top = remove ( stack )
284 return top
285 end
286end
287
288function metapost . getjobdata ( )
289 return top
290end
291
292
293
294local settext = function ( box , slot , str )
295 if top then
296
297
298
299 top . textexts [ slot ] = textakebox ( box )
300 end
301end
302
303local gettext = function ( box , slot )
304 if top then
305 texsetbox ( box , top . textexts [ slot ] )
306 top . textexts [ slot ] = false
307
308
309
310 end
311end
312
313metapost . settext = settext
314metapost . gettext = gettext
315
316implement { name = " mpsettext " , actions = settext , arguments = { " integer " , " integer " } }
317implement { name = " mpgettext " , actions = gettext , arguments = { " integer " , " integer " } }
318
319
320
321
322
323metapost . reducetogray = true
324
325local models = { }
326
327function models . all ( cr )
328 local n = # cr
329 if n = = 0 then
330 return checked_color_pair ( )
331 elseif metapost . reducetogray then
332 if n = = 1 then
333 local s = cr [ 1 ]
334 return checked_color_pair ( f_gray , s , s )
335 elseif n = = 3 then
336 local r = cr [ 1 ]
337 local g = cr [ 2 ]
338 local b = cr [ 3 ]
339 if r = = g and g = = b then
340 return checked_color_pair ( f_gray , r , r )
341 else
342 return checked_color_pair ( f_rgb , r , g , b , r , g , b )
343 end
344 else
345 local c = cr [ 1 ]
346 local m = cr [ 2 ]
347 local y = cr [ 3 ]
348 local k = cr [ 4 ]
349 if c = = m and m = = y and y = = 0 then
350 k = 1 - k
351 return checked_color_pair ( f_gray , k , k )
352 else
353 return checked_color_pair ( f_cmyk , c , m , y , k , c , m , y , k )
354 end
355 end
356 elseif n = = 1 then
357 local s = cr [ 1 ]
358 return checked_color_pair ( f_gray , s , s )
359 elseif n = = 3 then
360 local r = cr [ 1 ]
361 local g = cr [ 2 ]
362 local b = cr [ 3 ]
363 return checked_color_pair ( f_rgb , r , g , b , r , g , b )
364 else
365 local c = cr [ 1 ]
366 local m = cr [ 2 ]
367 local y = cr [ 3 ]
368 local k = cr [ 4 ]
369 return checked_color_pair ( f_cmyk , c , m , y , k , c , m , y , k )
370 end
371end
372
373function models . rgb ( cr )
374 local n = # cr
375 if n = = 0 then
376 return checked_color_pair ( )
377 elseif metapost . reducetogray then
378 if n = = 1 then
379 local s = cr [ 1 ]
380 return checked_color_pair ( f_gray , s , s )
381 elseif n = = 3 then
382 local r = cr [ 1 ]
383 local g = cr [ 2 ]
384 local b = cr [ 3 ]
385 if r = = g and g = = b then
386 return checked_color_pair ( f_gray , r , r )
387 else
388 return checked_color_pair ( f_rgb , r , g , b , r , g , b )
389 end
390 else
391 local c = cr [ 1 ]
392 local m = cr [ 2 ]
393 local y = cr [ 3 ]
394 local k = cr [ 4 ]
395 if c = = m and m = = y and y = = 0 then
396 k = 1 - k
397 return checked_color_pair ( f_gray , k , k )
398 else
399 local r , g , b = cmyktorgb ( c , m , y , k )
400 return checked_color_pair ( f_rgb , r , g , b , r , g , b )
401 end
402 end
403 elseif n = = 1 then
404 local s = cr [ 1 ]
405 return checked_color_pair ( f_gray , s , s )
406 else
407 local r = cr [ 1 ]
408 local g = cr [ 2 ]
409 local b = cr [ 3 ]
410 local r , g , b
411 if n = = 3 then
412 r , g , b = cmyktorgb ( r , g , b , cr [ 4 ] )
413 end
414 return checked_color_pair ( f_rgb , r , g , b , r , g , b )
415 end
416end
417
418function models . cmyk ( cr )
419 local n = # cr
420 if n = = 0 then
421 return checked_color_pair ( )
422 elseif metapost . reducetogray then
423 if n = = 1 then
424 local s = cr [ 1 ]
425 return checked_color_pair ( f_gray , s , s )
426 elseif n = = 3 then
427 local r = cr [ 1 ]
428 local g = cr [ 2 ]
429 local b = cr [ 3 ]
430 if r = = g and g = = b then
431 return checked_color_pair ( f_gray , r , r )
432 else
433 local c , m , y , k = rgbtocmyk ( r , g , b )
434 return checked_color_pair ( f_cmyk , c , m , y , k , c , m , y , k )
435 end
436 else
437 local c = cr [ 1 ]
438 local m = cr [ 2 ]
439 local y = cr [ 3 ]
440 local k = cr [ 4 ]
441 if c = = m and m = = y and y = = 0 then
442 k = 1 - k
443 return checked_color_pair ( f_gray , k , k )
444 else
445 return checked_color_pair ( f_cmyk , c , m , y , k , c , m , y , k )
446 end
447 end
448 elseif n = = 1 then
449 local s = cr [ 1 ]
450 return checked_color_pair ( f_gray , s , s )
451 else
452 local c = cr [ 1 ]
453 local m = cr [ 2 ]
454 local y = cr [ 3 ]
455 local k = cr [ 4 ]
456 if n = = 3 then
457 if c = = m and m = = y then
458 k , c , m , y = 1 - c , 0 , 0 , 0
459 else
460 c , m , y , k = rgbtocmyk ( c , m , y )
461 end
462 end
463 return checked_color_pair ( f_cmyk , c , m , y , k , c , m , y , k )
464 end
465end
466
467function models . gray ( cr )
468 local n = # cr
469 local s = 0
470 if n = = 0 then
471 return checked_color_pair ( )
472 elseif n = = 4 then
473 s = cmyktogray ( cr [ 1 ] , cr [ 2 ] , cr [ 3 ] , cr [ 4 ] )
474 elseif n = = 3 then
475 s = rgbtogray ( cr [ 1 ] , cr [ 2 ] , cr [ 3 ] )
476 else
477 s = cr [ 1 ]
478 end
479 return checked_color_pair ( f_gray , s , s )
480end
481
482models [ 1 ] = models . all
483models [ 2 ] = models . gray
484models [ 3 ] = models . rgb
485models [ 4 ] = models . cmyk
486
487setmetatableindex ( models , function ( t , k )
488 local v = models . gray
489 t [ k ] = v
490 return v
491end )
492
493local function colorconverter ( cs )
494 return models [ outercolormodel ] ( cs )
495end
496
497local factor = 65536 * ( 7227 / 7200 )
498
499implement {
500 name = " mpsetsxsy " ,
501 arguments = { " dimen " , " dimen " , " dimen " } ,
502 actions = function ( wd , ht , dp )
503 local hd = ht + dp
504 setmacro ( " mlib_sx " , wd ~ = 0 and factor / wd or 0 )
505 setmacro ( " mlib_sy " , hd ~ = 0 and factor / hd or 0 )
506 end
507}
508
509local function sxsy ( wd , ht , dp )
510 local hd = ht + dp
511 return ( wd ~ = 0 and factor / wd ) or 0 , ( hd ~ = 0 and factor / hd ) or 0
512end
513
514metapost . sxsy = sxsy
515
516
517
518local do_begin_fig = " ; beginfig(1) ; "
519local do_end_fig = " ; endfig ; "
520local do_safeguard = " ; "
521
522function metapost . preparetextextsdata ( )
523 local textexts = top . textexts
524 local collected = { }
525 for k , data in sortedhash ( top . texdata ) do
526 local texorder = data . texorder
527 for n = 1 , # texorder do
528 local box = textexts [ texorder [ n ] ]
529 if box then
530 collected [ n ] = box
531 else
532 break
533 end
534 end
535 end
536 mp . mf_tt_initialize ( collected )
537end
538
539local runmetapost = metapost . run
540
541local function checkaskedfig ( askedfig )
542 if not askedfig then
543 return " direct " , true
544 elseif askedfig = = " all " then
545 return " all " , false
546 elseif askedfig = = " direct " then
547 return " all " , true
548 else
549 askedfig = tonumber ( askedfig )
550 if askedfig then
551 return askedfig , false
552 else
553 return " direct " , true
554 end
555 end
556end
557
558local function extrapass ( )
559 if trace_runs then
560 report_metapost ( " second run of job %s, asked figure %a " , top . nofruns , top . askedfig )
561 end
562 metapost . preparetextextsdata ( )
563 runmetapost {
564 mpx = top . mpx ,
565 askedfig = top . askedfig ,
566 incontext = true ,
567 data = {
568 top . wrappit and do_begin_fig or " " ,
569 no_trial_run ,
570 top . initializations ,
571 do_safeguard ,
572 top . data ,
573 top . wrappit and do_end_fig or " " ,
574 } ,
575 }
576end
577
578
579
580
581
582
583
584function metapost . graphic_base_pass ( specification )
585 local mpx = specification . mpx
586 local top = startjob ( true , " base " , mpx )
587 local data = specification . data or " "
588 local inclusions = specification . inclusions or " "
589 local initializations = specification . initializations or " "
590 local askedfig ,
591 wrappit = checkaskedfig ( specification . figure )
592 nofruns = nofruns + 1
593 top . askedfig = askedfig
594 top . wrappit = wrappit
595 top . nofruns = nofruns
596 metapost . namespace = specification . namespace or " "
597 top . mpx = mpx
598 top . data = data
599 top . initializations = initializations
600 if trace_runs then
601 report_metapost ( " running job %s, asked figure %a " , nofruns , askedfig )
602 end
603 runmetapost {
604 mpx = mpx ,
605 askedfig = askedfig ,
606 incontext = true ,
607 data = {
608 inclusions ,
609 wrappit and do_begin_fig or " " ,
610 initializations ,
611 do_safeguard ,
612 data ,
613 wrappit and do_end_fig or " " ,
614 } ,
615 }
616 context ( stopjob )
617end
618
619local function oldschool ( mpx , data , trial_run , flusher , was_multi_pass , is_extra_pass , askedfig , incontext )
620 metapost . process {
621 mpx = mpx ,
622 flusher = flusher ,
623 askedfig = askedfig ,
624 useplugins = incontext ,
625 incontext = incontext ,
626 data = data ,
627 }
628end
629
630function metapost . process ( specification , ... )
631 if type ( specification ) ~ = " table " then
632 oldschool ( specification , ... )
633 else
634 startjob ( specification . incontext or specification . useplugins , " process " , false )
635 runmetapost ( specification )
636 stopjob ( )
637 end
638end
639
640
641
642local sequencers = utilities . sequencers
643local appendgroup = sequencers . appendgroup
644local appendaction = sequencers . appendaction
645
646local resetteractions = sequencers . new { arguments = " t " }
647local processoractions = sequencers . new { arguments = " object,prescript,before,after " }
648
649appendgroup ( resetteractions , " system " )
650appendgroup ( processoractions , " system " )
651
652
653
654local scriptsplitter = Ct ( Ct (
655 C ( ( 1 - S ( " = " ) ) ^ 1 ) * S ( " = " ) ^ 1 * C ( ( 1 - S ( " \n\r " ) ) ^ 0 ) * S ( " \n\r " ) ^ 0
656) ^ 0 )
657
658local function splitprescript ( script )
659 local hash = lpegmatch ( scriptsplitter , script )
660 for i = # hash , 1 , -1 do
661 local h = hash [ i ]
662 if h = = " reset " then
663 for k , v in next , hash do
664 if type ( k ) ~ = " number " then
665 hash [ k ] = nil
666 end
667 end
668 else
669 hash [ h [ 1 ] ] = h [ 2 ]
670 end
671 end
672 if trace_scripts then
673 report_scripts ( table . serialize ( hash , " prescript " ) )
674 end
675 return hash
676end
677
678metapost . splitprescript = splitprescript
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694function metapost . pluginactions ( what , t , flushfigure )
695 if top and top . plugmode then
696 for i = 1 , # what do
697 local wi = what [ i ]
698 if type ( wi ) = = " function " then
699
700 flushfigure ( t )
701 t = { }
702 wi ( )
703 else
704 t [ # t + 1 ] = wi
705 end
706 end
707 return t
708 end
709end
710
711function metapost . resetplugins ( t )
712 if top and top . plugmode then
713 outercolormodel = colors . currentmodel ( )
714 resetteractions . runner ( t )
715 end
716end
717
718function metapost . processplugins ( object )
719 if top and top . plugmode then
720 local prescript = object . prescript
721 if prescript and # prescript > 0 then
722 local before = { }
723 local after = { }
724 processoractions . runner ( object , splitprescript ( prescript ) or { } , before , after )
725 return # before > 0 and before , # after > 0 and after
726 else
727 local c = object . color
728 if c and # c > 0 then
729 local b , a = colorconverter ( c )
730 return { b } , { a }
731 end
732 end
733 end
734end
735
736
737
738local basepoints = number . dimenfactors [ " bp " ]
739
740local function cm ( object )
741 local op = object . path
742 if op then
743 local first = op [ 1 ]
744 local second = op [ 2 ]
745 local fourth = op [ 4 ]
746 if fourth then
747 local tx = first . x_coord
748 local ty = first . y_coord
749 local sx = second . x_coord - tx
750 local sy = fourth . y_coord - ty
751 local rx = second . y_coord - ty
752 local ry = fourth . x_coord - tx
753 if sx = = 0 then sx = 0 . 00001 end
754 if sy = = 0 then sy = 0 . 00001 end
755 return sx , rx , ry , sy , tx , ty
756 end
757 end
758 return 1 , 0 , 0 , 1 , 0 , 0
759end
760
761metapost . cm = cm
762
763
764
765local function cl_reset ( t )
766 t [ # t + 1 ] = metapost . colorinitializer ( )
767end
768
769
770
771local tx_reset , tx_process do
772
773 local eol = S ( " \n\r " ) ^ 1
774 local cleaner = Cs ( ( P ( " @@ " ) / " @ " + P ( " @ " ) / " %% " + P ( 1 ) ) ^ 0 )
775 local splitter = Ct (
776 ( (
777 P ( " s: " ) * C ( ( 1 - eol ) ^ 1 )
778 + P ( " n: " ) * ( ( 1 - eol ) ^ 1 / tonumber )
779 + P ( " b: " ) * ( ( 1 - eol ) ^ 1 / toboolean )
780 ) * eol ^ 0 ) ^ 0 )
781
782 local function applyformat ( s )
783 local t = lpegmatch ( splitter , s )
784 if # t = = 1 then
785 return s
786 else
787 local f = lpegmatch ( cleaner , t [ 1 ] )
788 return formatters [ f ] ( unpack ( t , 2 ) )
789 end
790 end
791
792 local fmt = formatters [ " %s %s %s % t " ]
793
794 local pat = lpeg . tsplitter ( " : " , tonumber )
795
796 local f_gray_yes = formatters [ " s=%.3N,a=%i,t=%.3N " ]
797 local f_gray_nop = formatters [ " s=%.3N " ]
798 local f_rgb_yes = formatters [ " r=%.3N,g=%.3N,b=%.3N,a=%.3N,t=%.3N " ]
799 local f_rgb_nop = formatters [ " r=%.3N,g=%.3N,b=%.3N " ]
800 local f_cmyk_yes = formatters [ " c=%.3N,m=%.3N,y=%.3N,k=%.3N,a=%.3N,t=%.3N " ]
801 local f_cmyk_nop = formatters [ " c=%.3N,m=%.3N,y=%.3N,k=%.3N " ]
802
803 local ctx_MPLIBsetNtext = context . MPLIBsetNtextX
804 local ctx_MPLIBsetCtext = context . MPLIBsetCtextX
805 local ctx_MPLIBsettext = context . MPLIBsettextX
806
807 local bp = number . dimenfactors . bp
808
809 local mp_index = 0
810 local mp_target = 0
811 local mp_c = nil
812 local mp_a = nil
813 local mp_t = nil
814
815 local function processtext ( )
816 local mp_text = top . texstrings [ mp_index ]
817 local mp_regime = top . texregimes [ mp_index ]
818 if mp_regime and tonumber ( mp_regime ) > = 0 then
819 mp_text = function ( )
820 context . sprint ( mp_regime , top . texstrings [ mp_index ] or " " )
821 end
822 end
823 if not mp_text then
824 report_textexts ( " missing text for index %a " , mp_index )
825 elseif not mp_c then
826 ctx_MPLIBsetNtext ( mp_target , mp_text )
827 elseif # mp_c = = 1 then
828 if mp_a and mp_t then
829 ctx_MPLIBsetCtext ( mp_target , f_gray_yes ( mp_c [ 1 ] , mp_a , mp_t ) , mp_text )
830 else
831 ctx_MPLIBsetCtext ( mp_target , f_gray_nop ( mp_c [ 1 ] ) , mp_text )
832 end
833 elseif # mp_c = = 3 then
834 if mp_a and mp_t then
835 ctx_MPLIBsetCtext ( mp_target , f_rgb_yes ( mp_c [ 1 ] , mp_c [ 2 ] , mp_c [ 3 ] , mp_a , mp_t ) , mp_text )
836 else
837 ctx_MPLIBsetCtext ( mp_target , f_rgb_nop ( mp_c [ 1 ] , mp_c [ 2 ] , mp_c [ 3 ] ) , mp_text )
838 end
839 elseif # mp_c = = 4 then
840 if mp_a and mp_t then
841 ctx_MPLIBsetCtext ( mp_target , f_cmyk_yes ( mp_c [ 1 ] , mp_c [ 2 ] , mp_c [ 3 ] , mp_c [ 4 ] , mp_a , mp_t ) , mp_text )
842 else
843 ctx_MPLIBsetCtext ( mp_target , f_cmyk_nop ( mp_c [ 1 ] , mp_c [ 2 ] , mp_c [ 3 ] , mp_c [ 4 ] ) , mp_text )
844 end
845 else
846
847 ctx_MPLIBsetNtext ( mp_target , mp_text )
848 end
849 end
850
851 local madetext = nil
852
853 function mp . mf_some_text ( index , str , regime )
854 mp_target = index
855 mp_index = index
856 mp_c = nil
857 mp_a = nil
858 mp_t = nil
859 top . texstrings [ mp_index ] = str
860 top . texregimes [ mp_index ] = regime or -1
861 texrunlocal ( " mptexttoks " )
862 local box = textakebox ( " mptextbox " )
863 top . textexts [ mp_target ] = box
864 mp . triplet ( bp * box . width , bp * box . height , bp * box . depth )
865 madetext = nil
866 end
867
868 function mp . mf_made_text ( index )
869 mp . mf_some_text ( index , madetext , catcodes . numbers . ctxcatcodes )
870 end
871
872
873
874
875 function metapost . processing ( )
876 return top and true or false
877 end
878
879 function metapost . remaptext ( replacement )
880 if top then
881 local mapstrings = top . mapstrings
882 local mapindices = top . mapindices
883 local label = replacement . label
884 local index = 0
885 if label then
886 local found = mapstrings [ label ]
887 if found then
888 setmetatableindex ( found , replacement )
889 index = found . index
890 else
891 index = # mapindices + 1
892 replacement . index = index
893 mapindices [ index ] = replacement
894 mapstrings [ label ] = replacement
895 end
896 end
897 return index
898 else
899 return 0
900 end
901 end
902
903 function metapost . remappedtext ( what )
904 return top and ( top . mapstrings [ what ] or top . mapindices [ tonumber ( what ) ] )
905 end
906
907 function mp . mf_map_move ( index )
908 mp . triplet ( top . mapmoves [ index ] )
909 end
910
911 function mp . mf_map_text ( index , str , regime )
912 local map = top . mapindices [ tonumber ( str ) ]
913 if type ( map ) = = " table " then
914 local text = map . text
915 local overload = map . overload
916 local offset = 0
917 local width = 0
918 local where = nil
919
920 mp_index = index
921
922 if overload then
923 top . texstrings [ mp_index ] = map . template or map . label or " error "
924 top . texregimes [ mp_index ] = regime or -1
925 texrunlocal ( " mptexttoks " )
926 local box = textakebox ( " mptextbox " ) or new_hlist ( )
927 width = bp * box . width
928 where = overload . where
929 end
930
931 top . texstrings [ mp_index ] = overload and overload . text or text or " error "
932 top . texregimes [ mp_index ] = regime or -1
933 texrunlocal ( " mptexttoks " )
934 local box = textakebox ( " mptextbox " ) or new_hlist ( )
935 local twd = bp * box . width
936 local tht = bp * box . height
937 local tdp = bp * box . depth
938
939 if where then
940 local scale = 1
941 if where = = " l " or where = = " left " then
942 offset = scale * ( twd - width )
943 elseif where = = " m " or where = = " middle " then
944 offset = scale * ( twd - width ) / 2
945 end
946 end
947
948 top . textexts [ mp_index ] = box
949 top . mapmoves [ mp_index ] = { offset , map . dx or 0 , map . dy or 0 }
950
951 mp . triplet ( twd , tht , tdp )
952 madetext = nil
953 return
954 else
955 map = type ( map ) = = " string " and map or str
956 return mp . mf_some_text ( index , context . escape ( map ) or map )
957 end
958 end
959
960
961
962
963
964
965
966
967 local reported = false
968 local alwayswrap = false
969
970 function metapost . maketext ( s , mode )
971 if not reported then
972 reported = true
973 report_metapost ( " use 'textext(.....)' instead of 'btex ..... etex' " )
974 end
975 if mode and mode = = 1 then
976 if trace_btexetex then
977 report_metapost ( " ignoring verbatimtex: [[%s]] " , s )
978 end
979 elseif alwayswrap then
980 if trace_btexetex then
981 report_metapost ( " rewrapping btex ... etex [[%s]] " , s )
982 end
983 return ' rawtextext(" ' . . gsub ( s , ' " ' , ' "&ditto&" ' ) . . ' ") '
984 elseif metapost . currentmpxstatus ( ) ~ = 0 then
985 if trace_btexetex then
986 report_metapost ( " rewrapping btex ... etex at the outer level [[%s]] " , s )
987 end
988 return ' rawtextext(" ' . . gsub ( s , ' " ' , ' "&ditto&" ' ) . . ' ") '
989 else
990 if trace_btexetex then
991 report_metapost ( " handling btex ... etex: [[%s]] " , s )
992 end
993
994 madetext = s
995 return " rawmadetext "
996 end
997 end
998
999 function mp . mf_formatted_text ( index , fmt , ... )
1000 local t = { }
1001 for i = 1 , select ( " # " , ... ) do
1002 local ti = select ( i , ... )
1003 if type ( ti ) ~ = " table " then
1004 t [ # t + 1 ] = ti
1005 end
1006 end
1007 local f = lpegmatch ( cleaner , fmt )
1008 local s = formatters [ f ] ( unpack ( t ) ) or " "
1009 mp . mf_some_text ( index , s )
1010 end
1011
1012 interfaces . implement {
1013 name = " mptexttoks " ,
1014 actions = processtext ,
1015 }
1016
1017 tx_reset = function ( )
1018 if top then
1019 top . texhash = { }
1020 top . texlast = 0
1021 end
1022 end
1023
1024 tx_process = function ( object , prescript , before , after )
1025 local data = top . texdata [ metapost . properties . number ]
1026 local index = tonumber ( prescript . tx_index )
1027 if index then
1028 if trace_textexts then
1029 report_textexts ( " using index %a " , index )
1030 end
1031
1032 mp_c = object . color
1033 if # mp_c = = 0 then
1034 local txc = prescript . tx_color
1035 if txc then
1036 mp_c = lpegmatch ( pat , txc )
1037 end
1038 end
1039 mp_a = tonumber ( prescript . tr_alternative )
1040 mp_t = tonumber ( prescript . tr_transparency )
1041
1042 mp_index = index
1043 mp_target = top . texlast - 1
1044 top . texlast = mp_target
1045
1046 local mp_text = top . texstrings [ mp_index ]
1047 local mp_hash = prescript . tx_cache
1048 local box
1049 if mp_hash = = " no " then
1050 texrunlocal ( " mptexttoks " )
1051 box = textakebox ( " mptextbox " )
1052 else
1053 local cache = data . texhash
1054 if mp_hash then
1055 mp_hash = tonumber ( mp_hash )
1056 end
1057 if mp_hash then
1058 local extradata = top . extradata
1059 if extradata then
1060 cache = extradata . globalcache
1061 if not cache then
1062 cache = { }
1063 extradata . globalcache = cache
1064 end
1065 if trace_runs then
1066 if cache [ mp_hash ] then
1067 report_textexts ( " reusing global entry %i " , mp_hash )
1068 else
1069 report_textexts ( " storing global entry %i " , mp_hash )
1070 end
1071 end
1072 else
1073 mp_hash = nil
1074 end
1075 end
1076 if not mp_hash then
1077 mp_hash = fmt ( mp_text , mp_a or " - " , mp_t or " - " , mp_c or " - " )
1078 end
1079 box = cache [ mp_hash ]
1080 if box then
1081 box = copylist ( box )
1082 else
1083 texrunlocal ( " mptexttoks " )
1084 box = textakebox ( " mptextbox " )
1085 cache [ mp_hash ] = box
1086 end
1087 end
1088 top . textexts [ mp_target ] = box
1089
1090 if box then
1091
1092 local sx , rx , ry , sy , tx , ty = cm ( object )
1093 local target = mp_target
1094 before [ # before + 1 ] = function ( )
1095 context . MPLIBgettextscaledcm ( target ,
1096 f_f ( sx ) ,
1097 f_f ( rx ) ,
1098 f_f ( ry ) ,
1099 f_f ( sy ) ,
1100 f_f ( tx ) ,
1101 f_f ( ty ) ,
1102 sxsy ( box . width , box . height , box . depth ) )
1103 end
1104 else
1105 before [ # before + 1 ] = function ( )
1106 report_textexts ( " unknown %s " , index )
1107 end
1108 end
1109 if not trace_textexts then
1110 object . path = false
1111 end
1112 object . color = false
1113 object . grouped = true
1114 object . istext = true
1115 end
1116 end
1117
1118end
1119
1120
1121
1122
1123local function bx_process ( object , prescript , before , after )
1124 local bx_category = prescript . bx_category
1125 local bx_name = prescript . bx_name
1126 if bx_category and bx_name then
1127 if trace_textexts then
1128 report_textexts ( " category %a, name %a " , bx_category , bx_name )
1129 end
1130 local sx , rx , ry , sy , tx , ty = cm ( object )
1131 local wd , ht , dp = nodes . boxes . dimensions ( bx_category , bx_name )
1132 before [ # before + 1 ] = function ( )
1133 context . MPLIBgetboxscaledcm ( bx_category , bx_name ,
1134 f_f ( sx ) ,
1135 f_f ( rx ) ,
1136 f_f ( ry ) ,
1137 f_f ( sy ) ,
1138 f_f ( tx ) ,
1139 f_f ( ty ) ,
1140 sxsy ( wd , ht , dp ) )
1141 end
1142 if not trace_textexts then
1143 object . path = false
1144 end
1145 object . color = false
1146 object . grouped = true
1147 object . istext = true
1148 end
1149end
1150
1151
1152
1153
1154local gt_reset , gt_process do
1155
1156 local graphics = { }
1157
1158
1159 local mp_index = 0
1160 local mp_str = " "
1161
1162 function mp . mf_graphic_text ( index , str )
1163 if not graphics [ index ] then
1164 mp_index = index
1165 mp_str = str
1166 texrunlocal ( " mpgraphictexttoks " )
1167 end
1168 end
1169
1170 interfaces . implement {
1171 name = " mpgraphictexttoks " ,
1172 actions = function ( )
1173 context . MPLIBgraphictext ( mp_index , mp_str )
1174 end ,
1175 }
1176
1177end
1178
1179
1180
1181local function sh_process ( object , prescript , before , after )
1182 local sh_type = prescript . sh_type
1183 if sh_type then
1184 nofshades = nofshades + 1
1185 local domain = lpegmatch ( domainsplitter , prescript . sh_domain or " 0 1 " )
1186 local centera = lpegmatch ( centersplitter , prescript . sh_center_a or " 0 0 " )
1187 local centerb = lpegmatch ( centersplitter , prescript . sh_center_b or " 0 0 " )
1188 local transform = toboolean ( prescript . sh_transform or " yes " , true )
1189
1190 local sx = 1
1191 local sy = 1
1192 local sr = 1
1193 local dx = 0
1194 local dy = 0
1195 if transform then
1196 local first = lpegmatch ( coordinatesplitter , prescript . sh_first or " 0 0 " )
1197 local setx = lpegmatch ( coordinatesplitter , prescript . sh_set_x or " 0 0 " )
1198 local sety = lpegmatch ( coordinatesplitter , prescript . sh_set_y or " 0 0 " )
1199
1200 local x = setx [ 1 ]
1201 local y = sety [ 1 ]
1202
1203 if x = = 0 or y = = 0 then
1204
1205 else
1206 local path = object . path
1207 local path1x = path [ 1 ] . x_coord
1208 local path1y = path [ 1 ] . y_coord
1209 local path2x = path [ x ] . x_coord
1210 local path2y = path [ y ] . y_coord
1211
1212 local dxa = path2x - path1x
1213 local dya = path2y - path1y
1214 local dxb = setx [ 2 ] - first [ 1 ]
1215 local dyb = sety [ 2 ] - first [ 2 ]
1216
1217 if dxa = = 0 or dya = = 0 or dxb = = 0 or dyb = = 0 then
1218
1219 else
1220 sx = dxa / dxb ; if sx < 0 then sx = - sx end
1221 sy = dya / dyb ; if sy < 0 then sy = - sy end
1222
1223 sr = sqrt ( sx ^ 2 + sy ^ 2 )
1224
1225 dx = path1x - sx * first [ 1 ]
1226 dy = path1y - sy * first [ 2 ]
1227 end
1228 end
1229 end
1230
1231 local steps = tonumber ( prescript . sh_step ) or 1
1232 local sh_color_a = prescript . sh_color_a_1 or prescript . sh_color_a or " 1 "
1233 local sh_color_b = prescript . sh_color_b_1 or prescript . sh_color_b or " 1 "
1234 local ca , cb , colorspace , name , model , separation , fractions
1235 if prescript . sh_color = = " into " and prescript . sp_name then
1236
1237 local value_a , components_a , fractions_a , name_a
1238 local value_b , components_b , fractions_b , name_b
1239 for i = 1 , # prescript do
1240
1241
1242
1243
1244
1245
1246
1247 local tag = prescript [ i ] [ 1 ]
1248 if not name_a and tag = = " sh_color_a " then
1249 value_a = prescript [ i -5 ] [ 2 ]
1250 components_a = prescript [ i -4 ] [ 2 ]
1251 fractions_a = prescript [ i -3 ] [ 2 ]
1252 name_a = prescript [ i -2 ] [ 2 ]
1253 elseif not name_b and tag = = " sh_color_b " then
1254 value_b = prescript [ i -5 ] [ 2 ]
1255 components_b = prescript [ i -4 ] [ 2 ]
1256 fractions_b = prescript [ i -3 ] [ 2 ]
1257 name_b = prescript [ i -2 ] [ 2 ]
1258 end
1259 if name_a and name_b then
1260 break
1261 end
1262 end
1263 ca , cb , separation , name = checkandconvertspot (
1264 name_a , fractions_a , components_a , value_a ,
1265 name_b , fractions_b , components_b , value_b
1266 )
1267 else
1268 local colora = lpegmatch ( colorsplitter , sh_color_a )
1269 local colorb = lpegmatch ( colorsplitter , sh_color_b )
1270 ca , cb , colorspace , name , model = checkandconvert ( colora , colorb )
1271
1272 if steps > 1 then
1273 ca = { ca }
1274 cb = { cb }
1275 fractions = { tonumber ( prescript [ formatters [ " sh_fraction_%i " ] ( 1 ) ] ) or 0 }
1276 for i = 2 , steps do
1277 local colora = lpegmatch ( colorsplitter , prescript [ formatters [ " sh_color_a_%i " ] ( i ) ] )
1278 local colorb = lpegmatch ( colorsplitter , prescript [ formatters [ " sh_color_b_%i " ] ( i ) ] )
1279 ca [ i ] , cb [ i ] = checkandconvert ( colora , colorb , model )
1280 fractions [ i ] = tonumber ( prescript [ formatters [ " sh_fraction_%i " ] ( i ) ] ) or ( i / steps )
1281 end
1282 end
1283 end
1284 if not ca or not cb then
1285 ca , cb , colorspace , name = checkandconvert ( )
1286 steps = 1
1287 end
1288 if sh_type = = " linear " then
1289 local coordinates = { dx + sx * centera [ 1 ] , dy + sy * centera [ 2 ] , dx + sx * centerb [ 1 ] , dy + sy * centerb [ 2 ] }
1290 lpdf . linearshade ( name , domain , ca , cb , 1 , colorspace , coordinates , separation , steps > 1 and steps , fractions )
1291 elseif sh_type = = " circular " then
1292 local factor = tonumber ( prescript . sh_factor ) or 1
1293 local radiusa = factor * tonumber ( prescript . sh_radius_a )
1294 local radiusb = factor * tonumber ( prescript . sh_radius_b )
1295 local coordinates = { dx + sx * centera [ 1 ] , dy + sy * centera [ 2 ] , sr * radiusa , dx + sx * centerb [ 1 ] , dy + sy * centerb [ 2 ] , sr * radiusb }
1296 lpdf . circularshade ( name , domain , ca , cb , 1 , colorspace , coordinates , separation , steps > 1 and steps , fractions )
1297 else
1298
1299 end
1300 before [ # before + 1 ] = " q /Pattern cs "
1301 after [ # after + 1 ] = formatters [ " W n /%s sh Q " ] ( name )
1302
1303 object . colored = false
1304 object . type = false
1305 object . grouped = true
1306 end
1307end
1308
1309
1310
1311local function bm_process ( object , prescript , before , after )
1312 local bm_xresolution = prescript . bm_xresolution
1313 if bm_xresolution then
1314 before [ # before + 1 ] = f_cm_b ( cm ( object ) )
1315 before [ # before + 1 ] = function ( )
1316 figures . bitmapimage {
1317 xresolution = tonumber ( bm_xresolution ) ,
1318 yresolution = tonumber ( prescript . bm_yresolution ) ,
1319 width = 1 / basepoints ,
1320 height = 1 / basepoints ,
1321 data = object . postscript
1322 }
1323 end
1324 before [ # before + 1 ] = s_cm_e
1325 object . path = false
1326 object . color = false
1327 object . grouped = true
1328 end
1329end
1330
1331
1332
1333local function ps_process ( object , prescript , before , after )
1334 local ps_label = prescript . ps_label
1335 if ps_label then
1336 local op = object . path
1337 local first = op [ 1 ]
1338 local third = op [ 3 ]
1339 local x = first . x_coord
1340 local y = first . y_coord
1341 local w = third . x_coord - x
1342 local h = third . y_coord - y
1343 local properties = metapost . properties
1344 x = x - properties . llx
1345 y = properties . ury - y
1346 before [ # before + 1 ] = function ( )
1347 context . MPLIBpositionwhd ( ps_label , x , y , w , h )
1348 end
1349 object . path = false
1350 end
1351end
1352
1353
1354
1355
1356
1357
1358function mp . mf_external_figure ( filename )
1359 local f = figures . getinfo ( filename )
1360 local w = 0
1361 local h = 0
1362 if f then
1363 local u = f . used
1364 if u and u . fullname then
1365 w = u . width or 0
1366 h = u . height or 0
1367 end
1368 else
1369 report_metapost ( " external figure %a not found " , filename )
1370 end
1371 mp . triplet ( w / 65536 , h / 65536 , 0 )
1372end
1373
1374local function fg_process ( object , prescript , before , after )
1375 local fg_name = prescript . fg_name
1376 if fg_name then
1377 before [ # before + 1 ] = f_cm_b ( cm ( object ) )
1378 before [ # before + 1 ] = function ( )
1379 context . MPLIBfigure ( fg_name , prescript . fg_mask or " " )
1380 end
1381 before [ # before + 1 ] = s_cm_e
1382 object . path = false
1383 object . grouped = true
1384 end
1385end
1386
1387
1388
1389local value = Cs ( (
1390 ( Carg ( 1 ) * C ( ( 1 - P ( " , " ) ) ^ 1 ) ) / function ( a , b ) return f_f3 ( a * tonumber ( b ) ) end
1391 + P ( " , " ) ) ^ 1
1392)
1393
1394
1395
1396local t_list = attributes . list [ attributes . private ( ' transparency ' ) ]
1397local c_list = attributes . list [ attributes . private ( ' color ' ) ]
1398
1399local remappers = {
1400 [ 1 ] = formatters [ " s=%s " ] ,
1401 [ 3 ] = formatters [ " r=%s,g=%s,b=%s " ] ,
1402 [ 4 ] = formatters [ " c=%s,m=%s,y=%s,k=%s " ] ,
1403}
1404
1405local processlast = 0
1406local processhash = setmetatableindex ( function ( t , k )
1407 processlast = processlast + 1
1408 local v = formatters [ " mp_%s " ] ( processlast )
1409 defineprocesscolor ( v , k , true , true )
1410 t [ k ] = v
1411 return v
1412end )
1413
1414local function checked_transparency ( alternative , transparency , before , after )
1415 alternative = tonumber ( alternative ) or 1
1416 transparency = tonumber ( transparency ) or 0
1417 before [ # before + 1 ] = formatters [ " /Tr%s gs " ] ( registertransparency ( nil , alternative , transparency , true ) )
1418 after [ # after + 1 ] = " /Tr0 gs "
1419end
1420
1421local function tr_process ( object , prescript , before , after )
1422
1423 local tr_alternative = prescript . tr_alternative
1424 if tr_alternative then
1425 checked_transparency ( tr_alternative , prescript . tr_transparency , before , after )
1426 end
1427 local cs = object . color
1428 if cs and # cs > 0 then
1429 local c_b , c_a
1430 local sp_type = prescript . sp_type
1431 if not sp_type then
1432 c_b , c_a = colorconverter ( cs )
1433 else
1434 local sp_name = prescript . sp_name or " black "
1435 if sp_type = = " spot " then
1436 local sp_value = prescript . sp_value or " 1 "
1437 local components = split ( sp_value , " : " )
1438 local specification = remappers [ # components ]
1439 if specification then
1440 specification = specification ( unpack ( components ) )
1441 else
1442 specification = " s=0 "
1443 end
1444 local sp_spec = processhash [ specification ]
1445 definespotcolor ( sp_name , sp_spec , " p=1 " , true )
1446 sp_type = " named "
1447 elseif sp_type = = " multitone " then
1448 local sp_value = prescript . sp_value or " 1 "
1449 local sp_specs = { }
1450 local sp_list = split ( sp_value , " " )
1451 for i = 1 , # sp_list do
1452 local sp_value = sp_list [ i ]
1453 local components = split ( sp_value , " : " )
1454 local specification = remappers [ # components ]
1455 if specification then
1456 specification = specification ( unpack ( components ) )
1457 else
1458 specification = " s=0 "
1459 end
1460 local sp_spec = processhash [ specification ]
1461 sp_specs [ i ] = formatters [ " %s=1 " ] ( sp_spec )
1462 end
1463 sp_specs = concat ( sp_specs , " , " )
1464 definemultitonecolor ( sp_name , sp_specs , " " , " " )
1465 sp_type = " named "
1466 elseif sp_type = = " named " then
1467 cs = { 1 }
1468 end
1469 if sp_type = = " named " then
1470
1471
1472
1473 if not tr_alternative then
1474
1475 local t = t_list [ sp_name ]
1476 local v = t and transparencyvalue ( t )
1477 if v then
1478 checked_transparency ( v [ 1 ] , v [ 2 ] , before , after )
1479 end
1480 end
1481 local c = c_list [ sp_name ]
1482 local v = c and colorvalue ( c )
1483 if v then
1484
1485 local colorspace = v [ 1 ]
1486 local factor = cs [ 1 ]
1487 if colorspace = = 2 then
1488 local s = factor * v [ 2 ]
1489 c_b , c_a = checked_color_pair ( f_gray , s , s )
1490 elseif colorspace = = 3 then
1491 local r = factor * v [ 3 ]
1492 local g = factor * v [ 4 ]
1493 local b = factor * v [ 5 ]
1494 c_b , c_a = checked_color_pair ( f_rgb , r , g , b , r , g , b )
1495 elseif colorspace = = 4 or colorspace = = 1 then
1496 local c = factor * v [ 6 ]
1497 local m = factor * v [ 7 ]
1498 local y = factor * v [ 8 ]
1499 local k = factor * v [ 9 ]
1500 c_b , c_a = checked_color_pair ( f_cmyk , c , m , y , k , c , m , y , k )
1501 elseif colorspace = = 5 then
1502
1503 local name = v [ 10 ]
1504 local value = split ( v [ 13 ] , " , " )
1505 if factor ~ = 1 then
1506 for i = 1 , # value do
1507 value [ i ] = f_scn ( factor * ( tonumber ( value [ i ] ) or 1 ) )
1508 end
1509 end
1510 value = concat ( value , " " )
1511 c_b , c_a = checked_color_pair ( f_spot , name , name , value , value )
1512 else
1513 local s = factor * v [ 2 ]
1514 c_b , c_a = checked_color_pair ( f_gray , s , s )
1515 end
1516 end
1517 end
1518 end
1519 if c_a and c_b then
1520 before [ # before + 1 ] = c_b
1521 after [ # after + 1 ] = c_a
1522 end
1523 end
1524end
1525
1526
1527
1528local function la_process ( object , prescript , before , after )
1529 local la_name = prescript . la_name
1530 if la_name then
1531 before [ # before + 1 ] = backends . codeinjections . startlayer ( la_name )
1532 insert ( after , 1 , backends . codeinjections . stoplayer ( ) )
1533 end
1534end
1535
1536
1537
1538local function gr_process ( object , prescript , before , after )
1539 local gr_state = prescript . gr_state
1540 if not gr_state then
1541 return
1542 elseif gr_state = = " start " then
1543 local gr_type = utilities . parsers . settings_to_set ( prescript . gr_type )
1544 local path = object . path
1545 local p1 = path [ 1 ]
1546 local p2 = path [ 2 ]
1547 local p3 = path [ 3 ]
1548 local p4 = path [ 4 ]
1549 local llx = min ( p1 . x_coord , p2 . x_coord , p3 . x_coord , p4 . x_coord )
1550 local lly = min ( p1 . y_coord , p2 . y_coord , p3 . y_coord , p4 . y_coord )
1551 local urx = max ( p1 . x_coord , p2 . x_coord , p3 . x_coord , p4 . x_coord )
1552 local ury = max ( p1 . y_coord , p2 . y_coord , p3 . y_coord , p4 . y_coord )
1553 before [ # before + 1 ] = function ( )
1554 context . MPLIBstartgroup (
1555 gr_type . isolated and 1 or 0 ,
1556 gr_type . knockout and 1 or 0 ,
1557 llx , lly , urx , ury
1558 )
1559 end
1560 elseif gr_state = = " stop " then
1561 after [ # after + 1 ] = function ( )
1562 context . MPLIBstopgroup ( )
1563 end
1564 end
1565 object . path = false
1566 object . color = false
1567 object . grouped = true
1568end
1569
1570
1571
1572local ot_reset , ot_process do
1573
1574 local outlinetexts = { }
1575
1576 ot_reset = function ( )
1577 outlinetexts = { }
1578 end
1579
1580 local mp_index = 0
1581 local mp_kind = " "
1582 local mp_str = " "
1583
1584 function mp . mf_outline_text ( index , str , kind )
1585 if not outlinetexts [ index ] then
1586 mp_index = index
1587 mp_kind = kind
1588 mp_str = str
1589 texrunlocal ( " mpoutlinetoks " )
1590 end
1591 end
1592
1593 interfaces . implement {
1594 name = " mpoutlinetoks " ,
1595 actions = function ( )
1596 context . MPLIBoutlinetext ( mp_index , mp_kind , mp_str )
1597 end ,
1598 }
1599
1600 implement {
1601 name = " MPLIBconvertoutlinetext " ,
1602 arguments = { " integer " , " string " , " integer " } ,
1603 actions = function ( index , kind , box )
1604 local boxtomp = fonts . metapost . boxtomp
1605 if boxtomp then
1606 outlinetexts [ index ] = boxtomp ( box , kind )
1607 else
1608 outlinetexts [ index ] = " "
1609 end
1610 end
1611 }
1612
1613 function mp . mf_get_outline_text ( index )
1614 mp . print ( outlinetexts [ index ] or " draw origin; " )
1615 end
1616
1617end
1618
1619
1620
1621local p1 = P ( " mf_object= " )
1622local p2 = lpeg . patterns . eol * p1
1623local pattern = ( 1 - p2 ) ^ 0 * p2 + p1
1624
1625function metapost . isobject ( str )
1626 return pattern and str ~ = " " and lpegmatch ( p , str ) and true or false
1627end
1628
1629local function installplugin ( specification )
1630 local reset = specification . reset
1631 local process = specification . process
1632 local object = specification . object
1633 if reset then
1634 appendaction ( resetteractions , " system " , reset )
1635 end
1636 if process then
1637 appendaction ( processoractions , " system " , process )
1638 end
1639end
1640
1641metapost . installplugin = installplugin
1642
1643
1644
1645installplugin { name = " outline " , reset = ot_reset , process = ot_process }
1646installplugin { name = " color " , reset = cl_reset , process = cl_process }
1647installplugin { name = " text " , reset = tx_reset , process = tx_process }
1648installplugin { name = " group " , reset = gr_reset , process = gr_process }
1649installplugin { name = " graphictext " , reset = gt_reset , process = gt_process }
1650installplugin { name = " shade " , reset = sh_reset , process = sh_process }
1651installplugin { name = " bitmap " , reset = bm_reset , process = bm_process }
1652installplugin { name = " box " , reset = bx_reset , process = bx_process }
1653installplugin { name = " position " , reset = ps_reset , process = ps_process }
1654installplugin { name = " figure " , reset = fg_reset , process = fg_process }
1655installplugin { name = " layer " , reset = la_reset , process = la_process }
1656installplugin { name = " transparency " , reset = tr_reset , process = tr_process }
1657 |