{"version":3,"file":"generateFillStyle.mjs","sources":["../../src/utils/generateFillStyle.ts"],"sourcesContent":["import { TEXT_GRADIENT } from 'pixijs/text';\n\nimport type { ICanvas, ICanvasRenderingContext2D } from 'pixijs/core';\nimport type { TextMetrics, TextStyle } from 'pixijs/text';\n\n// TODO: Prevent code duplication b/w generateFillStyle & Text#generateFillStyle\n\n/**\n * Generates the fill style. Can automatically generate a gradient based on the fill style being an array\n * @private\n * @param canvas\n * @param context\n * @param {object} style - The style.\n * @param resolution\n * @param {string[]} lines - The lines of text.\n * @param metrics\n * @returns {string|number|CanvasGradient} The fill style\n */\nexport function generateFillStyle(\n    canvas: ICanvas,\n    context: ICanvasRenderingContext2D,\n    style: TextStyle,\n    resolution: number,\n    lines: string[],\n    metrics: TextMetrics\n): string | CanvasGradient | CanvasPattern\n{\n    // TODO: Can't have different types for getter and setter. The getter shouldn't have the number type as\n    //       the setter converts to string. See this thread for more details:\n    //       https://github.com/microsoft/TypeScript/issues/2521\n    const fillStyle: string | string[] | CanvasGradient | CanvasPattern = style.fill as any;\n\n    if (!Array.isArray(fillStyle))\n    {\n        return fillStyle;\n    }\n    else if (fillStyle.length === 1)\n    {\n        return fillStyle[0];\n    }\n\n    // the gradient will be evenly spaced out according to how large the array is.\n    // ['#FF0000', '#00FF00', '#0000FF'] would created stops at 0.25, 0.5 and 0.75\n    let gradient: string[] | CanvasGradient;\n\n    // a dropshadow will enlarge the canvas and result in the gradient being\n    // generated with the incorrect dimensions\n    const dropShadowCorrection = (style.dropShadow) ? style.dropShadowDistance : 0;\n\n    // should also take padding into account, padding can offset the gradient\n    const padding = style.padding || 0;\n\n    const width = (canvas.width / resolution) - dropShadowCorrection - (padding * 2);\n    const height = (canvas.height / resolution) - dropShadowCorrection - (padding * 2);\n\n    // make a copy of the style settings, so we can manipulate them later\n    const fill = fillStyle.slice();\n    const fillGradientStops = style.fillGradientStops.slice();\n\n    // wanting to evenly distribute the fills. So an array of 4 colours should give fills of 0.25, 0.5 and 0.75\n    if (!fillGradientStops.length)\n    {\n        const lengthPlus1 = fill.length + 1;\n\n        for (let i = 1; i < lengthPlus1; ++i)\n        {\n            fillGradientStops.push(i / lengthPlus1);\n        }\n    }\n\n    // stop the bleeding of the last gradient on the line above to the top gradient of the this line\n    // by hard defining the first gradient colour at point 0, and last gradient colour at point 1\n    fill.unshift(fillStyle[0]);\n    fillGradientStops.unshift(0);\n\n    fill.push(fillStyle[fillStyle.length - 1]);\n    fillGradientStops.push(1);\n\n    if (style.fillGradientType === TEXT_GRADIENT.LINEAR_VERTICAL)\n    {\n        // start the gradient at the top center of the canvas, and end at the bottom middle of the canvas\n        gradient = context.createLinearGradient(width / 2, padding, width / 2, height + padding);\n\n        // we need to repeat the gradient so that each individual line of text has the same vertical gradient effect\n        // ['#FF0000', '#00FF00', '#0000FF'] over 2 lines would create stops at 0.125, 0.25, 0.375, 0.625, 0.75, 0.875\n\n        // There's potential for floating point precision issues at the seams between gradient repeats.\n        // The loop below generates the stops in order, so track the last generated one to prevent\n        // floating point precision from making us go the teeniest bit backwards, resulting in\n        // the first and last colors getting swapped.\n        let lastIterationStop = 0;\n\n        // Actual height of the text itself, not counting spacing for lineHeight/leading/dropShadow etc\n        const textHeight = metrics.fontProperties.fontSize + style.strokeThickness;\n\n        // textHeight, but as a 0-1 size in global gradient stop space\n        const gradStopLineHeight = textHeight / height;\n\n        for (let i = 0; i < lines.length; i++)\n        {\n            const thisLineTop = metrics.lineHeight * i;\n\n            for (let j = 0; j < fill.length; j++)\n            {\n                // 0-1 stop point for the current line, multiplied to global space afterwards\n                let lineStop = 0;\n\n                if (typeof fillGradientStops[j] === 'number')\n                {\n                    lineStop = fillGradientStops[j];\n                }\n                else\n                {\n                    lineStop = j / fill.length;\n                }\n\n                const globalStop = (thisLineTop / height) + (lineStop * gradStopLineHeight);\n\n                // Prevent color stop generation going backwards from floating point imprecision\n                let clampedStop = Math.max(lastIterationStop, globalStop);\n\n                clampedStop = Math.min(clampedStop, 1); // Cap at 1 as well for safety's sake to avoid a possible throw.\n                gradient.addColorStop(clampedStop, fill[j]);\n                lastIterationStop = clampedStop;\n            }\n        }\n    }\n    else\n    {\n        // start the gradient at the center left of the canvas, and end at the center right of the canvas\n        gradient = context.createLinearGradient(padding, height / 2, width + padding, height / 2);\n\n        // can just evenly space out the gradients in this case, as multiple lines makes no difference\n        // to an even left to right gradient\n        const totalIterations = fill.length + 1;\n        let currentIteration = 1;\n\n        for (let i = 0; i < fill.length; i++)\n        {\n            let stop: number;\n\n            if (typeof fillGradientStops[i] === 'number')\n            {\n                stop = fillGradientStops[i];\n            }\n            else\n            {\n                stop = currentIteration / totalIterations;\n            }\n            gradient.addColorStop(stop, fill[i]);\n            currentIteration++;\n        }\n    }\n\n    return gradient;\n}\n"],"names":[],"mappings":";;AAkBO,SAAA,iBAAA,CACH,MACA,EAAA,OAAA,EACA,KACA,EAAA,UAAA,EACA,OACA,OAEJ,EAAA;AAII,EAAA,MAAM,YAAgE,KAAM,CAAA,IAAA,CAAA;AAE5E,EAAA,IAAI,CAAC,KAAA,CAAM,OAAQ,CAAA,SAAS,CAC5B,EAAA;AACI,IAAO,OAAA,SAAA,CAAA;AAAA,GACX,MAAA,IACS,SAAU,CAAA,MAAA,KAAW,CAC9B,EAAA;AACI,IAAA,OAAO,SAAU,CAAA,CAAA,CAAA,CAAA;AAAA,GACrB;AAIA,EAAI,IAAA,QAAA,CAAA;AAIJ,EAAA,MAAM,oBAAwB,GAAA,KAAA,CAAM,UAAc,GAAA,KAAA,CAAM,kBAAqB,GAAA,CAAA,CAAA;AAG7E,EAAM,MAAA,OAAA,GAAU,MAAM,OAAW,IAAA,CAAA,CAAA;AAEjC,EAAA,MAAM,KAAS,GAAA,MAAA,CAAO,KAAQ,GAAA,UAAA,GAAc,uBAAwB,OAAU,GAAA,CAAA,CAAA;AAC9E,EAAA,MAAM,MAAU,GAAA,MAAA,CAAO,MAAS,GAAA,UAAA,GAAc,uBAAwB,OAAU,GAAA,CAAA,CAAA;AAGhF,EAAM,MAAA,IAAA,GAAO,UAAU,KAAM,EAAA,CAAA;AAC7B,EAAM,MAAA,iBAAA,GAAoB,KAAM,CAAA,iBAAA,CAAkB,KAAM,EAAA,CAAA;AAGxD,EAAI,IAAA,CAAC,kBAAkB,MACvB,EAAA;AACI,IAAM,MAAA,WAAA,GAAc,KAAK,MAAS,GAAA,CAAA,CAAA;AAElC,IAAA,KAAA,IAAS,CAAI,GAAA,CAAA,EAAG,CAAI,GAAA,WAAA,EAAa,EAAE,CACnC,EAAA;AACI,MAAkB,iBAAA,CAAA,IAAA,CAAK,IAAI,WAAW,CAAA,CAAA;AAAA,KAC1C;AAAA,GACJ;AAIA,EAAK,IAAA,CAAA,OAAA,CAAQ,UAAU,CAAE,CAAA,CAAA,CAAA;AACzB,EAAA,iBAAA,CAAkB,QAAQ,CAAC,CAAA,CAAA;AAE3B,EAAA,IAAA,CAAK,IAAK,CAAA,SAAA,CAAU,SAAU,CAAA,MAAA,GAAS,CAAE,CAAA,CAAA,CAAA;AACzC,EAAA,iBAAA,CAAkB,KAAK,CAAC,CAAA,CAAA;AAExB,EAAI,IAAA,KAAA,CAAM,gBAAqB,KAAA,aAAA,CAAc,eAC7C,EAAA;AAEI,IAAW,QAAA,GAAA,OAAA,CAAQ,qBAAqB,KAAQ,GAAA,CAAA,EAAG,SAAS,KAAQ,GAAA,CAAA,EAAG,SAAS,OAAO,CAAA,CAAA;AASvF,IAAA,IAAI,iBAAoB,GAAA,CAAA,CAAA;AAGxB,IAAA,MAAM,UAAa,GAAA,OAAA,CAAQ,cAAe,CAAA,QAAA,GAAW,KAAM,CAAA,eAAA,CAAA;AAG3D,IAAA,MAAM,qBAAqB,UAAa,GAAA,MAAA,CAAA;AAExC,IAAA,KAAA,IAAS,CAAI,GAAA,CAAA,EAAG,CAAI,GAAA,KAAA,CAAM,QAAQ,CAClC,EAAA,EAAA;AACI,MAAM,MAAA,WAAA,GAAc,QAAQ,UAAa,GAAA,CAAA,CAAA;AAEzC,MAAA,KAAA,IAAS,CAAI,GAAA,CAAA,EAAG,CAAI,GAAA,IAAA,CAAK,QAAQ,CACjC,EAAA,EAAA;AAEI,QAAA,IAAI,QAAW,GAAA,CAAA,CAAA;AAEf,QAAI,IAAA,OAAO,iBAAkB,CAAA,CAAA,CAAA,KAAO,QACpC,EAAA;AACI,UAAA,QAAA,GAAW,iBAAkB,CAAA,CAAA,CAAA,CAAA;AAAA,SAGjC,MAAA;AACI,UAAA,QAAA,GAAW,IAAI,IAAK,CAAA,MAAA,CAAA;AAAA,SACxB;AAEA,QAAM,MAAA,UAAA,GAAc,WAAc,GAAA,MAAA,GAAW,QAAW,GAAA,kBAAA,CAAA;AAGxD,QAAA,IAAI,WAAc,GAAA,IAAA,CAAK,GAAI,CAAA,iBAAA,EAAmB,UAAU,CAAA,CAAA;AAExD,QAAc,WAAA,GAAA,IAAA,CAAK,GAAI,CAAA,WAAA,EAAa,CAAC,CAAA,CAAA;AACrC,QAAS,QAAA,CAAA,YAAA,CAAa,WAAa,EAAA,IAAA,CAAK,CAAE,CAAA,CAAA,CAAA;AAC1C,QAAoB,iBAAA,GAAA,WAAA,CAAA;AAAA,OACxB;AAAA,KACJ;AAAA,GAGJ,MAAA;AAEI,IAAW,QAAA,GAAA,OAAA,CAAQ,qBAAqB,OAAS,EAAA,MAAA,GAAS,GAAG,KAAQ,GAAA,OAAA,EAAS,SAAS,CAAC,CAAA,CAAA;AAIxF,IAAM,MAAA,eAAA,GAAkB,KAAK,MAAS,GAAA,CAAA,CAAA;AACtC,IAAA,IAAI,gBAAmB,GAAA,CAAA,CAAA;AAEvB,IAAA,KAAA,IAAS,CAAI,GAAA,CAAA,EAAG,CAAI,GAAA,IAAA,CAAK,QAAQ,CACjC,EAAA,EAAA;AACI,MAAI,IAAA,IAAA,CAAA;AAEJ,MAAI,IAAA,OAAO,iBAAkB,CAAA,CAAA,CAAA,KAAO,QACpC,EAAA;AACI,QAAA,IAAA,GAAO,iBAAkB,CAAA,CAAA,CAAA,CAAA;AAAA,OAG7B,MAAA;AACI,QAAA,IAAA,GAAO,gBAAmB,GAAA,eAAA,CAAA;AAAA,OAC9B;AACA,MAAS,QAAA,CAAA,YAAA,CAAa,IAAM,EAAA,IAAA,CAAK,CAAE,CAAA,CAAA,CAAA;AACnC,MAAA,gBAAA,EAAA,CAAA;AAAA,KACJ;AAAA,GACJ;AAEA,EAAO,OAAA,QAAA,CAAA;AACX;;;;"}