/* CCGallery - HTML5 Multimedia Gallery 
 * Copyright 2011, Nilok Bose  
 * http://codecanyon.net/user/cosmocoder
*/

jQuery(function (c) {
    var j = c("#ccgallery"),
        g = c("#thumbGallery"),
        h = c("#thumbGallery").find("ul"),
        f = c("#itemList"),
        d = c("#coverContainer"),
        e = c.browser.msie ? true : false,
        a = e && c.browser.version < 9 && IE7.recalc ? true : false;
    c.ajax({
        type: "GET",
        url: "config.xml",
        dataType: "xml",
        success: function (k) {
            i(c(k))
        }
    });

    function i(u) {
        var k = u.find("file"),
            p = k.find("cover"),
            o = k.find("thumb"),
            n = k.find("title"),
            s = k.find("description"),
            t = k.length,
            m = 0;
        var r = "";
        for (var q = 0; q < t; q++) {
            r += '<li data-id="' + (q + 1) + '" data-type="' + k.eq(q).attr("type") + '">';
            r += '<img src="' + o.eq(q).text() + '" alt="" />';
            r += '<div class="details">';
            r += "<h2>" + n.eq(q).text() + "</h2>";
            r += '<p class="description">' + s.eq(q).text() + "</p>";
            r += "</div>";
            r += "</li>"
        }
        h.html(r);
        var w = "",
            v = "";
        for (var q = 0; q < t; q++) {
            w += '<img src="' + p.eq(q).text() + '" alt="" />';
            v += '<li data-id="' + (q + 1) + '" data-type="' + k.eq(q).attr("type") + '">';
            v += "<h2>" + n.eq(q).text() + "</h2>";
            v += '<p class="description">' + s.eq(q).text() + "</p>";
            v += "</li>"
        }
        d.html(w);
        f.html(v);
        if (a) {
            f.delegate("li", "mouseleave click", function (x) {
                c(this).removeClass("ie7_class7")
            });
            h.delegate("li", "mouseleave", function (x) {
                c(this).removeClass("ie7_class4")
            })
        }
        var l;
        if (c("#gocoverflow").hasClass("active")) {
            l = "coverflow"
        } else {
            l = "thumbnails"
        }
        j.find("img").load(function () {
            m++;
            if (m === 2 * t) {
                j.css({
                    height: "auto",
                    background: "none"
                });
                if (l === "coverflow") {
                    d.parent().fadeIn(600)
                } else {
                    g.fadeIn(600)
                }
                b(t, k)
            }
        })
    }
    function b(q, o) {
        var H = h.clone(),
            B = f.clone();
        c("menu").delegate("a.navbuttons", "click", function () {
            var b = c(this),
                ae = b.index("a.navbuttons"),
                ah = c("section.displayStyle");
            b.addClass("active").siblings().removeClass("active");
            if (b.parent().is("#sortButtons")) {
                var d, af;
                if (b.data("type") === "all") {
                    d = H.find("li");
                    af = B.find("li")
                } else {
                    d = H.find("li[data-type=" + b.data("type") + "]");
                    af = B.find("li[data-type=" + b.data("type") + "]")
                }
                h.quicksand(d, {
                    duration: 800,
                    adjustHeight: "dynamic",
                    useScaling: false
                }, function () {
                    h.css("height", "auto");
                    if (a) {
                        IE7.recalc()
                    }
                });
                f.quicksand(af, {
                    duration: 800,
                    adjustHeight: "dynamic",
                    useScaling: false
                }, function () {
                    f.css("height", "auto");
                    J();
                    if (a) {
                        IE7.recalc()
                    }
                })
            } else {
                if (ah.eq(ae).is(":visible")) {
                    return false
                } else {
                    ah.filter(":visible").fadeOut(600, function () {
                        ah.eq(ae).fadeIn(600)
                    })
                }
            }
        });
        h.delegate("img", "click", function () {
            var a = c(this).parent(),
                ae = a.data("type"),
                ad = o.eq(a.data("id") - 1).find("source");
            T(ae, ad, a.find("h2")[0].innerHTML, a.find("p")[0].innerHTML)
        });
        var bc = d.find("img"),
            K = c('<div class="cwrapper"/>').appendTo(d).hide(),
            G = c('<canvas class="fade"/>').appendTo(d),
            l = d.width(),
            m = 0,
            D, O = q % 2 === 0 ? q / 2 - 1 : (q + 1) / 2 - 1,
            Z = getRGB(c("body").css("background-color")),
            R, p = document.createElement("canvas").getContext ? true : false;
        for (var W = 0; W < q; W++) {
            if (m < bc.eq(W)[0].height) {
                m = bc.eq(W)[0].height;
                D = m
            }
        }
        if (p) {
            m = 1.5 * m;
            d.height(m)
        } else {
            d.height(m)
        }
        var F = [],
            r = [],
            Y = [],
            y = [],
            n = [],
            t = [],
            z = [],
            M = [],
            U = bc[O].width;

        function V() {
            if (p) {
                for (var a = 0; a < q; a++) {
                    var b, e, af, ag, ad = f.find("li").eq(a).data("id") - 1;
                    Y[a] = bc[ad].width;
                    y[a] = bc[ad].height;
                    F[a] = c('<canvas class="cover"/>').appendTo(K).data("index", a);
                    r[a] = F[a][0].getContext("2d");
                    F[a][0].width = Y[a];
                    F[a][0].height = 1.5 * y[a];
                    n[a] = new Plane(Y[a], 1.5 * y[a], 300, r[a], "#666", Z, bc[ad]);
                    if (a < O) {
                        b = a;
                        n[a].rotation.y = Math.PI / 4;
                        n[a].position.z = 100;
                        n[a].render();
                        t[a] = n[a].maxwidth;
                        z[a] = n[a].maxoffset;
                        af = t[a];
                        e = l / 2 - F[a][0].width / 2 - U / 2 - t[a] / 2 + (a - O + 1) * 40 + z[a] / 2;
                        ag = l / 2 - af / 2 - U / 2 - af / 2 + (a - O + 1) * 40
                    } else {
                        if (a > O) {
                            b = q - 1 - a;
                            n[a].rotation.y = -Math.PI / 4;
                            n[a].position.z = 100;
                            n[a].render();
                            t[a] = n[a].maxwidth;
                            z[a] = n[a].maxoffset;
                            af = t[a];
                            e = l / 2 - F[a][0].width / 2 + U / 2 + t[a] / 2 + (a - O - 1) * 40 - z[a] / 2;
                            ag = l / 2 + U / 2 + (a - O - 1) * 40
                        } else {
                            if (a === O) {
                                b = a;
                                e = l / 2 - U / 2;
                                n[a].rotation.y = Math.PI / 4;
                                n[a].position.z = 100;
                                n[a].render();
                                t[a] = n[a].maxwidth;
                                z[a] = n[a].maxoffset;
                                n[a].rotation.y = 0;
                                n[a].position.z = 0;
                                n[a].render();
                                af = Y[a];
                                ag = l / 2 - af / 2
                            }
                        }
                    }
                    F[a].css({
                        zIndex: b,
                        left: e,
                        top: D - y[a],
                        bottom: "auto"
                    });
                    M[a] = c('<a class="coverclick"/>').appendTo(d).data("index", a);
                    M[a].css({
                        left: ag,
                        top: D - y[a],
                        bottom: "auto",
                        zIndex: q + 2 + b,
                        width: af,
                        height: F[a][0].height
                    })
                }
            } else {
                for (var a = 0; a < q; a++) {
                    var e, b, ad = f.find("li").eq(a).data("id") - 1;
                    Y[a] = bc.eq(ad)[0].width;
                    y[a] = bc.eq(ad)[0].height;
                    F[a] = c('<div class="cover"/>').appendTo(K).data("index", a).append(bc.eq(ad).clone());
                    t[a] = 0.7 * Y[a];
                    if (a < O) {
                        e = l / 2 - U / 2 - t[a] + (a - O) * 40;
                        b = a;
                        F[a].width(t[a]);
                        F[a].height(t[a] * y[a] / Y[a])
                    } else {
                        if (a > O) {
                            e = l / 2 + U / 2 + (a - O) * 40;
                            b = q - 1 - a;
                            F[a].width(t[a]);
                            F[a].height(t[a] * y[a] / Y[a])
                        } else {
                            if (a === O) {
                                e = l / 2 - U / 2;
                                b = a;
                                F[a].width(Y[a]);
                                F[a].height(y[a])
                            }
                        }
                    }
                    F[a].css({
                        left: e,
                        zIndex: b
                    });
                    M[a] = c('<a class="coverclick"/>').appendTo(d).data("index", a);
                    M[a].css({
                        left: e,
                        bottom: 0,
                        top: "auto",
                        zIndex: q + 2 + b,
                        width: F[a].width(),
                        height: F[a].height()
                    })
                }
            }
        }
        V();
        if (p) {
            G.css({
                position: "absolute",
                bottom: "0",
                left: "0",
                zIndex: q + 1
            });
            G[0].width = l;
            G[0].height = m;
            var x = G[0].getContext("2d"),
                X = x.createLinearGradient(0, 0, l, 0);
            X.addColorStop(0, "rgba(" + Z.r + "," + Z.g + "," + Z.b + ", 1.0)");
            X.addColorStop(0.35, "rgba(" + Z.r + "," + Z.g + "," + Z.b + ", 0.0)");
            X.addColorStop(0.65, "rgba(" + Z.r + "," + Z.g + "," + Z.b + ", 0.0)");
            X.addColorStop(1, "rgba(" + Z.r + "," + Z.g + "," + Z.b + ", 1.0)");
            x.fillStyle = X;
            x.rect(0, 0, l, m);
            x.fill()
        }
        bc.hide();
        K.fadeIn(600);
        f.find("li").eq(O).addClass("active");
        R = f.find("li").eq(O).data("id");
        M[O].addClass("active");
        var N = c("#scrollbar-track"),
            ab = N.find(".ui-slider-handle"),
            C = ab.wrap('<div class="ui-handle-helper-parent"/>').parent();
        N.slider({
            animate: true,
            max: q - 1,
            min: 0,
            value: O,
            slide: function (a, b) {
                I(b.value)
            }
        });
        C.width(N.width() - ab.width());
        c("#next").click(function () {
            N.slider("option", "value", O + 1);
            I(O + 1)
        });
        c("#prev").click(function () {
            N.slider("option", "value", O - 1);
            I(O - 1)
        });
        c(document).keydown(function (a) {
            var b = a.keyCode || a.charCode;
            if (b === 39) {
                N.slider("value", O + 1);
                I(O + 1)
            } else {
                if (b === 37) {
                    N.slider("option", "value", O - 1);
                    I(O - 1)
                }
            }
        });
        d.delegate("a.coverclick", "click", function () {
            var a = c(this),
                ad = a.data("index");
            if (a.hasClass("active")) {
                f.find("li").eq(ad).trigger("click")
            } else {
                if (ad !== O) {
                    N.slider("option", "value", ad);
                    I(ad)
                }
            }
        });
        d.mousewheel(function (a, b) {
            b = -Math.round(b);
            if (b !== 0) {
                N.slider("option", "value", O + b);
                I(O + b)
            }
        });
        var s = false;
        d.hover(function () {
            s = true
        }, function () {
            s = false
        });
        c(window).mousewheel(function () {
            if (s) {
                return false
            }
        });
        f.delegate("li", "click", function () {
            var a = c(this),
                ad = f.find("li").index(a);
            if (a.hasClass("active")) {
                T(a.data("type"), o.eq(a.data("id") - 1).find("source"), a.find("h2")[0].innerHTML, a.find("p")[0].innerHTML)
            } else {
                if (ad !== O) {
                    a.addClass("active").siblings().removeClass("active");
                    N.slider("option", "value", ad);
                    I(ad)
                }
            }
        });

        function J() {
            var a = f.find("li"),
                ad = a.filter("[data-id=" + R + "]");
            if (ad.length === 1) {
                a.removeClass("active");
                ad.addClass("active")
            } else {
                if (ad.length === 0) {
                    ad = a.eq(0);
                    ad.addClass("active");
                    R = ad.data("id")
                }
            }
            K.empty();
            d.find("a.coverclick").remove();
            O = a.index(ad);
            q = a.length;
            U = bc.eq(R - 1)[0].width;
            V();
            G.css("z-index", q + 1);
            M[O].addClass("active");
            N.slider("option", "max", q - 1);
            N.slider("option", "value", O)
        }
        function I(a) {
            if (a >= 0 && a < q) {
                var b = a > O ? "next" : "prev",
                    ae = q;
                f.find("li").removeClass("active").eq(a).addClass("active");
                R = f.find("li").eq(a).data("id");
                M[O].removeClass("active");
                M[a].addClass("active");
                if (p) {
                    while (ae--) {
                        var d, ai, ag, ah;
                        if (ae < a) {
                            d = ae;
                            ai = l / 2 - F[ae][0].width / 2 - Y[a] / 2 - t[ae] / 2 + (ae - a + 1) * 40 + z[ae] / 2;
                            ag = t[ae];
                            ah = l / 2 - ag / 2 - Y[a] / 2 - ag / 2 + (ae - a + 1) * 40
                        } else {
                            if (ae > a) {
                                d = q - 1 - ae;
                                ai = l / 2 - F[ae][0].width / 2 + Y[a] / 2 + t[ae] / 2 + (ae - a - 1) * 40 - z[ae] / 2;
                                ag = t[ae];
                                ah = l / 2 - ag / 2 + Y[a] / 2 + ag / 2 + (ae - a - 1) * 40
                            } else {
                                if (ae === a) {
                                    d = q;
                                    ai = l / 2 - F[a][0].width / 2;
                                    ag = Y[a];
                                    ah = l / 2 - ag / 2
                                }
                            }
                        }
                        F[ae].css("zIndex", d);
                        M[ae].css({
                            zIndex: q + 2 + d,
                            width: ag,
                            left: ah
                        });
                        F[ae].stop().animate({
                            left: ai
                        }, 600);
                        if (b === "next") {
                            if (ae > O && ae < a) {
                                n[ae].rotation.y = Math.PI / 4;
                                n[ae].render()
                            } else {
                                if (ae === a) {
                                    c(n[ae].position).stop().animate({
                                        z: 0
                                    }, 600);
                                    c(n[ae].rotation).stop().animate({
                                        y: 0
                                    }, {
                                        duration: 600,
                                        step: function () {
                                            this.parent.render()
                                        }
                                    })
                                } else {
                                    if (ae === O) {
                                        c(n[ae].position).stop().animate({
                                            z: 100
                                        }, 600);
                                        c(n[ae].rotation).stop().animate({
                                            y: Math.PI / 4
                                        }, {
                                            duration: 600,
                                            step: function () {
                                                this.parent.render()
                                            }
                                        })
                                    }
                                }
                            }
                        } else {
                            if (ae > a && ae < O) {
                                n[ae].rotation.y = -Math.PI / 4;
                                n[ae].render()
                            } else {
                                if (ae === O) {
                                    c(n[ae].position).stop().animate({
                                        z: 100
                                    }, 600);
                                    c(n[ae].rotation).stop().animate({
                                        y: -Math.PI / 4
                                    }, {
                                        duration: 600,
                                        step: function () {
                                            this.parent.render()
                                        }
                                    })
                                } else {
                                    if (ae === a) {
                                        c(n[ae].position).stop().animate({
                                            z: 0
                                        }, 600);
                                        c(n[ae].rotation).stop().animate({
                                            y: 0
                                        }, {
                                            duration: 600,
                                            step: function () {
                                                this.parent.render()
                                            }
                                        })
                                    }
                                }
                            }
                        }
                    }
                } else {
                    while (ae--) {
                        var d, ai, ag, af;
                        if (ae < a) {
                            ai = l / 2 - Y[a] / 2 - t[ae] + (ae - a) * 40;
                            d = ae;
                            ag = t[ae];
                            af = t[ae] * y[ae] / Y[ae]
                        } else {
                            if (ae > a) {
                                ai = l / 2 + Y[a] / 2 + (ae - a) * 40;
                                d = q - 1 - ae;
                                ag = t[ae];
                                af = t[ae] * y[ae] / Y[ae]
                            } else {
                                if (ae === a) {
                                    ai = l / 2 - Y[a] / 2;
                                    d = q;
                                    ag = Y[ae];
                                    af = y[ae]
                                }
                            }
                        }
                        F[ae].css("zIndex", d);
                        M[ae].css({
                            zIndex: q + 2 + d,
                            width: ag,
                            height: af,
                            left: ai
                        });
                        F[ae].stop().animate({
                            left: ai,
                            width: ag,
                            height: af
                        }, 600)
                    }
                }
                O = a
            }
        }
        var k = c('<div id="mask"/>').appendTo("body"),
            u = c('<div id="overlayLoader"/>').appendTo("body"),
            S = c('<div id="overlay"/>').appendTo("body"),
            w = c('<div id="overlayContent"/>').appendTo(S),
            E = c('<a id="close"/>').appendTo(S),
            P, L = c(window);
        w.html('<div class="details"><h2></h2><p></p></div>');
        var bd = w.find("h2"),
            A = w.find("p");

        function T(i, j, l, m) {
            bd[0].innerHTML = l;
            A[0].innerHTML = m;
            var n = L.scrollTop() + L.height() / 2;
            k.css("height", c(document).height()).fadeIn(400, function () {
                u.css("top", n).show();
                if (i === "photo") {
                    if (e) {
                        S.css({
                            visibility: "hidden",
                            display: "block"
                        });
                        w.css({
                            visibility: "hidden",
                            display: "block"
                        })
                    }
                    var a = c('<img src="' + j.text() + '" alt="" />').appendTo(w);
                    a[0].onload = function () {
                        v(a[0]);
                        if (e) {
                            S.css({
                                visibility: "visible",
                                display: "none"
                            });
                            w.css({
                                visibility: "visible",
                                display: "none"
                            })
                        }
                        Q(a[0].width, a[0].height + 80, n)
                    }
                } else {
                    if (i === "audio") {
                        var b = '<audio controls preload="auto">',
                            ap = '<audio controls preload="auto"';
                        for (var d = 0, ao = j.length; d < ao; d++) {
                            var f = j.eq(d).text(),
                                ar = f.split(".").pop();
                            if (ar === "ogg") {
                                b += '<source type="audio/ogg" src="' + f + '" />'
                            } else {
                                if (ar === "mp3") {
                                    b += '<source type="audio/mpeg" src="' + f + '" />';
                                    ap += 'type="audio/mpeg" src="' + f + '"></audio>'
                                }
                            }
                        }
                        b += "</audio>";
                        if (c.browser.safari) {
                            w.append(ap)
                        } else {
                            w.append(innerShiv(b))
                        }
                        Q(400, 110, n)
                    } else {
                        if (i === "video") {
                            if (j.eq(0).text().indexOf("youtube") !== -1) {
                                var g = j.eq(0).text().split("v=")[1],
                                    h = '<iframe width="480" height="270" src="http://www.youtube.com/embed/' + g + '?rel=0" frameborder="0" allowfullscreen></iframe>';
                                w.append(h)
                            } else {
                                if (j.eq(0).text().indexOf("vimeo") !== -1) {
                                    var g = j.eq(0).text().split("/").pop(),
                                        h = '<iframe src="http://player.vimeo.com/video/' + g + '" width="480" height="270" frameborder="0"></iframe>';
                                    w.append(h)
                                } else {
                                    var h = '<video controls preload="auto" width="480" height="270">',
                                        an = '<video controls preload="auto" width="480" height="270"';
                                    for (var d = 0, ao = j.length; d < ao; d++) {
                                        var f = j.eq(d).text(),
                                            ar = f.split(".").pop();
                                        if (ar === "mp4") {
                                            h += '<source type="video/mp4" src="' + f + '" />';
                                            an += 'type="video/mp4" src="' + f + '"></video>'
                                        } else {
                                            if (ar === "webm") {
                                                h += '<source type="video/webm" src="' + f + '" />'
                                            } else {
                                                if (ar === "ogv") {
                                                    h += '<source type="video/ogg" src="' + f + '" />'
                                                }
                                            }
                                        }
                                    }
                                    h += "</video>";
                                    if (c.browser.safari) {
                                        w.append(an)
                                    } else {
                                        w.append(innerShiv(h))
                                    }
                                }
                            }
                            Q(480, 350, n)
                        }
                    }
                }
            })
        }
        function Q(d, e, f) {
            var g = -(e + 40) / 2,
                ae = -(d + 40) / 2;
            u.hide();
            S.css({
                width: d,
                height: e,
                top: f,
                marginTop: g,
                marginLeft: ae
            }).slideDown(600, function () {
                w.fadeIn(400).find("audio,video").mediaelementplayer({
                    success: function (b, c) {
                        if (a) {
                            P = b;
                            IE7.recalc()
                        }
                    }
                })
            })
        }
        E.click(function () {
            w.fadeOut(400, function () {
                S.slideUp(600, function () {
                    if (P) {
                        P.pause();
                        P = ""
                    }
                    w.children().not("div.details").remove();
                    k.fadeOut(400)
                })
            })
        });

        function v(a) {
            var b = L.width() - 120,
                af = L.height() - 200,
                ag = b / af,
                ad = a.width / a.height;
            if (a.width > b || a.height > af) {
                if (ad === ag) {
                    a.width = b;
                    a.height = af
                } else {
                    a.width = af * ad;
                    a.height = af;
                    if (a.width > b) {
                        a.width = b;
                        a.height = b / ad
                    }
                }
            }
        }
    }
});

