Hatena::ブログ(Diary)

名もないテクノ手 このページをアンテナに追加 RSSフィード

EPUB版『InDesign者のための正規表現入門』

InDesignのTips一覧

2011-02-02

[][][]CPubってなんだ?

本日、PAGE 2011を見学してきた。お目当ては株式会社ニューキャストさんのCPubである。CPubとはナニか? ぼくがグダグダ講説を垂れるよりまず下記エントリーを読んでいただきたい。

ひとことでいうなら、Wikiを利用したCMSだ。Wiki記法によるマークダウンによってコンテンツを構造化して保持しようという目論みだ。マークダウンを使えば、XMLやプログラミングなしに文書を構造化でき、エンジニアリングに詳しくない編集者や著者もブログ感覚で文書を作成・編集できる。

Wikiを利用した出版物向けの文書構造化の取り組みはCPubだけではない。『電子書籍で生き残る技術−紙との差、規格の差を乗り越える−』に紹介されている、TOP STUDIOさんのReVIEWなどもある。またある出版社ではWordPressを積極的に取り入れ、自社での変換ノウハウを蓄積されている会社もある。

CPubが一般的なCMSと違うところを2つあげてみよう。ひとつは、このCMSが(電子出版と紙媒体を含む)出版物を念頭に置いて設計されていること。ニューキャストさんは長年、出版の制作を生業とされている会社だ。このノウハウが生かされているわけだ。ふたつめは、IDML書出しができること。現状、制作会社への原稿の多くはMS Wordやマーキングテキストで渡されている。これらはたいていテキスト洗浄を必要としそのままでは使えない。じゃあ、XML入稿なら文句はあるまい。いやいやXMLって聞くだけでもう腰が引けてしまう。そこでCPubで書き出したIDMLを原稿に使えるのだ。粗組みしたIDMLには段落スタイルや文字スタイルが適用されているし、図版や表もIDML上で再現できる。

CPubを使えば、著者・編集者・校正者などのグループワークを円滑に行えるし、用途によってEPUB、IDML、bookreaderへと出力できる。なにより、InDesignドキュメントを中間ファイルにしようなどというリスキーで野放図なワークフローに混乱させられなくて済む。

実際に動作画面を見てみると、予想以上にシンプルで気負いがない。興味本位でお話を伺ったところによると、写真図版はFlickrなどのWebServiceから直リンクできるらしい。さらに任意のタグ(とその記法)を追加編集できるようになるとのこと。IDMLはStoryをごっそり入れかるような方法を採っているようだ。今春から専用サイトでテスト稼働が始まるとの情報も得た。

今後の課題として、誰がいつどこを直したかのバージョニングが可視化できること。また、WordPressやMediaWikiなど主要なプラットフォームからのインポート/エクスポートを挙げておきたい。今後の動きに注目だ。

2010-12-16

[][][][]合成フォントの名前を変更する

合成フォントは英語版にはない機能です。和欧混植があたりまえの日本語特有の機能といっても差し支えありません。そのためかどうかわかりませんが、InDesignの登場当初から鬼門のように不具合の多い機能であると思います。

合成フォント機能をより安全に使うためには、英数字とハイフンのみで命名すべきです。Fontographerなどでフォントを作成された経験がある方は、フォントの命名規則がけっこう神経質であるのをご承知かもしれません。内部的にフォントとして処理されるわけですから、その関連性は容易に想像できます。

やや古い記事になりますが、「見つからないフォント」とは?の中でAdobeのナット・マッカリーさんが非ローマ字による命名がトラブルの一因ではないかと示唆されています。

ぼく自身、なんどかトラブルに遭い使用する名前を変更することで回避した経験則がありました。「名前を変更」といっても、実際に合成フォント名はInDesignでは変更できません。新規合成フォントを作ってセットを複製して、現在使われている古い合成フォントをすべて置き換えなくちゃいけません。もうちょっとラクできんものか、と。IDMLで変えちゃえばいいじゃん。という実験です。実験なので、以下自己責任で試してみてください。


1)用意したドキュメントには「fuga-seuzo」と「hoge-seuzo」という2つの合成フォントを作成しました。

