マクロツイーター

はてダから移行した記事の表示が崩れてますが、そのうちに直せればいいのに(えっ)

チョット arara してみた件

arara とは

簡単に言うと、arara とは「LaTeX 用ビルドツール」の一種であり、つまり、latexmk と同類のツールである。

arara の一番の特徴は「やりたいことを明示する」という点である。latexmk がコンパイルの手順を暗黙的に決めている点が多いのに対し、arara では手順を書いたファイルを事前に用意する必要がある。(ただし、pdflatex や biber などの有名なツールに対する手順ファイルはソフトウェア配布に含まれている。)

また、arara では文書ファイルにどの手順を適用すべきかも明示する必要がある。このために、文書ファイルの先頭にコメントの形で指示を記述する。例えば、下記のコメント行をファイルの先頭に書くと、そのファイルには pdflatex 用の手順が適用されることになる。

% arara: pdflatex

さっそく arara で文書をコンパイルしてみた

準備

TeX Live 2018 には arara が含まれているので、これを利用することにする。

arara は Java で実装されているので、Java 処理系(JRE)のインストールが必要である。

今回は、カスタムの設定を利用するので、そのための前設定を行う。以下、ホームディレクトリ(Windows では %UserProfile%)を ~ で表す。

  • カスタム設定用のディレクト~/.arara/rules を作成する。
  • カスタム設定を有効にするために、以下の内容の設定ファイル(YAML 形式)を ~/araraconfig.yaml に配置する。((“@{userhome}”がホームディレクトリを表す。YAML 形式の文法的制約のため、@{...} を含む値を記述する場合には、特に意味の無いタグ <arara> を前置する必要があるらしい。))

    [araraconfig.yaml]
    !config
    paths:
    - <arara> @{userhome}/.arara/rules
    filetypes:
    - extension: saty
      pattern: "^\\s*%\\s+"
    
カスタムの規則を作成する

先ほど説明したような“コンパイルの手順”のことを、arara では「規則」(rule)と呼ぶ。規則は YAML 形式のファイルを用いて定義される。

ここでは以下のような規則を作成した。

[satysfi.yaml]
!config
identifier: satysfi
name: SATySFi
command: <arara> satysfi @{fullpath} "@{file}"
arguments:
- identifier: fullpath
  flag: <arara> @{isTrue(parameters.fullpath,"--full-path")}

このファイルを ~/.arara/rules/satysfi.yaml に配置した。

文書に“指令”を追加する

arara で文書をコンパイルする場合、文書の先頭に所望の動作をコメントの形で書き込む。このコメント行のことを「指令」(directive)という。最も単純な形では指令は以下のようになる。

% arara: <規則名>

ここでは次のような文書ファイルを用意した。

[araratest.saty]
% arara: satysfi
@require: stdja

StdJa.document (|
  title = {とにかくararaしてみる};
  author = {某ZR};
  show-title = true;
  show-toc = false;
|) '<
  +pn {※ただし\TeX;以外}
>
文書を arara する

それでは、arara を起動して先ほどの文書 araratest.saty をコンパイルしてみよう。以下のコマンドを実行する。

arara araratest

実行結果は……

  __ _ _ __ __ _ _ __ __ _
 / _` | '__/ _` | '__/ _` |
