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) {
        var thisStn = routeInfo.drawStations[drawInfo.index];

        var font = loadResource("font", "mtrsteamloco:fonts/source-han-sans.otf");
        var fontBold = loadResource("font", "mtrsteamloco:fonts/source-han-sans-bold.otf");

        g.setColor(routeInfo.routeColor);
        if (isNumLine(routeInfo.routeName) && hasCjkPart(routeInfo.routeName) && hasNonCjkPart(routeInfo.routeName)) {
            var currentX = widthPercent(0.1) + drawStrUnified(g, fontBold, String(getCJKLineName(getMatching(routeInfo.routeName, true))), widthPercent(0.1), heightPercent(0.725), h * 0.2, 0);
            drawStrDL(g, fontBold, font, `号线|${getMatching(routeInfo.routeName, false)}`, currentX, heightPercent(0.525), h * 0.2, 0, 0);
            currentX = widthPercent(0.9) - drawStrDL(g, fontBold, font, `号线|${getMatching(routeInfo.routeName, false)}`, widthPercent(0.9), heightPercent(0.525), h * 0.2, 2, 0);
            widthPercent(0.1) + drawStrUnified(g, fontBold, String(getCJKLineName(getMatching(routeInfo.routeName, true))), currentX, heightPercent(0.725), h * 0.225, 2);
        } else {
            drawStrDL(g, fontBold, font, routeInfo.routeName, widthPercent(0.1), heightPercent(0.525), h * 0.2, 0, 1);
            drawStrDL(g, fontBold, font, routeInfo.routeName, widthPercent(0.9), heightPercent(0.525), h * 0.2, 2, 1);
        }

        g.setColor(Color.BLACK);
        drawStrDL(g, fontBold, font, thisStn.stationName, widthPercent(0.5), heightPercent(0.275), h * 0.45, 1, 1);
    }

    function widthPercent(p) {
        return x + w * p;
    }
    function heightPercent(p) {
        return y + h * p;
    }
}