f:id:seuzo:20101216154912p:image


2)IDMLに書出し、伸長しました。

f:id:seuzo:20101216154913p:image


3)まず、「META-INF」フォルダの中の「metadata.xml」を編集します。それぞれのリソースがリストされるのがわかります。該当のフォント名を書き換えます。

               <rdf:li rdf:parseType="Resource">
                  <stFnt:fontName>hoge-seuzo</stFnt:fontName>
                  <stFnt:fontFamily>hoge-seuzo</stFnt:fontFamily>
                  <stFnt:fontFace/>
                  <stFnt:fontType>ATC</stFnt:fontType>
                  <stFnt:versionString>hoge-seuzo</stFnt:versionString>
                  <stFnt:composite>true</stFnt:composite>
                  <stFnt:fontFileName>hoge-seuzo</stFnt:fontFileName>
                  <stFnt:childFontFiles>
                     <rdf:Seq>
                        <rdf:li>A-OTF-GothicBBBPro-Medium.otf</rdf:li>
                        <rdf:li>A-OTF-RyuminPro-Regular.otf</rdf:li>
                        <rdf:li>UniversLTStd.otf</rdf:li>
                     </rdf:Seq>
                  </stFnt:childFontFiles>
               </rdf:li>

「metadata.xml」の中の「fuga-seuzo」と「hoge-seuzo」を、それぞれ「fuga-ichikawa」と「hoge-ichikawa」置き換えて保存します。


4)フォント定義のためのリソースを編集します。「Resources」フォルダの「Fonts.xml」を編集します。

検索するとわかりますが、名前参照部分は「FontFamily」要素で宣言されています。

	</FontFamily>
	<FontFamily Self="di128" Name="">
		<Font Self="di128Fontnfuga-seuzo" FontFamily="fuga-seuzo" Name="fuga-seuzo Regular" PostScriptName="ATC-*fuga-seuzo" Status="Installed" FontStyleName="" FontType="ATC" WritingScript="1" FullName="fuga-seuzo" FullNameNative="fuga-seuzo" FontStyleNameNative="" PlatformName="$ID/" Version=""/>
	</FontFamily>
	<FontFamily Self="di141" Name="hoge-seuzo">
		<Font Self="di141Fontnhoge-seuzo" FontFamily="hoge-seuzo" Name="hoge-seuzo Regular" PostScriptName="ATC-*hoge-seuzo" Status="Installed" FontStyleName="" FontType="ATC" WritingScript="1" FullName="hoge-seuzo" FullNameNative="hoge-seuzo" FontStyleNameNative="" PlatformName="$ID/" Version=""/>
	</FontFamily>

さらに「CompositeFont」要素の属性でフォント参照され、「CompositeFontEntry」要素内に各々の設定値があります。

	<CompositeFont Self="CompositeFont/hoge-seuzo" Name="hoge-seuzo">
		<CompositeFontEntry Self="u110" Name="$ID/Kanji" FontStyle="Medium" RelativeSize="100" HorizontalScale="100" VerticalScale="100" Locked="true" ScaleOption="true" BaselineShift="0">
			<Properties>
				<AppliedFont type="string">A-OTF 中ゴシックBBB Pro</AppliedFont>
			</Properties>
		</CompositeFontEntry>
...(以下略)

「Fonts.xml」の中の「fuga-seuzo」と「hoge-seuzo」を、それぞれ「fuga-ichikawa」と「hoge-ichikawa」置き換えて保存します。


5)段落スタイルと文字スタイルで使われているフォントを変更するために、「Resources」フォルダの「Styles.xml」を編集します。