function getRGB(c) {
    var e, d, a;
    if (c.indexOf("#") === 0) {
        if (c.length === 4) {
            e = c.substring(1, 4).substring(0, 1);
            e = parseInt(e + e, 16);
            d = c.substring(1, 4).substring(1, 2);
            d = parseInt(d + d, 16);
            a = c.substring(1, 4).substring(2, 3);
            a = parseInt(a + a, 16)
        } else {
            e = parseInt(c.substring(1, 7).substring(0, 2), 16);
            d = parseInt(c.substring(1, 7).substring(2, 4), 16);
            a = parseInt(c.substring(1, 7).substring(4, 6), 16)
        }
    } else {
        if (c.indexOf("rgb") === 0) {
            e = c.split("(")[1].split(",")[0];
            d = c.split("(")[1].split(",")[1];
            a = c.split("(")[1].split(",")[2].split(")")[0]
        }
    }
    return {
        r: e,
        g: d,
        b: a
    }
}
function Plane(c, l, e, n, g, p, i) {
    this.width = c;
    this.height = l;
    this.focalLength = e;
    this.ctx = n;
    this.color = g;
    this.rotation = {
        x: 0,
        y: 0,
        z: 0,
        parent: this
    };
    this.position = {
        x: 0,
        y: 0,
        z: 0
    };
    var d = this.ctx.canvas,
        f = d.width,
        k = d.height,
        o = f / 2,
        m = k / 2;
    var b = [make3DPoint(-this.width / 2, this.height / 2, 0), make3DPoint(this.width / 2, this.height / 2, 0), make3DPoint(this.width / 2, -this.height / 2, 0), make3DPoint(-this.width / 2, -this.height / 2, 0)];
    var j = document.createElement("canvas").getContext("2d");
    j.canvas.width = this.width;
    j.canvas.height = this.height;
    j.drawImage(i, 0, 0, i.width, i.height, 0, 0, i.width, i.height);
    j.save();
    j.restore();
    j.scale(1, -1);
    j.translate(0, -i.height);
    j.drawImage(i, 0, 0, i.width, i.height, 0, -i.height, i.width, i.height);
    j.restore();
    j.scale(1, -1);
    var h = 0.5 * i.height,
        a = j.createLinearGradient(0, 0, 0, h);
    a.addColorStop(0, "rgba(" + p.r + "," + p.g + "," + p.b + ", 0.5)");
    a.addColorStop(1, "rgba(" + p.r + "," + p.g + "," + p.b + ", 1.0)");
    j.fillStyle = a;
    j.rect(0, 0, i.width, h);
    j.fill();
    this.render = function () {
        var r = Transform3DTo2D(b, this.rotation, this.position, this.focalLength, o, m);
        d.width = 1;
        d.width = f;
        var q = [r[0], r[1], r[3], r[2]];
        mapTexture(n, q, j.canvas);
        this.maxwidth = r[1].x - r[0].x;
        this.maxoffset = Math.abs((r[0].x - 0) - (f - r[1].x))
    }
}
function make3DPoint(a, c, b) {
    return {
        x: a,
        y: c,
        z: b
    }
}
function make2DPoint(a, b) {
    return {
        x: a,
        y: b
    }
}
function Transform3DTo2D(w, j, D, h, u, t) {
    var k = [],
        A = Math.sin,
        a = Math.cos,
        r = A(j.x),
        e = a(j.x),
        p = A(j.y),
        d = a(j.y),
        o = A(j.z),
        b = a(j.z),
        n, m, l, g, f, s, q, C, B, c;
    var v = w.length;
    while (v--) {
        n = w[v].x;
        m = w[v].y;
        l = w[v].z;
        g = e * m - r * l;
        f = r * m + e * l;
        q = d * f + p * n;
        s = -p * f + d * n;
        C = b * s - o * g;
        B = o * s + b * g;
        n = C + D.x;
        m = B + D.y;
        l = q + D.z;
        c = h / (h + l);
        n = n * c + u;
        m = -(m * c) + t;
        k[v] = make2DPoint(n, m)
    }
    return k
};

