Ticket #28187

SumatraPDFでRyumin-LightがMSゴシックになる

Open Date: 2012-04-27 21:19 Last Update: 2016-06-18 18:02

Reporter:
Owner:
(None)
Type:
Status:
Closed
Component:
(None)
MileStone:
(None)
Priority:
5 - Medium
Severity:
5 - Medium
Resolution:
Remind
File:
2

Details

バグ……じゃないかもしれませんが. LuaTeX-jaでフォント非埋め込みのPDFをSumatraPDFで開くとフォントがすべてMSゴシックになります. SumatraPDFのソースを見ると,

if(fontdesc->flags & PDF_FD_SERIF)serif = 1;
とあって,serifが1だとMS明朝,そうでなければゴシックが選ばれるようです.(ちなみにPDF_FD_SERIF = 2)

kmaedaさんに教えてもらったことによれば,ほとんどハードコーティングされているらしいので,この値を変更するのは難しいようです.がんばればできる可能性があるかもしれませんが,LuaTeX-jaががんばるのはお門違いな気もします.

どうするのがよいでしょう?

以下kmaedaさんに教えてもらったことです.

writefont.w の do_pdf_font() ですが,ここに font_encodingbytes(f) が 2 だったら仮想的な font map entry を作るという処理が書いてあります. そして,

fm->fd_flags = 4; /* can perhaps be done better */

となっています.

となると,次に考えられるのは ltj-rmlgbm.lua で fontdata.encodingbytes=1 とやって,適切なマップファイルを与えてやることなんですが,さてどうすればよいのでしょうか(そもそもできるのか)?

Ticket History (3/17 Histories)

2012-04-27 21:19 Updated by: abenori
  • New Ticket "SumatraPDFでRyumin-LightがMSゴシックになる" created
2012-04-27 23:33 Updated by: h7k
Comment

「調べる」とかいっといて,全然実際に調べてないですが……,

次に考えられるのは ltj-rmlgbm.lua で fontdata.encodingbytes=1 とやって,適切なマップファイルを与えてやる

これってできるのかなあ.writefont.w 中の do_pdf_font() を見ると,

