DIRECTORY
Atom USING [GetPName],
Basics USING [bitsPerWord],
FS USING [StreamOpen],
Imager USING [ClassRep, Context, ContextRep, Error, MakeGray],
ImagerBackdoor USING [Clipper, IntKey, RealKey],
ImagerBox USING [Rectangle],
ImagerColor USING [Color, ColorOperator, ColorOperatorClassRep, ConstantColor, NarrowToOpConstantColor, OpConstantColor, SampledBlack, SampledColor, SpecialColor, Structure],
ImagerColorPrivate USING [ColorOperatorClass, ColorOperatorClassRep, Element, GrayFromColor, SampleEncoding, SGet, SSize],
ImagerFont USING [Font, Typeface, TypefaceRep, XChar, XStringProc],
ImagerInterpress USING [],
ImagerInterpressBackdoor USING [VectorProc],
ImagerInterpressPrivate USING [Data, DataRep, endPSForm, firstPSForm, Frame, FrameRep, Ref, Rep],
ImagerPath ,
ImagerPixelArray USING [MaxSampleValue, PixelArray, Transfer],
ImagerPrivate USING [Class, ClassRep, DefaultDoIfVisible, DefaultDoWithBuffer, DefaultDrawBitmap, DefaultDrawObject, DefaultDrawPixels, DefaultGetBounds, DefaultGetTransformation, DefaultMaskBitmap, DefaultMoveViewRectangle, DefaultTestViewRectangle, DefaultTransform, DefaultViewClip, DefaultViewClipRectangleI, DefaultViewReset, DefaultViewTranslateI],
ImagerSample USING [Clear, GetBase, ObtainScratchMap, ReleaseScratchMap, RasterSampleMap, Sample],
ImagerStroke,
ImagerTransformation USING [ApplyPreScale, Copy, Equal, Factor, FactoredTransformation, Scale, Transformation],
ImagerTypeface USING [TypefaceRep],
IO USING [Close, Error, GetIndex, PutBlock, PutRope, SetLength, STREAM, UnsafePutBlock],
PSMaster USING [ImagerVariable, PutByte, PutInt, PutIdentifier, PutIntBytes, PutName, PutOp, PutReal, PutRational, PutSequence, PutSequenceText, PutString],
RefText USING [AppendChar],
Rope,
Vector2 USING [VEC];
~
BEGIN
OPEN PSMaster, ImagerInterpressPrivate;
ROPE: TYPE ~ Rope.ROPE;
STREAM: TYPE ~ IO.STREAM;
VectorProc: TYPE ~ ImagerInterpressBackdoor.VectorProc;
VEC: TYPE ~ Vector2.VEC;
Rectangle: TYPE ~ ImagerBox.Rectangle;
Transformation: TYPE ~ ImagerTransformation.Transformation;
PathProc: TYPE ~ ImagerPath.PathProc;
Color: TYPE ~ ImagerColor.Color;
ConstantColor: TYPE ~ ImagerColor.ConstantColor;
OpConstantColor: TYPE ~ ImagerColor.OpConstantColor;
SpecialColor: TYPE ~ ImagerColor.SpecialColor;
SampledColor: TYPE ~ ImagerColor.SampledColor;
SampledBlack: TYPE ~ ImagerColor.SampledBlack;
Typeface: TYPE ~ REF TypefaceRep;
TypefaceRep: PUBLIC TYPE ~ ImagerTypeface.TypefaceRep;
Sample: TYPE ~ ImagerSample.Sample;
PixelArray: TYPE ~ ImagerPixelArray.PixelArray;
ColorOperator: TYPE ~ ImagerColor.ColorOperator;
ColorOperatorClassRep: PUBLIC TYPE ~ ImagerColorPrivate.ColorOperatorClassRep;
Font: TYPE ~ ImagerFont.Font;
XChar: TYPE ~ ImagerFont.XChar;
XStringProc: TYPE ~ ImagerFont.XStringProc;
IntKey: TYPE ~ ImagerBackdoor.IntKey;
RealKey: TYPE ~ ImagerBackdoor.RealKey;
Clipper: TYPE ~ ImagerBackdoor.Clipper;
Context: TYPE ~ Imager.Context;
Class: TYPE ~ ImagerPrivate.Class;
ClassRep:
PUBLIC
TYPE ~ ImagerPrivate.ClassRep;
-- export to Imager
Rep: PUBLIC TYPE ~ ImagerInterpressPrivate.Rep;
Fetch:
PROC [data: Data, ref:
REF]
RETURNS [found:
BOOL, index:
INT] ~ {
frame: Frame ~ data.frame;
FOR i:
NAT
DECREASING
IN [0..frame.size)
DO
IF frame[i]=ref THEN RETURN[found: TRUE, index: i];
ENDLOOP;
RETURN[found: FALSE, index: 0];
};
Store:
PROC [data: Data, ref:
REF]
RETURNS [
INT] ~ {
frame: Frame ~ data.frame;
i: NAT ~ frame.size;
frame[i] ← ref; frame.size ← i+1;
RETURN[i];
};
DoBody:
PROC [data: Data, action:
PROC] ~ {
stream: STREAM ~ data.stream;
frame: Frame ~ data.frame;
savedSize: NAT ~ frame.size;
PutOp[stream, beginBody];
action[! UNWIND => frame.size ← savedSize];
PutOp[stream, endBody];
frame.size ← savedSize;
};
Create:
PUBLIC
PROC [fileName:
ROPE, header:
ROPE]
RETURNS [Ref] ~ {
stream: STREAM ~ FS.StreamOpen[fileName, $create];
IF header = NIL THEN header ← "Interpress/Xerox/3.0 ";
RETURN[CreateFromStream[stream, header]];
};
CreateFromStream:
PUBLIC
PROC [stream:
STREAM, header:
ROPE]
RETURNS [Ref] ~ {
frame: Frame ~ NEW[FrameRep[topFrameSize]];
buffer: REF TEXT ~ NEW[TEXT[200]];
version: NAT ~ IF Rope.Match["*3.0 ", header] THEN 3 ELSE 2;
data: Data ~ NEW[DataRep ← [stream: stream, frame: frame, buffer: buffer, version: version]];
context: Context ~ NEW[Imager.ContextRep ← [class: ipClass, data: data]];
ref: Ref ~ NEW[Rep ← [page: 0, context: context, data: data]];
frame.size ← 0;
IO.PutRope[stream, header];
PutOp[stream, beginBlock]; -- begin master
PutOp[stream, beginBody]; -- begin preamble
RETURN[ref];
};
DeclareFont:
PUBLIC
PROC [self: Ref, font: Font] ~ {
IF self.page=0 THEN [] ← FetchFont[self.data, font];
};
DeclareColor:
PUBLIC
PROC [self: Ref, color: Color] ~ {
IF self.page=0 THEN [] ← FetchColor[self.data, color];
};
DeclareColorOperator:
PUBLIC
PROC [self: Ref, colorOperator: ColorOperator] ~ {
data: Data ~ self.data;
IF self.page=0 AND data.version >= 3 THEN [] ← FetchColorOperator[data, colorOperator];
};
DeclarePixelArray:
PUBLIC
PROC [self: Ref, pixelArray: PixelArray] ~ {
data: Data ~ self.data;
IF data.version < 3 AND (pixelArray.samplesPerPixel # 1 OR pixelArray.MaxSampleValue[0] # 1) THEN RETURN;
IF self.page=0 THEN [] ← FetchPixelArray[data, pixelArray];
};
DeclareIdentifier:
PUBLIC
PROC [self: Ref, identifier:
ATOM] ~ {
IF self.page=0 THEN [] ← FetchIdentifier[self.data, identifier];
};
StreamFromRef:
PUBLIC
PROC [self: Ref]
RETURNS [stream:
STREAM] ~ {
data: Data ~ self.data;
RETURN [data.stream];
};
PushInt:
PUBLIC
PROC [self: Ref, n:
INT] ~ {
data: Data ~ self.data;
stream: STREAM ~ data.stream;
PutInt[stream, n];
};
PushReal:
PUBLIC
PROC [self: Ref, r:
REAL] ~ {
data: Data ~ self.data;
stream: STREAM ~ data.stream;
PutReal[stream, r];
};
PushRational:
PUBLIC
PROC [self: Ref, numerator, denominator:
INT] ~ {
data: Data ~ self.data;
stream: STREAM ~ data.stream;
PutRational[stream, numerator, denominator];
};
PushVector:
PUBLIC
PROC [self: Ref, vectorProc: VectorProc] ~ {
data: Data ~ self.data;
stream: STREAM ~ data.stream;
count: INT ← 0;
putIdentifier:
PROC [identifier:
ATOM] ~ {
found: BOOL; index: INT;
[found, index] ← Fetch[data, identifier];
IF NOT found THEN PutIdentifier[stream, Atom.GetPName[identifier]]
ELSE FGet[stream, index];
count ← count + 1;
};
putString:
PROC [rope: Rope.
ROPE] ~ {
PutString[stream, rope];
count ← count + 1;
};
putInt:
PROC [int:
INT] ~ {
PutInt[stream, int];
count ← count + 1;
};
putReal:
PROC [real:
REAL] ~ {
PutReal[stream, real];
count ← count + 1;
};
putRational:
PROC [n, d:
INT] ~ {
PutRational[stream, n, d];
count ← count + 1;
};
putTransformation:
PROC [t: Transformation] ~ {
PutTransformation[stream, t];
count ← count + 1;
};
putVector:
PROC [v:
PROC] ~ {
save: INT ~ count;
count ← 0;
v[];
PutInt[stream, count];
PutOp[stream, makevec];
count ← save + 1;
};
putImageOp:
PROC [action:
PROC [Imager.Context]] ~ {
bodyAction: PROC ~ { action[self.context] };
PutOp[stream, makesimpleco];
DoBody[data, bodyAction];
count ← count + 1;
};
IF data.pushVectorActive THEN ERROR Imager.Error[[$InvalidOperationSequence, "Cannot call PushVector recursively"]];
data.pushVectorActive ← TRUE;
IF self.page#0 THEN ERROR Imager.Error[[$InvalidOperationSequence, "Cannot add to preamble after pages have begun"]];
vectorProc[putIdentifier, putString, putInt, putReal, putRational, putTransformation, putVector, putImageOp];
PutInt[stream, count];
PutOp[stream, makevec];
data.pushVectorActive ← FALSE;
};
PushPixelArray:
PUBLIC
PROC [self: Ref, pa: PixelArray] ~ {
data: Data ~ self.data;
MakePixelArray[data, pa]
};
PushColorOperator:
PUBLIC
PROC [self: Ref, op: ColorOperator] ~ {
data: Data ~ self.data;
MakeColorOperator[data, op]
};
GetContext:
PUBLIC
PROC [self: Ref]
RETURNS [Imager.Context] = {
data: Data ~ self.data;
stream: STREAM ~ data.stream;
frame: Frame ~ data.frame;
IF self.page=0 THEN PutOp[stream, endBody]; -- end preamble
self.page ← self.page+1;
data.savedSize ← frame.size;
PutOp[stream, beginBody];
PutInt[stream, 1]; ISet[stream, priorityImportant]; -- default priorityImportant to TRUE
RETURN [self.context];
};
NewPage:
PUBLIC
PROC [self: Ref, context: Imager.Context, last:
BOOL] ~ {
data: Data ~ self.data;
frame: Frame ~ data.frame;
stream: STREAM ~ data.stream;
PutOp[stream, endBody];
frame.size ← data.savedSize;
IF
NOT last
THEN {
self.page ← self.page+1;
PutOp[stream, beginBody];
IF data.version >= 3
THEN {
PutInt[stream, 1]; ISet[stream, priorityImportant]; -- default priorityImportant to TRUE
};
};
};
DoPage:
PUBLIC
PROC [self: Ref, action:
PROC [Imager.Context], scale:
REAL ← 1] ~ {
data: Data ~ self.data;
stream: STREAM ~ data.stream;
pageBody:
PROC ~ {
IF data.version >= 3
THEN {
PutInt[stream, 1]; ISet[stream, priorityImportant]; -- default priorityImportant to TRUE
};
IF scale#1
THEN {
PutReal[stream, scale];
PutOp[stream, scale];
PutOp[stream, concatt];
};
action[self.context];
};
IF self.page=0 THEN PutOp[stream, endBody]; -- end preamble
self.page ← self.page+1;
DoBody[data, pageBody];
};
Close:
PUBLIC
PROC [self: Ref] ~ {
data: Data ~ self.data;
Finish[self];
IO.Close[data.stream];
};
Finish:
PUBLIC
PROC [self: Ref] ~ {
data: Data ~ self.data;
stream: STREAM ~ data.stream;
IF self.page=0 THEN PutOp[stream, endBody]; -- end preamble
PutOp[stream, endBlock]; -- end master
};
MakeVec:
PROC [stream:
STREAM, n:
INT] ~ {
PutInt[stream, n];
PutOp[stream, array];
PutOp[stream, astore];
};
PutVec:
PROC [stream:
STREAM, v:
VEC] ~ {
PutReal[stream, v.x]; PutReal[stream, v.y];
};
PutVecI:
PROC [stream:
STREAM, x, y:
INTEGER] ~ {
PutInt[stream, x]; PutInt[stream, y];
};
PutTransformation:
PROC [stream:
STREAM, m: Transformation] ~ {
PutOp[stream, beginarray];
PutReal[stream, m.a];
PutReal[stream, m.d];
PutReal[stream, m.b];
PutReal[stream, m.e];
PutReal[stream, m.c];
PutReal[stream, m.f];
PutOp[stream, endarray];
};
PutPath:
PROC [stream:
STREAM, path: PathProc, closed:
BOOL ←
FALSE] ~ {
moveTo:
PROC [p:
VEC] ~ {
PutVec[stream, p];
PutOp[stream, moveto];
};
lineTo:
PROC [p1:
VEC] ~ {
PutVec[stream, p1];
PutOp[stream, lineto];
};
curveTo:
PROC [p1, p2, p3:
VEC] ~ {
PutVec[stream, p1];
PutVec[stream, p2];
PutVec[stream, p3];
PutOp[stream, curveto];
};
close:
PROC ~ {
IF closed THEN PutOp[stream, closepath];
};
ImagerPath.Transform[path: path,
moveTo: moveTo, lineTo: lineTo, curveTo: curveTo, close: close];
};
RectanglePath:
PROC [r: Rectangle, action:
PROC [PathProc]] ~ {
x1: REAL ~ r.x; x2: REAL ~ r.x+r.w;
y1: REAL ~ r.y; y2: REAL ~ r.y+r.h;
path: PathProc ~ { moveTo[[x1, y1]]; lineTo[[x2, y1]]; lineTo[[x2, y2]]; lineTo[[x1, y2]] };
action[path];
};
PutSampleEncoding:
PROC [stream:
STREAM, map: ImagerColorPrivate.SampleEncoding] ~ {
IF map=NIL THEN PutInt[stream, 0]
ELSE {
FOR i: Sample IN[0..map.size) DO PutReal[stream, map[i]] ENDLOOP;
MakeVec[stream, map.size];
};
};
identity: Transformation ~ ImagerTransformation.Scale[1];
MakeFont:
PROC [data: Data, font: Font] ~ {
stream: STREAM ~ data.stream;
typeface: Typeface ~ font.typeface;
name: ROPE ← typeface.name;
IF data.version < 3
THEN {
v: INT ← Rope.Find[name, "xc1-2-2", 0, FALSE]; -- hack to back-convert font names
subst: ROPE ~ "xc1-1-1";
IF v >= 0 THEN name ← Rope.Replace[base: name, start: v, len: Rope.Size[subst], with: subst];
};
PutName[stream, name];
PutOp[stream, findfont];
IF typeface.alternateMetrics #
NIL
AND data.version >= 3
THEN {
IF Rope.Find[s1: typeface.alternateMetrics, s2: "/"] >= 0
THEN { PutName[stream, typeface.alternateMetrics] }
ELSE { PutIdentifier[stream, typeface.alternateMetrics] };
PutOp[stream, alternatemetrics];
};
IF
NOT font.charToClient.Equal[identity]
THEN {
PutTransformation[stream, font.charToClient];
PutOp[stream, modifyfont];
};
};
MakePixelArray:
PROC [data: Data, pa: PixelArray] ~ {
stream: STREAM ~ data.stream;
samplesPerPixel: NAT ~ pa.samplesPerPixel;
sSize: NAT ~ pa.sSize;
fSize: NAT ~ pa.fSize;
maxSample: Sample ← 0;
bitsPerSample: NAT ← 0;
PutInt[stream, sSize]; -- xPixels
PutInt[stream, fSize]; -- yPixels
PutInt[stream, samplesPerPixel]; -- samplesPerPixel
IF samplesPerPixel = 1
THEN {
maxSample ← ImagerPixelArray.MaxSampleValue[pa, 0];
PutInt[stream, maxSample];
PutInt[stream, 1]; -- samplesInterleaved; use 1 for compatibility with older interpress versions
}
ELSE {
FOR i:
NAT
IN[0..samplesPerPixel)
DO
m: Sample ~ ImagerPixelArray.MaxSampleValue[pa, i];
PutInt[stream, m];
maxSample ← MAX[maxSample, m];
ENDLOOP;
MakeVec[stream, samplesPerPixel]; -- maxSampleValue
PutInt[stream, 0]; -- samplesInterleaved
};
PutTransformation[stream, pa.m]; -- m
bitsPerSample ←
SELECT maxSample
FROM
1 => 1,
IN[2..255] => 8,
IN[256..LAST[CARDINAL]] => 16,
ENDCASE => ERROR; -- can't handle it yet
IF bitsPerSample=1
AND samplesPerPixel = 1
THEN
TRUSTED {
bigWordsPerLine: INT ~ (INT[fSize]+31)/32;
paddedBitsPerLine: INT ~ bigWordsPerLine*32;
wordsPerLine: INT ~ paddedBitsPerLine/Basics.bitsPerWord;
bytesPerLine: INT ~ paddedBitsPerLine/8;
dataByteCount: INT ~ bytesPerLine*sSize;
lineBuffer: ImagerSample.RasterSampleMap ~ ImagerSample.ObtainScratchMap[box: [max: [s: 1, f: paddedBitsPerLine]], bitsPerSample: 1];
ImagerSample.Clear[lineBuffer];
PutSequence[stream, $sequencePackedPixelVector, 4+dataByteCount];
PutIntBytes[stream, 1, 2]; -- 1 bit per sample
PutIntBytes[stream, fSize, 2]; -- number of pixels per scan line, excluding padding
IO.SetLength[stream, IO.GetIndex[stream]+dataByteCount ! IO.Error => CONTINUE]; -- pre-allocate a portion of the file
FOR s:
NAT
IN[0..sSize)
DO
ImagerPixelArray.Transfer[pa: pa, i: 0, s: s, f: 0, dst: lineBuffer, size: [1, fSize]];
TRUSTED {
rawBase: LONG POINTER ~ ImagerSample.GetBase[lineBuffer].word;
IO.UnsafePutBlock[stream, [base: rawBase, startIndex: 0, count: bytesPerLine]];
};
ENDLOOP;
ImagerSample.ReleaseScratchMap[lineBuffer];
}
ELSE {
bytesPerSample: NAT ~ (bitsPerSample+7)/8;
paddedBitsPerSample: NAT ~ bytesPerSample*8;
bytesPerLine: INT ~ INT[bytesPerSample]*fSize;
lineBuffer: ImagerSample.RasterSampleMap ~ ImagerSample.ObtainScratchMap[box: [max: [s: 1, f: fSize]], bitsPerSample: paddedBitsPerSample];
dataByteCount: INT ~ INT[samplesPerPixel]*INT[sSize]*INT[fSize]*bytesPerSample;
ImagerSample.Clear[lineBuffer];
IO.SetLength[stream, IO.GetIndex[stream]+dataByteCount ! IO.Error => CONTINUE]; -- pre-allocate a portion of the file
PutSequence[stream, $sequenceLargeVector, 1+dataByteCount];
PutByte[stream, bytesPerSample];
FOR i:
NAT
IN [0..samplesPerPixel)
DO
FOR s:
NAT
IN [0..sSize)
DO
ImagerPixelArray.Transfer[pa: pa, i: i, s: s, f: 0, dst: lineBuffer, size: [1, fSize]];
TRUSTED {
rawBase: LONG POINTER ~ ImagerSample.GetBase[lineBuffer].word;
IO.UnsafePutBlock[stream, [base: rawBase, startIndex: 0, count: bytesPerLine]];
};
ENDLOOP;
ENDLOOP;
};
PutOp[stream, makepixelarray];
};
gray: OpConstantColor ~
NARROW[Imager.MakeGray[0.5]];
MakeColor:
PROC [data: Data, color: Color] ~ {
stream: STREAM ~ data.stream;
WITH color
SELECT
FROM
c: OpConstantColor => {
IF data.version < 3
OR c.colorOperator = gray.colorOperator
THEN {
PutReal[stream, ImagerColorPrivate.GrayFromColor[c]];
PutOp[stream, makegray];
}
ELSE {
FOR i: NAT IN [0..c.size) DO PutInt[stream, c[i]] ENDLOOP;
MakeVec[stream, c.size];
FGet[stream, FetchColorOperator[data, c.colorOperator]];
PutOp[stream, do];
};
};
color: SampledColor => {
FGet[stream, FetchPixelArray[data, color.pa]];
PutTransformation[stream, color.um];
FGet[stream, FetchColorOperator[data, color.colorOperator]];
PutOp[stream, makesampledcolor];
};
color: SampledBlack => {
FGet[stream, FetchPixelArray[data, color.pa]];
PutTransformation[stream, color.um];
PutInt[stream, IF color.clear THEN 1 ELSE 0];
PutOp[stream, makesampledblack];
};
color: SpecialColor => {
IF color.name #
NIL
THEN {
PutName[stream, color.name];
PutOp[stream, findcolor];
}
ELSE MakeColor[data, ImagerColor.NarrowToOpConstantColor[color]];
};
ENDCASE => ERROR;
};
MakeStructure:
PROC [data: Data, structure: ImagerColor.Structure] ~
TRUSTED {
stream: STREAM ~ data.stream;
size: INT ~ ImagerColorPrivate.SSize[structure];
FOR i:
INT
IN [0..size)
DO
element: ImagerColorPrivate.Element ~ ImagerColorPrivate.SGet[structure, i];
WITH e: element
SELECT
FROM
int => PutInt[stream, e.int];
real => PutReal[stream, e.real];
structure => MakeStructure[data, e.structure];
color => MakeColor[data, e.color];
colorOperator => FGet[stream, FetchColorOperator[data, e.colorOperator]];
ENDCASE => ERROR;
ENDLOOP;
MakeVec[stream, size];
};
MakeColorOperator:
PROC [data: Data, colorOperator: ColorOperator] ~ {
stream: STREAM ~ data.stream;
colorOperatorClass: ImagerColorPrivate.ColorOperatorClass ~ colorOperator.class;
structure: ImagerColor.Structure ~ colorOperatorClass.GetCreateData[colorOperator];
MakeStructure[data, structure];
PutName[stream, colorOperatorClass.name];
PutOp[stream, findcolormodeloperator];
PutOp[stream, do];
IF colorOperator.renderingHints #
NIL
THEN {
MakeStructure[data, colorOperator.renderingHints];
MakeVec[stream, 2];
PutName[stream, "Xerox/Research/AddRenderingHints"];
PutOp[stream, findcolormodeloperator];
PutOp[stream, do];
};
};
FetchFont:
PROC [data: Data, font: Font]
RETURNS [
INT] ~ {
found: BOOL; index: INT;
[found, index] ← Fetch[data, font];
IF
NOT found
THEN {
MakeFont[data, font];
FSet[data.stream, index ← Store[data, font]];
};
RETURN[index];
};
FetchIdentifier:
PROC [data: Data, identifier:
ATOM]
RETURNS [
INT] ~ {
found: BOOL; index: INT;
[found, index] ← Fetch[data, identifier];
IF
NOT found
THEN {
PutIdentifier[data.stream, Atom.GetPName[identifier]];
FSet[data.stream, index ← Store[data, identifier]];
};
RETURN[index];
};
FetchColor:
PROC [data: Data, color: Color]
RETURNS [
INT] ~ {
found: BOOL; index: INT;
[found, index] ← Fetch[data, color];
IF
NOT found
THEN {
MakeColor[data, color];
FSet[data.stream, index ← Store[data, color]];
};
RETURN[index];
};
FetchPixelArray:
PROC [data: Data, pixelArray: PixelArray]
RETURNS [
INT] ~ {
found: BOOL; index: INT;
[found, index] ← Fetch[data, pixelArray];
IF
NOT found
THEN {
MakePixelArray[data, pixelArray];
FSet[data.stream, index ← Store[data, pixelArray]];
};
RETURN[index];
};
FetchColorOperator:
PROC [data: Data, colorOperator: ColorOperator]
RETURNS [
INT] ~ {
found: BOOL; index: INT;
[found, index] ← Fetch[data, colorOperator];
IF
NOT found
THEN {
MakeColorOperator[data, colorOperator];
FSet[data.stream, index ← Store[data, colorOperator]];
};
RETURN[index];
};
PSDoSave:
PROC [context: Context, action:
PROC, all:
BOOL] ~ {
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
IF all
AND data.version >= 3
THEN {
PutOp[stream, makesimpleco];
DoBody[data, action];
PutOp[stream, dosaveall];
}
ELSE {
PutOp[stream, dosavesimplebody];
DoBody[data, action];
};
};
PSSetInt:
PROC [context: Context, key: IntKey, val:
INT] ~ {
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
SELECT key
FROM
strokeEnd => {
PutInt[stream,
SELECT val
FROM
ORD[Imager.StrokeEnd[butt]] => 0,
ORD[Imager.StrokeEnd[round]] => 1,
ORD[Imager.StrokeEnd[square]] => 2,
ENDCASE => val];
PutOp[stream, setlinecap];
};
strokeJoint => {
PutInt[stream,
SELECT val
FROM
ORD[Imager.StrokeEnd[miter]] => 0,
ORD[Imager.StrokeEnd[round]] => 1,
ORD[Imager.StrokeEnd[bevel]] => 2,
ENDCASE => val];
PutOp[stream, setlinejoin];
};
priorityImportant => { PutInt[stream, val]; ISet[stream, priorityImportant] };
noImage => { PutInt[stream, val]; ISet[stream, noImage] };
ENDCASE => ERROR Imager.Error[[$unimplemented, "Unimplemented key for SetInt"]];
};
PSSetReal:
PROC [context: Context, key: RealKey, val:
REAL] ~ {
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
SELECT key
FROM
strokeWidth => { PutReal[stream, val]; PutPrimitive[stream, setlinewidth] };
amplifySpace => { data.amplifySpace ← val };
underlineStart => { PutReal[stream, val]; ISet[stream, underlineStart] };
correctShrink => { PutReal[stream, val]; ISet[stream, correctShrink] };
ENDCASE => ERROR Imager.Error[[$unimplemented, "Unimplemented key for SetReal"]];
};
PSSetFont:
PROC [context: Context, font: Font] ~ {
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
IF font #
NIL
THEN {
PutInt[stream, FetchFont[data, font]];
PutOp[stream, setfont];
};
};
TryFetchSetColor:
PROC [data: Data, color: Color]
RETURNS [
BOOL] ~ {
found: BOOL; index: INT;
[found, index] ← Fetch[data, color];
IF found THEN {FGet[data.stream, index]; ISet[data.stream, color]};
RETURN [found]
};
PSSetColor:
PROC [context: Context, color: Color] ~ {
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
IF TryFetchSetColor[data, color] THEN RETURN;
WITH color
SELECT
FROM
color: OpConstantColor => {
WITH color
SELECT
FROM
c: OpConstantColor => {
IF c.colorOperator = gray.colorOperator
THEN {
PutReal[stream, ImagerColorPrivate.GrayFromColor[c]];
PutOp[stream, setgray];
RETURN;
};
MakeColor[data, color];
ISet[stream, color];
RETURN;
};
ENDCASE => NULL;
};
color: SampledColor => {
IF data.getTDone
AND color.um.form = data.getTForm
THEN {
um: Transformation ← ImagerTransformation.Copy[color.um];
um.form ← 0;
ImagerTransformation.ApplyPreScale[um, 1];
PSSetSampledColor[context, color.pa, um, color.colorOperator];
RETURN;
};
};
color: SampledBlack => {
IF data.getTDone
AND color.um.form = data.getTForm
THEN {
um: Transformation ← ImagerTransformation.Copy[color.um];
um.form ← 0;
ImagerTransformation.ApplyPreScale[um, 1];
PSSetSampledBlack[context, color.pa, um, color.clear];
RETURN;
};
};
ENDCASE;
FGet[stream, FetchColor[data, color]];
ISet[stream, color];
};
PSSetT:
PROC [context: Context, m: Transformation] ~ {
ERROR Imager.Error[[$unimplemented, "SetT not implemented"]];
};
PSSetClipper:
PROC [context: Context, clipper: Clipper] ~ {
ERROR Imager.Error[[$unimplemented, "SetClipper not implemented"]];
};
PSGetInt:
PROC [context: Context, key: IntKey]
RETURNS[
INT] ~ {
ERROR Imager.Error[[$unimplemented, "Not implemented"]];
};
PSGetReal:
PROC [context: Context, key: RealKey]
RETURNS[
REAL] ~ {
ERROR Imager.Error[[$unimplemented, "Not implemented"]];
};
PSGetT:
PROC [context: Context]
RETURNS[Transformation] ~ {
ERROR Imager.Error[[$unimplemented, "Not implemented"]];
m: Transformation ← ImagerTransformation.Scale[1.0];
data: Data ~ NARROW[context.data];
IF NOT data.getTDone THEN {
data.getTDone ← TRUE;
IF (data.getTForm ← data.getTForm + 1) = endPSForm THEN data.getTForm ← firstPSForm;
};
m.form ← data.getTForm;
RETURN [m];
};
PSGetClipper:
PROC [context: Context]
RETURNS[Clipper] ~ {
ERROR Imager.Error[[$unimplemented, "Not implemented"]];
};
PSGetFont:
PROC [context: Context]
RETURNS[Font] ~ {
ERROR Imager.Error[[$unimplemented, "Not implemented"]];
};
PSGetColor:
PROC [context: Context]
RETURNS[Color] ~ {
ERROR Imager.Error[[$unimplemented, "Not implemented"]];
};
PSConcatT:
PROC [context: Context, m: Transformation] ~ {
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
PutTransformation[stream, m];
PutOp[stream, concat];
};
PSScale2T:
PROC [context: Context, s:
VEC] ~ {
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
PutVec[stream, s];
PutOp[stream, scale];
};
PSRotateT:
PROC [context: Context, a:
REAL] ~ {
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
PutReal[stream, a];
PutOp[stream, rotate];
};
PSTranslateT:
PROC [context: Context, t:
VEC] ~ {
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
PutVec[stream, t];
PutOp[stream, translate];
};
PSMove:
PROC [context: Context, rounded:
BOOL] ~ {
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
***** fix this *****
PutOp[stream, getcurrentpoint];
PutOp[stream, translate];
};
PSSetXY:
PROC [context: Context, p:
VEC] ~ {
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
PutVec[stream, p];
PutOp[stream, moveto];
};
PSSetXYRel:
PROC [context: Context, v:
VEC] ~ {
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
PutVec[stream, p];
PutOp[stream, rmoveto];
};
PutXString:
PROC [context: Context, string: XStringProc] ~ {
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
text: REF TEXT ← data.buffer;
set: BYTE ← 0;
action:
PROC [char: XChar] ~ {
IF char.set#set
THEN {
text ← RefText.AppendChar[to: text, from: VAL[255]];
text ← RefText.AppendChar[to: text, from: VAL[set ← char.set]];
};
text ← RefText.AppendChar[to: text, from: VAL[char.code]];
};
text.length ← 0;
string[action];
PutSequence[stream, $sequenceString, text.length];
IO.PutBlock[self: stream, block: text, startIndex: 0, count: text.length];
};
PSShow:
PROC [context: Context, string: XStringProc, xrel:
BOOL] ~ {
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
IF xrel THEN ERROR Imager.Error[[$unimplemented, "Not implemented"]];
IF data.amplifySpace=1.0
THEN {
PutXString[context, string];
PutOp[stream, show];
}
ELSE {
***** fix this *****
ERROR Imager.Error[[$unimplemented, "Not implemented"]];
};
};
PSShowBackward:
PROC [context: Context, string: XStringProc] ~ {
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
***** fix this *****
ERROR Imager.Error[[$unimplemented, "Not implemented"]];
};
PSShowAndFixedXRel:
PROC [context: Context, string: XStringProc, x:
REAL] ~ {
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
PutVec[stream, [x, 0]];
PutXString[context, string];
PutOp[stream, ashow];
};
PSShowText:
PROC [context: Context, text:
REF
READONLY
TEXT, start, len:
NAT, xrel:
BOOL] ~ {
string: XStringProc ~ { ImagerFont.MapText[text, start, len, charAction] };
PSShow[context, string, xrel];
};
PSStartUnderline:
PROC [context: Context] ~ {
ERROR Imager.Error[[$unimplemented, "Not implemented"]];
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
PutOp[stream, startunderline];
};
PSMaskUnderline:
PROC [context: Context, dy, h:
REAL] ~ {
ERROR Imager.Error[[$unimplemented, "Not implemented"]];
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
PutReal[stream, dy];
PutReal[stream, h];
PutOp[stream, maskunderline];
};
PSCorrectMask:
PROC [context: Context] ~ {
ERROR Imager.Error[[$unimplemented, "Not implemented"]];
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
PutOp[stream, correctmask];
};
PSCorrectSpace:
PROC [context: Context, v:
VEC] ~ {
ERROR Imager.Error[[$unimplemented, "Not implemented"]];
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
PutVec[stream, v];
PutOp[stream, correctspace];
};
PSSpace:
PROC [context: Context, x:
REAL] ~ {
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
PutVec[stream, [x, 0]];
PutOp[stream, rmoveto];
};
PSSetCorrectMeasure:
PROC [context: Context, v:
VEC] ~ {
***** fix this *****
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
PutVec[stream, v];
PutOp[stream, setcorrectmeasure];
};
PSSetCorrectTolerance:
PROC [context: Context, v:
VEC] ~ {
***** fix this *****
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
PutVec[stream, v];
PutOp[stream, setcorrecttolerance];
};
PSCorrect:
PROC [context: Context, action:
PROC] ~ {
***** fix this *****
action[];
data: Data ~ NARROW[context.data];
PutOp[data.stream, correct];
DoBody[data, action];
};
PSDontCorrect:
PROC [context: Context, action:
PROC, saveCP:
BOOL] ~ {
ERROR Imager.Error[[$unimplemented, "Not implemented"]];
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
IGet[stream, correctPass];
PutInt[stream, 0]; ISet[stream, correctPass];
IF saveCP THEN { IGet[stream, DCScpx]; IGet[stream, DCScpy] };
PutInt[stream, 0]; PutOp[stream, mark];
action[];
PutOp[stream, unmark0];
IF saveCP THEN { ISet[stream, DCScpy]; ISet[stream, DCScpx] };
ISet[stream, correctPass];
};
PSSetGray:
PROC [context: Context, f:
REAL] ~ {
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
PutReal[stream, 1-f];
PutOp[stream, setgray];
};
PSSetSampledColor:
PROC [context: Context,
pa: PixelArray, m: Transformation, colorOperator: ColorOperator] ~ {
***** fix this *****
SetGray[context, 0.5];
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
IF data.version < 3 THEN { PSSetGray[context, 0.5]; RETURN };
FGet[stream, FetchPixelArray[data, pa]]; -- pa
PutTransformation[stream, m];
FGet[stream, FetchColorOperator[data, colorOperator]]; -- colorOperator
PutOp[stream, setsampledcolor];
};
PSSetSampledBlack:
PROC [context: Context,
pa: PixelArray, m: Transformation, clear:
BOOL] ~ {
***** fix this *****
SetGray[context, 0.5];
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
FGet[stream, FetchPixelArray[data, pa]]; -- pa
PutTransformation[stream, m];
IF data.version < 3
THEN {
IGet[stream, T];
PutOp[stream, concat];
PutInt[stream, IF clear THEN 1 ELSE 0]; -- clear
PutOp[stream, makesampledblack];
ISet[stream, color];
}
ELSE {
PutInt[stream, IF clear THEN 1 ELSE 0]; -- clear
PutOp[stream, setsampledblack];
};
};
PSMaskFill:
PROC [context: Context, path: PathProc, oddWrap:
BOOL ←
FALSE] ~ {
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
PutPath[stream, path];
PutOp[stream, IF oddWrap THEN eofill ELSE fill];
};
PSMaskRectangle:
PROC [context: Context, r: Rectangle] ~ {
action: PROC [path: PathProc] ~ { PSMaskFill[context, path] };
RectanglePath[r, action];
};
PSMaskRectangleI:
PROC [context: Context, x, y, w, h:
INTEGER] ~ {
action: PROC [path: PathProc] ~ { PSMaskFill[context, path] };
RectanglePath[[x: x, y: y, w w, h: h], action];
};
PSMaskStroke:
PROC [context: Context, path: PathProc, closed:
BOOL ←
FALSE] ~ {
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
PutPath[stream, path, closed];
PutOp[stream, stroke];
};
PSMaskVector:
PROC [context: Context, p1, p2:
VEC] ~ {
path: PathProc ~ { moveTo[p1]; lineTo[p2] };
PSMaskStroke[context, path];
};
PSMaskDashedStroke:
PROC [context: Context, path: PathProc,
patternLen:
NAT, pattern:
PROC [
NAT]
RETURNS [
REAL], offset, length:
REAL] ~ {
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
action:
PROC ~ {
PutOp[stream, beginarray];
FOR i: NAT IN[0..patternLen) DO PutReal[stream, pattern[i]] ENDLOOP;
PutOp[stream, endarray];
PutReal[stream, offset];
***** fix this: length is ignored *****
PutOp[stream, setdash];
PutPath[stream, path];
PutOp[stream, stroke];
};
DoGSave[data, action];
};
PSMaskPixel:
PROC [context: Context, pa: PixelArray] ~ {
***** fix this *****
Imager.Error[[$unimplemented, "MaskPixel not implemented"]];
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
MakePixelArray[data, pa];
PutOp[stream, maskpixel];
};
PSClip:
PROC [context: Context, path: PathProc, oddWrap:
BOOL, exclude:
BOOL] ~ {
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
IF exclude THEN ERROR Imager.Error[[$unimplemented, "Excluding clip not implemented."]];
PutPath[stream, path];
PutOp[stream, IF oddWrap THEN eoclip ELSE clip];
};
PSClipRectangle:
PROC [context: Context, r: Rectangle, exclude:
BOOL] ~ {
action: PROC [path: PathProc] ~ { PSClip[context, path, FALSE, exclude] };
RectanglePath[r, action];
};
PSClipRectangleI:
PROC [context: Context, x, y, w, h:
INTEGER, exclude:
BOOL] ~ {
action: PROC [path: PathProc] ~ { PSClip[context, path, FALSE, exclude] };
RectanglePath[[x: x, y: y, w w, h: h], action];
};
PSGetCP:
PROC [context: Context, rounded:
BOOL]
RETURNS [
VEC] ~ {
Imager.Error[[$unimplemented, "GetCP not implemented"]];
};
PSGetBoundingRectangle:
PROC [context: Context]
RETURNS [Rectangle] ~ {
Imager.Error[[$unimplemented, "GetBoundingRectangle not implemented"]];
};
ipClass: Class ~
NEW[ClassRep ← [
type: $Interpress,
DoSave: PSDoSave,
SetInt: PSSetInt,
SetReal: PSSetReal,
SetT: PSSetT,
SetFont: PSSetFont,
SetColor: PSSetColor,
SetClipper: PSSetClipper,
GetInt: PSGetInt,
GetReal: PSGetReal,
GetT: PSGetT,
GetFont: PSGetFont,
GetColor: PSGetColor,
GetClipper: PSGetClipper,
ConcatT: PSConcatT,
Scale2T: PSScale2T,
RotateT: PSRotateT,
TranslateT: PSTranslateT,
Move: PSMove,
SetXY: PSSetXY,
SetXYRel: PSSetXYRel,
GetCP: PSGetCP,
StartUnderline: PSStartUnderline,
MaskUnderline: PSMaskUnderline,
CorrectMask: PSCorrectMask,
CorrectSpace: PSCorrectSpace,
Space: PSSpace,
SetCorrectMeasure: PSSetCorrectMeasure,
SetCorrectTolerance: PSSetCorrectTolerance,
Correct: PSCorrect,
DontCorrect: PSDontCorrect,
SetGray: PSSetGray,
SetSampledColor: PSSetSampledColor,
SetSampledBlack: PSSetSampledBlack,
Clip: PSClip,
ClipRectangle: PSClipRectangle,
ClipRectangleI: PSClipRectangleI,
Show: PSShow,
ShowBackward: PSShowBackward,
MaskFill: PSMaskFill,
MaskRectangle: PSMaskRectangle,
MaskStroke: PSMaskStroke,
MaskPixel: PSMaskPixel,
ShowAndFixedXRel: PSShowAndFixedXRel,
ShowText: PSShowText,
MaskRectangleI: PSMaskRectangleI,
MaskVector: PSMaskVector,
MaskDashedStroke: PSMaskDashedStroke,
MaskBitmap: ImagerPrivate.DefaultMaskBitmap,
DrawBitmap: ImagerPrivate.DefaultDrawBitmap,
DrawPixels: ImagerPrivate.DefaultDrawPixels,
DoIfVisible: ImagerPrivate.DefaultDoIfVisible,
DoWithBuffer: ImagerPrivate.DefaultDoWithBuffer,
DrawObject: ImagerPrivate.DefaultDrawObject,
GetBounds: ImagerPrivate.DefaultGetBounds,
ViewReset: ImagerPrivate.DefaultViewReset,
ViewTranslateI: ImagerPrivate.DefaultViewTranslateI,
ViewClip: ImagerPrivate.DefaultViewClip,
ViewClipRectangleI: ImagerPrivate.DefaultViewClipRectangleI,
GetTransformation: ImagerPrivate.DefaultGetTransformation,
Transform: ImagerPrivate.DefaultTransform,
MoveViewRectangle: ImagerPrivate.DefaultMoveViewRectangle,
TestViewRectangle: ImagerPrivate.DefaultTestViewRectangle
]];