FrameMaker 10とExtendedScriptのセミナーがAdobe eSeminarであったみたいです。
その時のサンプルデータとスライドが下のブログに上がっています。 http://frameautomation.com/2011/05/31/framemaker-10-extendscript-slides/
オブジェクトチェックにObjectValid()というメソッドがあったのか。
あと、イベント処理とかもいけるのか。
FrameMaker 10とExtendedScriptのセミナーがAdobe eSeminarであったみたいです。
その時のサンプルデータとスライドが下のブログに上がっています。 http://frameautomation.com/2011/05/31/framemaker-10-extendscript-slides/
オブジェクトチェックにObjectValid()というメソッドがあったのか。
あと、イベント処理とかもいけるのか。
スクリプトを使ってカーソルの位置にアンカー枠を作成してその中に画像を挿入する例。
オブジェクトビュアーの列挙型の情報がアレなので結局FDKリファレンスを見たほうが早いという罠。
(function(){
// Insert illust filename
var InsertFile = "hogehoge.jpg";
var docObj = app.ActiveDoc;
if (docObj.id === 0)
{
Alert("select document", Constants.FF_ALERT_CONTINUE_NOTE);
return;
}
var selObj = docObj.TextSelection;
if (selObj.beg.obj.id === selObj.end.obj.id && selObj.beg.offset === selObj.end.offset)
{
// Add Anchored frame
var aframeObj = docObj.NewAnchoredAFrame(selObj.beg);
aframeObj.AnchorType = Constants.FV_ANCHOR_BELOW;
aframeObj.FP_Alignment = Constants.FV_ALIGN_CENTER;
// Insert illust in anchored frame
var graphicObj = docObj.NewGraphicObject (Constants.FO_Inset, aframeObj);
graphicObj.InsetFile = InsertFile;
graphicObj.InsetDpi = 150;
// Fit anchored frame
aframeObj.Width = graphicObj.Width;
aframeObj.Height = graphicObj.Height;
}
else
{
Alert("select text insert location", Constants.FF_ALERT_CONTINUE_NOTE);
}
})();
PDF間で特定の位置にリンクする場合、移動先名を設定しないとできません。
iTextで作成する場合、PdfDestinationで飛び先の位置を設定を予め作成したあとにそれぞれのページに追加します。 PdfContentByteもしくはPdfWriterのどちらかから追加できます。また一括でAddNamedDestinationsを使って一括に登録することが可能です。次は新規文書に移動先を設定する例です。
using System;
using System.Drawing;
using iTextSharp.text;
using iTextSharp.text.pdf;
namespace ConsoleApplication1
{
class Program
{
const float pt2mm = 72f / 25.4f;
static void Main(string[] args)
{
string savePdf = "hogehoge.pdf";
string loadPdf = "fugafuga.pdf";
// 新規から作成
string outputPath = @"hogehoge.pdf";
Document pdoc = new Document(PageSize.A4);
PdfWriter pw = PdfWriter.GetInstance(pdoc, new FileStream(outputPath, FileMode.Create));
// 移動先の場所を設定
PdfDestination dest = new PdfDestination(PdfDestination.XYZ, 105 * pt2mm, 148.5F * pt2mm, 0);
// コンテンツの書き出し
pdoc.Open();
PdfContentByte pcb = pw.DirectContent;
pcb.LocalDestination("name1", dest); // 移動先名の作成
Paragraph p = new Paragraph("Hello World");
pdoc.Add(p);
pcb.ClosePath();
pdoc.NewPage();
pw.AddNamedDestination("name2", 2, dest); // 移動先名の作成
pcb.ClosePath();
pdoc.Close();
}
}
}
だが既存のPDFに追加する場合、新規から作成する場合と同じ設定を行ってもバグなのか分からないが追加することはできません。
仕方が無いので直接命令を書き込みます。
移動先の設定はCatalog→Names→Dests→Namesで取得できます。
PdfReader pdf = new PdfReader(@"hogehoge.pdf");
PdfDictionary root = pdf.Catalog;
PdfDictionary pDests = root.GetAsDict(PdfName.NAMES).GetAsDict(PdfName.DESTS);
PdfArray pDestNames = pDests.GetAsArray(PdfName.NAMES);
if (pDestNames == null)
{
// 移動先の設定がない場合、作成する
pDests.Put(PdfName.NAMES, new PdfArray());
pDestNames = pDests.GetAsArray(PdfName.NAMES);
}
配列に移動先名、移動先の設定の順番に書き込みます。
PdfDestination dest = new PdfDestination(PdfDestination.XYZ, 0, 0, 0);
dest.AddPage(pdf.GetPageOrigRef(1));
pDestNames.Add(new PdfString("name1"));
pDestNames.Add(dest);
まとめると次のとおりになります。
using System;
using System.Drawing;
using iTextSharp.text;
using iTextSharp.text.pdf;
namespace ConsoleApplication1
{
class Program
{
const float pt2mm = 72f / 25.4f;
static void Main(string[] args)
{
string sourcePdf = @"hogehoge.pdf";
string outputPath = @"fugafuga.pdf";
PdfReader pdf = new PdfReader(sourcePdf);
PdfStamper stamper = new PdfStamper(pdf, new FileStream(outputPath, FileMode.Create));
// 既存PDFにあれこれ追加
PdfContentByte cb = stamper.GetUnderContent(1);
cb.BeginText();
cb.SetFontAndSize(BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.EMBEDDED), 18);
cb.ShowTextAligned(Element.ALIGN_LEFT, "Sample", 30, 600, 0);
cb.EndText();
// 移動先の生成
PdfDestination dest = new PdfDestination(PdfDestination.XYZ, 0, 0, 0);
if (dest.HasPage())
dest.ArrayList[0] = pdf.GetPageOrigRef(2);
else
dest.AddPage(pdf.GetPageOrigRef(2));
// 移動先を設定
PdfDictionary root = pdf.Catalog;
PdfDictionary pDests = root.GetAsDict(PdfName.NAMES).GetAsDict(PdfName.DESTS);
PdfArray pDestNames = pDests.GetAsArray(PdfName.NAMES);
if (pDestNames == null)
{
pDests.Put(PdfName.NAMES, new PdfArray());
pDestNames = pDests.GetAsArray(PdfName.NAMES);
}
pDestNames.Add(new PdfString("name"));
pDestNames.Add(dest);
stamper.Close();
pdf.Close();
}
}
}
var mMenu = app.GetNamedMenu("!MakerMainMenu");
var nMenu = mMenu.DefineAndAddMenu("APIMenu", "TextApi");
nMenu.DefineAndAddCommand(1, "GetTextCmd", "Get Text","");
nMenu.DefineAndAddCommand(2, "AddTextCmd","Insert Text","\\!GT");
nMenu.DefineAndAddCommand(3, "DeleteTextCmd", "Delete Text", "\\!IT");
nMenu.DefineAndAddCommand(4, "ColorTextCmd", "Color Text", "\\!DT");
nMenu.DefineAndAddCommand(5, "FontSizeCmd", "Change Font Size", "\\!CT");
UpdateMenus();
function Command(command)
{
var doc = app.ActiveDoc;
if(doc.id === 0)
Alert("Please selected Document.", Constants.FF_ALERT_CONTINUE_WARN);
switch(command)
{
/* Get text from selection. */
case 1:
var tr = doc.TextSelection;
if (tr.beg.obj.id === 0 || ((tr.beg.obj.id === tr.end.obj.id) && (tr.beg.offset === tr.end.offset)))
{
Alert("Please select some text and try again.", Constants.FF_ALERT_CONTINUE_WARN);
break;
}
var textItems = doc.GetTextForRange(tr, Constants.FTI_String);
alert(CreateStringFromTextItems(textItems));
break;
/* Add text. */
case 2:
var tr = doc.TextSelection;
if (tr.beg.obj.id === 0)
{
Alert("Please select an insertion point and try again.", Constants.FF_ALERT_CONTINUE_WARN);
break;
}
if (!((tr.beg.obj.id === tr.end.obj.id) && (tr.beg.offset === tr.end.offset)))
{
if (Alert("Do you wish to overwrite the selected text?", Constants.FF_ALERT_NO_DEFAULT))
break;
}
doc.AddText(tr.beg, "The new CoffeeTool\011");
break;
/* Delete selected text. */
case 3:
var tr = doc.TextSelection;
if (tr.beg.obj.id === 0 || ((tr.beg.obj.id === tr.end.obj.id) && (tr.beg.offset === tr.end.offset)))
{
Alert("Please select some text and try again.", Constants.FF_ALERT_CONTINUE_WARN);
break;
}
doc.DeleteText(tr);
break;
/* Change the color of selected text to Red. */
case 4:
var tr = doc.TextSelection;
if (tr.beg.obj.id === 0 || ((tr.beg.obj.id === tr.end.obj.id) && (tr.beg.offset === tr.end.offset)))
{
Alert("Please select some text and try again.", Constants.FF_ALERT_CONTINUE_WARN);
break;
}
var color = doc.GetNamedObject(Constants.FO_Color, "Red"); // Color name is different in each language.
var props = doc.GetTextProps(tr.beg);
var i = GetPropIndex(props, Constants.FP_Color);
props[i].propVal.obj = color;
doc.SetTextProps(tr, props);
break;
/* Change the font size of the selected text to 30 points. */
case 5:
var tr = doc.TextSelection;
if (tr.beg.obj.id === 0 || ((tr.beg.obj.id === tr.end.obj.id) && (tr.beg.offset === tr.end.offset)))
{
Alert("Please select some text and try again.", Constants.FF_ALERT_CONTINUE_WARN);
break;
}
/* Allocate memory for the property list. */
props = AllocatePropVals(1);
/* Set up the properties. */
props[0].propIdent.num = Constants.FP_FontSize;
props[0].propVal.ival = 30 * 65536;
props[0].propVal.valType = Constants.FT_Metric;
/* Apply the property list to the text selection. */
doc.SetTextProps(tr, props);
break;
}
}
/***************************************************************
* Create a string from an TextItems structure.
****************************************************************/
function CreateStringFromTextItems(textItems)
{
var s = "";
for (var i = 0; i < textItems.length; i++)
{
if (textItems[i].dataType === Constants.FTI_String)
{
s += textItems[i].sdata;
}
}
return s;
}
FrameMaker 10の発表、そして出荷が始まったらしい。
昨年末に動画で登場していたときにはすでにマスターアップが完了していたということなのだろう。
アップグレード内容はS1000、DITA1.2対応、それに関連する機能の強化が主なんだろう。市販のCMS(SharePoint、Documentum)に対応といったところだ。
早速、体験版を入れてあれこれ触ってみて目についた新しい機能は
下は10分位で適当に作ったスクリプトです。選択した画像のアンカー枠の大きさを選択した画像の大きさに合わせるスクリプトです。
var docObj = app.ActiveDoc;
var selGfx = docObj.FirstSelectedGraphicInDoc;
var afrmObj = selGfx.FrameParent;
afrmObj.Width = selGfx.Width;
afrmObj.Height = selGfx.Height;
selGfx.LocX = 0;
selGfx.LocY = 0;
問題はバージョンアップできるのが8からということか。(TCS3だと7.xからできるが本体より高い)
まだ世の中で動いているシステムの大半が7.x以下ではないだろうか。
Wordデータを英語環境に持って行くと2バイトフォントが使われている箇所を探せないかという話があったのでいい方法はないかな?
下のサンプルは少々強引だが・・・選択範囲に使用している文字のフォント名を取得してWin32APIを使用してフォントが2バイト(日中韓)フォントかの確認をしています。
当然OSに無いフォントがある場合は正常に動作しません。たぶん・・・。
簡単に説明するとCharacter.Font.Nameが実際に表示されているフォントでCharacter.Font.ASCIIが欧文フォント、Character.Font.NameFarEastが日中韓フォントのどれかになります。
他にもアラビア語用とかも選択できるみたいだがめんどくさいので割愛ということで。
Option Explicit
Private Const LF_FACESIZE As Long = 32&
Private Const LF_FULLFACESIZE As Long = 64&
Private Const DEVICE_FONTTYPE As Long = &H2&
Private Const RASTER_FONTTYPE As Long = &H1&
Private Const TRUETYPE_FONTTYPE As Long = &H4&
Private Type LOGFONT
lfHeight As Long
lfWidth As Long
lfEscapement As Long
lfOrientation As Long
lfWeight As Long
lfItalic As Byte
lfUnderline As Byte
lfStrikeOut As Byte
lfCharSet As Byte
lfOutPrecision As Byte
lfClipPrecision As Byte
lfQuality As Byte
lfPitchAndFamily As Byte
lfFaceName(LF_FACESIZE - 1&) As Byte
End Type
Type NEWTEXTMETRIC
tmHeight As Long
tmAscent As Long
tmDescent As Long
tmInternalLeading As Long
tmExternalLeading As Long
tmAveCharWidth As Long
tmMaxCharWidth As Long
tmWeight As Long
tmOverhang As Long
tmDigitizedAspectX As Long
tmDigitizedAspectY As Long
tmFirstChar As Byte
tmLastChar As Byte
tmDefaultChar As Byte
tmBreakChar As Byte
tmItalic As Byte
tmUnderlined As Byte
tmStruckOut As Byte
tmPitchAndFamily As Byte
tmCharSet As Byte
ntmFlags As Long
ntmSizeEM As Long
ntmCellHeight As Long
ntmAveWidth As Long
End Type
Private Const ANSI_CHARSET As Byte = 0&
Private Const BALTIC_CHARSET As Byte = 186&
Private Const CHINESEBIG5_CHARSET As Byte = 136&
Private Const DEFAULT_CHARSET As Byte = 1&
Private Const EASTEUROPE_CHARSET As Byte = 238&
Private Const GB2312_CHARSET As Byte = 134&
Private Const GREEK_CHARSET As Byte = 161&
Private Const HANGUL_CHARSET As Byte = 129&
Private Const MAC_CHARSET As Byte = 77&
Private Const OEM_CHARSET As Byte = 255&
Private Const RUSSIAN_CHARSET As Byte = 204&
Private Const SHIFTJIS_CHARSET As Byte = 128&
Private Const SYMBOL_CHARSET As Byte = 2&
Private Const TURKISH_CHARSET As Byte = 162&
Private Const VIETNAMESE_CHARSET As Byte = 163&
Private IsCJK As Boolean ' CJKフォントかの確認
Private Declare Function EnumFontFamiliesEx Lib "gdi32" Alias "EnumFontFamiliesExA" ( _
ByVal hdc As Long, _
lpLogFont As LOGFONT, _
ByVal lpEnumFontProc As Long, _
ByVal LParam As Long, _
ByVal dw As Long _
) As Long
Private Declare Sub MoveMemory Lib "kernel32" Alias "RtlMoveMemory" ( _
Destination As Any, _
Source As Any, _
ByVal Length As Long _
)
Private Declare Function GetDC Lib "user32" ( _
ByVal hwnd As Long _
) As Long
Public Sub CheckFarEastFont()
' フォントが日中韓フォントかの確認
Dim wd_Selection As Word.Selection
Dim i As Long
Set wd_Selection = Application.Selection
For i = 1 To wd_Selection.Characters.Count
With wd_Selection.Characters(i)
If .Font.Name = .Font.NameFarEast And .Font.Name <> "" Then
Call FontCheck(.Font)
End If
End With
Next
End Sub
Private Sub FontCheck(wd_Font As Word.Font)
' フォントが日中韓のエンコードを所持しているかの確認
Dim bytBuf() As Byte
Dim udtLogFont As LOGFONT
bytBuf = StrConv(wd_Font.Name, vbFromUnicode)
With udtLogFont
.lfCharSet = DEFAULT_CHARSET
Call MoveMemory(.lfFaceName(0), bytBuf(0), UBound(bytBuf) + 1&)
.lfPitchAndFamily = 0&
End With
IsCJK = False
Call EnumFontFamiliesEx(GetDC(0), udtLogFont, AddressOf EnumFontFamProc, ByVal 0&, 0)
If IsCJK Then
wd_Font.Animation = wdAnimationMarchingRedAnts ' CJKフォントの場合赤い線のアニメーション
Else
wd_Font.Animation = wdAnimationNone
End If
End Sub
Private Function EnumFontFamProc(lpNLF As LOGFONT, lpNTM As NEWTEXTMETRIC, ByVal FontType As Long, LParam As Long) As Long
Dim FaceName As String
FaceName = StrConv(lpNLF.lfFaceName, vbUnicode)
Debug.Print Left$(FaceName, InStr(FaceName, vbNullChar) - 1) ' フォント名
EnumFontFamProc = 1
Select Case lpNLF.lfCharSet
Case SHIFTJIS_CHARSET, GB2312_CHARSET, CHINESEBIG5_CHARSET, HANGUL_CHARSET:
IsCJK = True
End Select
End Function
しかし、Unicodeの時代なのに未だに2バイト文字というのもなんだかなぁ。
忙しくて、ずうっと放置プレイだった。
まぁ、今年起きそうなことを予想という名の落書きを。
半年以内で起きるだろう・・・たぶん。
正直言って今の作り方ではいたずらに体力を消耗しているだけで何も生み出さないだろう。
この状況に誰もが電子書籍は本当に必要なのだろうかと思うだろう。
だが、ホリエモンが月840円のメルマガを1万人に売っているわけで・・・内容は別としてテキストのみの商品が何人もの人間が苦労して創り上げた電子書籍より売上も制作費の安さが勝っているわけです。
ほかにも同人誌でも1ヶ月で3万ダウンロードの売上を出したサークルもあるわけだから、電子書籍がダメという理由ではないと思う。
まぁ何が言いたいかというとあれこれ複雑な規格つくるよりhtmlやPDFでいいんじゃないという話。重要なのは中身だよ。
既定路線だろう。
今後もケータイからちょっとしたガジェット、カーナビなんかも。
いや・・・専用カーナビ不要論とかでてくるかも。
ただ、法人向けはWindows Phone 7かなとは思っているが日本でいつ出るのやら。
アプリの量が膨大になって目的のアプリが見つかりづらいなどの不満が両者から公然と出てくるかも。
特に電子書籍型アプリとか、あと著作者に許諾を得ずに作成されて登録される海賊版アプリ。
何かしらの方策は打つとは思うけど。
XPの販売終了、セキュリティの問題からWindows7に普及が加速するだろう。
問題は金のない中小企業がついていけるかというところ。
iPhone、Andoroid、PCとの共通の言語はとなるとJAVAではなく手軽さ、作成のしやすさからhtml5だろう。
そして、なんだかんだいってもInternetExplore 9のリリース。
あれこれ、書いてみたが今までのコンテンツのリファイン(焼き直し)という感じが強いかも。
要は声が大きい人が素晴らしいといえばみんな群がるという構造は今年も続くだろうという話。