|
|
|||||||||
|
|||||||||
|
TX09 - Postscript フォントファイル名の翻訳(97 年 11 月 17 日) Q: どうすればフォント名を Postscript フォントファイルの名前に翻訳できますか。 A: Postscript フォントの名前は
FOND リソース内部に格納されている情報を使って決定されます。この情報は、スタイルマッピングテーブルの中に格納されています。このテーブルの詳細については、『Inside
Macintosh: Text』の 4-99 ページから 4-105 ページを参照してください。基本的な手順としては、FOND
とスタイル情報を取り出して、有効な Postscript 名を構築します。 |
|
---------------------------------------------------------------------------- #include <fonts.h>
#include <Strings.h>
typedef short int16;
typedef long int32;
typedef FamRec **FamRecHdl;
typedef StyleTable *StyleTablePtr;
#define MIN(a,b) ((a)<(b)?(a):(b))
void main (void);
void GetPrinterFontName (Str255 screenName, Str255 printerName);
int32 MyCompressStyle(Style aStyle);
void MyNthStyleName(int32 index, Ptr q, Str255 s);
void MyPSFontName(FamRec **fh, Style aStyle, Str255 PSName);
void ConcatPStrings (Str255 targetStr, ConstStr255Param appendStr);
void ConcatPStrings (Str255 targetStr, ConstStr255Param appendStr)
{
short appendLen;
/* コピーするバイト数を計算する。最大 255 まで */
appendLen = MIN(appendStr[0], 255 - targetStr[0]);
if (appendLen > 0) {
BlockMoveData(appendStr+1, targetStr+targetStr[0]+1, (long) appendLen);
targetStr[0] += appendLen;
}
}
void main (void)
{
Str255 printer;
// 標準的な Mac の初期化を実行する
InitGraf(&qd.thePort);
InitFonts();
InitWindows();
InitMenus();
TEInit();
InitDialogs(nil);
InitCursor();
MaxApplZone();
MoreMasters();
MoreMasters();
MoreMasters();
GetPrinterFontName ("\pTimes", printer);
Debugger();
}
void GetPrinterFontName(Str255 screenName, Str255 printerName)
{
int16 fontNum;
FMetricRec theMetrics;
WidthTable **wTabHan;
GetFNum( screenName, &fontNum);
TextFont( fontNum );
TextFace (bold + italic);
FontMetrics( &theMetrics );
wTabHan = (WidthTable **) theMetrics.wTabHandle;
MyPSFontName((FamRecHdl) (**wTabHan).fHand, bold+italic, printerName);
return;
}
int32 MyCompressStyle(Style aStyle)
// 短縮と伸張が相互に排他的であると仮定して、
// "StyleItem のセット" は [0..47] の中にマップされる
{
int32 styleCode;
styleCode = 0;
if (bold & aStyle)
styleCode = styleCode + 1;
if (italic & aStyle)
styleCode = styleCode + 2;
if (outline & aStyle)
styleCode = styleCode + 4;
if (shadow & aStyle)
styleCode = styleCode + 8;
if (condense & aStyle)
styleCode = styleCode + 16;
else if (extend & aStyle)
styleCode = styleCode + 32;
return( styleCode );
}
void MyNthStyleName(int32 index, Ptr q, Str255 s)
{
while (index > 1) {
q = (Ptr) (q + *q + 1);
// q^ = stringlength < 128 ... と仮定する
index -= 1;
}
BlockMove(q, &s[0], *q + 1);
// q^ = stringlength < 127 ... と仮定する
return;
}
void MyPSFontName(FamRec **fh, Style aStyle, Str255 PSName)
{
StyleTablePtr stp;
Ptr q; // スタイル名テーブルへのポインタ
Str255 styleName, suffixIndices;
int32 i, nbOfStrings, offset, whichIndex;
PSName[0] = '0';
offset = (**fh).ffStylOff;
if (offset > 0) {
q = ((Ptr) *fh) + offset;
stp = (StyleTablePtr) q;
q += sizeof (StyleTable);
// スタイル名テーブルはスタイルマッピングテーブルに従う
nbOfStrings = *(SInt16 *) q;
// チェックを行う範囲
q += sizeof (SInt16);
// これでフォントのベース名をポイントする
BlockMove(q, (Ptr) PSName, *q + 1);
// フォントのベース名。length < 128 と仮定する
whichIndex = stp->indexes[MyCompressStyle(aStyle)];
if (whichIndex > 1 && whichIndex <= nbOfStrings) {
MyNthStyleName(whichIndex, q, suffixIndices);
for (i=1;i <= suffixIndices[0];++i) {
MyNthStyleName(suffixIndices[i], q, styleName);
ConcatPStrings( PSName, styleName);
}
}
}
//ELSE FOND が壊れている
//else // FOND にスタイルマッピングテーブルがない
//return( PSName );
}
----------------------------------------------------------------------------
#define _SanityCheck_ 1
#ifndef _SanityCheck_
#define _SanityCheck_ 1
#endif
// これらのコードでは何らかのエラー変数を設定していません。
// 一般に、OSErr を通知するルーチンでは、適切に設定されているルーチンの内部に
// 変数を持つようにしてください。そうすれば、そのルーチンがすでに noErr に
// 設定されていないとき、"デフォルト" のエラーコードが返されます
#if _SanityCheck_
#define FAIL_NIL(y,msg) {if (y == NULL) {DebugStr(msg); goto error;}}
#define FAIL_OSERR(y,msg) {if (y != noErr) {DebugStr(msg); goto error;}}
#define FAIL_FALSE(y,msg) {if (!y) {DebugStr(msg); goto error;}}
#define SIGNAL_ERROR(msg) {DebugStr(msg); goto error;}
#else
#define FAIL_NIL(y,msg) {if (y == NULL) {goto error;}}
#define FAIL_OSERR(y,msg) {if (y != noErr) { goto error;}}
#define FAIL_FALSE(y,msg) {if (!y) {goto error;}}
#define SIGNAL_ERROR(msg) {goto error;}
#endif
void main (void);
// このルーチンは、渡されたフォントを含む、最初に使用可能なインストール済みファイルを返す
// また、このルーチンは目的のフォントを含むその他のファイルを検索するために使用できる魔法のクッキーを返す。
OSErr FontNameToFSSpec (ConstStr31Param inFont, FSSpec *outFile, long *outCookie);
OSErr NextFontToFSSpec (long *inOutCookie, FSSpec *outFile);
// 扱いが容易なため、次のルーチンは MoreFiles から借用している
/*****************************************************************************/
pascal OSErr GetFileLocation(short refNum,
short *vRefNum,
long *dirID,
StringPtr fileName);
/* オープンファイルの保存場所を取得する
GetFileLocation 関数はオープンファイルの保存場所 (ボリューム参照番号、ディレクトリ ID、および fileName) を取得する。
refNum input: オープンファイルのファイル参照番号
vRefNum output: ボリューム参照番号
dirID output: 親ディレクトリ ID
fileName input: ファイル名が返されるバッファ (最小限 Str63) へのポインタ、または nil でなければらない
output: ファイル名
結果コード
noErr 0 正常終了
nsvErr -35 指定されたボリュームが存在しない
fnOpnErr -38 ファイルがオープンされていない
rfNumErr -51 参照番号が存在しないアクセスパスを指定している
__________
関連項目: FSpGetFileLocation
*/
/*****************************************************************************/
pascal OSErr FSpGetFileLocation(short refNum,
FSSpec *spec);
/* FSSpec レコードに含まれるオープンファイルの保存場所を取得する
refNum input: オープンファイルのファイル参照番号
spec output: ファイル名と保存場所を含む FSSpec レコード
結果コード
noErr 0 正常終了
nsvErr -35 指定されたボリュームが存在しない
fnOpnErr -38 ファイルがオープンされていない
rfNumErr -51 参照番号が存在しないアクセスパスを指定している
__________
関連項目: GetFileLocation
*/
/*****************************************************************************/
pascal OSErr GetFileLocation(short refNum,
short *vRefNum,
long *dirID,
StringPtr fileName)
{
FCBPBRec pb;
OSErr error;
pb.ioNamePtr = fileName;
pb.ioVRefNum = 0;
pb.ioRefNum = refNum;
pb.ioFCBIndx = 0;
error = PBGetFCBInfoSync(&pb);
*vRefNum = pb.ioFCBVRefNum;
*dirID = pb.ioFCBParID;
return ( error );
}
/*****************************************************************************/
pascal OSErr FSpGetFileLocation(short refNum,
FSSpec *spec)
{
return ( GetFileLocation(refNum, &(spec->vRefNum), &(spec->parID), spec->name) );
}
OSErr FontNameToFSSpec (ConstStr31Param inFont, FSSpec *outFile, long *outCookie)
{
OSErr theErr= noErr;
short homeFile;
Handle fond;
*outCookie = NULL;
fond = GetNamedResource('FOND', inFont);
theErr = ResError();
FAIL_OSERR (theErr, "\p Failed to find any installed font file with that font name")
FAIL_NIL (fond, "\p Failed to find any installed font file with that font name")
homeFile = HomeResFile (fond);
theErr = ResError();
FAIL_OSERR (theErr, "\p Failed to find the resource's home")
theErr = FSpGetFileLocation(homeFile, outFile);
FAIL_OSERR (theErr, "\p couldn't convert the reference to a file spec")
// 処理成功。クッキーをセットして戻る
*outCookie = (long) fond;
return noErr;
error:
if (theErr != noErr)
theErr = paramErr;
*outCookie = NULL;
return theErr;
}
OSErr NextFontToFSSpec (long *inOutCookie, FSSpec *outFile)
{
OSErr theErr= noErr;
short homeFile;
Handle fond = (Handle) *inOutCookie;
if (fond == NULL) return paramErr;
fond = GetNextFOND (fond);
theErr = ResError();
FAIL_OSERR (theErr, "\p No more fonds left with that name")
FAIL_NIL (fond, "\p No more fonds left with that name")
homeFile = HomeResFile (fond);
theErr = ResError();
FAIL_OSERR (theErr, "\p Failed to find the resource's home")
theErr = FSpGetFileLocation(homeFile, outFile);
FAIL_OSERR (theErr, "\p couldn't convert the reference to a file spec")
// 処理成功。クッキーをセットして戻る
*inOutCookie = (long) fond;
return noErr;
error:
if (theErr != noErr)
theErr = paramErr;
*inOutCookie = NULL;
return theErr;
}
void main (void)
{
long oreo;
FSSpec fontFile;
OSErr theErr;
// ここでデバッガに入り、返された FSSpecs を通知する
theErr = FontNameToFSSpec("\pPalatino", &fontFile, &oreo);
Debugger();
while (oreo != 0)
{
theErr = NextFontToFSSpec (&oreo, &fontFile);
Debugger();
}
}
-- Tim Carroll
devsupport@apple.com
|