<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="zh-Hans-CN">
	<id>https://shanghaidc1.gaoice.run/index.php?action=history&amp;feed=atom&amp;title=MediaWiki%3APD-intro-engine.js</id>
	<title>MediaWiki:PD-intro-engine.js - 版本历史</title>
	<link rel="self" type="application/atom+xml" href="https://shanghaidc1.gaoice.run/index.php?action=history&amp;feed=atom&amp;title=MediaWiki%3APD-intro-engine.js"/>
	<link rel="alternate" type="text/html" href="https://shanghaidc1.gaoice.run/index.php?title=MediaWiki:PD-intro-engine.js&amp;action=history"/>
	<updated>2026-11-01T01:30:53Z</updated>
	<subtitle>本wiki上该页面的版本历史</subtitle>
	<generator>MediaWiki 1.46.2</generator>
	<entry>
		<id>https://shanghaidc1.gaoice.run/index.php?title=MediaWiki:PD-intro-engine.js&amp;diff=58087&amp;oldid=prev</id>
		<title>Gaoice：​创建页面，内容为“/* Project Divide — deterministic geometry, time in seconds. No DOM dependencies. */ (function (root, factory) {     // ResourceLoader also supplies `module`; in a browser publish on window.     if (typeof window !== &#039;undefined&#039;) { root.PDIntroEngine = factory(); }     else if (typeof module === &#039;object&#039; &amp;&amp; module.exports) { module.exports = factory(); } }(typeof window !== &#039;undefined&#039; ? window : this, function () {     &#039;use strict&#039;;     var TITLE = &#039;PROJECT…”</title>
		<link rel="alternate" type="text/html" href="https://shanghaidc1.gaoice.run/index.php?title=MediaWiki:PD-intro-engine.js&amp;diff=58087&amp;oldid=prev"/>
		<updated>2026-10-08T15:08:51Z</updated>

		<summary type="html">&lt;p&gt;创建页面，内容为“&lt;span class=&quot;autocomment&quot;&gt;Project Divide — deterministic geometry, time in seconds. No DOM dependencies.：​&lt;/span&gt; (function (root, factory) {     // ResourceLoader also supplies `module`; in a browser publish on window.     if (typeof window !== &amp;#039;undefined&amp;#039;) { root.PDIntroEngine = factory(); }     else if (typeof module === &amp;#039;object&amp;#039; &amp;amp;&amp;amp; module.exports) { module.exports = factory(); } }(typeof window !== &amp;#039;undefined&amp;#039; ? window : this, function () {     &amp;#039;use strict&amp;#039;;     var TITLE = &amp;#039;PROJECT…”&lt;/p&gt;
&lt;p&gt;&lt;b&gt;新页面&lt;/b&gt;&lt;/p&gt;&lt;div&gt;/* Project Divide — deterministic geometry, time in seconds. No DOM dependencies. */&lt;br /&gt;
(function (root, factory) {&lt;br /&gt;
    // ResourceLoader also supplies `module`; in a browser publish on window.&lt;br /&gt;
    if (typeof window !== &amp;#039;undefined&amp;#039;) { root.PDIntroEngine = factory(); }&lt;br /&gt;
    else if (typeof module === &amp;#039;object&amp;#039; &amp;amp;&amp;amp; module.exports) { module.exports = factory(); }&lt;br /&gt;
}(typeof window !== &amp;#039;undefined&amp;#039; ? window : this, function () {&lt;br /&gt;
    &amp;#039;use strict&amp;#039;;&lt;br /&gt;
    var TITLE = &amp;#039;PROJECT DIVIDE&amp;#039;, CHARS = &amp;#039;ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+-/=&amp;lt;&amp;gt;[]&amp;#039;;&lt;br /&gt;
    function clamp(x) { return Math.max(0, Math.min(1, x)); }&lt;br /&gt;
    function smooth(x) { x = clamp(x); return x*x*(3-2*x); }&lt;br /&gt;
    function hash(a, b, seed) {&lt;br /&gt;
        var n = Math.imul(a + 8192, 374761393) ^ Math.imul(b + 8192, 668265263) ^ seed;&lt;br /&gt;
        n = Math.imul(n ^ (n &amp;gt;&amp;gt;&amp;gt; 13), 1274126177);&lt;br /&gt;
        return ((n ^ (n &amp;gt;&amp;gt;&amp;gt; 16)) &amp;gt;&amp;gt;&amp;gt; 0) / 4294967296;&lt;br /&gt;
    }&lt;br /&gt;
    function create(seed) {&lt;br /&gt;
        seed = seed &amp;gt;&amp;gt;&amp;gt; 0;&lt;br /&gt;
        var order = [];&lt;br /&gt;
        for (var i = 0; i &amp;lt; TITLE.length; i++) { if (TITLE[i] !== &amp;#039; &amp;#039;) { order.push(i); } }&lt;br /&gt;
        order.sort(function (a, b) { return hash(a, 71, seed) - hash(b, 71, seed); });&lt;br /&gt;
        var locks = {};&lt;br /&gt;
        order.forEach(function (index, rank) { locks[index] = 0.8 + rank * (3.4 / 12); });&lt;br /&gt;
        function column(index, time) {&lt;br /&gt;
            var direction = hash(index, 1, seed) &amp;lt; 0.5 ? -1 : 1;&lt;br /&gt;
            var speed = direction * (5 + hash(index, 2, seed) * 6);&lt;br /&gt;
            var on = hash(index, 3, seed) * 0.8;&lt;br /&gt;
            var isTitle = Object.prototype.hasOwnProperty.call(locks, index);&lt;br /&gt;
            var stop = isTitle ? locks[index] : 4.8;&lt;br /&gt;
            var offset;&lt;br /&gt;
            if (isTitle) { offset = time &amp;gt;= stop ? 0 : speed * (time - stop); }&lt;br /&gt;
            else {&lt;br /&gt;
                var phase = hash(index, 4, seed);&lt;br /&gt;
                var end = direction &amp;gt; 0 ? Math.ceil(phase + speed * 0.3) : Math.floor(phase + speed * 0.3);&lt;br /&gt;
                if (time &amp;lt; 4.2) { offset = phase + speed * (time - 4.2); }&lt;br /&gt;
                else {&lt;br /&gt;
                    var u = clamp((time - 4.2) / 0.6);&lt;br /&gt;
                    // Cubic Hermite: preserve velocity on entry, stop on an integer row.&lt;br /&gt;
                    offset = (2*u*u*u - 3*u*u + 1)*phase + (u*u*u - 2*u*u + u)*0.6*speed + (-2*u*u*u + 3*u*u)*end;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            return { offset: offset, speed: speed, stop: stop, locked: isTitle &amp;amp;&amp;amp; time &amp;gt;= stop,&lt;br /&gt;
                alpha: clamp((time - on) / 0.13), title: isTitle };&lt;br /&gt;
        }&lt;br /&gt;
        function frame(time) {&lt;br /&gt;
            var p = clamp((time - 6.2) / 1.1);&lt;br /&gt;
            return { time: time, scale: 1 + 9*(0.5*p + 0.5*p*p),&lt;br /&gt;
                opacity: time &amp;gt;= 7.3 ? 0 : 1-clamp((time-7.05)/0.25),&lt;br /&gt;
                locked: order.filter(function (i) { return time &amp;gt;= locks[i]; }).length,&lt;br /&gt;
                aligned: time &amp;gt;= 4.8, done: time &amp;gt;= 7.3 };&lt;br /&gt;
        }&lt;br /&gt;
        function titleEffect(index, time) {&lt;br /&gt;
            var elapsed = time-locks[index], hit = 0;&lt;br /&gt;
            if (elapsed &amp;gt;= 0 &amp;amp;&amp;amp; elapsed &amp;lt; 0.22) {&lt;br /&gt;
                hit = elapsed &amp;lt; 0.06 ? smooth(elapsed/0.06) : 1-smooth((elapsed-0.06)/0.16);&lt;br /&gt;
            }&lt;br /&gt;
            var sweepProgress = (time-4.2)/0.45;&lt;br /&gt;
            var sweep = sweepProgress &amp;gt;= 0 &amp;amp;&amp;amp; sweepProgress &amp;lt;= 1 ?&lt;br /&gt;
                Math.max(0, 1-Math.abs(index-(-1.5+16*sweepProgress))/1.5) : 0;&lt;br /&gt;
            return { scale: 1+0.12*hit, hit: hit, sweep: sweep };&lt;br /&gt;
        }&lt;br /&gt;
        function cellState(index, row, time) {&lt;br /&gt;
            if (Object.prototype.hasOwnProperty.call(locks,index) &amp;amp;&amp;amp; row === 0) {&lt;br /&gt;
                return { char: TITLE[index], scaleX: 1, flash: 0, zero: false, settled: true };&lt;br /&gt;
            }&lt;br /&gt;
            var original = CHARS[Math.floor(hash(index,row+100,seed)*CHARS.length)];&lt;br /&gt;
            var elapsed = time-(6.2+hash(index,row+900,seed)*0.5);&lt;br /&gt;
            if (elapsed &amp;lt; 0) { return { char: original, scaleX: 1, flash: 0, zero: false, settled: true }; }&lt;br /&gt;
            if (elapsed &amp;gt;= 0.2) { return { char: &amp;#039;0&amp;#039;, scaleX: 1, flash: 0, zero: true, settled: true }; }&lt;br /&gt;
            var before = elapsed &amp;lt; 0.08;&lt;br /&gt;
            var phase = before ? smooth(elapsed/0.08) : smooth((elapsed-0.08)/0.12);&lt;br /&gt;
            return { char: before ? original : &amp;#039;0&amp;#039;, scaleX: before ? 1-0.85*phase : 0.15+0.85*phase,&lt;br /&gt;
                flash: before ? smooth(elapsed/0.025) : 1-phase, zero: !before, settled: false };&lt;br /&gt;
        }&lt;br /&gt;
        function cell(index,row,time) { return cellState(index,row,time).char; }&lt;br /&gt;
        return { seed: seed, order: order, locks: locks, column: column, frame: frame,&lt;br /&gt;
            cell: cell, cellState: cellState, titleEffect: titleEffect };&lt;br /&gt;
    }&lt;br /&gt;
    function geometry(width, height) {&lt;br /&gt;
        var cw = Math.min(28, width / 16), rh = cw * 36/28;&lt;br /&gt;
        return { width: width, height: height, cw: cw, rh: rh,&lt;br /&gt;
            first: Math.floor(7-width/2/cw)-1, last: Math.ceil(7+width/2/cw)+1 };&lt;br /&gt;
    }&lt;br /&gt;
    // One atlas per rendering context and current cell size/DPR. Frames reuse it;&lt;br /&gt;
    // resize replaces it; released contexts can be collected. No external assets.&lt;br /&gt;
    var atlases = new WeakMap();&lt;br /&gt;
    function atlas(ctx,g,dpr) {&lt;br /&gt;
        var key = g.cw.toFixed(4)+&amp;#039;:&amp;#039;+dpr, cached = atlases.get(ctx);&lt;br /&gt;
        if (cached &amp;amp;&amp;amp; cached.key === key) { return cached; }&lt;br /&gt;
        var ratio = g.cw/28, pad = Math.ceil(20*ratio);&lt;br /&gt;
        var tw = Math.ceil(g.cw+2*pad), th = Math.ceil(g.rh+2*pad);&lt;br /&gt;
        var pw = Math.ceil(tw*dpr), ph = Math.ceil(th*dpr);&lt;br /&gt;
        var chars = CHARS, sheet = ctx.canvas.ownerDocument.createElement(&amp;#039;canvas&amp;#039;);&lt;br /&gt;
        sheet.width = pw*chars.length; sheet.height = ph*2;&lt;br /&gt;
        // Bake the atlas on the CPU once. A GPU-backed source canvas can trigger&lt;br /&gt;
        // repeated cross-surface readbacks when composited into another canvas.&lt;br /&gt;
        var s = sheet.getContext(&amp;#039;2d&amp;#039;, { willReadFrequently: true });&lt;br /&gt;
        if (!s) { throw new Error(&amp;#039;Glyph atlas unavailable&amp;#039;); }&lt;br /&gt;
        s.font = &amp;#039;500 &amp;#039;+(g.cw*0.68*dpr)+&amp;#039;px ui-monospace, SFMono-Regular, Consolas, &amp;quot;Liberation Mono&amp;quot;, monospace&amp;#039;;&lt;br /&gt;
        s.textAlign = &amp;#039;center&amp;#039;; s.textBaseline = &amp;#039;middle&amp;#039;;&lt;br /&gt;
        for (var bright=0;bright&amp;lt;2;bright++) {&lt;br /&gt;
            for(var i=0;i&amp;lt;chars.length;i++) {&lt;br /&gt;
                var x=i*pw+pw/2, y=bright*ph+ph/2+0.5*dpr;&lt;br /&gt;
                s.fillStyle = bright ? &amp;#039;#ffffff&amp;#039; : &amp;#039;#bec5cd&amp;#039;;&lt;br /&gt;
                s.shadowColor = bright ? &amp;#039;rgba(255,255,255,0.95)&amp;#039; : &amp;#039;rgba(255,255,255,0.65)&amp;#039;;&lt;br /&gt;
                s.shadowBlur = 7*ratio*dpr; s.fillText(chars[i],x,y);&lt;br /&gt;
                s.shadowBlur = 2*ratio*dpr; s.fillText(chars[i],x,y);&lt;br /&gt;
                s.shadowBlur = 0; s.fillText(chars[i],x,y);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        var block = ctx.canvas.ownerDocument.createElement(&amp;#039;canvas&amp;#039;);&lt;br /&gt;
        block.width = pw; block.height = ph;&lt;br /&gt;
        var b = block.getContext(&amp;#039;2d&amp;#039;, { willReadFrequently: true });&lt;br /&gt;
        if (!b) { throw new Error(&amp;#039;Title atlas unavailable&amp;#039;); }&lt;br /&gt;
        b.fillStyle = &amp;#039;#fff&amp;#039;; b.shadowColor = &amp;#039;rgba(255,255,255,0.85)&amp;#039;;&lt;br /&gt;
        var bx=(pw-g.cw*dpr)/2+0.5*dpr, by=(ph-g.rh*dpr)/2+0.5*dpr;&lt;br /&gt;
        b.shadowBlur = 12*ratio*dpr; b.fillRect(bx,by,(g.cw-1)*dpr,(g.rh-1)*dpr);&lt;br /&gt;
        b.shadowBlur = 4*ratio*dpr; b.fillRect(bx,by,(g.cw-1)*dpr,(g.rh-1)*dpr);&lt;br /&gt;
        cached = {key:key,sheet:sheet,block:block,pw:pw,ph:ph,tw:pw/dpr,th:ph/dpr,chars:chars};&lt;br /&gt;
        atlases.set(ctx,cached); return cached;&lt;br /&gt;
    }&lt;br /&gt;
    function draw(ctx, model, time, width, height, dpr) {&lt;br /&gt;
        var g = geometry(width, height), f = model.frame(time), a = atlas(ctx,g,dpr);&lt;br /&gt;
        ctx.setTransform(dpr, 0, 0, dpr, 0, 0);&lt;br /&gt;
        ctx.globalAlpha = 1;&lt;br /&gt;
        ctx.fillStyle = &amp;#039;#090b0e&amp;#039;; ctx.fillRect(0, 0, width, height);&lt;br /&gt;
        ctx.save(); ctx.translate(width/2, height/2); ctx.scale(f.scale, f.scale);&lt;br /&gt;
        ctx.font = &amp;#039;500 &amp;#039; + (g.cw*0.68) + &amp;#039;px ui-monospace, SFMono-Regular, Consolas, &amp;quot;Liberation Mono&amp;quot;, monospace&amp;#039;;&lt;br /&gt;
        ctx.textAlign = &amp;#039;center&amp;#039;; ctx.textBaseline = &amp;#039;middle&amp;#039;;&lt;br /&gt;
        var span = Math.ceil(height/2/f.scale/g.rh)+2;&lt;br /&gt;
        var first = Math.floor(7-width/2/f.scale/g.cw)-2, last = Math.ceil(7+width/2/f.scale/g.cw)+2;&lt;br /&gt;
        // Peripheral glyphs first; title highlights never get painted over by a later column.&lt;br /&gt;
        for (var col = first; col &amp;lt;= last; col++) {&lt;br /&gt;
            var c = model.column(col, time), x = (col-7)*g.cw;&lt;br /&gt;
            if (c.alpha &amp;lt;= 0) { continue; }&lt;br /&gt;
            for (var row = Math.floor(-span-c.offset); row &amp;lt;= Math.ceil(span-c.offset); row++) {&lt;br /&gt;
                var y = (row+c.offset)*g.rh;&lt;br /&gt;
                if (col === 7 &amp;amp;&amp;amp; Math.abs(y) &amp;lt; g.rh) { continue; }&lt;br /&gt;
                if (c.locked &amp;amp;&amp;amp; row === 0) { continue; }&lt;br /&gt;
                var state = model.cellState(col,row,time), slot = a.chars.indexOf(state.char);&lt;br /&gt;
                var dw = a.tw*state.scaleX, dx = x+g.cw/2-dw/2;&lt;br /&gt;
                ctx.globalAlpha = c.alpha;&lt;br /&gt;
                ctx.drawImage(a.sheet,slot*a.pw,0,a.pw,a.ph,dx,y-a.th/2,dw,a.th);&lt;br /&gt;
                if (state.flash &amp;gt; 0) {&lt;br /&gt;
                    ctx.globalAlpha = c.alpha*state.flash;&lt;br /&gt;
                    ctx.drawImage(a.sheet,slot*a.pw,a.ph,a.pw,a.ph,dx,y-a.th/2,dw,a.th);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        // Reserve the title gap before emitting light, preserving outward bloom into the gap.&lt;br /&gt;
        ctx.globalAlpha = 1; ctx.fillStyle = &amp;#039;#090b0e&amp;#039;;&lt;br /&gt;
        ctx.fillRect(0, -g.rh/2, g.cw, g.rh);&lt;br /&gt;
        var titles = [];&lt;br /&gt;
        for (var index=0;index&amp;lt;TITLE.length;index++) {&lt;br /&gt;
            if (TITLE[index] === &amp;#039; &amp;#039; || !model.column(index,time).locked) { continue; }&lt;br /&gt;
            var effect = model.titleEffect(index,time), cx = (index-6.5)*g.cw;&lt;br /&gt;
            titles.push({x:cx,effect:effect,char:TITLE[index]});&lt;br /&gt;
            ctx.save(); ctx.translate(cx,0); ctx.scale(effect.scale,effect.scale);&lt;br /&gt;
            ctx.globalAlpha = 0.75;&lt;br /&gt;
            ctx.drawImage(a.block,-a.tw/2,-a.th/2,a.tw,a.th);&lt;br /&gt;
            ctx.globalAlpha = Math.min(1,0.75*(effect.hit+effect.sweep));&lt;br /&gt;
            ctx.drawImage(a.block,-a.tw/2,-a.th/2,a.tw,a.th);&lt;br /&gt;
            ctx.globalAlpha = 1; ctx.fillStyle = &amp;#039;#fff&amp;#039;;&lt;br /&gt;
            ctx.fillRect(-g.cw/2+0.5,-g.rh/2+0.5,g.cw-1,g.rh-1);&lt;br /&gt;
            ctx.restore();&lt;br /&gt;
        }&lt;br /&gt;
        // Crisp dark lettering is always the final pass, including during pulse/sweep.&lt;br /&gt;
        ctx.globalAlpha = 1; ctx.fillStyle = &amp;#039;#090b0e&amp;#039;;&lt;br /&gt;
        titles.forEach(function(t) {&lt;br /&gt;
            ctx.save(); ctx.translate(t.x,0); ctx.scale(t.effect.scale,t.effect.scale);&lt;br /&gt;
            ctx.fillText(t.char,0,0.5); ctx.restore();&lt;br /&gt;
        });&lt;br /&gt;
        ctx.restore(); ctx.globalAlpha = 1;&lt;br /&gt;
        return f;&lt;br /&gt;
    }&lt;br /&gt;
    return { version: &amp;#039;glow-v2-cpu-atlas&amp;#039;, title: TITLE, create: create, geometry: geometry, draw: draw };&lt;br /&gt;
}));&lt;/div&gt;</summary>
		<author><name>Gaoice</name></author>
	</entry>
</feed>