たとえば段落スタイル「01スタイルfuga」は「ParagraphStyle」要素の中にこのようになっています。「AppliedFont」要素でフォント名で参照されています。

		<ParagraphStyle Self="ParagraphStyle/01スタイルfuga" Name="01スタイルfuga" Imported="false" NextStyle="ParagraphStyle/01スタイルfuga" KeyboardShortcut="0 0" PointSize="9" Composer="HL Single J" OTFContextualAlternate="false" Rensuuji="false" TreatIdeographicSpaceAsSpace="true">
			<Properties>
				<BasedOn type="string">$ID/[No paragraph style]</BasedOn>
				<PreviewColor type="enumeration">Nothing</PreviewColor>
				<AppliedFont type="object">CompositeFont/fuga-seuzo</AppliedFont>
				<Mojikumi type="object">MojikumiTable/honbun-yoko</Mojikumi>
				<KinsokuSet type="object">KinsokuTable/kinsoku</KinsokuSet>
			</Properties>
		</ParagraphStyle>

同様に文字スタイルはこうなっています。

		<CharacterStyle Self="CharacterStyle/12-文字スタイルfuga" Imported="false" KeyboardShortcut="0 0" Name="12-文字スタイルfuga" FontStyle="">
			<Properties>
				<BasedOn type="string">$ID/[No character style]</BasedOn>
				<PreviewColor type="enumeration">Nothing</PreviewColor>
				<AppliedFont type="string">fuga-seuzo</AppliedFont>
			</Properties>
		</CharacterStyle>

該当部分をすべて書き換えて保存します。


6)文中で唐突にフォント指定してある(段落スタイルや文字スタイルになっていない)場合は、「Stories」フォルダの中のそれぞれのストーリー(ファイル)の中で「CharacterStyleRange」の「AppliedFont」が指定されています。

			<CharacterStyleRange AppliedCharacterStyle="CharacterStyle/$ID/[No character style]" PointSize="9" OTFContextualAlternate="false">
				<Properties>
					<AppliedFont type="object">CompositeFont/fuga-seuzo</AppliedFont>
				</Properties>
				<Content>唐突</Content>
			</CharacterStyleRange>

該当部分を書き換えて保存します。


7)IDMLに戻します。これを使うとフォルダをドラッグ&ドロップするだけですから簡単ですよ。

Drag and Drop AppleScripts for EPUB, IDML, etc. | InDesignSecrets

f:id:seuzo:20101216154914p:image


8)InDesignで開きます。書き換わっているのがわかります。

f:id:seuzo:20101216154915p:image


実験に使用したドキュメントをダウンロードできます。

2010-12-17.zip 直


ちなみに

IDMS(スニペット)だと伸長の必要もなく、完全な名前参照なので、より書き換えが容易です。各要素名もIDMLに準じています。異なるドキュメントでオブジェクトをコピペした時に「あ、合成フォント入ってるじゃん」とがっかりしなくて済みます。ただし、それに気がつくのはたいていコピーした後なんですが...orz


参照

5節フォント/IDMLWiki/ja

[InDesign]合成フォント名で使用不可な文字 | diary NET. 1.2mg

[InDesign]合成フォントで使用不可な文字についてもう少し調べてみた | diary NET. 1.2mg

2009-04-21

[][][]公式ドキュメントの日本語訳

IDMLWikiで進められていました公式ドキュメントの日本語訳がひとまず完成しました。

これらのドキュメントは有志のユーザーによって無給で行われ、すべての方に無償で公開されています。ご尽力いただいた方、とりわけ長大な10章と付録B, C、クックブックのほとんどを翻訳されたRRRさんに感謝します。ありがとうございました。

ここでひとつお願いがあります。わたしも含めて翻訳者の多くはIDMLについて初心者同然です。したがって翻訳が不十分な部分があります。IDMLに取り組んでいらっしゃる方でもしお気づきの箇所がありましたら、お知らせいただければ幸いです。もちろん、コミットしていただいてご自分で直していただいても構いません。そのためのWikiです。


IDMLWikiでの最初の目標を達成しました。これからはIDMLに関するサービスや事例、オリジナルなコンテンツをご紹介し、IDMLのポータルサイトになれるとよいと思っております。そういった事例やコンテンツを書かれた方は、ご紹介させていただきたく思います。お気軽にお申し出ください。

まだ時期尚早かもしれませんが、IDMLの勉強会や読書会などができるといいなぁ、と夢が膨らんでいます。勉強会等で発表したいネタなどをお持ちの方のご連絡もおまちしております。