| (_| | | | (_| | | | (_| |
 \__,_|_|  \__,_|_|  \__,_|

Running SATySFi... SUCCESS

……どうやら無事に arara できたようである。


ZR「いやだって、arara で TeX 文書をコンパイルしてもネタにならないじゃん」
*「そもそも SATySFi を出せば何でもネタになるという発想がアレ」
ZR「………………」

LuaLaTeX で和文しない速さを調べてみた

風評が流れるのは憂慮すべきことである。

そういうわけで、欧文の LuaLaTeX のコンパイル速度について、簡単に調べてみることにする。

実験してみた

実験方法
  • テスト用文書として「世界人権宣言(UDHR)の英語の全文を 50 回記したもの」(udhrmain.tex)を使う。レターサイズで 313 ページ。
  • Windows 10 + TeX Live 2018 の環境において、pdfLaTeX と LuaLaTeXコンパイル所要時間を比較する。
  • 3 回予備で実行した後、9 回実行して所要時間を計測、その中間にある 5 回分の平均値を求めた。
実験結果
  • pdfLaTeX: 1.497 秒
  • LuaLateX: 5.560 秒

LuaLaTeX の方が 3.71 倍遅い

※生データは result.txt の通り。

まとめ

というわけで、「LuaTeX(LuaTeX-ja ではない)のタイプセットは遅い」という風評が打破されて、代わりに「LuaTeX(LuaTeX-ja ではない)のタイプセットは遅い」という知見が確立された。めでたしめでたし。

TeX Live 2018 で日本語ファイル名するとアレ(1)

TeX Live 2018 において「入力エンコーディングの既定値を UTF-8 にする」という重要な変更が行われた(参考)。その副作用として、「LaTeX 起動時に、非 ASCII 文字を含む文書ファイル名を使うとエラーになる」という不具合が報告されている。

(不具合の例)
C>uplatex TeXはアレ.tex
This is e-upTeX, Version 3.14159265-p3.8.1-u1.23-180226-2.6 (utf8.uptex) (TeX Li
ve 2018/W32TeX) (preloaded format=uplatex)
 restricted \write18 enabled.
entering extended mode
! I can't find file `TeX'.
<to be read again>
                   \protect
<*> TeX
        ヘアレ.tex
(Press Enter to retry, or Control-Z to exit)
Please type another input file name: x
(c:/texlive/2018/texmf-dist/tex/latex/tools/x.tex
pLaTeX2e <2018-05-20u02> (based on LaTeX2e <2018-04-01> patch level 4)

本記事では、この不具合について、てきとーに書き流す。

※ソースファイル上での \input での読込については対象外。

アレは本当にソレのせいなのか

そもそも、(La)TeX における非 ASCII のファイル名の扱いはまだまだアドホックなところが多分に残っている。なので、この問題の対策に関しては、

  • UTF-8 既定化」が原因であるパターン
  • そもそも原理的に失敗するパターン

の見極めが必要である。例えば、WindowsTeX Live)上の XeLaTeX では非 ASCII のファイル名(例えば「xelatex TeXはアレ.tex」)は失敗するが、これは「UTF-8 既定化」とは無関係*1であり、最初から失敗するパターンに該当する。

アレの原因を調べる方法

非 ASCII のファイル名のエラーの原因が「UTF-8 既定化」であるかは以下の何れかの方法で調べられる。

  • TeX Live 2017 以前では同じコマンド起動が成功していたのであれば、「UTF-8 既定化」が原因である。
  • LaTeXlatex/platex/uplatex/pdflatex)の代わりに敢えて plain TeX(etex/eptex/euptex/pdftex)を起動してみる。例えば、「uplatex TeXはアレ.tex」の代わりに「euptex TeXはアレ.tex」を実行する。「UTF-8 既定化」が原因であるならば、plain TeX は指定のファイルを読み込むはず*2である。もちろん、“期待通り”読み込まれた場合は、先頭の「\documentclass」の箇所で「! Undefined control sequence.」のエラーになるだろう。((\documentclassLaTeX 専用の命令である。念のため。))

アレになるパターン

大雑把にいうと、「ファイル名のバイト列を inputenc が“欧文の UTF-8”として解釈しようとしたが、形式不正であった」という場合にエラーになる。

Windows な欧文 (pdf)LaTeX

※日本語版の Windows を仮定する。

pdflatex TeXはアレ.tex

Windows なので、ファイル名は SJIS で与えられる。*3inputenc の機構はこのバイト列を UTF-8 でデコードしようとするが、UTF-8 としては形式不正であるためエラーになる。

Windows な upLaTeX
uplatex TeXはアレ.tex

Windows なので、ファイル名は SJIS で与えられる。upLaTeX は非 ASCII 文字をまず UTF-8和文として解釈してみる((pTeX 系の場合は、まず「非 ASCII 文字を和文として解釈する」という過程が入る。例えば、Windows 上の「platex TeXはアレ」の場合は、まず SJIS和文として解釈してそれが成功するため、“欧文の UTF-8”として解釈される過程には進まないためエラーは発生しないのである。))が失敗し、次に、inputenc が欧文の UTF-8 としてデコードしようとして、形式不正であるためエラーになる。

コマンドラインの文字列については入力漢字コード(-kanji オプション)は適用されず、和文の解釈については、常に内部漢字コード(-kanji-internal オプション)が適用されるようである。TeX Live の upLaTeX の内部漢字コードは UTF-8 である。

Linux/macpLaTeX

※「ロケールUTF-8 である」と仮定する。

platex アレ

# または
platex -kanji=utf8 アレ

※先述の通り、入力漢字コード(-kanji)は無関係。

  • ロケールUTF-8 なので、ファイル名は UTF-8 のバイト列“E3 82 A2 E3 83 AC”で与えられる。
  • Linux/mac 上の TeX Live の pLaTeX の内部漢字コードは EUC である。従って、platex はこれを EUC和文として解釈してみる。
  • その結果、EUC として解釈できる“A2 E3”が和文“≪”と見なされ、残りは欧文のバイトとして扱われる。つまり“^^e3^^82≪^^83^^ac”となる。
  • これを inputenc が欧文の UTF-8 バイト列として解釈しようとする。
  • 元々は正当な UTF-8 のバイト列であったが、途中が和文に置き換わっているため不正であり、エラーになる。((具体的には、“^^e3^^82≪”の 3 トークンを(E3 が先頭の 3 バイトの列と見なして)“1 文字”として読んだ後、UTF-8 の非先頭バイトの^^83に引っかかる。))

ややこしい。

※なお、TeX Live 2017 以前の場合は、「inputenc が欧文 UTF-8 として解釈する」という過程は入らない。この場合、TeX エンジンは“^^e3^^82≪^^83^^ac”という名前のファイルを探索するが、その際に和文の“≪”は再び EUCエンコードされるため、結局「E3 82 A2 E3 83 AC」という元のバイト列に戻る。ロケールUTF-8 であるため、結果的に、OS が探すファイル名の文字列は期待通り「アレ」になる。

(続くはず)

*1:XeLaTeX・LuaLaTeX は当初から UTF-8 専用なので「UTF-8 既定化」の対象にならない。

*2:UTF-8 既定化」は LaTeX の方針なので、plain TeX は無関係である。

*3:正確にいうと、「コマンドラインの文字列を SJIS(CP932)でエンコードしたバイト列が argv に与えられる」ということ。

Windows の ANSI コードページを知りたい話(2)

前回の続き)

PerlANSI コードページを知りたい

Win32 モジュールを使う

Win32 モジュールは Win32 API の(比較的)単純なラッパーである関数群を提供するもの。

use strict;
use Win32;
# ANSI コードページ
print("ANSI cp = ", Win32::GetACP(), "\n");
# OEM コードページ
print("OEM cp = ", Win32::GetOEMCP(), "\n");
# コンソール入力コードページ
print("console input cp = ", Win32::GetConsoleCP(), "\n"); 
# コンソール出力コードページ
print("console output cp = ", Win32::GetConsoleOutputCP(), "\n");

日本語版 Windows だと結果は全部「932」になる。

ANSI cp = 932
OEM cp = 932
console input cp = 932
console output cp = 932

エラー対策を考慮すると以下のようになる。

use strict;

## ansi_codepage()
# ANSIコードページの値を返す。失敗時およびWindowsでない場合は
# undefを返す。
sub ansi_codepage() {
  my ($ret);
  # Windowsでないならundef
  ($^O eq 'MSWin32') or return $ret;
  eval {
    # Win32モジュールは無いかもしれない
    require Win32;
    $ret = Win32::GetACP();
  };
  # 前のevalの成功時のみ値が返る
  return $ret;
}

print("ANSI cp = ", ansi_codepage(), "\n");
ANSI cp = 932
Encode::Locale モジュールを使う
use strict;
use Encode::Locale;

# 現在のロケールの文字コード
# WindowsではANSIコードページの文字コード(固定らしい)
print($Encode::Locale::ENCODING_LOCALE, "\n");
# コンソール入力コードページの文字コード
# Windows以外では ENCODING_LOCALE と同じになるらしい
print($Encode::Locale::ENCODING_CONSOLE_IN, "\n");
# コンソール出漁コードページの文字コード
# Windows以外では ENCODING_LOCALE と同じになるらしい
print($Encode::Locale::ENCODING_CONSOLE_OUT, "\n");

日本語版 Windows での実行結果は以下の通り。

cp932
cp932
cp932

Encode::Locale は Windows 専用ではない。(UTF-8 運用の)Linux では以下のような結果が得られる。

UTF-8
UTF-8
UTF-8

なお、Encode::Locale の主たる目的は、「Encode モジュールで使う文字コード'locale' を指定することで先述の ENCODING_LOCALE が使われるようにする」ことである。すなわち、前回に挙げたような、非 ASCII のファイル名を扱いたい場合には、このモジュールを読み込んで 'locale' 指定を使うと環境費依存で所望の処理が行える。

# 文字コードはUTF-8
use strict;
use utf8;
use Encode qw(encode);
use Encode::Locale;

my $f = 'アレ.txt'; # Unicode文字列
# 文字コード名を 'locale' にすると、ENCODING_LOCALE による
# バイト列に変換される
open(my $h, '>', encode('locale', $f)) or die;
print $h ("TeX\n");
close($h);

LuaANSI コードページを知りたい

Lua の場合、標準 C 関数の setlocale() の単純なラッパーである os.setlocale() という標準ライブラリ関数が用意されているので、これを利用して ANSI コードページを取得できる。

--- ansi_codepage()
-- ANSIコードページの値を返す.
-- @returns ANSIコードページの値(失敗=nil)
function ansi_codepage()
  local ok, ret = pcall(function()
    -- setlocale(LC_CTYPE, NULL) と同じ. 
    -- 現在のロケールの値の文字列を返す.
    local org = assert(os.setlocale(nil, "ctype"))
    -- Windowsにおいて, 既定のロケールを設定し, そのときに特に
    -- ANSIコードページを指定する. 戻り値は実際のロケールの値
    -- で, Windowsの場合 "言語_地域.コードページ" という形式の
    -- 文字列になる.
    -- Windows以外では ".ACP" というロケール名は無効であるため,
    -- nilを返し, assertがエラーを発する.
    local ret = assert(os.setlocale(".ACP", "ctype"))
    -- 一度変更したロケールを元に戻す.
    assert(os.setlocale(org, "ctype"))
    -- 先述の文字列の中のコードページの数字列を抽出し, 数値に変換
    -- したものを返す. 形式不正ならエラーになる.
    return assert(tonumber(ret:match("^.*%.(%d+)$")))
  end)
  -- 失敗ならnil, 成功ならret
  return (ok or nil) and ret
end

print(("ANSI cp = %s"):format(ansi_codepage()))

日本語版 Windows での実行結果は以下の通り。

ANSI cp = 932

Windows の ANSI コードページを知りたい話(1)

問題の背景とか

ANSI コードページについてテキトーに語る

基本的に、イマドキの Windows は文字列を(論理的には*1)「Unicode 文字の列」として扱う。Windows のフツーの GUI プログラムは Unicode 文字列を直接扱う。しかし、Windows 的にレガシーな「文字列をバイト列として扱う」ような API*2を使う場合には、文字列とバイト列の間で相互変換が必要になる。

このような場合に用いられる文字コードANSI コードページである。要するに「システムで規定された、レガシー文字コードの種類」(の一つ)である。(コードページ(code page)とは文字コードの種類を表す整数値を指す用語。)例えば、日本語版 Windows の既定の ANSI コードページは「932」で、これは“Microsoft 的なシフト JIS”を表し、また、英語版 Windows の既定の ANSI コードページは「1252」で、これは“Microsoft 的な Latin-1”を表す。

※「システムの規定値(または設定値)であるレガシー文字コード」には他にも「OEM コードページ」とかイロイロあるけど詳細は省略。

マルチプラットフォームCUI プログラムでは「バイト列扱いの API」が使われることが多く、そういうプログラムの動作は ANSI コードページに依存することになる。

Python な文字列の話

以下では、プログラム言語における“文字列”の扱いと Windows のそれとの整合性について述べてみる。

Windows 上の Python でファイルを作成する場合に、次のように非 ASCII 文字のファイル名を指定したとする。

# -*- coding: utf-8 -*-
with open('アレ.txt', 'w') as f:
    f.write("TeX\n")

これは期待通り、「アレ.txt」というな雨のファイルを作成する。Python は文字列を(論理的には*3)「Unicode 文字の列」として扱う。つまり、“Python の文字列”の 'アレ.txt' が表すのは「アレ.txt」という Unicode 文字列であり、従って、最終的に WindowsAPI を呼ぶ場合には(バイト列ではなく)この文字列を渡すべきであり、また実際にそう処理しているため期待通りの結果が得られているわけである。

最近のプログラム言語は、Python と同様に、文字列を「Unicode 文字の列」として扱うものが多く*4、そういう言語(かつ Windows にちゃんと対応したもの)であれば、非 ASCII 文字のファイル名は正常に取り扱えるであろう。

Lua な文字列の話

ところが、Lua だと事情は異なる。

-- このファイルの文字コードは UTF-8
local n = 'アレ.txt'
-- n == '\xE3\x82\xA2\xE3\x83\xAC.txt' である
local f = assert(io.open(n, 'w'))
f:write("TeX\n")
f:close()

Lua は文字列を単なるバイト列として扱う言語である。つまり、“Lua の文字列”の 'アレ.txt' が表すものは「E3 82 A2 E3 83 AC 2E 74 78 74」というバイト列でしかない。文字コードの情報が欠けているため、このバイト列単体では「アレ.txt」という文字列を表さない。

そこで、LuaWindows の機能を呼び出す場合、“文字列が渡せない”ため、必然的に「文字列をバイト列として扱う」API が利用される。その結果、先述の通り、バイト列は ANSI コードページで解釈されることになる。例えば、日本語版 Winddows の既定であれば、「E3 82 A2 E3 83 AC 2E 74 78 74」をコードページ 932(シフト JIS)で解釈して、「繧「繝ャ.txt」という名前のファイルが作成される。

Perl な文字列の話

アレアレなことで有名な Perl では、アレアレなことになる。

# このファイルの文字コードは UTF-8
use v5.20;
use utf8;
my $n = 'アレ.txt';
# $n eq "\x{30A2}\x{30EC}.txt" である
open(my $h, '>', $n) or die;
print $h ("TeX\n");
close($h);

PerlPython 等と同じく文字列を(論理的には)「Unicode 文字の列」として扱う。*5だから、“Perl の文字列”の 'アレ.txt' はそのまま「アレ.txt」という文字列である。((例えば、substr('アレ.txt', 0, 1) は先頭の 1 文字(1 バイトでなく)の 'ア' を返す。 ))

ということは、作成されるファイル名は Python の時と同じく「アレ.txt」となるべきであるが、実際にはなぜか Lua の時と同じ「繧「繝ャ.txt」になってしまう。アレアレである。

さらにもっとアレアレな例を挙げる。

# このファイルの文字コードは UTF-8
use v5.20;
#use utf8; # これの有無は無関係

my $n1 = "\xB1";
my $n2 = substr("\xB1\x{100}", 0, 1);
# $n1 と $n2 は同じ文字列…
($n1 eq $n2) or die 'WOO'; # …なのは確か

# $n1 のファイル名で作成
open(my $h1, '>', $n1) or die;
print $h1 ("TeX\n");
close($h1);
# $n2 のファイル名で追記
open(my $h2, '>>', $n2) or die;
print $h2 ("expl3\n");
close($h2);

$n1$n2 はともに "\xB1" という文字列であり、事実、$n1 eq $n2 が成立している。なので、上掲のプログラムはファイルを 1 つだけ作成するはずである。ところが、日本語版の Windows で実行すると、2 つのファイルが作られるというアレアレなことになる。

  • $n1 に対する open は「ア」(B1)というファイルを作る。
  • $n2 に対する open は「ツア」(C2 B1)というファイルを作る。

どうやら、Perl は常に「文字列をバイト列として扱う」API を使っていて、しかもその際に“Perl の文字列”の内部表現のバイト列をそのまま渡しているようなのである。“Perl の文字列”の内部表現には 2 種類あって、$n1$n2 は同じ文字列であるが内部表現が異なる((“Perl の文字列”の内部表現には「直接」と「UTF-8」があり、$n1 は「直接」形式なので、"\xB1" が「B1」というバイト列になり、$n2 は「UTF-8」形式なので、"\xB1" が「C2 B1」というバイト列になったと考えられる。Perl によくある「UTF-8 フラグの亡霊問題」(同じ文字列のはずなのに挙動が異なる)の一種なんだろう。))ため、WindowsAPI に別のバイト列として渡されたと推定できる。

実用的な慣習としては、Perl ではファイル名は常にバイト列と見なすべきなのだろう。つまり、「文字列をバイト列として扱う」API に渡したときに辻褄が合うように、プログラマが文字列を適切な文字コードでバイト列に変換する必要がある。Windwos の場合は、ANSI コードページに依存するということになる。

# このファイルの文字コードは UTF-8
use v5.20;
use utf8;
use Encode qw(encode);
# 再度確認: "Perl の文字列"はUnicode文字列とバイト列の
# 何れを表すのにも用いられる

my $n1 = "アレ.txt"; # Unicode文字列
# ANSI コードページのバイト列に変換する
my $n2 = encode('cp932', $n1); # バイト列

open(my $h, '>', $n2) or die;
print $h ("TeX\n");
close($h);

上記のプログラムは、日本語版 Windows において、期待通り「アレ.txt」という名のファイルを作成する。

とりあえずまとめ

Windows の機能(ファイル操作など)を利用するプログラムの場合:

  • Python とか Ruby とかは ANSI コードページに依存しない。
  • LuaPerlANSI コードページに依存する。
  • Perl はアレアレ。

「日本語 Windows だったら CP932 だろ常考」の終焉

既に述べたとおり、日本語版の WindowsANSI コードページは 932(シフト JIS)である。これは Windows が登場してから 20 年以上経っても変わっていない。だから“日本語版 Windows ユーザ専用の CUI プログラム”では「ANSI コードページは 932」という決め打ちが行われることが多い。これは実際に文字列のエンコードを行う場合の他に、所謂「ダメ文字対策*6」を行う場合も含まれる。

ところが、最近はその状況が変わってきているようである。

どうやら、Windows 10 が「ANSI コードページを 65001(UTF-8 を表すコードページ)にする運用」をサポートし始めたようだ。*7いまや「文字コードUTF-8 が正義」な時代であるので、この流れは自然なことであろう。それゆえ、日本語 Windows ユーザでも ANSI コードページを UTF-8 にしている人は増えていく可能性は大いにあるだろう。そうなると、プログラム側での「ANSI コードページは 932」という決め打ちは破綻してしまう。

というわけで帰結は

PerlLua で、ANSI コードページの設定値が何であるかを知りたい。

ふう、やっと導入の話が終わった……。

続く

*1:つまり、内部表現は「符号化形式(CEF)としての UTF-16」であるが、それは捨象する、ということ。要するに、Windows にとって“ネイティブ”な符号化文字集合Unicode である。

*2:POSIX 互換のシステム関数や C ライブラリの関数も含む。

*3:再び内部表現については捨象する。

*4:Ruby は少し特殊で、“Ruby の文字列”は「Unicode 文字の列」ではないが、単なるバイト列ではなく文字としての情報を持っているため、“Ruby の文字列”を Unicode 文字列に変換できる。従って、Windows での動作についてこの点で問題になることはない。

*5:ただし Perl はアレアレなので、“Perl の文字列”は文字列とバイト列の何れを表すのにも用いられる。アレアレである。

*6:2 バイト目が 5C である 2 バイト文字が「\」と見なされるのを防ぐこと。ANSI コードページが 932 でない場合は、この対策はかえって有害になる。

*7:ANSI コードページを UTF−8 にできる」ということは、もはや「ANSI コードページはレガシーな文字コード」という位置づけではなくなる。

Noto CJK のフォント名情報も理解したい話

一覧表

詳細は Source Han の時と同じ。

※横幅を抑えるため、以下の表では「Noto」を「N.」と略記している。

実際の
ウェイト
完全名ファミリ
[組版的ファミリ]
サブファミリ
[組版的〜]
PostScript 名
[Noto Serif CJK JP(非サブセット)]
RegularN. Serif CJK JPN. Serif CJK JPRegularN.SerifCJKjp-Regular
BoldN. Serif CJK JP BoldN. Serif CJK JPBoldN.SerifCJKjp-Bold
MediumN. Serif CJK JP MediumN. Serif CJK JP Medium
[N. Serif CJK JP]
Regular
[Medium]
N.SerifCJKjp-Medium
[Noto Sans CJK JP(非サブセット)]
RegularN. Sans CJK JP RegularN. Sans CJK JP Regular
[N. Sans CJK JP]
RegularN.SansCJKjp-Regular
BoldN. Sans CJK JP BoldN. Sans CJK JP Bold
[N. Sans CJK JP]
Regular
[Bold]
N.SansCJKjp-Bold
MediumN. Sans CJK JP MediumN. Sans CJK JP Medium
[N. Sans CJK JP]
Regular
[Medium]
N.SansCJKjp-Medium
[Noto Serif CJK SC(非サブセット)]
RegularN. Serif CJK SCN. Serif CJK SCRegularN.SerifCJKsc-Regular
BoldN. Serif CJK SC BoldN. Serif CJK SCBoldN.SerifCJKsc-Bold
MediumN. Serif CJK SC MediumN. Serif CJK SC Medium
[N. Serif CJK SC]
Regular
[Medium]
N.SerifCJKsc-Medium
[Noto Sans CJK SC(非サブセット)]
RegularN. Sans CJK SC RegularN. Sans CJK SC Regular
[N. Sans CJK SC]
RegularN.SansCJKsc-Regular
BoldN. Sans CJK SC BoldN. Sans CJK SC Bold
[N. Sans CJK SC]
Regular
[Bold]
N.SansCJKsc-Bold
MediumN. Sans CJK SC MediumN. Sans CJK SC Medium
[N. Sans CJK SC]
Regular
[Medium]
N.SansCJKsc-Medium
[Noto Serif JP(地域別サブセット)]
RegularN. Serif JPN. Serif JPRegularN.SerifJP-Regular
BoldN. Serif JP BoldN. Serif JPBoldN.SerifJP-Bold
MediumN. Serif JP MediumN. Serif JP Medium
[N. Serif JP]
Regular
[Medium]
N.SerifJP-Medium
[Noto Sans JP(地域別サブセット)]
RegularN. Sans JP RegularN. Sans JP Regular
[N. Sans JP]
RegularN.SansJP-Regular
BoldN. Sans JP BoldN. Sans JP Bold
[N. Sans JP]
Regular
[Bold]
N.SansJP-Bold
MediumN. Sans JP MediumN. Sans JP Medium
[N. Sans JP]
Regular
[Medium]
N.SansJP-Medium
[Noto Serif SC(地域別サブセット)]
RegularN. Serif SCN. Serif SCRegularN.SerifSC-Regular
BoldN. Serif SC BoldN. Serif SCBoldN.SerifSC-Bold
MediumN. Serif SC MediumN. Serif SC Medium
[N. Serif SC]
Regular
[Medium]
N.SerifSC-Medium
[Noto Sans JP(地域別サブセット)]
RegularN. Sans SC RegularN. Sans SC Regular
[N. Sans SC]
RegularN.SansSC-Regular
BoldN. Sans SC BoldN. Sans SC Bold
[N. Sans SC]
Regular
[Bold]
N.SansSC-Bold
MediumN. Sans SC MediumN. Sans SC Medium
[N. Sans SC]
Regular
[Medium]
N.SansSC-Medium

まとめ

基本的に Source Han の時と同じ感じ。Serif と Sans でルールが違うのも同じ。当然ながらファミリ名は異なる。

  • 組版的ファミリ」(Typographic family;ID=16)は“Noto Serif”または“Noto Sans”の後に以下の語を追加したもの。ただし「ファミリ」と一致する場合は記載されない。
    • 非サブセット・日本語版: CJK JP
    • 非サブセット・韓国語版: CJK KR
    • 非サブセット・簡体字中国語版: CJK TC
    • 非サブセット・繁体字中国語版: CJK SC
    • 地域別サブセット・日本版: JP
    • 地域別サブセット・韓国版: KR
    • 地域別サブセット・中国版: SC
    • 地域別サブセット・台湾版: TC
  • 組版的ファミリ」から「ファミリ」(ID=1)を得る規則は同じ。
  • PostScript 名の構成部分の「空白無し組版的ファミリ」については、非サブセットの「CJK XX」の接尾は「CJKxx」という形に変える。 例えば、「Noto Serif CJK JP」の Regular の PostScript 名は「NotoSerifCJKjp-Regular」。

新しい BXjscls の話(v1.9)

TeX Live 2018 および W32TeX は既に更新されている。

近いうちに、メジャー改版となる 2.0 版のリリースを予定していて、今回の 1.9 版はそれに向けた準備が含まれる。

textwidth と textwidth-limit と \jsTextWidthLimit と

もともと bxjsbook では、他の BXJS クラスと異なり、textwidth-limit というオプションで一行の文字数を指定していた。ところが、1.8 版において、行の長さを指定する全クラス共通のオプションである textwidth が新設された。そして、bxjsbook においては、この textwidth は旧来の textwidth-limit と全く同じ役割を果たす(\fullwidth 以下の範囲内で \textwidth の値を決める*1)ものなので、両方存在するのは無駄である。

従って、2.0 版においては、汎用性の高い textwidth の方を残し textwidth-limit は非推奨の扱いにする予定である。

従来の仕様では、textwidth-limit で指定した値は \jsTextWidthLimit という数値マクロに保存される。((というか、元々は「bxjsbook の \textwidth を変えるにはこのマクロを直接再定義する」という仕様であった。))2.0 版の仕様では textwidth-limit は「textwidth の旧式の別インタフェース」となるため、それを見越して今回(1.9 版)の改修において、 textwidth で行長を指定した場合にも \jsTextWidthLimit に一行の文字数の値を保存することにした。

通常は、textwidth で指定した長さ値は実際には全角の整数倍に切り捨てられるが、\jsTextWidthLimit に入るのは切り捨てた後の整数値である。ここで、whole-zw-lines=false を指定して整数全角の切り捨てを無効化した場合は、\jsTextWidthLimit には実数値(行長÷全角幅)が入ることになる。

一部のオプションの名前がそのうち変わる話

2.0 版において、以下の 4 つの(ほとんど使われていないであろう)真偽値型オプションの名前を変更する予定である。

  • (no)jsdisguise-js=<真偽値>
  • (no)zwuse-zw=<真偽値>
  • (no)precisetextprecise-text=<真偽値>
  • (no)simplejasetupsimple-ja-setup=<真偽値>

1.9 版では、この変更を見越して、新名称のオプションを別名として用意した。つまり、1.9 版では両方のオプションが使用可能でかつ正当である。2.0 版では古いオプションは非推奨になる予定である(後述)。

その他もろもろ

  • 元号について、BXwareki パッケージが利用可能であれば、その情報を利用する。
  • jafontscale が認識されないバグを修正。

補足:今よりもっと新しい BXjscls の話

2.0 版では、次のような(互換性に影響のある)変更を予定している。

  • geometry 4.x 版のサポートを廃止し、5.0 版以降を必須とする。
    ※ geometry 4.x 版 の使用は 1.2 版 [2016/08/01] において非推奨となっている。
  • \ifdraft 命令を廃止する。代わりに \ifjsDraft を使う必要がある。 ((LaTeX ユーザレベルで \ifthenelse{\boolean{draft}}... を使っている場合、\ifthenelse{\boolean{jsDraft}}... に変更してもよいが、それよりも ifdraft パッケージの使用の方を推奨する。))
    ※ 1.2 版 [2016/08/01] において非推奨となっている。
  • (u)pLaTeX 以外のエンジンにおいて、ja オプションを省略する(この場合和文ドライバは minimal になる)指定を非推奨とする。
  • 以下に挙げる、旧版との互換性のためのオプションを非推奨とする(廃止ではない)。
    • (no)js (→ disguise-js=<真偽値>)
    • (no)zw (→ use-zw=<真偽値>)
    • (no)precisetext (→ precise-text=<真偽値>)
    • (no)simplejasetup (→ simple-ja-setup=<真偽値>)
    • textwidth-limit=<整数> (→ textwidth-limit=<整数>zw)
    • dvipdfmx-if-dvi (→ dvi=dvipdfmx)
    • magstyle=mag/real/xreal (→ magstyle=usemag/nomag/nomag*)
    • jadriver=<名前> (→ ja=<名前>)
    • noscale (→ scale=1)

*1:ただし、指定の書式について、textwidth-limit は全角単位の整数値、textwidth は長さ値で指定するという違いがある。textwidth で指定した場合も、普通は全角の整数倍に切り捨てられる。