static Font selectSmallFont()

in src/agent/ConsoleFont.cc [508:600]


static Font selectSmallFont(int codePage, int columns, bool isNewW10) {
    // Iterate over a set of font sizes according to the code page, and select
    // one.

    const wchar_t *faceName = nullptr;
    unsigned int fontFamily = 0;
    const FontSize *table = nullptr;
    size_t tableSize = 0;

    switch (codePage) {
        case 932: // Japanese
            faceName = kMSGothic;
            fontFamily = 0x36;
            if (isNewW10) {
                table = k932GothicWin10;
                tableSize = COUNT_OF(k932GothicWin10);
            } else if (isAtLeastWindows8()) {
                table = k932GothicWin8;
                tableSize = COUNT_OF(k932GothicWin8);
            } else {
                table = k932GothicVista;
                tableSize = COUNT_OF(k932GothicVista);
            }
            break;
        case 936: // Chinese Simplified
            faceName = kNSimSun;
            fontFamily = 0x36;
            table = k936SimSun;
            tableSize = COUNT_OF(k936SimSun);
            break;
        case 949: // Korean
            faceName = kGulimChe;
            fontFamily = 0x36;
            table = k949GulimChe;
            tableSize = COUNT_OF(k949GulimChe);
            break;
        case 950: // Chinese Traditional
            faceName = kMingLight;
            fontFamily = 0x36;
            table = k950MingLight;
            tableSize = COUNT_OF(k950MingLight);
            break;
        default:
            faceName = kLucidaConsole;
            fontFamily = 0x36;
            table = kLucidaFontSizes;
            tableSize = COUNT_OF(kLucidaFontSizes);
            break;
    }

    size_t bestIndex = static_cast<size_t>(-1);
    std::tuple<int, int> bestScore = std::make_tuple(-1, -1);

    // We might want to pick the smallest possible font, because we don't know
    // how large the monitor is (and the monitor size can change).  We might
    // want to pick a larger font to accommodate console programs that resize
    // the console on their own, like DOS edit.com, which tends to resize the
    // console to 80 columns.

    for (size_t i = 0; i < tableSize; ++i) {
        const int width = table[i].width * columns;

        // In general, we'd like to pick a font size where cutting the number
        // of columns in half doesn't immediately violate the minimum width
        // constraint.  (e.g. To run DOS edit.com, a user might resize their
        // terminal to ~100 columns so it's big enough to show the 80 columns
        // post-resize.)  To achieve this, give priority to fonts that allow
        // this halving.  We don't want to encourage *very* large fonts,
        // though, so disable the effect as the number of columns scales from
        // 80 to 40.
        const int halfColumns = std::min(columns, std::max(40, columns / 2));
        const int halfWidth = table[i].width * halfColumns;

        std::tuple<int, int> thisScore = std::make_tuple(-1, -1);
        if (width >= 160 && halfWidth >= 160) {
            // Both sizes are good.  Prefer the smaller fonts.
            thisScore = std::make_tuple(2, -width);
        } else if (width >= 160) {
            // Prefer the smaller fonts.
            thisScore = std::make_tuple(1, -width);
        } else {
            // Otherwise, prefer the largest font in our table.
            thisScore = std::make_tuple(0, width);
        }
        if (thisScore > bestScore) {
            bestIndex = i;
            bestScore = thisScore;
        }
    }

    ASSERT(bestIndex != static_cast<size_t>(-1));
    return Font { faceName, fontFamily, table[bestIndex].size };
}