function mapTexture(j, i, e) {
    var h = 3,
        g = 28,
        b = getProjectiveTransform(i);
    var d = b.transformProjectiveVector([0, 0, 1]),
        a = b.transformProjectiveVector([1, 0, 1]),
        f = b.transformProjectiveVector([0, 1, 1]),
        c = b.transformProjectiveVector([1, 1, 1]);
    j.save();
    j.beginPath();
    j.moveTo(d[0], d[1]);
    j.lineTo(a[0], a[1]);
    j.lineTo(c[0], c[1]);
    j.lineTo(f[0], f[1]);
    j.closePath();
    j.clip();
    divide(0, 0, 1, 1, d, a, f, c, b, h, g, j, e);
    j.restore()
}
function divide(o, W, m, V, U, T, S, Q, x, u, l, s, h) {
    var C = Math.abs,
        B = Math.max,
        g = Math.min,
        q = Math.sqrt;
    if (u) {
        var M = [T[0] + S[0] - 2 * U[0], T[1] + S[1] - 2 * U[1]],
            K = [T[0] + S[0] - 2 * Q[0], T[1] + S[1] - 2 * Q[1]],
            I = [M[0] + K[0], M[1] + K[1]],
            E = C((I[0] * I[0] + I[1] * I[1]) / (M[0] * K[0] + M[1] * K[1]));
        M = [T[0] - U[0] + Q[0] - S[0], T[1] - U[1] + Q[1] - S[1]];
        K = [S[0] - U[0] + Q[0] - T[0], S[1] - U[1] + Q[1] - T[1]];
        var A = C(M[0] * K[1] - M[1] * K[0]);
        if ((o === 0 && m === 1) || ((0.25 + E * 5) * A > (l * l))) {
            var c = (o + m) / 2,
                w = (W + V) / 2,
                a = x.transformProjectiveVector([c, w, 1]),
                i = x.transformProjectiveVector([c, W, 1]),
                t = x.transformProjectiveVector([c, V, 1]),
                p = x.transformProjectiveVector([o, w, 1]),
                j = x.transformProjectiveVector([m, w, 1]);
            --u;
            divide(o, W, c, w, U, i, p, a, x, u, l, s, h);
            divide(c, W, m, w, i, T, a, j, x, u, l, s, h);
            divide(o, w, c, V, p, a, S, t, x, u, l, s, h);
            divide(c, w, m, V, a, j, t, Q, x, u, l, s, h);
            return
        }
    }
    s.save();
    s.beginPath();
    s.moveTo(U[0], U[1]);
    s.lineTo(T[0], T[1]);
    s.lineTo(Q[0], Q[1]);
    s.lineTo(S[0], S[1]);
    s.closePath();
    var P = [T[0] - U[0], T[1] - U[1]],
        y = [Q[0] - T[0], Q[1] - T[1]],
        R = [S[0] - Q[0], S[1] - Q[1]],
        k = [U[0] - S[0], U[1] - S[1]];
    var H = C(P[0] * k[1] - P[1] * k[0]),
        G = C(y[0] * P[1] - y[1] * P[0]),
        D = C(R[0] * y[1] - R[1] * y[0]),
        F = C(k[0] * R[1] - k[1] * R[0]),
        n = B(B(H, G), B(F, D)),
        d = 0,
        b = 0,
        L = 0,
        J = 0;
    switch (n) {
    case H:
        s.transform(P[0], P[1], -k[0], -k[1], U[0], U[1]);
        if (m !== 1) {
            L = 1.05 / q(P[0] * P[0] + P[1] * P[1])
        }
        if (V !== 1) {
            J = 1.05 / q(k[0] * k[0] + k[1] * k[1])
        }
        break;
    case G:
        s.transform(P[0], P[1], y[0], y[1], T[0], T[1]);
        if (m !== 1) {
            L = 1.05 / q(P[0] * P[0] + P[1] * P[1])
        }
        if (V !== 1) {
            J = 1.05 / q(y[0] * y[0] + y[1] * y[1])
        }
        d = -1;
        break;
    case D:
        s.transform(-R[0], -R[1], y[0], y[1], Q[0], Q[1]);
        if (m !== 1) {
            L = 1.05 / q(R[0] * R[0] + R[1] * R[1])
        }
        if (V !== 1) {
            J = 1.05 / q(y[0] * y[0] + y[1] * y[1])
        }
        d = -1;
        b = -1;
        break;
    case F:
        s.transform(-R[0], -R[1], -k[0], -k[1], S[0], S[1]);
        if (m !== 1) {
            L = 1.05 / q(R[0] * R[0] + R[1] * R[1])
        }
        if (V !== 1) {
            J = 1.05 / q(k[0] * k[0] + k[1] * k[1])
        }
        b = -1;
        break
    }
    var f = (m - o),
        e = (V - W),
        O = L * f,
        N = J * e;
    var v = h.width,
        z = h.height;
    s.drawImage(h, o * v, W * z, g(m - o + O, 1) * v, g(V - W + N, 1) * z, d, b, 1 + L, 1 + J);
    s.restore()
}
function getProjectiveTransform(b) {
    var c = new Matrix(9, 8, [
        [1, 1, 1, 0, 0, 0, -b[3].x, -b[3].x, -b[3].x],
        [0, 1, 1, 0, 0, 0, 0, -b[2].x, -b[2].x],
        [1, 0, 1, 0, 0, 0, -b[1].x, 0, -b[1].x],
        [0, 0, 1, 0, 0, 0, 0, 0, -b[0].x],
        [0, 0, 0, -1, -1, -1, b[3].y, b[3].y, b[3].y],
        [0, 0, 0, 0, -1, -1, 0, b[2].y, b[2].y],
        [0, 0, 0, -1, 0, -1, b[1].y, 0, b[1].y],
        [0, 0, 0, 0, 0, -1, 0, 0, b[0].y]
    ]);
    var d = c.rowEchelon().values;
    var a = new Matrix(3, 3, [
        [-d[0][8], -d[1][8], -d[2][8]],
        [-d[3][8], -d[4][8], -d[5][8]],
        [-d[6][8], -d[7][8], 1]
    ]);
    return a
};
var Matrix = function (a, c, b) {
        this.w = a;
        this.h = c;
        this.values = b || Matrix.allocate(c)
    };
