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];
    var routeInfo = drawInfo.routeInfo;
    g.setColor(Color.WHITE);
    g.fillRect(x, y, w, h);
    if (routeInfo != null && routeInfo != undefined) {
        const thisStn = routeInfo.drawStations[drawInfo.index];
        const thisStnDL = getNonExtraParts(thisStn.stationName);
        const font = loadResource("font", "mtrsteamloco:fonts/simhei.otf");
        const fontEN = loadResource("font", "mtrsteamloco:fonts/arial.ttf");
        const stationName = parseStr(thisStnDL);
        const maxWidth = getDLStringWidth(g, font, font, "长度上限六字", h * 0.26);
        const origCNWidth = getDLStringWidth(g, font, font, stationName[0], h * 0.26);
        const origENWidth = getDLStringWidth(g, fontEN, fontEN, stationName[1], h * 0.15);
        const stnCNWidth = origCNWidth > maxWidth ? maxWidth : origCNWidth;
        const stnENWidth = origENWidth > maxWidth ? maxWidth : origENWidth;
        const mixRoundRect = getDLStringWidth(g, font, font, "wwwwwwwwwwww", h * 0.135);
        var RoundRect = stnENWidth;
        if (stnCNWidth > stnENWidth) RoundRect = stnCNWidth;
        if (RoundRect < mixRoundRect) RoundRect = mixRoundRect;
        g.setColor(routeInfo.routeColor);
        const roundRectX = widthPercent(0.5) - (RoundRect + h * 0.6) / 2;
        g.fillRoundRect(roundRectX, heightPercent(0.25), RoundRect + h * 0.6, h * 0.5, h * 0.5, h * 0.5);
        g.setColor(Color.WHITE);
        const oldTransform = g.getTransform();
        g.translate(widthPercent(0.5), heightPercent(0.5));
        g.scale(stnCNWidth / origCNWidth, 1.0);
        g.translate(-widthPercent(0.5), -heightPercent(0.5));
        drawStrUnified(g, font, stationName[0], widthPercent(0.5), heightPercent(0.5), h * 0.26, 1);
        g.setTransform(oldTransform);
        g.translate(widthPercent(0.5), heightPercent(0.7));
        g.scale(stnENWidth / origENWidth, 1.0);
        g.translate(-widthPercent(0.5), -heightPercent(0.7));
        drawStrUnified(g, fontEN, stationName[1], widthPercent(0.5), heightPercent(0.7), h * 0.125, 1);
        g.setTransform(oldTransform);
        g.fillRect(widthPercent(0.5) - (RoundRect + h * 0.3) / 2, heightPercent(0.55), RoundRect + h * 0.3, h * 0.025);
        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 routeSuffixStr = routeSuffixParse[0] + "|" + routeSuffixParse[1];
        if (routeNumber != "") {
            const maxSuffixWidth = getDLStringWidth(g, font, fontEN, "号线|Line 99", h * 0.2);
            const origRouteSuffixWidth = getDLStringWidth(g, font, fontEN, routeSuffixStr, h * 0.2);
            const routeSuffixWidth = origRouteSuffixWidth > maxSuffixWidth ? maxSuffixWidth : origRouteSuffixWidth;
            const maxNumWidth = getDLStringWidth(g, fontEN, fontEN, "9", h * 0.375) * 0.9;
            const origRouteNumberWidth = getDLStringWidth(g, fontEN, fontEN, routeNumber, h * 0.4);
            const routeNumberWidth = origRouteNumberWidth > maxNumWidth ? maxNumWidth : origRouteNumberWidth;
            g.setColor(routeInfo.routeColor);
            g.fillOval(roundRectX - h * 0.6, heightPercent(0.25), h * 0.5, h * 0.5);
            g.setColor(Color.WHITE);
            g.fillOval(roundRectX - h * 0.6 + h * 0.025, heightPercent(0.25) + h * 0.025, h * 0.45, h * 0.45);
            g.setColor(Color.BLACK);
            g.translate(roundRectX - routeSuffixWidth - h * 0.11, heightPercent(0.425));
            g.scale(routeSuffixWidth / origRouteSuffixWidth, 1.0);
            g.translate(-(roundRectX - routeSuffixWidth - h * 0.11), -heightPercent(0.425));
            drawStrDL(g, font, fontEN, routeSuffixStr, roundRectX - routeSuffixWidth - h * 0.11, heightPercent(0.425), h * 0.175, 0, 0);
            g.setTransform(oldTransform);
            g.translate(roundRectX - routeSuffixWidth - h * 0.11, heightPercent(0.625));
            g.scale(routeNumberWidth / origRouteNumberWidth, 1.0);
            g.translate(-(roundRectX - routeSuffixWidth - h * 0.11), -heightPercent(0.625));
            drawStrUnified(g, fontEN, routeNumber, roundRectX - routeSuffixWidth - h * 0.11, heightPercent(0.625), h * 0.375, 2);
            g.setTransform(oldTransform);
        } else {
            const maxRouteNameWidth = getDLStringWidth(g, font, fontEN, "三个字|w", h * 0.25);
            const origRouteNameWidth = getDLStringWidth(g, font, fontEN, routeName, h * 0.25);
            const routeNameWidth = origRouteNameWidth > maxRouteNameWidth ? maxRouteNameWidth : origRouteNameWidth;
            g.setColor(routeInfo.routeColor);
            g.fillOval(roundRectX - h * 0.6, heightPercent(0.25), h * 0.5, h * 0.5);
            g.setColor(Color.WHITE);
            g.fillOval(roundRectX - h * 0.6 + h * 0.025, heightPercent(0.25) + h * 0.025, h * 0.45, h * 0.45);
            g.setColor(Color.BLACK);
            g.translate(roundRectX - routeNameWidth / 2 - h * 0.11, heightPercent(0.4));
            g.scale(routeNameWidth / origRouteNameWidth, 1.0);
            g.translate(-(roundRectX - routeNameWidth / 2 - h * 0.11), -heightPercent(0.4));
            drawStrDL(g, font, fontEN, routeName, roundRectX - routeNameWidth / 2 - h * 0.11, heightPercent(0.4), h * 0.2, 1, 1);
        }
    }
    function widthPercent(p) {
        return x + w * p;
    }
    function heightPercent(p) {
        return y + h * p;
    }
    function parseStr(src) {
        return String(src).split('|');
    }
}