Fossil SCM

Recompiled pikchr.js/wasm with latest emscripten. Fixed a left-shifted SVG truncation case. Ported example script selection from legacy pikchrshow into the new version.

stephan 2022-06-07 22:22 pikchrshow-wasm
Commit 6c07b28636dac56ab54b7b4c21bb467b96f3b81f0ed7947943c393d2179a13aa
+83 -80
--- extsrc/pikchr.js
+++ extsrc/pikchr.js
@@ -53,41 +53,41 @@
5353
scriptDirectory = scriptDirectory.substr(0, scriptDirectory.replace(/[?#].*/, "").lastIndexOf("/") + 1);
5454
} else {
5555
scriptDirectory = "";
5656
}
5757
{
58
- read_ = (url => {
58
+ read_ = url => {
5959
var xhr = new XMLHttpRequest();
6060
xhr.open("GET", url, false);
6161
xhr.send(null);
6262
return xhr.responseText;
63
- });
63
+ };
6464
if (ENVIRONMENT_IS_WORKER) {
65
- readBinary = (url => {
65
+ readBinary = url => {
6666
var xhr = new XMLHttpRequest();
6767
xhr.open("GET", url, false);
6868
xhr.responseType = "arraybuffer";
6969
xhr.send(null);
7070
return new Uint8Array(xhr.response);
71
- });
71
+ };
7272
}
73
- readAsync = ((url, onload, onerror) => {
73
+ readAsync = (url, onload, onerror) => {
7474
var xhr = new XMLHttpRequest();
7575
xhr.open("GET", url, true);
7676
xhr.responseType = "arraybuffer";
77
- xhr.onload = (() => {
77
+ xhr.onload = () => {
7878
if (xhr.status == 200 || xhr.status == 0 && xhr.response) {
7979
onload(xhr.response);
8080
return;
8181
}
8282
onerror();
83
- });
83
+ };
8484
xhr.onerror = onerror;
8585
xhr.send(null);
86
- });
86
+ };
8787
}
88
- setWindowTitle = (title => document.title = title);
88
+ setWindowTitle = title => document.title = title;
8989
} else {}
9090
9191
var out = Module["print"] || console.log.bind(console);
9292
9393
var err = Module["printErr"] || console.warn.bind(console);
@@ -110,76 +110,10 @@
110110
111111
if (typeof WebAssembly != "object") {
112112
abort("no native wasm support detected");
113113
}
114114
115
-function setValue(ptr, value, type = "i8", noSafe) {
116
- if (type.endsWith("*")) type = "i32";
117
- switch (type) {
118
- case "i1":
119
- HEAP8[ptr >> 0] = value;
120
- break;
121
-
122
- case "i8":
123
- HEAP8[ptr >> 0] = value;
124
- break;
125
-
126
- case "i16":
127
- HEAP16[ptr >> 1] = value;
128
- break;
129
-
130
- case "i32":
131
- HEAP32[ptr >> 2] = value;
132
- break;
133
-
134
- case "i64":
135
- tempI64 = [ value >>> 0, (tempDouble = value, +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? (Math.min(+Math.floor(tempDouble / 4294967296), 4294967295) | 0) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0) ],
136
- HEAP32[ptr >> 2] = tempI64[0], HEAP32[ptr + 4 >> 2] = tempI64[1];
137
- break;
138
-
139
- case "float":
140
- HEAPF32[ptr >> 2] = value;
141
- break;
142
-
143
- case "double":
144
- HEAPF64[ptr >> 3] = value;
145
- break;
146
-
147
- default:
148
- abort("invalid type for setValue: " + type);
149
- }
150
-}
151
-
152
-function getValue(ptr, type = "i8", noSafe) {
153
- if (type.endsWith("*")) type = "i32";
154
- switch (type) {
155
- case "i1":
156
- return HEAP8[ptr >> 0];
157
-
158
- case "i8":
159
- return HEAP8[ptr >> 0];
160
-
161
- case "i16":
162
- return HEAP16[ptr >> 1];
163
-
164
- case "i32":
165
- return HEAP32[ptr >> 2];
166
-
167
- case "i64":
168
- return HEAP32[ptr >> 2];
169
-
170
- case "float":
171
- return HEAPF32[ptr >> 2];
172
-
173
- case "double":
174
- return Number(HEAPF64[ptr >> 3]);
175
-
176
- default:
177
- abort("invalid type for getValue: " + type);
178
- }
179
-}
180
-
181115
var wasmMemory;
182116
183117
var ABORT = false;
184118
185119
var EXITSTATUS;
@@ -205,11 +139,13 @@
205139
writeArrayToMemory(arr, ret);
206140
return ret;
207141
}
208142
};
209143
function convertReturnValue(ret) {
210
- if (returnType === "string") return UTF8ToString(ret);
144
+ if (returnType === "string") {
145
+ return UTF8ToString(ret);
146
+ }
211147
if (returnType === "boolean") return Boolean(ret);
212148
return ret;
213149
}
214150
var func = getCFunc(ident);
215151
var cArgs = [];
@@ -572,14 +508,81 @@
572508
} else {
573509
func(callback.arg === undefined ? null : callback.arg);
574510
}
575511
}
576512
}
513
+
514
+function getValue(ptr, type = "i8") {
515
+ if (type.endsWith("*")) type = "i32";
516
+ switch (type) {
517
+ case "i1":
518
+ return HEAP8[ptr >> 0];
519
+
520
+ case "i8":
521
+ return HEAP8[ptr >> 0];
522
+
523
+ case "i16":
524
+ return HEAP16[ptr >> 1];
525
+
526
+ case "i32":
527
+ return HEAP32[ptr >> 2];
528
+
529
+ case "i64":
530
+ return HEAP32[ptr >> 2];
531
+
532
+ case "float":
533
+ return HEAPF32[ptr >> 2];
534
+
535
+ case "double":
536
+ return Number(HEAPF64[ptr >> 3]);
537
+
538
+ default:
539
+ abort("invalid type for getValue: " + type);
540
+ }
541
+ return null;
542
+}
577543
578544
function getWasmTableEntry(funcPtr) {
579545
return wasmTable.get(funcPtr);
580546
}
547
+
548
+function setValue(ptr, value, type = "i8") {
549
+ if (type.endsWith("*")) type = "i32";
550
+ switch (type) {
551
+ case "i1":
552
+ HEAP8[ptr >> 0] = value;
553
+ break;
554
+
555
+ case "i8":
556
+ HEAP8[ptr >> 0] = value;
557
+ break;
558
+
559
+ case "i16":
560
+ HEAP16[ptr >> 1] = value;
561
+ break;
562
+
563
+ case "i32":
564
+ HEAP32[ptr >> 2] = value;
565
+ break;
566
+
567
+ case "i64":
568
+ tempI64 = [ value >>> 0, (tempDouble = value, +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? (Math.min(+Math.floor(tempDouble / 4294967296), 4294967295) | 0) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0) ],
569
+ HEAP32[ptr >> 2] = tempI64[0], HEAP32[ptr + 4 >> 2] = tempI64[1];
570
+ break;
571
+
572
+ case "float":
573
+ HEAPF32[ptr >> 2] = value;
574
+ break;
575
+
576
+ case "double":
577
+ HEAPF64[ptr >> 3] = value;
578
+ break;
579
+
580
+ default:
581
+ abort("invalid type for setValue: " + type);
582
+ }
583
+}
581584
582585
function ___assert_fail(condition, filename, line, func) {
583586
abort("Assertion failed: " + UTF8ToString(condition) + ", at: " + [ filename ? UTF8ToString(filename) : "unknown filename", line, func ? UTF8ToString(func) : "unknown function" ]);
584587
}
585588
@@ -625,18 +628,18 @@
625628
return (stackAlloc = Module["stackAlloc"] = Module["asm"]["j"]).apply(null, arguments);
626629
};
627630
628631
Module["cwrap"] = cwrap;
629632
633
+Module["stackSave"] = stackSave;
634
+
635
+Module["stackRestore"] = stackRestore;
636
+
630637
Module["setValue"] = setValue;
631638
632639
Module["getValue"] = getValue;
633640
634
-Module["stackSave"] = stackSave;
635
-
636
-Module["stackRestore"] = stackRestore;
637
-
638641
var calledRun;
639642
640643
function ExitStatus(status) {
641644
this.name = "ExitStatus";
642645
this.message = "Program terminated with exit(" + status + ")";
643646
--- extsrc/pikchr.js
+++ extsrc/pikchr.js
@@ -53,41 +53,41 @@
53 scriptDirectory = scriptDirectory.substr(0, scriptDirectory.replace(/[?#].*/, "").lastIndexOf("/") + 1);
54 } else {
55 scriptDirectory = "";
56 }
57 {
58 read_ = (url => {
59 var xhr = new XMLHttpRequest();
60 xhr.open("GET", url, false);
61 xhr.send(null);
62 return xhr.responseText;
63 });
64 if (ENVIRONMENT_IS_WORKER) {
65 readBinary = (url => {
66 var xhr = new XMLHttpRequest();
67 xhr.open("GET", url, false);
68 xhr.responseType = "arraybuffer";
69 xhr.send(null);
70 return new Uint8Array(xhr.response);
71 });
72 }
73 readAsync = ((url, onload, onerror) => {
74 var xhr = new XMLHttpRequest();
75 xhr.open("GET", url, true);
76 xhr.responseType = "arraybuffer";
77 xhr.onload = (() => {
78 if (xhr.status == 200 || xhr.status == 0 && xhr.response) {
79 onload(xhr.response);
80 return;
81 }
82 onerror();
83 });
84 xhr.onerror = onerror;
85 xhr.send(null);
86 });
87 }
88 setWindowTitle = (title => document.title = title);
89 } else {}
90
91 var out = Module["print"] || console.log.bind(console);
92
93 var err = Module["printErr"] || console.warn.bind(console);
@@ -110,76 +110,10 @@
110
111 if (typeof WebAssembly != "object") {
112 abort("no native wasm support detected");
113 }
114
115 function setValue(ptr, value, type = "i8", noSafe) {
116 if (type.endsWith("*")) type = "i32";
117 switch (type) {
118 case "i1":
119 HEAP8[ptr >> 0] = value;
120 break;
121
122 case "i8":
123 HEAP8[ptr >> 0] = value;
124 break;
125
126 case "i16":
127 HEAP16[ptr >> 1] = value;
128 break;
129
130 case "i32":
131 HEAP32[ptr >> 2] = value;
132 break;
133
134 case "i64":
135 tempI64 = [ value >>> 0, (tempDouble = value, +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? (Math.min(+Math.floor(tempDouble / 4294967296), 4294967295) | 0) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0) ],
136 HEAP32[ptr >> 2] = tempI64[0], HEAP32[ptr + 4 >> 2] = tempI64[1];
137 break;
138
139 case "float":
140 HEAPF32[ptr >> 2] = value;
141 break;
142
143 case "double":
144 HEAPF64[ptr >> 3] = value;
145 break;
146
147 default:
148 abort("invalid type for setValue: " + type);
149 }
150 }
151
152 function getValue(ptr, type = "i8", noSafe) {
153 if (type.endsWith("*")) type = "i32";
154 switch (type) {
155 case "i1":
156 return HEAP8[ptr >> 0];
157
158 case "i8":
159 return HEAP8[ptr >> 0];
160
161 case "i16":
162 return HEAP16[ptr >> 1];
163
164 case "i32":
165 return HEAP32[ptr >> 2];
166
167 case "i64":
168 return HEAP32[ptr >> 2];
169
170 case "float":
171 return HEAPF32[ptr >> 2];
172
173 case "double":
174 return Number(HEAPF64[ptr >> 3]);
175
176 default:
177 abort("invalid type for getValue: " + type);
178 }
179 }
180
181 var wasmMemory;
182
183 var ABORT = false;
184
185 var EXITSTATUS;
@@ -205,11 +139,13 @@
205 writeArrayToMemory(arr, ret);
206 return ret;
207 }
208 };
209 function convertReturnValue(ret) {
210 if (returnType === "string") return UTF8ToString(ret);
 
 
211 if (returnType === "boolean") return Boolean(ret);
212 return ret;
213 }
214 var func = getCFunc(ident);
215 var cArgs = [];
@@ -572,14 +508,81 @@
572 } else {
573 func(callback.arg === undefined ? null : callback.arg);
574 }
575 }
576 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
577
578 function getWasmTableEntry(funcPtr) {
579 return wasmTable.get(funcPtr);
580 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
581
582 function ___assert_fail(condition, filename, line, func) {
583 abort("Assertion failed: " + UTF8ToString(condition) + ", at: " + [ filename ? UTF8ToString(filename) : "unknown filename", line, func ? UTF8ToString(func) : "unknown function" ]);
584 }
585
@@ -625,18 +628,18 @@
625 return (stackAlloc = Module["stackAlloc"] = Module["asm"]["j"]).apply(null, arguments);
626 };
627
628 Module["cwrap"] = cwrap;
629
 
 
 
 
630 Module["setValue"] = setValue;
631
632 Module["getValue"] = getValue;
633
634 Module["stackSave"] = stackSave;
635
636 Module["stackRestore"] = stackRestore;
637
638 var calledRun;
639
640 function ExitStatus(status) {
641 this.name = "ExitStatus";
642 this.message = "Program terminated with exit(" + status + ")";
643
--- extsrc/pikchr.js
+++ extsrc/pikchr.js
@@ -53,41 +53,41 @@
53 scriptDirectory = scriptDirectory.substr(0, scriptDirectory.replace(/[?#].*/, "").lastIndexOf("/") + 1);
54 } else {
55 scriptDirectory = "";
56 }
57 {
58 read_ = url => {
59 var xhr = new XMLHttpRequest();
60 xhr.open("GET", url, false);
61 xhr.send(null);
62 return xhr.responseText;
63 };
64 if (ENVIRONMENT_IS_WORKER) {
65 readBinary = url => {
66 var xhr = new XMLHttpRequest();
67 xhr.open("GET", url, false);
68 xhr.responseType = "arraybuffer";
69 xhr.send(null);
70 return new Uint8Array(xhr.response);
71 };
72 }
73 readAsync = (url, onload, onerror) => {
74 var xhr = new XMLHttpRequest();
75 xhr.open("GET", url, true);
76 xhr.responseType = "arraybuffer";
77 xhr.onload = () => {
78 if (xhr.status == 200 || xhr.status == 0 && xhr.response) {
79 onload(xhr.response);
80 return;
81 }
82 onerror();
83 };
84 xhr.onerror = onerror;
85 xhr.send(null);
86 };
87 }
88 setWindowTitle = title => document.title = title;
89 } else {}
90
91 var out = Module["print"] || console.log.bind(console);
92
93 var err = Module["printErr"] || console.warn.bind(console);
@@ -110,76 +110,10 @@
110
111 if (typeof WebAssembly != "object") {
112 abort("no native wasm support detected");
113 }
114
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115 var wasmMemory;
116
117 var ABORT = false;
118
119 var EXITSTATUS;
@@ -205,11 +139,13 @@
139 writeArrayToMemory(arr, ret);
140 return ret;
141 }
142 };
143 function convertReturnValue(ret) {
144 if (returnType === "string") {
145 return UTF8ToString(ret);
146 }
147 if (returnType === "boolean") return Boolean(ret);
148 return ret;
149 }
150 var func = getCFunc(ident);
151 var cArgs = [];
@@ -572,14 +508,81 @@
508 } else {
509 func(callback.arg === undefined ? null : callback.arg);
510 }
511 }
512 }
513
514 function getValue(ptr, type = "i8") {
515 if (type.endsWith("*")) type = "i32";
516 switch (type) {
517 case "i1":
518 return HEAP8[ptr >> 0];
519
520 case "i8":
521 return HEAP8[ptr >> 0];
522
523 case "i16":
524 return HEAP16[ptr >> 1];
525
526 case "i32":
527 return HEAP32[ptr >> 2];
528
529 case "i64":
530 return HEAP32[ptr >> 2];
531
532 case "float":
533 return HEAPF32[ptr >> 2];
534
535 case "double":
536 return Number(HEAPF64[ptr >> 3]);
537
538 default:
539 abort("invalid type for getValue: " + type);
540 }
541 return null;
542 }
543
544 function getWasmTableEntry(funcPtr) {
545 return wasmTable.get(funcPtr);
546 }
547
548 function setValue(ptr, value, type = "i8") {
549 if (type.endsWith("*")) type = "i32";
550 switch (type) {
551 case "i1":
552 HEAP8[ptr >> 0] = value;
553 break;
554
555 case "i8":
556 HEAP8[ptr >> 0] = value;
557 break;
558
559 case "i16":
560 HEAP16[ptr >> 1] = value;
561 break;
562
563 case "i32":
564 HEAP32[ptr >> 2] = value;
565 break;
566
567 case "i64":
568 tempI64 = [ value >>> 0, (tempDouble = value, +Math.abs(tempDouble) >= 1 ? tempDouble > 0 ? (Math.min(+Math.floor(tempDouble / 4294967296), 4294967295) | 0) >>> 0 : ~~+Math.ceil((tempDouble - +(~~tempDouble >>> 0)) / 4294967296) >>> 0 : 0) ],
569 HEAP32[ptr >> 2] = tempI64[0], HEAP32[ptr + 4 >> 2] = tempI64[1];
570 break;
571
572 case "float":
573 HEAPF32[ptr >> 2] = value;
574 break;
575
576 case "double":
577 HEAPF64[ptr >> 3] = value;
578 break;
579
580 default:
581 abort("invalid type for setValue: " + type);
582 }
583 }
584
585 function ___assert_fail(condition, filename, line, func) {
586 abort("Assertion failed: " + UTF8ToString(condition) + ", at: " + [ filename ? UTF8ToString(filename) : "unknown filename", line, func ? UTF8ToString(func) : "unknown function" ]);
587 }
588
@@ -625,18 +628,18 @@
628 return (stackAlloc = Module["stackAlloc"] = Module["asm"]["j"]).apply(null, arguments);
629 };
630
631 Module["cwrap"] = cwrap;
632
633 Module["stackSave"] = stackSave;
634
635 Module["stackRestore"] = stackRestore;
636
637 Module["setValue"] = setValue;
638
639 Module["getValue"] = getValue;
640
 
 
 
 
641 var calledRun;
642
643 function ExitStatus(status) {
644 this.name = "ExitStatus";
645 this.message = "Program terminated with exit(" + status + ")";
646
--- extsrc/pikchr.wasm
+++ extsrc/pikchr.wasm
cannot compute difference between binary files
11
--- extsrc/pikchr.wasm
+++ extsrc/pikchr.wasm
0 annot compute difference between binary files
1
--- extsrc/pikchr.wasm
+++ extsrc/pikchr.wasm
0 annot compute difference between binary files
1
--- src/fossil.page.pikchrshowasm.js
+++ src/fossil.page.pikchrshowasm.js
@@ -56,10 +56,11 @@
5656
},
5757
/* Various DOM elements. */
5858
e: {
5959
previewCopyButton: E('#preview-copy-button'),
6060
previewModeLabel: E('label[for=preview-copy-button]'),
61
+ zoneInputButtons: E('.zone-wrapper.input > legend > .button-bar'),
6162
zoneOutputButtons: E('.zone-wrapper.output > legend > .button-bar'),
6263
outText: E('#pikchr-output-text'),
6364
pikOutWrapper: E('#pikchr-output-wrapper'),
6465
pikOut: E('#pikchr-output'),
6566
btnRender: E('#btn-render')
@@ -202,10 +203,14 @@
202203
return text;;
203204
};
204205
const renderCurrentText = function(){
205206
const text = getCurrentText();
206207
if(text) PS.render(text);
208
+ };
209
+ const setCurrentText = function(txt){
210
+ taInput.value = txt;
211
+ renderCurrentText();
207212
};
208213
PS.e.btnRender.addEventListener('click',function(ev){
209214
ev.preventDefault();
210215
renderCurrentText();
211216
},false);
@@ -334,11 +339,13 @@
334339
break;
335340
default: throw new Error("Unhandled render mode: "+mode);
336341
}
337342
let vw = null, vh = null;
338343
if('svg'===mode && !this.config.renderAutofit && !m.isError){
339
- vw = m.width; vh = m.height;
344
+ vw = m.width+1; vh = m.height+1;
345
+ /* +1 is b/c the SVG uses floating point sizes but pikchr() returns
346
+ truncated integers. */
340347
}
341348
this.e.pikOut.style.width = vw && vw+'px';
342349
this.e.pikOut.style.height = vh && vh+'px';
343350
}.bind(PS))/*'pikchr' msg handler*/;
344351
@@ -408,10 +415,36 @@
408415
const cmdClick = function(){PS.render(this.dataset.cmd);};
409416
EAll('button[data-cmd]').forEach(
410417
e => e.addEventListener('click', cmdClick, false)
411418
);
412419
420
+
421
+ ////////////////////////////////////////////////////////////
422
+ // Set up selection list of predefined scripts...
423
+ if(true){
424
+ const selectScript = PS.e.selectScript = D.select(),
425
+ cbWrap = D.addClass(D.span(),'labeled-input');
426
+ D.append(PS.e.zoneInputButtons, D.append(cbWrap, selectScript));
427
+ PS.predefinedPiks.forEach(function(script,ndx){
428
+ const opt = D.option(script.code ? script.code.trim() :'', script.name);
429
+ D.append(selectScript, opt);
430
+ if(!ndx) selectScript.selectedIndex = 0 /*timing/ordering workaround*/;
431
+ if(ndx && !script.code){
432
+ /* Treat entries w/ no code as separators EXCEPT for the
433
+ first one, which we want to keep selectable solely for
434
+ cosmetic reasons. */
435
+ D.disable(opt);
436
+ }
437
+ });
438
+ delete PS.predefinedPiks;
439
+ selectScript.addEventListener('change', function(ev){
440
+ const val = ev.target.value;
441
+ if(!val) return;
442
+ setCurrentText(val);
443
+ }, false);
444
+ }/*Examples*/
445
+
413446
/**
414447
TODO: Handle load/import of an external pikchr file.
415448
*/
416449
if(0) E('#load-pikchr').addEventListener('change',function(){
417450
const f = this.files[0];
@@ -526,6 +559,178 @@
526559
})()/*ForceResizeKludge*/;
527560
528561
delete ForceResizeKludge.$disabled;
529562
ForceResizeKludge();
530563
}/*onPikchrshowLoaded()*/;
564
+
565
+
566
+ /**
567
+ Predefined scripts. Each entry is an object:
568
+
569
+ {
570
+ name: required string,
571
+ code: optional code string. An entry with a falsy code is treated
572
+ like a separator in the resulting SELECT element (a
573
+ disabled OPTION).
574
+ }
575
+ */
576
+ PS.predefinedPiks = [
577
+ {name: "-- Example Scripts --", code: false},
578
+/*
579
+ The following were imported from the pikchr test scripts:
580
+
581
+ https://fossil-scm.org/pikchr/dir/examples
582
+*/
583
+{name:"Cardinal headings",code:` linerad = 5px
584
+C: circle "Center" rad 150%
585
+ circle "N" at 1.0 n of C; arrow from C to last chop ->
586
+ circle "NE" at 1.0 ne of C; arrow from C to last chop <-
587
+ circle "E" at 1.0 e of C; arrow from C to last chop <->
588
+ circle "SE" at 1.0 se of C; arrow from C to last chop ->
589
+ circle "S" at 1.0 s of C; arrow from C to last chop <-
590
+ circle "SW" at 1.0 sw of C; arrow from C to last chop <->
591
+ circle "W" at 1.0 w of C; arrow from C to last chop ->
592
+ circle "NW" at 1.0 nw of C; arrow from C to last chop <-
593
+ arrow from 2nd circle to 3rd circle chop
594
+ arrow from 4th circle to 3rd circle chop
595
+ arrow from SW to S chop <->
596
+ circle "ESE" at 2.0 heading 112.5 from Center \
597
+ thickness 150% fill lightblue radius 75%
598
+ arrow from Center to ESE thickness 150% <-> chop
599
+ arrow from ESE up 1.35 then to NE chop
600
+ line dashed <- from E.e to (ESE.x,E.y)
601
+ line dotted <-> thickness 50% from N to NW chop
602
+`},{name:"Core object types",code:`AllObjects: [
603
+
604
+# First row of objects
605
+box "box"
606
+box rad 10px "box (with" "rounded" "corners)" at 1in right of previous
607
+circle "circle" at 1in right of previous
608
+ellipse "ellipse" at 1in right of previous
609
+
610
+# second row of objects
611
+OVAL1: oval "oval" at 1in below first box
612
+oval "(tall &" "thin)" "oval" width OVAL1.height height OVAL1.width \
613
+ at 1in right of previous
614
+cylinder "cylinder" at 1in right of previous
615
+file "file" at 1in right of previous
616
+
617
+# third row shows line-type objects
618
+dot "dot" above at 1in below first oval
619
+line right from 1.8cm right of previous "lines" above
620
+arrow right from 1.8cm right of previous "arrows" above
621
+spline from 1.8cm right of previous \
622
+ go right .15 then .3 heading 30 then .5 heading 160 then .4 heading 20 \
623
+ then right .15
624
+"splines" at 3rd vertex of previous
625
+
626
+# The third vertex of the spline is not actually on the drawn
627
+# curve. The third vertex is a control point. To see its actual
628
+# position, uncomment the following line:
629
+#dot color red at 3rd vertex of previous spline
630
+
631
+# Draw various lines below the first line
632
+line dashed right from 0.3cm below start of previous line
633
+line dotted right from 0.3cm below start of previous
634
+line thin right from 0.3cm below start of previous
635
+line thick right from 0.3cm below start of previous
636
+
637
+
638
+# Draw arrows with different arrowhead configurations below
639
+# the first arrow
640
+arrow <- right from 0.4cm below start of previous arrow
641
+arrow <-> right from 0.4cm below start of previous
642
+
643
+# Draw splines with different arrowhead configurations below
644
+# the first spline
645
+spline same from .4cm below start of first spline ->
646
+spline same from .4cm below start of previous <-
647
+spline same from .4cm below start of previous <->
648
+
649
+] # end of AllObjects
650
+
651
+# Label the whole diagram
652
+text "Examples Of Pikchr Objects" big bold at .8cm above north of AllObjects
653
+`},{name:"Swimlanes",code:` $laneh = 0.75
654
+
655
+ # Draw the lanes
656
+ down
657
+ box width 3.5in height $laneh fill 0xacc9e3
658
+ box same fill 0xc5d8ef
659
+ box same as first box
660
+ box same as 2nd box
661
+ line from 1st box.sw+(0.2,0) up until even with 1st box.n \
662
+ "Alan" above aligned
663
+ line from 2nd box.sw+(0.2,0) up until even with 2nd box.n \
664
+ "Betty" above aligned
665
+ line from 3rd box.sw+(0.2,0) up until even with 3rd box.n \
666
+ "Charlie" above aligned
667
+ line from 4th box.sw+(0.2,0) up until even with 4th box.n \
668
+ "Darlene" above aligned
669
+
670
+ # fill in content for the Alice lane
671
+ right
672
+A1: circle rad 0.1in at end of first line + (0.2,-0.2) \
673
+ fill white thickness 1.5px "1"
674
+ arrow right 50%
675
+ circle same "2"
676
+ arrow right until even with first box.e - (0.65,0.0)
677
+ ellipse "future" fit fill white height 0.2 width 0.5 thickness 1.5px
678
+A3: circle same at A1+(0.8,-0.3) "3" fill 0xc0c0c0
679
+ arrow from A1 to last circle chop "fork!" below aligned
680
+
681
+ # content for the Betty lane
682
+B1: circle same as A1 at A1-(0,$laneh) "1"
683
+ arrow right 50%
684
+ circle same "2"
685
+ arrow right until even with first ellipse.w
686
+ ellipse same "future"
687
+B3: circle same at A3-(0,$laneh) "3"
688
+ arrow right 50%
689
+ circle same as A3 "4"
690
+ arrow from B1 to 2nd last circle chop
691
+
692
+ # content for the Charlie lane
693
+C1: circle same as A1 at B1-(0,$laneh) "1"
694
+ arrow 50%
695
+ circle same "2"
696
+ arrow right 0.8in "goes" "offline"
697
+C5: circle same as A3 "5"
698
+ arrow right until even with first ellipse.w \
699
+ "back online" above "pushes 5" below "pulls 3 & 4" below
700
+ ellipse same "future"
701
+
702
+ # content for the Darlene lane
703
+D1: circle same as A1 at C1-(0,$laneh) "1"
704
+ arrow 50%
705
+ circle same "2"
706
+ arrow right until even with C5.w
707
+ circle same "5"
708
+ arrow 50%
709
+ circle same as A3 "6"
710
+ arrow right until even with first ellipse.w
711
+ ellipse same "future"
712
+D3: circle same as B3 at B3-(0,2*$laneh) "3"
713
+ arrow 50%
714
+ circle same "4"
715
+ arrow from D1 to D3 chop
716
+`},{
717
+ name: "The Stuff of Dreams",
718
+ code:`
719
+O: text "DREAMS" color grey
720
+circle rad 0.9 at 0.6 above O thick color red
721
+text "INEXPENSIVE" big bold at 0.9 above O color red
722
+
723
+circle rad 0.9 at 0.6 heading 120 from O thick color green
724
+text "FAST" big bold at 0.9 heading 120 from O color green
725
+
726
+circle rad 0.9 at 0.6 heading -120 from O thick color blue
727
+text "HIGH" big bold "QUALITY" big bold at 0.9 heading -120 from O color blue
728
+
729
+text "EXPENSIVE" at 0.55 below O color cyan
730
+text "SLOW" at 0.55 heading -60 from O color magenta
731
+text "POOR" "QUALITY" at 0.55 heading 60 from O color gold
732
+`}
733
+ ];
734
+
735
+
531736
})(window.fossil);
532737
--- src/fossil.page.pikchrshowasm.js
+++ src/fossil.page.pikchrshowasm.js
@@ -56,10 +56,11 @@
56 },
57 /* Various DOM elements. */
58 e: {
59 previewCopyButton: E('#preview-copy-button'),
60 previewModeLabel: E('label[for=preview-copy-button]'),
 
61 zoneOutputButtons: E('.zone-wrapper.output > legend > .button-bar'),
62 outText: E('#pikchr-output-text'),
63 pikOutWrapper: E('#pikchr-output-wrapper'),
64 pikOut: E('#pikchr-output'),
65 btnRender: E('#btn-render')
@@ -202,10 +203,14 @@
202 return text;;
203 };
204 const renderCurrentText = function(){
205 const text = getCurrentText();
206 if(text) PS.render(text);
 
 
 
 
207 };
208 PS.e.btnRender.addEventListener('click',function(ev){
209 ev.preventDefault();
210 renderCurrentText();
211 },false);
@@ -334,11 +339,13 @@
334 break;
335 default: throw new Error("Unhandled render mode: "+mode);
336 }
337 let vw = null, vh = null;
338 if('svg'===mode && !this.config.renderAutofit && !m.isError){
339 vw = m.width; vh = m.height;
 
 
340 }
341 this.e.pikOut.style.width = vw && vw+'px';
342 this.e.pikOut.style.height = vh && vh+'px';
343 }.bind(PS))/*'pikchr' msg handler*/;
344
@@ -408,10 +415,36 @@
408 const cmdClick = function(){PS.render(this.dataset.cmd);};
409 EAll('button[data-cmd]').forEach(
410 e => e.addEventListener('click', cmdClick, false)
411 );
412
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
413 /**
414 TODO: Handle load/import of an external pikchr file.
415 */
416 if(0) E('#load-pikchr').addEventListener('change',function(){
417 const f = this.files[0];
@@ -526,6 +559,178 @@
526 })()/*ForceResizeKludge*/;
527
528 delete ForceResizeKludge.$disabled;
529 ForceResizeKludge();
530 }/*onPikchrshowLoaded()*/;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
531 })(window.fossil);
532
--- src/fossil.page.pikchrshowasm.js
+++ src/fossil.page.pikchrshowasm.js
@@ -56,10 +56,11 @@
56 },
57 /* Various DOM elements. */
58 e: {
59 previewCopyButton: E('#preview-copy-button'),
60 previewModeLabel: E('label[for=preview-copy-button]'),
61 zoneInputButtons: E('.zone-wrapper.input > legend > .button-bar'),
62 zoneOutputButtons: E('.zone-wrapper.output > legend > .button-bar'),
63 outText: E('#pikchr-output-text'),
64 pikOutWrapper: E('#pikchr-output-wrapper'),
65 pikOut: E('#pikchr-output'),
66 btnRender: E('#btn-render')
@@ -202,10 +203,14 @@
203 return text;;
204 };
205 const renderCurrentText = function(){
206 const text = getCurrentText();
207 if(text) PS.render(text);
208 };
209 const setCurrentText = function(txt){
210 taInput.value = txt;
211 renderCurrentText();
212 };
213 PS.e.btnRender.addEventListener('click',function(ev){
214 ev.preventDefault();
215 renderCurrentText();
216 },false);
@@ -334,11 +339,13 @@
339 break;
340 default: throw new Error("Unhandled render mode: "+mode);
341 }
342 let vw = null, vh = null;
343 if('svg'===mode && !this.config.renderAutofit && !m.isError){
344 vw = m.width+1; vh = m.height+1;
345 /* +1 is b/c the SVG uses floating point sizes but pikchr() returns
346 truncated integers. */
347 }
348 this.e.pikOut.style.width = vw && vw+'px';
349 this.e.pikOut.style.height = vh && vh+'px';
350 }.bind(PS))/*'pikchr' msg handler*/;
351
@@ -408,10 +415,36 @@
415 const cmdClick = function(){PS.render(this.dataset.cmd);};
416 EAll('button[data-cmd]').forEach(
417 e => e.addEventListener('click', cmdClick, false)
418 );
419
420
421 ////////////////////////////////////////////////////////////
422 // Set up selection list of predefined scripts...
423 if(true){
424 const selectScript = PS.e.selectScript = D.select(),
425 cbWrap = D.addClass(D.span(),'labeled-input');
426 D.append(PS.e.zoneInputButtons, D.append(cbWrap, selectScript));
427 PS.predefinedPiks.forEach(function(script,ndx){
428 const opt = D.option(script.code ? script.code.trim() :'', script.name);
429 D.append(selectScript, opt);
430 if(!ndx) selectScript.selectedIndex = 0 /*timing/ordering workaround*/;
431 if(ndx && !script.code){
432 /* Treat entries w/ no code as separators EXCEPT for the
433 first one, which we want to keep selectable solely for
434 cosmetic reasons. */
435 D.disable(opt);
436 }
437 });
438 delete PS.predefinedPiks;
439 selectScript.addEventListener('change', function(ev){
440 const val = ev.target.value;
441 if(!val) return;
442 setCurrentText(val);
443 }, false);
444 }/*Examples*/
445
446 /**
447 TODO: Handle load/import of an external pikchr file.
448 */
449 if(0) E('#load-pikchr').addEventListener('change',function(){
450 const f = this.files[0];
@@ -526,6 +559,178 @@
559 })()/*ForceResizeKludge*/;
560
561 delete ForceResizeKludge.$disabled;
562 ForceResizeKludge();
563 }/*onPikchrshowLoaded()*/;
564
565
566 /**
567 Predefined scripts. Each entry is an object:
568
569 {
570 name: required string,
571 code: optional code string. An entry with a falsy code is treated
572 like a separator in the resulting SELECT element (a
573 disabled OPTION).
574 }
575 */
576 PS.predefinedPiks = [
577 {name: "-- Example Scripts --", code: false},
578 /*
579 The following were imported from the pikchr test scripts:
580
581 https://fossil-scm.org/pikchr/dir/examples
582 */
583 {name:"Cardinal headings",code:` linerad = 5px
584 C: circle "Center" rad 150%
585 circle "N" at 1.0 n of C; arrow from C to last chop ->
586 circle "NE" at 1.0 ne of C; arrow from C to last chop <-
587 circle "E" at 1.0 e of C; arrow from C to last chop <->
588 circle "SE" at 1.0 se of C; arrow from C to last chop ->
589 circle "S" at 1.0 s of C; arrow from C to last chop <-
590 circle "SW" at 1.0 sw of C; arrow from C to last chop <->
591 circle "W" at 1.0 w of C; arrow from C to last chop ->
592 circle "NW" at 1.0 nw of C; arrow from C to last chop <-
593 arrow from 2nd circle to 3rd circle chop
594 arrow from 4th circle to 3rd circle chop
595 arrow from SW to S chop <->
596 circle "ESE" at 2.0 heading 112.5 from Center \
597 thickness 150% fill lightblue radius 75%
598 arrow from Center to ESE thickness 150% <-> chop
599 arrow from ESE up 1.35 then to NE chop
600 line dashed <- from E.e to (ESE.x,E.y)
601 line dotted <-> thickness 50% from N to NW chop
602 `},{name:"Core object types",code:`AllObjects: [
603
604 # First row of objects
605 box "box"
606 box rad 10px "box (with" "rounded" "corners)" at 1in right of previous
607 circle "circle" at 1in right of previous
608 ellipse "ellipse" at 1in right of previous
609
610 # second row of objects
611 OVAL1: oval "oval" at 1in below first box
612 oval "(tall &" "thin)" "oval" width OVAL1.height height OVAL1.width \
613 at 1in right of previous
614 cylinder "cylinder" at 1in right of previous
615 file "file" at 1in right of previous
616
617 # third row shows line-type objects
618 dot "dot" above at 1in below first oval
619 line right from 1.8cm right of previous "lines" above
620 arrow right from 1.8cm right of previous "arrows" above
621 spline from 1.8cm right of previous \
622 go right .15 then .3 heading 30 then .5 heading 160 then .4 heading 20 \
623 then right .15
624 "splines" at 3rd vertex of previous
625
626 # The third vertex of the spline is not actually on the drawn
627 # curve. The third vertex is a control point. To see its actual
628 # position, uncomment the following line:
629 #dot color red at 3rd vertex of previous spline
630
631 # Draw various lines below the first line
632 line dashed right from 0.3cm below start of previous line
633 line dotted right from 0.3cm below start of previous
634 line thin right from 0.3cm below start of previous
635 line thick right from 0.3cm below start of previous
636
637
638 # Draw arrows with different arrowhead configurations below
639 # the first arrow
640 arrow <- right from 0.4cm below start of previous arrow
641 arrow <-> right from 0.4cm below start of previous
642
643 # Draw splines with different arrowhead configurations below
644 # the first spline
645 spline same from .4cm below start of first spline ->
646 spline same from .4cm below start of previous <-
647 spline same from .4cm below start of previous <->
648
649 ] # end of AllObjects
650
651 # Label the whole diagram
652 text "Examples Of Pikchr Objects" big bold at .8cm above north of AllObjects
653 `},{name:"Swimlanes",code:` $laneh = 0.75
654
655 # Draw the lanes
656 down
657 box width 3.5in height $laneh fill 0xacc9e3
658 box same fill 0xc5d8ef
659 box same as first box
660 box same as 2nd box
661 line from 1st box.sw+(0.2,0) up until even with 1st box.n \
662 "Alan" above aligned
663 line from 2nd box.sw+(0.2,0) up until even with 2nd box.n \
664 "Betty" above aligned
665 line from 3rd box.sw+(0.2,0) up until even with 3rd box.n \
666 "Charlie" above aligned
667 line from 4th box.sw+(0.2,0) up until even with 4th box.n \
668 "Darlene" above aligned
669
670 # fill in content for the Alice lane
671 right
672 A1: circle rad 0.1in at end of first line + (0.2,-0.2) \
673 fill white thickness 1.5px "1"
674 arrow right 50%
675 circle same "2"
676 arrow right until even with first box.e - (0.65,0.0)
677 ellipse "future" fit fill white height 0.2 width 0.5 thickness 1.5px
678 A3: circle same at A1+(0.8,-0.3) "3" fill 0xc0c0c0
679 arrow from A1 to last circle chop "fork!" below aligned
680
681 # content for the Betty lane
682 B1: circle same as A1 at A1-(0,$laneh) "1"
683 arrow right 50%
684 circle same "2"
685 arrow right until even with first ellipse.w
686 ellipse same "future"
687 B3: circle same at A3-(0,$laneh) "3"
688 arrow right 50%
689 circle same as A3 "4"
690 arrow from B1 to 2nd last circle chop
691
692 # content for the Charlie lane
693 C1: circle same as A1 at B1-(0,$laneh) "1"
694 arrow 50%
695 circle same "2"
696 arrow right 0.8in "goes" "offline"
697 C5: circle same as A3 "5"
698 arrow right until even with first ellipse.w \
699 "back online" above "pushes 5" below "pulls 3 & 4" below
700 ellipse same "future"
701
702 # content for the Darlene lane
703 D1: circle same as A1 at C1-(0,$laneh) "1"
704 arrow 50%
705 circle same "2"
706 arrow right until even with C5.w
707 circle same "5"
708 arrow 50%
709 circle same as A3 "6"
710 arrow right until even with first ellipse.w
711 ellipse same "future"
712 D3: circle same as B3 at B3-(0,2*$laneh) "3"
713 arrow 50%
714 circle same "4"
715 arrow from D1 to D3 chop
716 `},{
717 name: "The Stuff of Dreams",
718 code:`
719 O: text "DREAMS" color grey
720 circle rad 0.9 at 0.6 above O thick color red
721 text "INEXPENSIVE" big bold at 0.9 above O color red
722
723 circle rad 0.9 at 0.6 heading 120 from O thick color green
724 text "FAST" big bold at 0.9 heading 120 from O color green
725
726 circle rad 0.9 at 0.6 heading -120 from O thick color blue
727 text "HIGH" big bold "QUALITY" big bold at 0.9 heading -120 from O color blue
728
729 text "EXPENSIVE" at 0.55 below O color cyan
730 text "SLOW" at 0.55 heading -60 from O color magenta
731 text "POOR" "QUALITY" at 0.55 heading 60 from O color gold
732 `}
733 ];
734
735
736 })(window.fossil);
737
--- src/style.pikchrshow.css
+++ src/style.pikchrshow.css
@@ -86,11 +86,11 @@
8686
render-while-typing mode is on. */
8787
/*max-width: 50%;*/
8888
}
8989
#pikchr-output {
9090
padding: 0;
91
- margin: 0;
91
+ margin: 0 auto/*auto resolves a weird left-shift truncation of the SVG*/;
9292
}
9393
#pikchr-output-wrapper {
9494
flex: 1 1 auto;
9595
overflow: auto;
9696
}
9797
--- src/style.pikchrshow.css
+++ src/style.pikchrshow.css
@@ -86,11 +86,11 @@
86 render-while-typing mode is on. */
87 /*max-width: 50%;*/
88 }
89 #pikchr-output {
90 padding: 0;
91 margin: 0;
92 }
93 #pikchr-output-wrapper {
94 flex: 1 1 auto;
95 overflow: auto;
96 }
97
--- src/style.pikchrshow.css
+++ src/style.pikchrshow.css
@@ -86,11 +86,11 @@
86 render-while-typing mode is on. */
87 /*max-width: 50%;*/
88 }
89 #pikchr-output {
90 padding: 0;
91 margin: 0 auto/*auto resolves a weird left-shift truncation of the SVG*/;
92 }
93 #pikchr-output-wrapper {
94 flex: 1 1 auto;
95 overflow: auto;
96 }
97

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button