function draw(g, state, drawInfo) {
    var x = drawInfo.texArea[0];
    var y = drawInfo.texArea[1];
    var w = drawInfo.texArea[2] - drawInfo.texArea[0];
    var h = drawInfo.texArea[3] - drawInfo.texArea[1];
    const headAlign = drawInfo.arrowDirection ? Number(drawInfo.arrowDirection) : 0;
    var routeInfo = drawInfo.routeInfo;
    g.setColor(Color.WHITE);
    g.fillRect(x, y, w, h);
    if (routeInfo != null && routeInfo != undefined) {
        const terminalStnDL = getNonExtraParts(routeInfo.drawStations[routeInfo.drawStations.length - 1].stationName);
        const terStaName = parseStr(terminalStnDL);
        const font = loadResource("font", "mtrsteamloco:fonts/simhei.otf");
        const fontEN = loadResource("font", "mtrsteamloco:fonts/arial.ttf");
        if (drawInfo.index == routeInfo.drawStations.length - 1) {
            drawStrDL(g, font, fontEN, "终点站|Terminus", widthPercent(0.5), heightPercent(0.25), h * 0.4, 1, 1);
        } else {
            const routeName = routeInfo.routeName;
            const match = routeName.match(/^([A-Za-z]*\d*|.)(.+)$/);
            const routeNumber = match != null ? match[1] : "";
            const routeSuffix = match != null ? match[2] : "";
            const routeSuffixParse = parseStr(routeSuffix);
            const origRouteNumberWidth = getDLStringWidth(g, fontEN, fontEN, routeNumber, h * 0.35);
            const maxNumWidth = getDLStringWidth(g, fontEN, fontEN, "99", h * 0.35);
            const routeNumberWidth = origRouteNumberWidth > maxNumWidth * 0.9 ? maxNumWidth * 0.9 : origRouteNumberWidth;
            const oldTransform = g.getTransform();
            if (headAlign == 0 || headAlign == 1) {
                g.drawImage(changeImageColor(loadResource("img", "fangsu:sign/jtl.png"), routeInfo.routeColor), widthPercent(0.1), heightPercent(0.3), h * 0.4, h * 0.4, null);
                g.setColor(Color.BLACK);
                drawStrDL(g, font, fontEN, `往${terStaName[0]}|To ${terStaName[1]}`, widthPercent(0.1) + h * 0.45, heightPercent(0.3), h * 0.375, 0, 0);
                if (routeNumber != "") {
                    g.setColor(Color.BLACK);
                    drawStrDL(g, font, fontEN, `${routeSuffixParse[0]}|${routeSuffixParse[1]}`, widthPercent(0.8), heightPercent(0.3), h * 0.375, 0, 0);
                    g.setColor(routeInfo.routeColor);
                    g.fillRoundRect(widthPercent(0.8) - h * 0.4, heightPercent(0.325), h * 0.375, h * 0.375, h * 0.1, h * 0.1);
                    g.setColor(Color.WHITE);
                    g.translate(widthPercent(0.8) - h * 0.4 + h * 0.375 / 2, heightPercent(0.3) + h * 0.35);
                    g.scale(routeNumberWidth / origRouteNumberWidth, 1.0);
                    g.translate(-(widthPercent(0.8) - h * 0.4 + h * 0.375 / 2), - (heightPercent(0.3) + h * 0.35));
                    drawStrUnified(g, fontEN, routeNumber, widthPercent(0.8) - h * 0.4 + h * 0.375 / 2, heightPercent(0.3) + h * 0.35, h * 0.35, 1);
                    g.setTransform(oldTransform);
                } else {
                    var routeDL = parseStr(routeName);
                    var origCNWidth = getDLStringWidth(g, font, font, routeDL[0], h * 0.25);
                    var origENWidth = getDLStringWidth(g, fontEN, fontEN, routeDL[1], h * 0.1);
                    var maxWidth = getDLStringWidth(g, font, font, "四个汉字", h * 0.25);
                    var CNWidth = origCNWidth > maxWidth ? maxWidth : origCNWidth;
                    var ENWidth = origENWidth > maxWidth ? maxWidth : origENWidth;
                    var rectWidth = CNWidth > ENWidth ? CNWidth : ENWidth;
                    g.setColor(routeInfo.routeColor);
                    g.fillRoundRect(widthPercent(0.8) - (rectWidth + h * 0.1) / 2, heightPercent(0.325), rectWidth + h * 0.1, h * 0.375, h * 0.1, h * 0.1);
                    g.setColor(Color.WHITE);
                    g.translate(widthPercent(0.8), heightPercent(0.3) + h * 0.27);
                    g.scale(CNWidth / origCNWidth, 1.0);
                    g.translate(-(widthPercent(0.8)), - (heightPercent(0.3) + h * 0.27));
                    drawStrUnified(g, font, routeDL[0], widthPercent(0.8), heightPercent(0.3) + h * 0.27, h * 0.25, 1);
                    g.setTransform(oldTransform);
                    g.translate(widthPercent(0.8), heightPercent(0.3) + h * 0.375);
                    g.scale(ENWidth * 0.9 / origENWidth, 1.0);
                    g.translate(-(widthPercent(0.8)), - (heightPercent(0.3) + h * 0.375));
                    drawStrUnified(g, fontEN, routeDL[1], widthPercent(0.8), heightPercent(0.3) + h * 0.375, h * 0.1, 1);
                    g.setTransform(oldTransform);
                }
            } else {
                g.drawImage(changeImageColor(loadResource("img", "fangsu:sign/jtr.png"), routeInfo.routeColor), widthPercent(0.9) - h * 0.4, heightPercent(0.3), h * 0.4, h * 0.4, null);
                g.setColor(Color.BLACK);
                drawStrDL(g, font, fontEN, `往${terStaName[0]}|To ${terStaName[1]}`, widthPercent(0.9) - h * 0.45, heightPercent(0.3), h * 0.375, 2, 2);
                if (routeNumber != "") {
                    g.setColor(routeInfo.routeColor);
                    g.fillRoundRect(widthPercent(0.1), heightPercent(0.325), h * 0.375, h * 0.375, h * 0.1, h * 0.1);
                    g.setColor(Color.WHITE);
                    g.translate(widthPercent(0.1) + h * 0.375 / 2, heightPercent(0.3) + h * 0.35);
                    g.scale(routeNumberWidth / origRouteNumberWidth, 1.0);
                    g.translate(-(widthPercent(0.1) + h * 0.375 / 2), - (heightPercent(0.3) + h * 0.35));
                    drawStrUnified(g, fontEN, routeNumber, widthPercent(0.1) + h * 0.375 / 2, heightPercent(0.3) + h * 0.35, h * 0.35, 1);
                    g.setTransform(oldTransform);
                    g.setColor(Color.BLACK);
                    drawStrDL(g, font, fontEN, `${routeSuffixParse[0]}|${routeSuffixParse[1]}`, widthPercent(0.1) + h * 0.4, heightPercent(0.3), h * 0.375, 0, 0);
                } else {
                    var routeDL = parseStr(routeName);
                    var origCNWidth = getDLStringWidth(g, font, font, routeDL[0], h * 0.25);
                    var origENWidth = getDLStringWidth(g, fontEN, fontEN, routeDL[1], h * 0.1);
                    var maxWidth = getDLStringWidth(g, font, font, "四个汉字", h * 0.25);
                    var CNWidth = origCNWidth > maxWidth ? maxWidth : origCNWidth;
                    var ENWidth = origENWidth > maxWidth ? maxWidth : origENWidth;
                    var rectWidth = CNWidth > ENWidth ? CNWidth : ENWidth;
                    g.setColor(routeInfo.routeColor);
                    g.fillRoundRect(widthPercent(0.2) - (rectWidth + h * 0.1) / 2, heightPercent(0.325), rectWidth + h * 0.1, h * 0.375, h * 0.1, h * 0.1);
                    g.setColor(Color.WHITE);
                    g.translate(widthPercent(0.2), heightPercent(0.3) + h * 0.27);
                    g.scale(CNWidth / origCNWidth, 1.0);
                    g.translate(-(widthPercent(0.2)), - (heightPercent(0.3) + h * 0.27));
                    drawStrUnified(g, font, routeDL[0], widthPercent(0.2), heightPercent(0.3) + h * 0.27, h * 0.25, 1);
                    g.setTransform(oldTransform);
                    g.translate(widthPercent(0.2), heightPercent(0.3) + h * 0.375);
                    g.scale(ENWidth * 0.9 / origENWidth, 1.0);
                    g.translate(-(widthPercent(0.2)), - (heightPercent(0.3) + h * 0.375));
                    drawStrUnified(g, fontEN, routeDL[1], widthPercent(0.2), heightPercent(0.3) + h * 0.375, h * 0.1, 1);
                    g.setTransform(oldTransform);
                }
            }
        }
    }
    function widthPercent(p) {
        return x + w * p;
    }
    function heightPercent(p) {
        return y + h * p;
    }
    function parseStr(src) {
        return String(src).split('|');
    }
}