2009-03-23

[][][][][][][]IDMSことはじめ:(3)IDMSの検証

IDMS用スキーマの生成

IDMSの妥当性を検証をするためには、スキーマが必要です。書かなくちゃいけない? いいえ、InDesignが環境に合わせて書き出してくれるのです。書き出しにはJavaScriptを使います。

var my_folder = Folder.selectDialog ("IDMS用スキーマ書き出し:書き出しフォルダを選んでください");
app.generateIDMLSchema(my_folder, false);

選択したディレクトリに2つのファイルが作成されます。

f:id:seuzo:20090321180853p:image

  • datatype.rnc
  • IDMarkupLanguage.rnc

この「.rnc」拡張子で書き出されたファイルは「RELAX NG Compact Syntax」(RELAX NG短縮構文)と呼ばれる形式です。


Adobe純正ツールでの)IDMSの検証

IDMLやIDMSの検証には、Adobeの用意した/SKD/devtools/sdktools/idmltoolsディレクトリに含まれる「validate.sh」(Mac)が使用できます。パスの通し方などは「InDesign CS4 IDML ReadMe(抄訳) - 名もないテクノ手」などを参照してください。

前述のようなディレクトリがカレントディレクトリであるとき

$ validate.sh schima/ *.idms

とすれば、すべてのIDMSファイルを検証できます。スキーマはディレクトリで指定する必要があります。2ファイルをわざとエラーが出るように書き換えてあります。下記のようなエラーがでました。

/Users/show/Desktop/IDMS/myOval.idms:5:82: error: required attributes missing
/Users/show/Desktop/IDMS/my_XML2.idms:5:22: error: element "Spread3" not allowed in this context

myOval.idmsの5行目に必要な属性がないこと、my_XML2.idmsの5行目のSpread3エレメントは文法違反になります。


(Rubyでの)IDMSの検証

Adobe純正ツールは確かにお手軽で便利なのですが、Javaツールなので実行コストが高いことや、(サーバー上で)Rubyから外部コマンドをキックすることのためらいがあります。やはりRuby内で生成したIDMSをRuby内で検証したいのが人情ってものでしょう^^

だがしかし! ここに2つの問題があります。

  1. Rubyの各種XMLライブラリはRELAX NG Compact Syntaxをサポートしない
  2. Rubyの標準ライブラリREXMLでは、スキーマの扱いにいくつかの不具合がある

ここでは、問題1を回避するためにTrangを使って、RELAX NG Compact Syntax形式をRELAX NGに変換します。スキーマが動的に必要でないなら、1度変換したスキーマを使い回せばいいのです。

問題2を回避するために、REXMLではなくて、LibxmlのRubyバインディングであるLibxml-Rubyを導入することにしました。


Trangを使ってスキーマの変換を行う

Trangはこちらからダウンロードできます。.zipアーカイブを伸長したら、ターミナルから下記のように実行します。

#実行にはJava環境が必要です。マニュアル参照。また、trang.jarにはパスが通っているものとします。

$ cd /foo/var/schima/  #スキーマがあるディレクトリに移動
$ java -jar trang.jar IDMarkupLanguage.rnc IDMarkupLanguage.rng

第1引数が入力ファイル、第2引数が出力ファイルになります。特にオプションを指定しない場合、フォーマット形式は拡張子を自動判定して決定されます。「IDMarkupLanguage.rnc」の7行目には「include "datatype.rnc"」が書かれているので、「datatype.rnc」も一緒に変換されます。実行すると、下記のように「IDMarkupLanguage.rng」「datatype.rng」が生成されました。

f:id:seuzo:20090323164007p:image


Libxml-Rubyを使ってIDMSの検証をする

gem環境があるなら、Libxml-Rubyのインストールは簡単です。

sudo gem install -r libxml-ruby

これで準備が(ようやく)整いました。さっそくIDMSの検証をしてみます。マニュアルにあるとおり、以下のスクリプトを実行します。

begin
  require 'rubygems'
rescue LoadError
end
require 'xml/libxml'

# parse schema as xml document
relaxng_document = XML::Document.file('schima/IDMarkupLanguage.rng')