Matrix.allocate = function (a, e) {
    var b = [],
        d = e,
        c = a;
    while (d--) {
        b[d] = [];
        while (c--) {
            b[d][c] = 0
        }
    }
    return b
};
Matrix.cloneValues = function (b) {
    clone = [];
    for (var c = 0, a = b.length; c < a; ++c) {
        clone[c] = [].concat(b[c])
    }
    return clone
};
Matrix.prototype.transformProjectiveVector = function (b) {
    var c = [];
    for (var e = 0; e < this.h; ++e) {
        c[e] = 0;
        for (var a = 0; a < this.w; ++a) {
            c[e] += this.values[e][a] * b[a]
        }
    }
    var d = 1 / (c[c.length - 1]);
    for (var e = 0; e < this.h; ++e) {
        c[e] *= d
    }
    return c
};
Matrix.prototype.rowEchelon = function () {
    if (this.w <= this.h) {
        throw "Matrix rowEchelon size mismatch"
    }
    var h = Matrix.cloneValues(this.values);
    for (var a = 0; a < this.h; ++a) {
        var f = h[a][a];
        while (f == 0) {
            for (var g = a + 1; g < this.h; ++g) {
                if (h[g][a] != 0) {
                    var i = h[g];
                    h[g] = h[a];
                    h[a] = i;
                    break
                }
            }
            if (g == this.h) {
                return new Matrix(this.w, this.h, h)
            } else {
                f = h[a][a]
            }
        }
        var b = 1 / f;
        for (var e = a; e < this.w; ++e) {
            h[a][e] *= b
        }
        for (var d = 0; d < this.h; ++d) {
            if (d == a) {
                continue
            }
            var c = h[d][a];
            h[d][a] = 0;
            for (var e = a + 1; e < this.w; ++e) {
                h[d][e] -= c * h[a][e]
            }
        }
    }
    return new Matrix(this.w, this.h, h)
};
