コモノExtendScript100本ノック

超初心者のDTPオペレーターが週にひとつスクリプトを書くブログ

070.【Id】Type1フォントを指定したフォントに置換する

挙動

アクティブドキュメントにType1フォントが使用されていた場合、指定したフォントに置換する。
オプションでスタイルやグリッドフォーマットの設定も変更する。
f:id:haraguai_is_bad:20200414153800p:plain:w300

コード

//@targetengine "changeType1Font"

var main = function() {
    app.scriptPreferences.enableRedraw = false;
    var doc = app.activeDocument;
    var usedT1Fonts = [];
    for (var i = 0; i < doc.fonts.length; i++) {
        if (doc.fonts[i].fontType === FontTypes.TYPE_1) { //フォントタイプは任意で変更
            usedT1Fonts.push(doc.fonts[i].fontFamily + "\t" + doc.fonts[i].fontStyleName) //doc.fonts[i].nameをとるとスタイル名が重複するため
        }
    }
    if (usedT1Fonts.length === 0) {
        alert("Type1フォントは使われていません")
        exit();
    }

    var appFonts = [];
    for (var i = 0; i < app.fonts.length; i++) {
        try {
            if (app.fonts[i].fontType === FontTypes.OPENTYPE_TT) {
                appFonts.push(app.fonts[i].name)
            }
        } catch (e) {
            //FontTypeが取得できないフォントがある?
        }
    }

    // ScriptUI
    var dialog = new Window("dialog");
    dialog.text = "Type1フォント一括置換";
    dialog.preferredSize.width = 300;
    dialog.orientation = "column";
    dialog.alignChildren = ["fill", "top"];

    var panel2 = dialog.add("panel");
    panel2.text = "ドキュメントのフォント";
    panel2.orientation = "column";
    panel2.alignChildren = ["left", "top"];

    var dropdown3 = panel2.add("dropdownlist", undefined, undefined, {
        items: usedT1Fonts
    });
    dropdown3.preferredSize.width = 200;

    var panel1 = dialog.add("panel");
    panel1.text = "次で置換";
    panel1.orientation = "row";
    panel1.alignChildren = ["left", "top"];

    var group2 = panel1.add("group");
    group2.orientation = "column";
    group2.alignChildren = ["left", "center"];

    var dropdown1 = group2.add("dropdownlist", undefined, undefined, {
        items: appFonts
    });
    dropdown1.preferredSize.width = 200;

    var checkbox1 = group2.add("checkbox");
    checkbox1.text = "スタイルおよびグリッドフォーマットを再定義";

    var button1 = dialog.add("button")
    button1.text = "実行"
    button1.onClick = function() {
        dialog.close(1);
    }

    var dlgResult = dialog.show();
    if (dlgResult !== 1) {
        alert("中断しました");
        exit();
    }
    var changeFrom = app.fonts.itemByName(dropdown3.selection.text);
    var changeTo = app.fonts.itemByName(dropdown1.selection.text);

    //レイヤーのロックを一時的に解除
    var layersInfo = [];
    for (var i = 0; i < doc.layers.length; i++) {
        layersInfo.push({
            obj: doc.layers[i],
            locked: doc.layers[i].locked
        });
    }
    doc.layers.everyItem().locked = false;

    //検索置換
    myChangeGrep(".+", "$0");

    //レイヤーのロックを戻す
    for (var i = 0; i < layersInfo.length; i++) {
        layersInfo[i]['obj'].locked = layersInfo[i]['locked'];
    }

    if (!checkbox1.value) {
        alert("完了しました");
        exit();
    }

    //文字スタイル変更
    var cStyles = doc.allCharacterStyles;
    for (var i = 0; i < cStyles.length; i++) {
        if (cStyles[i].appliedFont === changeFrom) {
            cStyles[i].appliedFont = changeTo;
        }
    }

    //段落スタイル変更
    var pStyles = doc.allParagraphStyles;
    for (var i = 0; i < pStyles.length; i++) {
        if (pStyles[i].appliedFont === changeFrom) {
            pStyles[i].appliedFont = changeTo;
        }
    }

    //フレームグリッド設定変更
    var st = doc.stories;
    for (var i = 0; i < st.length; i++) {
        //テキストフレームを回避
        try {
            if (st[i].gridData.appliedFont === changeFrom) {
                st[i].gridData.appliedFont = changeTo;
            }
        } catch (e) {}
    }

    alert("完了しました");


    //検索置換
    function myChangeGrep(findStr, changeStr) {
        app.findChangeGrepOptions.includeMasterPages = true;
        app.findChangeGrepOptions.includeFootnotes = true;
        app.findGrepPreferences = NothingEnum.NOTHING;
        app.findGrepPreferences.appliedFont = changeFrom;
        app.changeGrepPreferences = NothingEnum.NOTHING;
        app.changeGrepPreferences.appliedFont = changeTo;
        app.findGrepPreferences.findWhat = findStr;
        app.changeGrepPreferences.changeTo = changeStr;
        var result = app.changeGrep();
        app.findGrepPreferences = NothingEnum.NOTHING;
        app.changeGrepPreferences = NothingEnum.NOTHING;
        return result;
    }

}

app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.FAST_ENTIRE_SCRIPT, "changeType1Font.jsx");

メモ

分かったこと

gridDataを扱うときは親に注意する。
storyののgridDataで設定できてもtextFrameのgridDataでは設定できないプロパティもある。
InDesignを手で操作するときと同じ。

積み残し

  • システムフォントの取得がものすごーーく遅い。
  • ロックされたオブジェクト・非表示オブジェクトは対象外としている。前者は対象に含めた方がよいかもしれない。
  • テキストフレームは回避してフレームグリッドだけ扱いたい場合の処理。try~catchで逃げたけどあまりよくない気がする。
  • FontTypeが取得できないフォントがある?UNKNOWNにもならず、undefinedになる。

参考