function __fpHash(str) {
str = String(str);
var h = 0x811c9dc5;
for (var i = 0; i < str.length; i++) {
h ^= str.charCodeAt(i) & 0xff;
h = (h + ((h << 1) + (h << 4) + (h << 7) + (h << 8) + (h << 24))) >>> 0;
}
return ("0000000" + h.toString(16)).slice(-8);
}
function __fpHashBytes(bytes) {
var h = 0x811c9dc5;
var n = bytes ? bytes.length : 0;
for (var i = 0; i < n; i++) {
h ^= bytes[i] & 0xff;
h = (h + ((h << 1) + (h << 4) + (h << 7) + (h << 8) + (h << 24))) >>> 0;
}
return ("0000000" + h.toString(16)).slice(-8);
}
function __fpCanvas() {
try {
var c = document.createElement("canvas");
c.width = 280;
c.height = 60;
var ctx = c.getContext("2d");
if (!ctx) return { supported: false, dataURL: "" };
ctx.textBaseline = "top";
ctx.font = "14px 'Arial'";
ctx.textBaseline = "alphabetic";
ctx.fillStyle = "#f60";
ctx.fillRect(125, 1, 62, 20);
ctx.fillStyle = "#069";
ctx.fillText("drission,补环境🦊", 2, 15);
ctx.fillStyle = "rgba(102,204,0,0.7)";
ctx.fillText("drission,补环境🦊", 4, 17);
return { supported: true, dataURL: c.toDataURL() };
} catch (e) {
return { supported: false, dataURL: "", error: String(e && e.message) };
}
}
function __fpWebGL() {
try {
var c = document.createElement("canvas");
var gl = c.getContext("webgl") || c.getContext("experimental-webgl");
if (!gl) return { supported: false };
var pnames = [
7936, 7937, 7938, 35724, 3379, 34076, 34921, 36347, 36348, 35660, 35661, 34930, 36349, 3386, 33901, 33902, 3410, 3411, 3412, 3413, 3414, 3415, 34047, 34852, ];
var params = {};
for (var i = 0; i < pnames.length; i++) {
try {
var v = gl.getParameter(pnames[i]);
if (v && typeof v !== "string" && typeof v.length === "number") {
v = Array.prototype.slice.call(v); }
if (v !== null && v !== undefined) params[pnames[i]] = v;
} catch (e) {}
}
var uv = null;
var ur = null;
try {
var dbg = gl.getExtension("WEBGL_debug_renderer_info");
if (dbg) {
uv = gl.getParameter(dbg.UNMASKED_VENDOR_WEBGL);
ur = gl.getParameter(dbg.UNMASKED_RENDERER_WEBGL);
if (uv != null) params[37445] = uv;
if (ur != null) params[37446] = ur;
}
} catch (e) {}
var exts = [];
try {
exts = gl.getSupportedExtensions() || [];
} catch (e) {}
return {
supported: true,
parameters: params,
unmaskedVendor: uv,
unmaskedRenderer: ur,
extensions: exts,
};
} catch (e) {
return { supported: false, error: String(e && e.message) };
}
}
function __fpAudioAsync(cb) {
var done = false;
function fin(r) {
if (done) return;
done = true;
try {
cb(r);
} catch (e) {}
}
try {
var OAC = (typeof OfflineAudioContext !== "undefined" && OfflineAudioContext) ||
(typeof webkitOfflineAudioContext !== "undefined" && webkitOfflineAudioContext);
if (!OAC) {
fin({ supported: false });
return;
}
var ctx = new OAC(1, 5000, 44100);
var osc = ctx.createOscillator();
osc.type = "triangle";
if (osc.frequency && osc.frequency.value !== undefined) osc.frequency.value = 10000;
var comp = ctx.createDynamicsCompressor();
try {
if (comp.threshold) comp.threshold.value = -50;
if (comp.knee) comp.knee.value = 40;
if (comp.ratio) comp.ratio.value = 12;
if (comp.attack) comp.attack.value = 0;
if (comp.release) comp.release.value = 0.25;
} catch (e) {}
osc.connect(comp);
comp.connect(ctx.destination);
osc.start(0);
ctx.oncomplete = function (ev) {
try {
var data = ev.renderedBuffer.getChannelData(0);
var sum = 0;
var slice = [];
for (var i = 4500; i < 5000; i++) {
sum += Math.abs(data[i]);
slice.push(data[i]);
}
fin({ supported: true, sampleRate: ctx.sampleRate, sum: sum, slice: slice });
} catch (e) {
fin({ supported: false, error: String(e && e.message) });
}
};
var p = ctx.startRendering();
if (p && typeof p.then === "function") {
p.then(function (buf) {
try {
var data = buf.getChannelData(0);
var sum = 0;
var slice = [];
for (var i = 4500; i < 5000; i++) {
sum += Math.abs(data[i]);
slice.push(data[i]);
}
fin({ supported: true, sampleRate: ctx.sampleRate || 44100, sum: sum, slice: slice });
} catch (e) {
fin({ supported: false, error: String(e && e.message) });
}
});
}
} catch (e) {
fin({ supported: false, error: String(e && e.message) });
}
}
function __fpFonts() {
try {
var bases = ["monospace", "sans-serif", "serif"];
var probe = "mmmmmmmmmmlli水墨0Oo😀WiQ";
var size = "72px ";
var candidates = [
"Arial", "Arial Black", "Arial Narrow", "Arial Unicode MS", "Calibri", "Cambria",
"Comic Sans MS", "Consolas", "Courier", "Courier New", "Georgia", "Helvetica",
"Helvetica Neue", "Impact", "Lucida Console", "Lucida Grande", "Menlo", "Microsoft Sans Serif",
"Monaco", "MS Gothic", "MS PGothic", "MS Sans Serif", "Palatino", "Palatino Linotype",
"Segoe UI", "Tahoma", "Times", "Times New Roman", "Trebuchet MS", "Verdana", "Wingdings",
"PingFang SC", "Hiragino Sans GB", "STHeiti", "Songti SC", "Heiti SC", "Apple Color Emoji",
"Noto Sans CJK SC", "Source Han Sans", "WenQuanYi Micro Hei", "DejaVu Sans", "Liberation Sans",
"Ubuntu", "Roboto", "Microsoft YaHei", "SimSun", "SimHei", "KaiTi",
];
var c = document.createElement("canvas");
var ctx = c.getContext("2d");
if (!ctx) return { supported: false };
var widths = {};
function measure(font) {
ctx.font = font;
var w = ctx.measureText(probe).width;
widths[font] = w;
return w;
}
var baseW = {};
for (var b = 0; b < bases.length; b++) baseW[bases[b]] = measure(size + bases[b]);
var detected = [];
for (var i = 0; i < candidates.length; i++) {
var present = false;
for (var b2 = 0; b2 < bases.length; b2++) {
var w = measure(size + "'" + candidates[i] + "'," + bases[b2]);
if (w !== baseW[bases[b2]]) present = true;
}
if (present) detected.push(candidates[i]);
}
return {
supported: true,
detected: detected,
widths: widths,
hash: __fpHash(JSON.stringify(detected) + "|" + JSON.stringify(widths)),
};
} catch (e) {
return { supported: false, error: String(e && e.message) };
}
}
function __fpCanvasPixels() {
try {
var W = 96, H = 32;
var c = document.createElement("canvas");
c.width = W;
c.height = H;
var ctx = c.getContext("2d");
if (!ctx) return { supported: false };
var g = ctx.createLinearGradient(0, 0, W, H);
g.addColorStop(0, "#f60");
g.addColorStop(0.5, "#069");
g.addColorStop(1, "#0c6");
ctx.fillStyle = g;
ctx.fillRect(0, 0, W, H);
ctx.textBaseline = "top";
ctx.font = "14px 'Arial'";
ctx.fillStyle = "rgba(20,30,40,0.85)";
ctx.fillText("drission px🦊", 2, 2);
ctx.fillStyle = "rgba(255,255,255,0.6)";
ctx.beginPath();
ctx.arc(70, 16, 12, 0, Math.PI * 1.7);
ctx.fill();
var im = ctx.getImageData(0, 0, W, H);
var bytes = im.data;
var hash = __fpHashBytes(bytes);
var bin = "";
for (var i = 0; i < bytes.length; i += 8192) {
bin += String.fromCharCode.apply(null, Array.prototype.slice.call(bytes, i, i + 8192));
}
var data = "";
try { data = (typeof btoa === "function" ? btoa(bin) : ""); } catch (e) { data = ""; }
return { supported: true, width: W, height: H, hash: hash, data: data };
} catch (e) {
return { supported: false, error: String(e && e.message) };
}
}
function __fpRtc() {
try {
var RPC = (typeof RTCPeerConnection !== "undefined" && RTCPeerConnection) ||
(typeof webkitRTCPeerConnection !== "undefined" && webkitRTCPeerConnection) ||
(typeof mozRTCPeerConnection !== "undefined" && mozRTCPeerConnection);
if (!RPC) return { supported: false, codecsHash: "", audioCodecs: [], videoCodecs: [] };
function caps(kind) {
var out = [];
try {
if (typeof RTCRtpReceiver !== "undefined" && RTCRtpReceiver.getCapabilities) {
var cp = RTCRtpReceiver.getCapabilities(kind);
if (cp && cp.codecs) for (var i = 0; i < cp.codecs.length; i++) out.push(cp.codecs[i].mimeType);
}
} catch (e) {}
return out;
}
var a = caps("audio"), v = caps("video");
return {
supported: true,
audioCodecs: a,
videoCodecs: v,
codecsHash: __fpHash(a.join(",") + "|" + v.join(",")),
};
} catch (e) {
return { supported: false, error: String(e && e.message), audioCodecs: [], videoCodecs: [] };
}
}