ImagerInterpressFragmentImpl.mesa
Copyright © 1984, 1985 by Xerox Corporation. All rights reserved.
Michael Plass, June 16, 1986 1:53:16 pm PDT
Tim Diebert: October 9, 1985 9:44:55 am PDT
Doug Wyatt, November 21, 1985 3:14:29 pm PST
Rick Beach, July 23, 1986 9:15:39 am PDT
DIRECTORY
Atom,
Basics,
FS USING [StreamOpen],
Imager,
ImagerBackdoor USING [Clipper, IntKey, RealKey],
ImagerColor,
ImagerColorDefs USING [Color, ColorOperator, ConstantColor, SampledColor],
ImagerColorOperator,
ImagerColorOperatorPrivate USING [ColorOperatorImpl, ColorOperatorImplRep, SampleMap],
ImagerColorPrivate USING [ConstantColorImpl, ConstantColorImplRep],
ImagerFont USING [Font, XChar, XStringProc],
ImagerInterpressFragment USING [VectorProc],
ImagerOps,
ImagerPath USING [Filter, PathProc],
ImagerPixelArray USING [GetSamples, MaxSampleValue, PixelArray, UnsafeGetBits],
ImagerPixelMap,
ImagerPrivate USING [Class, ClassRep],
ImagerSample USING [GetPointer, NewBuffer, Sample, SampleBuffer, UnsafePutF, UnsafeSamples],
ImagerTransformation,
IO USING [Close, Error, GetIndex, PutBlock, PutRope, SetLength, STREAM, UnsafePutBlock],
IPMaster USING [PutByte, PutIdentifier, PutInt, PutIntBytes, PutName, PutOp, PutReal, PutSequence, PutString],
PrincOpsUtils USING [LongZero],
Real,
Rope USING [ROPE],
Vector2 USING [VEC];
ImagerInterpressFragmentImpl: CEDAR PROGRAM
IMPORTS Atom, FS, Imager, ImagerPath, ImagerPixelArray, ImagerSample, ImagerTransformation, IO, IPMaster, PrincOpsUtils
EXPORTS Imager, ImagerColorDefs, ImagerInterpressFragment
~ BEGIN OPEN IPMaster;
ROPE: TYPE ~ Rope.ROPE;
STREAM: TYPE ~ IO.STREAM;
VectorProc: TYPE ~ ImagerInterpressFragment.VectorProc;
BYTE: TYPE ~ Basics.BYTE;
VEC: TYPE ~ Vector2.VEC;
Rectangle: TYPE ~ ImagerTransformation.Rectangle;
Transformation: TYPE ~ ImagerTransformation.Transformation;
PathProc: TYPE ~ ImagerPath.PathProc;
Color: TYPE ~ ImagerColorDefs.Color;
ConstantColor: TYPE ~ ImagerColorDefs.ConstantColor;
SampledColor: TYPE ~ ImagerColorDefs.SampledColor;
ConstantColorImpl: TYPE ~ ImagerColorPrivate.ConstantColorImpl;
ConstantColorImplRep: PUBLIC TYPE ~ ImagerColorPrivate.ConstantColorImplRep;
Sample: TYPE ~ ImagerSample.Sample;
PixelArray: TYPE ~ ImagerPixelArray.PixelArray;
ColorOperator: TYPE ~ ImagerColorDefs.ColorOperator;
ColorOperatorImpl: TYPE ~ ImagerColorOperatorPrivate.ColorOperatorImpl;
ColorOperatorImplRep: PUBLIC TYPE ~ ImagerColorOperatorPrivate.ColorOperatorImplRep;
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
firstIPForm: NAT ~ 100;
endIPForm: NAT ~ 1000;
Data: TYPE ~ REF DataRep;
DataRep:
TYPE ~
RECORD[
stream: STREAM,
frame: Frame ← NIL,
buffer: REF TEXT ← NIL,
pushVectorActive: BOOL ← FALSE,
getTDone: BOOL ← FALSE,
getTForm: NAT ← firstIPForm,
savedSize: NAT ← 0
];
Frame: TYPE ~ REF FrameRep;
FrameRep:
TYPE ~
RECORD [size:
NAT, entries:
SEQUENCE max:
NAT
OF
REF];
Ref: TYPE ~ REF Rep;
Rep:
PUBLIC
TYPE ~
RECORD[
page: INT ← 0,
context: Imager.Context ← NIL,
data: Data ← NIL
];
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] ← [size: 0, entries: ]];
buffer: REF TEXT ~ NEW[TEXT[200]];
data: Data ~ NEW[DataRep ← [stream: stream, frame: frame, buffer: buffer]];
IO.PutRope[stream, header];
PutOp[stream, beginBlock]; -- begin master
RETURN[NEW[Rep ← [page: 0, context: NIL, data: data]]];
};
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];
};
PushVector:
PUBLIC
PROC [self: Ref, vectorProc: VectorProc] ~ {
data: Data ~ self.data;
stream: STREAM ~ data.stream;
count: INT ← 0;
putIdentifier:
PROC [identifier:
ATOM] ~ {
PutIdentifier[stream, Atom.GetPName[identifier]];
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;
};
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]] ~ {
ERROR Imager.Error[[code: $unimplemented,
explanation: "Cannot put image operations in Interpress fragment."]];
};
IF data.pushVectorActive
THEN
ERROR Imager.Error[[$InvalidOperationSequence, "Cannot call PushVector recursively"]];
data.pushVectorActive ← TRUE;
vectorProc[putIdentifier, putString, putInt, putReal, 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]
};
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;
PutOp[stream, endBlock]; -- end master
};
MakeVec:
PROC [stream:
STREAM, n:
INT] ~ {
PutInt[stream, n]; PutOp[stream, makevec];
};
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];
};
PutRectangle:
PROC [stream:
STREAM, r: Rectangle] ~ {
PutReal[stream, r.x]; PutReal[stream, r.y]; PutReal[stream, r.w]; PutReal[stream, r.h];
};
PutRectangleI:
PROC [stream:
STREAM, x, y, w, h:
INTEGER] ~ {
PutInt[stream, x]; PutInt[stream, y]; PutInt[stream, w]; PutInt[stream, h];
};
PutTransformation:
PROC [stream:
STREAM, m: Transformation] ~ {
f: ImagerTransformation.FactoredTransformation ~ ImagerTransformation.Factor[m];
depth: NAT ← 0;
IF f.r1#0
THEN {
PutReal[stream, f.r1]; PutOp[stream, rotate];
depth ← depth+1;
};
IF f.s.x#f.s.y
THEN {
PutVec[stream, f.s]; PutOp[stream, scale2];
depth ← depth+1;
}
ELSE
IF f.s.x#1
THEN {
PutReal[stream, f.s.x]; PutOp[stream, scale];
depth ← depth+1;
};
IF f.r2#0
THEN {
PutReal[stream, f.r2]; PutOp[stream, rotate];
depth ← depth+1;
};
IF f.t.x#0
OR f.t.y#0
THEN {
PutVec[stream, f.t]; PutOp[stream, translate];
depth ← depth+1;
};
WHILE depth>1 DO PutOp[stream, concat]; depth ← depth-1 ENDLOOP;
IF depth=0 THEN { PutInt[stream, 1]; PutOp[stream, scale] };
};
PutPath:
PROC [stream:
STREAM, path: PathProc, close:
PROC] ~ {
p0: VEC ← [0, 0];
moveTo:
PROC [p:
VEC] ~ {
PutVec[stream, p];
PutOp[stream, moveto];
p0 ← p;
};
lineTo:
PROC [p1:
VEC] ~ {
IF p1.y=p0.y
THEN {
PutReal[stream, p1.x];
PutOp[stream, linetox];
}
ELSE
IF p1.x=p0.x
THEN {
PutReal[stream, p1.y];
PutOp[stream, linetoy];
}
ELSE {
PutVec[stream, p1];
PutOp[stream, lineto];
};
p0 ← p1;
};
curveTo:
PROC [p1, p2, p3:
VEC] ~ {
PutVec[stream, p1];
PutVec[stream, p2];
PutVec[stream, p3];
PutOp[stream, curveto];
p0 ← p3;
};
conicTo:
PROC [p1, p2:
VEC, r:
REAL] ~ {
PutVec[stream, p1];
PutVec[stream, p2];
PutReal[stream, r];
PutOp[stream, conicto];
p0 ← p2;
};
arcTo:
PROC [p1, p2:
VEC] ~ {
PutVec[stream, p1];
PutVec[stream, p2];
PutOp[stream, arcto];
p0 ← p2;
};
ImagerPath.Filter[path: path, moveTo: moveTo, lineTo: lineTo,
curveTo: curveTo, conicTo: conicTo, arcTo: arcTo, close: close];
};
PutSampleMap:
PROC [stream:
STREAM, map: ImagerColorOperatorPrivate.SampleMap] ~ {
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];
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;
translate: VEC;
PutInt[stream, fSize]; -- xPixels
PutInt[stream, sSize]; -- 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
};
translate ← ImagerTransformation.Factor[pa.m].t;
ImagerTransformation.ApplyPostTranslate[pa.m, [-translate.x, pa.sSize-translate.y]]; -- normalize the pixel array transformation to have a [0, sSize] translation component
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;
rawWords: REF Basics.RawWords ~ NEW[Basics.RawWords[wordsPerLine]];
rawBase: LONG POINTER ~ @rawWords[0];
PrincOpsUtils.LongZero[where: rawBase, nwords: wordsPerLine];
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.UnsafeGetBits[pa: pa, i: 0, s: s, f: 0, dst: [word: rawBase, bit: 0], dstBpl: paddedBitsPerLine, width: fSize, height: 1, srcFunc: null, dstFunc: null];
IO.UnsafePutBlock[stream, [base: rawBase, startIndex: 0, count: bytesPerLine]];
ENDLOOP;
}
ELSE {
bytesPerSample: NAT ~ bitsPerSample/8;
bytesPerLine: INT ~ INT[bytesPerSample]*fSize;
buffer: ImagerSample.SampleBuffer ~ ImagerSample.NewBuffer[1, fSize];
block: REF TEXT ~ NEW[TEXT[bytesPerLine]];
dataByteCount: INT ~ INT[samplesPerPixel]*INT[sSize]*INT[fSize]*bytesPerSample;
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.GetSamples[pa: pa, i: i, s: s, f: 0, buffer: buffer, count: fSize];
TRUSTED {
samples: ImagerSample.UnsafeSamples ~ ImagerSample.GetPointer[buffer, 0, 0, fSize];
base: LONG POINTER ~ LOOPHOLE[block, LONG POINTER]+SIZE[TEXT[0]];
ImagerSample.UnsafePutF[samples: samples, count: fSize, s: 0, f: 0,
base: base, wordsPerLine: 0, bitsPerSample: bitsPerSample];
};
IO.PutBlock[self: stream, block: block, startIndex: 0, count: bytesPerLine];
ENDLOOP;
ENDLOOP;
};
PutOp[stream, makepixelarray];
};
MakeColorOperator:
PROC [data: Data, colorOperator: ColorOperator] ~ {
impl: ColorOperatorImpl ~ colorOperator.impl;
stream: STREAM ~ data.stream;
WITH impl
SELECT
FROM
impl:
REF ColorOperatorImplRep.grayLinear => {
PutReal[stream, impl.sWhite];
PutReal[stream, impl.sBlack];
PutSampleMap[stream, impl.map];
MakeVec[stream, 3];
PutName[stream, "Xerox/GrayLinear"];
};
impl:
REF ColorOperatorImplRep.grayDensity => {
PutReal[stream, impl.sWhite];
PutReal[stream, impl.sBlack];
PutReal[stream, impl.dBlack];
PutSampleMap[stream, impl.map];
MakeVec[stream, 4];
PutName[stream, "Xerox/GrayDensity"];
};
impl:
REF ColorOperatorImplRep.grayVisual => {
PutReal[stream, impl.sWhite];
PutReal[stream, impl.sBlack];
PutSampleMap[stream, impl.map];
MakeVec[stream, 3];
PutName[stream, "Xerox/GrayVisual"];
};
impl: REF ColorOperatorImplRep.map => {
FOR i: Sample IN[0..impl.size) DO MakeColor[data, impl[i]] ENDLOOP;
MakeVec[stream, impl.size];
PutName[stream, "Xerox/Map"];
};
impl:
REF ColorOperatorImplRep.rgbLinear => {
PutReal[stream, impl.maxSampleValue];
MakeVec[stream, 1];
PutName[stream, "Xerox/Research/RGBLinear"];
};
ENDCASE => ERROR Imager.Error[[code: $unimplemented,
explanation: "Color operator has unknown type."]];
PutOp[stream, findcolormodeloperator];
PutOp[stream, do];
};
END.