|
|
|||||||||
|
|||||||||
|
|
GX 05 - QuickDraw GX による EPS のサポート(95 年 5 月 1 日): 更新
Q: QuickDraw GX を使って EPS ファイルをサポートするための正しい方法を教えてください。
A: PostScript のシノニムを使うときには必要です。特に、QD の座標空間を考慮に入れておく必要があります。QD では、
この問題を扱うには、多数の方法があります。その 1 つに、 0 760 translate 1 -1 scale newpathこうすれば、残りの PostScript コードは、そのまま送信できます。ただし、GX オブジェクトを描画する前には、 translate および scale 演算の効果を元に戻すことを忘れないでください。そうしないと、GX オブジェクトの天地は逆になってしまいます。
Q: ご指摘の方法は、ユーザに EPS のエクスポートをさせないことを前提にすれば、たしかに多くのアプリケーションを対象に QuickDraw GX で EPS をサポートする方法として申し分ありません。しかし、EPS を位置に依存しないシェイプ (単調化されたピクチャ・シェイプの一部として) としてサポートする必要があるのです。次に示す方法は、ページの高さがわかっていることを前提にしているため、アプリケーション間 (たとえば、
A: Apple では、
これら 2 つの修正は、比較的簡単にインプリメントできるはずです。 ルーチン: EPSFileToShape
EPS ファイルを読み込み、その外部にシェイプを作成します。その中に PICT リソースが含まれている場合、それは Skia に変換されます。また、PICT リソースが含まれていない場合、四角形のシェイプは、0,0 を起点として、EPS の BoundingBox:: コメントから得られた境界ボックスの幅と高さになります。
いずれのケースでも、EPS ファイルは、 'post' タグ・シノニムとともにシェイプにアタッチされます。
このようにして追加の PostScript がアタッチされ、Skia-PostScript Imaging System を介して印刷を行うときにも、PostScript がシェイプの変形を経由して適切にレンダリングを行えるようになります (もちろん、ここで詳しいことを説明するわけにはいきませんが)。 このためのアルゴリズムは、『PostScript Language Reference Manual』(2nd edition) の 724 ページに記載されています。
/******************************************************/
gxShape EPSFileToShape(Str255 fName, short vRefNum)
{
OSErr status;
PicHandle thePict;
Rect theRect;
Point patStretch = {1,1};
gxShape theShape = nil;
short refNum;
gxTag synTag;
long size;
Handle hPsData;
long startComment, endComment;
Str32 num1;
char tagString[300];
long tagSize, pieceSize;
gxTranslationStatistic seanStats;
/** PostScript データを取得 **/
status = FSOpen(fName, vRefNum, &refNum);
ncheck(status);
GetEOF(refNum, &size);
hPsData = NewHandle(size);
HLock(hPsData);
/** EPS ファイル全体を読み込む **/
status = FSRead(refNum, &size, *hPsData);
ncheck(status);
FSClose(refNum);
/** 境界ボックスのコメントを検索 (数値のみ) **/
startComment = Munger(hPsData, 0, "%%BoundingBox:", 14, nil, 0) + 14;
endComment = Munger(hPsData , startComment, "\n", 1, nil, 0);
refNum = OpenRFPerm(fName, vRefNum, 0);
thePict = (PicHandle)GetResource('PICT', 256);
if (thePict != nil) {
theRect = (*thePict)->picFrame;
theShape = GXNewShape(gxPictureType);
(void) GXConvertPICTToShape(thePict, gxDefaultOptionsTranslation,
&theRect, &theRect, patStretch,
theShape, &seanStats);
status = GXGetGraphicsError(nil);
ncheck(status);
ReleaseResource((Handle)thePict);
} else {
float x1, y1, x2, y2;
gxRectangle theRectangle;
sscanf(*hPsData + startComment, "%f %f %f %f", &x1, &y1, &x2, &y2);
theRectangle.top = 0;
theRectangle.left = 0;
theRectangle.right = X2Fix(x2 - x1);
theRectangle.bottom = X2Fix(y2 - y1);
/** 埋め込み PostScript の原点変換のために
QuickDraw の四角形が必要 **/
theRect.top = 0;
theRect.left = 0;
theRect.bottom= theRectangle.bottom >> 16;
theRect.right = theRectangle.right >> 16;
theShape = GXNewRectangle(&theRectangle);
}//end if
CloseResFile(refNum);
/** QuickDraw 四角形の Left Bottom に変換 **/
tagSize = 0;
NumToString(theRect.left, num1);
num1[(unsigned char)num1[0] + 1] = ' ';
pieceSize = (unsigned char)num1[0] + 1;
BlockMove(&(num1[1]), tagString, pieceSize);
tagSize += pieceSize;
NumToString(theRect.bottom, num1);
pieceSize = (unsigned char)num1[0];
BlockMove(&(num1[1]), tagString + tagSize, pieceSize);
tagSize += pieceSize;
BlockMove(" translate\n", tagString + tagSize, 11);
tagSize += 11;
/** 座標軸を反転 **/
BlockMove(" 1 -1 scale\n", tagString + tagSize, 12);
tagSize += 12;
synTag = GXNewTag( gxPostScriptTag, tagSize, tagString);
GXSetShapeTags(theShape, gxPostScriptTag, 0, 0, 1, &synTag);
GXDisposeTag(synTag);
/** -(LLx) -(LLy) に変換 **/
// オペランド・スタック上のオペランド・コメント
文字列から得た 4 つのボックス番号
synTag = GXNewTag( gxPostScriptTag, endComment - startComment + 1,
*hPsData + startComment);
GXSetShapeTags(theShape, gxPostScriptTag, 0, 0, 1, &synTag);
GXDisposeTag(synTag);
// 後の 2 つをポップし、最初の 2 つを負の数に変換
synTag = GXNewTag( gxPostScriptTag, 36,
"pop pop neg exch neg exch translate\n");
GXSetShapeTags(theShape, gxPostScriptTag, 0, 0, 1, &synTag);
GXDisposeTag(synTag);
/** PostScript シノニム本体 **/
synTag = GXNewTag( gxPostScriptTag, size, *hPsData);
GXSetShapeTags(theShape, gxPostScriptTag, 0, 0, 1, &synTag);
GXDisposeTag(synTag);
DisposHandle(hPsData);
check(theShape);
return(theShape);
}//EPSFileToShape
[ Technical Q&A's : QuickDraw GX : GX Graphics : GX05 ] |
|