if (font_encodingbytes(f) == 2) {
...
  set_cidkeyed(fm);
  create_cid_fontdictionary(pdf, f);
...
} else {
  /* by now |font_map(f)|, if any, should have been set via |pdf_init_font()| */
  if ((fm = font_map(f)) == NULL
    || (fm->ps_name == NULL && fm->ff_name == NULL))
    writet3(pdf, f);
  else
    create_fontdictionary(pdf, f);
}
とあり,じゃあ,create_fontdictionary() はどうなっているか,というと
static void create_fontdictionary(PDF pdf, internal_font_number f)
{
    fo_entry *fo = new_fo_entry();
    fm_entry *fm = font_map(f);
    get_char_range(fo, f);      /* set |fo->first_char| and |fo->last_char| from |f| */
    if (fo->last_char > 255)
        fo->last_char = 255;    /* added 9-4-2008, mantis \#25 */
のように lasr_char <=255 制限があるので,うまくいかないという直感が.

本家に素直に機能をリクエストしてみるのがよいと思います.

2012-04-27 23:56 Updated by: kmaeda
Comment

lasr_char <=255 制限があるので,うまくいかないという直感が.

あのコメントを書いた時点でその手の問題があってうまく動かないのではないか,と思っていたのですが,やはりその可能性が高いのですね.

リクエストをするなら,どう書きましょうかね…….

2012-04-28 13:14 Updated by: h7k
Comment

luatex-twobyte-fdflags.patch として,font.fonts[n]fdflags フィールドを追加するパッチを作ってみました.本来はencodingbytes=1 の場合も考慮しないといけないのかもしれませんが,よくわからないのでそっちの場合は放置してあります.デフォルト値は FD_FLAGS_DEFAULT_TWOBYTES (=4) とし,動作をあわせています.

このパッチ適用後,ltj-rmlgbm.lua で fontdata.fdflags = 6 をしたら,きちんと /Flags 6 になってくれました.

2012-04-28 19:21 Updated by: abenori
Comment

luatex-twobyte-fdflags.patch として,font.fonts[n]fdflags フィールドを追加するパッチを作ってみました.

すばらしいです.こいつを本家に送りつける,というのがよいでしょうか.encodingbytes=1の時をきちんと考えるべき?

2012-04-28 20:07 Updated by: kmaeda
Comment

encodingbytes=1の時

encodingbytes=2 のときしか効かないよ,でもいいかもしれませんが,encodingbytes の値によらず効く仕様となると, fdflags フィールドのデフォルト値は -1 (nil でもいい?)などの「未設定」にしておいて, 設定されているときは従来の仕様で決定される値を上書きする,というのが自然ではないでしょうか. encodingbytes=1 のときにマップファイルなどで決まる値を優先となると,設定できる意味がないですし.

2012-04-28 20:43 Updated by: kmaeda
Comment

fdflags フィールドのデフォルト値は -1 (nil でもいい?)などの「未設定」にしておいて

ああ,でもフォントのテーブルの初期値から encodingbytes=1 のフォントの fdflags の値を得たい,ということも考えられますね. そもそもそういう使い道があるのかどうか知りませんけれども.

# この機能の CJK フォント非埋め込み以外の用途を知らないので適当なことを書いています.

2012-04-28 21:30 Updated by: h7k
Comment

fdflags フィールドのデフォルト値は -1 (nil でもいい?)などの「未設定」にしておいて

フォントのテーブルの初期値から encodingbytes=1 のフォントの fdflags の値を得たい

たぶんそれは厳しそう.フォントに対して pdf/pdffont.w 中の pdf_init_font() でマップファイルとの対応をつける (font_map(f) = fm;) ようですが,それはページが shipout される時(or 後?)に行われるようです.あくまでも「-1: 自動設定のまま」とすることになる?

1バイトフォントだと,pdfTeX の段階で fd_flags を

\pdfmapline{=ptmri8r Times-Italic 66<8r.enc <utmri8a.pfb}
(Lua からなら pdf.mapline())と指定できるのが中途半端なところです.

2012-04-28 22:20 Updated by: h7k
Comment

「TeX の内部フォント番号は違うが,実フォントは同じ」場合を考えると,今のままでは怪しいことがわかってきました.

安直に font.fonts[].fdflags のデフォルト値を -1 とし,writefont.w 中の create_fontdictionary() に

    fm_entry *fm = font_map(f);
+   fm->fd_flags = (font_fd_flags(f) != FD_FLAGS_NOT_SET_IN_MAPLINE) ?
+       font_fd_flags(f) : fm->fd_flags;
のような変更をしてみました.

そして,以下のソースを走らせ,PDF 中で実際にどうなっているかを調べました:

\pdfcompresslevel=0
\input luaotfload.sty
\pdfmapline{=ptmri8r Times-Italic 42<8r.enc <utmri8a.pfb}
\pdfmapline{=ptmr8r Times-Roman   42<8r.enc <utmr8a.pfb}
\pdfmapline{=ptmb8r Times-Bold    42<8r.enc <utmr8a.pfb} % 実フォントだけ共通

\directlua{local dr_orig = fonts.define.read
function fonts.define.read(name, size, id)
  local a = dr_orig(name, size, id)
  if math.floor(id/2)*2==id then a.fdflags=id*2 end
  return a
end}

\font\g=ptmri8r\g a         % id: 51 => -1
\font\h=ptmr8r\h b          % id: 52 => 104
\font\a=ptmr8r at 14pt\a b  % id: 53 => -1
\font\b=ptmb8r at 14pt\b b  % id: 54 => 108
\font\c=file:ipam.ttf at 12pt\c b  % id: 55 => -1
\font\d=file:ipam.ttf at 14pt\d b  % id: 56 => 108

%\directlua{
%for i,v in font.each() do
%  if i>=51 then print(' >>> : ',i,font.fonts[i].fdflags) end
%end}
\end
すると,IPA 明朝と utmr8a.pfb について
<</Type/FontDescriptor/FontName/EHDIYH+IPAMincho/Flags 4/FontBBox[0 -96 1000 773]/Ascent 773/CapHeight 750/Descent -96/ItalicAngle 0/StemV 86/XHeight 524/FontFile2 14 0 R/CIDSet 13 0 R>> % 7 0 obj
<</Type/FontDescriptor/FontName/SANKRU+NimbusRomNo9L-Regu/Flags 108/FontBBox[-168 -281 1000 924]/Ascent 690/CapHeight 690/Descent -209/ItalicAngle 0/StemV 85/XHeight 461/CharSet(/b)/FontFile 24 0 R>> % 27 0 obj
という結果になりました.「fdflags と実際に PDF で使われる値が食い違う」症状が起きていることになります.

一番いいのは mapline が2バイトフォントに対応してくれることですが…….

2012-04-29 02:48 Updated by: kmaeda
Comment

「TeX の内部フォント番号は違うが,実フォントは同じ」場合

そうか,psname(psname がなければ fullname)が同じフォントは出力 PDF では1つのフォントとして扱われてしまうんでしたっけ. となると,単純にフォントのテーブルに fdflags フィールドを追加するのはよろしくない,ということになりますかね.

一番いいのは mapline が2バイトフォントに対応してくれることですが…….

無思慮な危ないパッチを作ってみました (luatex-twobyte-mapline.patch).今のところ Flags 以外は無視しています. "ExtendFont" とか "SlantFont" とかいうのも扱うべきなのだろうか(これらはフォントテーブルに対応するパラメータがあるのだけれども).

\documentclass{ltjsarticle}
\pdfcompresslevel=0
\usepackage{luacode}
\begin{luacode}
local dr_orig = fonts.define.read
function fonts.define.read(name, size, id)
    f = dr_orig(name, size, id)
    if type(f) == 'table' and f.embedding == 'no' then
        pdf.mapline(f.name .. ' ' .. f.psname .. ' 6')
    end
    return f
end
\end{luacode}
\begin{document}
\large % 再定義後の fonts.define.read で Ryumin-Light を定義させる
あ
\end{document}

もはや map とか関係ない使い方な気がしますが,一応これで /Flags 6 になっていると思います.

2012-04-29 03:04 Updated by: kmaeda
Comment

おっと,なんか CMR10 が Type 3 になってるなぁ,と思っていたら,サンプルコード中の pdf.mapline() 引数先頭の = が抜けていました.

-        pdf.mapline(f.name .. ' ' .. f.psname .. ' 6')
+        pdf.mapline('=' .. f.name .. ' ' .. f.psname .. ' 6')

2012-04-29 08:44 Updated by: h7k
Comment

"ExtendFont" とか "SlantFont" とかいうのも扱うべきなのだろうか(これらはフォントテーブルに対応するパラメータがあるのだけれども).

マップ中の SlantFont と font.fonts[].slant の関係を見ていたら,これも「pdf_init_font 実行後に値が変わる」ようです.

%#!luatex
\pdfmapline{=ptmr8r Times-Roman ".5 SlantFont" <8r.enc <utmr8a.pfb}
\font\g=ptmr8r\g aiueo
\font\h=ptmb8r\h aiueo % 比較用
%\vfill\eject
\directlua{
for i,v in font.each() do
  if i>=51 then print(' >>> : ',i,font.fonts[i].slant, font.fonts[i].fdflags) end
end}
\end

上のソースで \vfill\eject の有無で,font.fonts[51].slant の値が変わります.


なお,dvipdfmx には,tt_aux.c

  /* Flags */
  if (os2->fsSelection & (1 << 0))
    flag |= ITALIC;
  if (os2->fsSelection & (1 << 5))
    flag |= FORCEBOLD;
  if (((os2->sFamilyClass >> 8) & 0xff) != 8)
    flag |= SERIF;
  if (((os2->sFamilyClass >> 8) & 0xff) == 10)
    flag |= SCRIPT;
  if (post->isFixedPitch)
    flag |= FIXEDWIDTH;
というコードがあります.


ここで悩むより,とにかく「2バイトフォントの fd_flags を 4 以外にできない?」と上流に投げた方が早く解決される……かな?

2012-04-30 05:47 Updated by: abenori
Comment

ここで悩むより,とにかく「2バイトフォントの fd_flags を 4 以外にできない?」と上流に投げた方が早く解決される……かな?

さんせーい.

2015-10-18 10:11 Updated by: h7k
  • Resolution Update from None to Remind
2016-06-18 18:02 Updated by: h7k
  • Status Update from Open to Closed
  • Ticket Close date is changed to 2016-06-18 18:02
Comment

症状自体は直っていないと思いますが,標準和文フォントが IPAex になったので実際に問題になる場面は少ないと思います.

Attachment File List

Edit

You are not logged in. I you are not logged in, your comment will be treated as an anonymous post. » Login