// 
// Font distance readabilty calculator
// v.1.0
// 3.4 mm Cap height = 1 m distance 
// 
// Author: Alex Kolodko with ChatGPT 3.5
// Contacts: alexkolodko.com
// Github: https://github.com/alexkolodko/adobe-scripts
// 

#target illustrator

// Function to calculate the cap height, x-height, and reading distance
function getTextMetrics(textSize, scaleMultiplier) {
    // Conversion factor from points to millimeters
    var pointsToMillimeters = 0.352778;

    // Calculate scaled text size
    var scaledTextSize = textSize * scaleMultiplier;

    // Assuming 70% of the font size is x-height and 70-80% is the typical range for cap height
    var capHeightPoints = scaledTextSize * 0.7; // Adjust this ratio if necessary
    var xHeightPoints = scaledTextSize * 0.5;

    // Convert points to millimeters
    var capHeightMM = capHeightPoints * pointsToMillimeters;
    var xHeightMM = xHeightPoints * pointsToMillimeters;

    // Calculate reading distance (e.g., 3.4 times the cap height)
    var readingDistance = capHeightMM / 3.4;

    return { textSize: scaledTextSize, xHeight: xHeightMM, capHeight: capHeightMM, readingDistance: readingDistance };
}

// Function to write metrics as text frames near selection
function writeMetricsAsTextFrames(metrics, position) {
    var sel = app.activeDocument.selection;

    if (sel.length > 0) {
        var textFrames = [];
        for (var i = 0; i < sel.length; i++) {
            var textFrame = app.activeDocument.activeLayer.textFrames.add();
            textFrame.contents = "Text Size:\t" + metrics.textSize.toFixed(2) + " pt\n" + // (" + (metrics.textSize * 0.352778).toFixed(2) + " mm)
                                 "Cap height:\t" + metrics.capHeight.toFixed(2) + " mm\n" +
                                 "x-height:\t" + metrics.xHeight.toFixed(2) + " mm\n" +
                                 "Distance:\t~" + metrics.readingDistance.toFixed(2) + " m";
            if (position === "below") {
                textFrame.top = sel[i].top - sel[i].height - 14;
                textFrame.left = sel[i].left;
            } else if (position === "above") {
                textFrame.top = sel[i].top + (14*4+7);
                textFrame.left = sel[i].left;
            }
            textFrames.push(textFrame);
        }
        app.activeDocument.selection = textFrames;
    } else {
        alert("Please make a selection.");
    }
}

// Main function
function main() {
    var doc = app.activeDocument;
    var sel = doc.selection;

    if (sel.length > 0 && sel[0].typename == 'TextFrame') {
        var textFrame = sel[0];
        var textSize = textFrame.textRange.characterAttributes.size;

        // Initial scale multiplier
        var scaleMultiplier = 1;

        // Calculate initial metrics
        var metrics = getTextMetrics(textSize, scaleMultiplier);

        // Create a dialog box to display results
        var dialog = new Window("dialog", "Font Distance Readability");
        dialog.orientation = "column";
        dialog.alignChildren = ["fill", "fill"];

        // Row group for Text Size
        var textSizeGroup = dialog.add("group");
        textSizeGroup.orientation = "row";
        var textSizeLabel = textSizeGroup.add("statictext", undefined, "Font Size:");
        textSizeLabel.preferredSize.width = 75; 
        var textSizeInput = textSizeGroup.add("edittext", undefined, metrics.textSize.toFixed(2) + " pt");
        textSizeInput.preferredSize.width = 175; 
        textSizeInput.enabled = true;

        // Row group for Cap Height
        var capHeightGroup = dialog.add("group");
        capHeightGroup.orientation = "row";
        var capHeightLabel = capHeightGroup.add("statictext", undefined, "Cap height:");
        capHeightLabel.preferredSize.width = 75; 
        var capHeightInput = capHeightGroup.add("edittext", undefined, metrics.capHeight.toFixed(2) + " mm");
        capHeightInput.preferredSize.width = 175; 
        capHeightInput.enabled = true;

        // Row group for X-height
        var xHeightGroup = dialog.add("group");
        xHeightGroup.orientation = "row";
        var xHeightLabel = xHeightGroup.add("statictext", undefined, "x-height:");
        xHeightLabel.preferredSize.width = 75; 
        var xHeightInput = xHeightGroup.add("edittext", undefined, metrics.xHeight.toFixed(2) + " mm");
        xHeightInput.preferredSize.width = 175; 
        xHeightInput.enabled = true;

        // Row group for Reading Distance
        var readingDistanceGroup = dialog.add("group");
        readingDistanceGroup.orientation = "row";
        var readingDistanceLabel = readingDistanceGroup.add("statictext", undefined, "Distance:");
        readingDistanceLabel.preferredSize.width = 75; 
        var readingDistanceInput = readingDistanceGroup.add("edittext", undefined, "~" + metrics.readingDistance.toFixed(2) + " m");
        readingDistanceInput.preferredSize.width = 175; 
        readingDistanceInput.enabled = true;
        readingDistanceInput.active = true;

       // Radio buttons group for scale multiplier
        var scaleMultiplierGroup = dialog.add("group");
        scaleMultiplierGroup.orientation = "row";
        var scaleLabel = scaleMultiplierGroup.add("statictext", undefined, "Scale 1:x");
        scaleLabel.preferredSize.width = 75; 
        var scaleRadios = [];
        var scaleValues = [1, 10, 100];
        for (var i = 0; i < scaleValues.length; i++) {
            var scaleRadio = scaleMultiplierGroup.add("radiobutton", undefined, scaleValues[i].toString());
            scaleRadio.value = i == 0; // Select the first option by default
            scaleRadios.push(scaleRadio);
        }

        // Event listener for scale radio buttons
        for (var i = 0; i < scaleRadios.length; i++) {
            scaleRadios[i].onClick = function() {
                var selectedScale = parseInt(this.text);
                updateMetrics(selectedScale);
            };
        }

        // Function to update metrics based on the selected scale
        function updateMetrics(selectedScale) {
            scaleMultiplier = selectedScale;
            metrics = getTextMetrics(textSize, scaleMultiplier);
            textSizeInput.text = metrics.textSize.toFixed(2) + " pt"; // (" + (metrics.textSize * 0.352778).toFixed(2) + " mm)
            capHeightInput.text = metrics.capHeight.toFixed(2) + " mm";
            xHeightInput.text = metrics.xHeight.toFixed(2) + " mm";
            readingDistanceInput.text = "~" + metrics.readingDistance.toFixed(2) + " m";
        }

        // Group row for two buttons: Paste as Text Above & Paste as Text Below
        var pasteGroup = dialog.add("group");
        pasteGroup.orientation = "row";
        
        pasteGroup.add("statictext", undefined, "Paste as Text:");

        var pasteAboveButton = pasteGroup.add("button", undefined, "Above");
        pasteAboveButton.onClick = function () {
            writeMetricsAsTextFrames(metrics, "above");
            dialog.close();
        };

        var pasteBelowButton = pasteGroup.add("button", undefined, "Below");
        pasteBelowButton.onClick = function () {
            writeMetricsAsTextFrames(metrics, "below");
            dialog.close();
        };
        // Button to close the dialog
        var closeButton = dialog.add("button", undefined, "Close");
        closeButton.onClick = function () {
            dialog.close();
        };

        // Show the dialog
        dialog.show();
    } else {
        alert("Please select a text frame.");
    }
}

// Execute the main function
main();