# prepare schema for validation
relaxng_schema = XML::RelaxNG.document(relaxng_document)

# parse xml document to be validated
instance = XML::Document.file('my_XML.idms')


# validate
instance.validate_relaxng(relaxng_schema)

あれ? 実行エラーが出ます。

Warning: failed to load external entity "datatype.rng".
Error: xmlRelaxNG: could not load datatype.rng.
Error: Failed to load include datatype.rng.
・#あとは延々とエラー
・
・

「datatype.rng」がねえよ、と言っているわけですね^^。実行スクリプトから見て、「IDMarkupLanguage.rng」は「schima」ディレクトリに入っています。ですから、「IDMarkupLanguage.rng」に6行目に書かれている

  <include href="datatype.rng"/>

  <include href="schima/datatype.rng"/>

に書き換えておく必要がありました。あるいは、どちらのスキーマも実行スクリプトと同じ階層に置いておくとか。

IDMSが正しく検証できれば、このスクリプトは無言です。楽しくないので、わざとタグ名を変更したファイル「my_XML2.idms」を指定してみました。すると...

Error: Expecting element Language, got Spread3.
Error: Expecting element FontFamily, got Spread3.
Error: Expecting element TextVariable, got Spread3.
Error: Element Document has extra content: Spread3.
test.rb:21:in `validate_relaxng': Error: Element Document has extra content: Spread3. (LibXML::XML::Error)
	from test.rb:21

と正しく指摘してくれます。めでたしめでたし


参照

2009-03-18

[][][][][][]IDMSことはじめ:(2)IDMSの生成

IDMSことはじめ:(1)IDMSとは - 名もないテクノ手のつづき。

前回は、スニペットがIDMSというXMLフォーマットであることを説明しました。


IDMSの生成

今回は、Rubyの標準ライブラリであるREXMLを使って、IDMSを生成してみたいと思います。

#! /usr/bin/ruby -Ku

require "rexml/document"

my_str = <<EOF
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<?aid style="50" type="snippet" readerVersion="6.0" featureSet="257" product="6.0(352)" ?>
<?aid SnippetType="PageItem"?>
<Document DOMVersion="6.0" Self="d">
	<Spread Self="ud0">
	</Spread>
</Document>
EOF

my_xml = REXML::Document.new my_str
my_Spread = my_xml.elements["/Document/Spread"]
my_Rectangle = my_Spread.add_element "Rectangle", {"Self"=>"ue5", "StrokeWeight"=>"0.5", "ItemTransform"=>"1 0 0 1 0 -421"}
my_Proerties = my_Rectangle.add_element "Properties"
my_PathGeometry = my_Proerties.add_element "PathGeometry"
my_GeometryPathType = my_PathGeometry.add_element "GeometryPathType", {"PathOpen"=>"false"}
my_PathPointArray = my_GeometryPathType.add_element "PathPointArray"
my_PathPointArray.add_element "PathPointType", {"Anchor"=>"50.25 100.25", "LeftDirection"=>"50.25 100.25", "RightDirection"=>"50.25 100.25"}
my_PathPointArray.add_element "PathPointType", {"Anchor"=>"50.25 299.75", "LeftDirection"=>"50.25 299.75", "RightDirection"=>"50.25 299.75"}
my_PathPointArray.add_element "PathPointType", {"Anchor"=>"199.75 299.75", "LeftDirection"=>"199.75 299.75", "RightDirection"=>"199.75 299.75"}
my_PathPointArray.add_element "PathPointType", {"Anchor"=>"199.75 100.25", "LeftDirection"=>"199.75 100.25", "RightDirection"=>"199.75 100.25"}
print my_xml

正直いって、XMLを手で書くのと手間は変わりません(w

あと、テスト中に気がついたのですけれど、このDOM階層が多少間違っていようと、要素名が間違っていようと、一切エラーはでないようでした。

ただ、ちゃんと図形にならないだけ^^

生成したXMLは、チェックしないといけないです。どうやって? Relax NGスキーマを使って。つづく...か?

参照

REXML API document (ja)

RubyでXML操作