private void calculateCharWidths(BufferedImage fontTexture, int width, int height) {
        int[] fontData = new int[width * height];
        fontTexture.getRGB(0, 0, width, height, fontData, 0, width);
        int maxCharWidth = width / 16;
        int maxCharHeight = height / 16;

        for (int character = 0; character < 128; ++character) {
            int col = character % 16;
            int row = character / 16;
            int offset = (col * maxCharWidth) + (row * maxCharHeight * width);

            if (character == 32) {
                // Space is always 33% width
                charWidths[32] = maxCharWidth / 3;
            } else {
                // Other chars' width is determined by examining pixels
                // First, find start of character (left-most non-empty column)
                int chStart = 0;
                for (int c = 0; c < maxCharWidth; c++) {
                    chStart = c;
                    if (!isColEmpty(fontData, offset + c, width, maxCharHeight)) {
                        break;
                    }
                }
                // Next, find end of character (right-most non-empty column)
                int chEnd = maxCharWidth - 1;
                for (int c = maxCharWidth - 1; c >= chStart; c--) {
                    chEnd = c;
                    if (!isColEmpty(fontData, offset + c, width, maxCharHeight)) {
                        break;
                    }
                }

                charOffsets[character] = chStart;
                charWidths[character] = chEnd - chStart + 1;
            }
        }
    }