ImagerInterpressImpl.mesa
Copyright © 1984, 1985 by Xerox Corporation. All rights reserved.
Michael Plass, January 3, 1986 12:56:56 pm PST
Doug Wyatt, September 23, 1985 5:07:01 pm PDT
Tim Diebert: October 9, 1985 9:44:55 am PDT
DIRECTORY
Basics,
FS USING [StreamOpen],
Imager,
ImagerBackdoor USING [Clipper, IntKey, RealKey],
ImagerColor,
ImagerColorDefs USING [Color, ColorOperator, ColorOperatorImplRep, ConstantColor, ConstantColorImplRep, PixelArray, SampledColor],
ImagerColorOperator,
ImagerColorOperatorPrivate USING [ColorOperatorImpl, ColorOperatorImplRep, SampleMap],
ImagerColorPrivate USING [ConstantColorImpl, ConstantColorImplRep],
ImagerFont USING [Font, XChar, XStringProc],
ImagerInterpress USING [],
ImagerInterpressBackdoor USING [],
ImagerOps,
ImagerPath USING [Filter, PathProc],
ImagerPixelArray USING [GetSamples, MaxSampleValue, PixelArray, UnsafeGetBits],
ImagerPixelMap,
ImagerPrivate USING [Class, ClassRep, DashPattern, DashSpec, StrokeDashes],
ImagerSample USING [GetPointer, NewBuffer, Sample, SampleBuffer, UnsafePutF, UnsafeSamples],
ImagerTransformation,
IO USING [Close, Error, GetIndex, PutBlock, PutRope, SetLength, STREAM, UnsafePutBlock],
IPMaster USING [ImagerVariable, PutByte, PutInt, PutIntBytes, PutName, PutOp, PutReal, PutSequence, PutSequenceText],
PrincOpsUtils USING [LongZero],
Real,
RefText USING [AppendChar],
Rope USING [ROPE],
Vector2 USING [VEC];
ImagerInterpressImpl: CEDAR PROGRAM
IMPORTS Basics, FS, Imager, ImagerColor, ImagerColorOperator, ImagerOps, ImagerPath, ImagerPixelArray, ImagerPixelMap, ImagerSample, ImagerTransformation, IO, IPMaster, PrincOpsUtils, Real, RefText
EXPORTS Imager, ImagerColorDefs, ImagerInterpress, ImagerInterpressBackdoor
~ BEGIN OPEN IPMaster;
ROPE: TYPE ~ Rope.ROPE;
STREAM: TYPE ~ IO.STREAM;
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;
StrokeDashes: TYPE ~ ImagerPrivate.StrokeDashes;
DashPattern: TYPE ~ ImagerPrivate.DashPattern;
DashSpec: TYPE ~ ImagerPrivate.DashSpec;
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,
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
];
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] ← [size: 0, entries: ]];
buffer: REF TEXT ~ NEW[TEXT[200]];
data: Data ~ NEW[DataRep ← [stream: stream, frame: frame, buffer: buffer]];
context: Context ~ NEW[Imager.ContextRep ← [class: ipClass, data: data]];
ref: Ref ~ NEW[Rep ← [page: 0, context: context, data: data]];
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] ~ {
IF self.page=0 THEN [] ← FetchColorOperator[self.data, colorOperator];
};
DeclarePixelArray:
PUBLIC
PROC [self: Ref, pixelArray: PixelArray] ~ {
IF self.page=0 THEN [] ← FetchPixelArray[self.data, pixelArray];
};
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] =
BEGIN
data: Data ~ self.data;
frame: Frame ~ data.frame;
stream: STREAM ~ data.stream;
PutOp[stream, endBody];
frame.size ← data.savedSize;
IF last
THEN
NULL
ELSE {
self.page ← self.page+1;
PutOp[stream, beginBody];
PutInt[stream, 1]; ISet[stream, priorityImportant]; -- default priorityImportant to TRUE
};
END;
DoPage:
PUBLIC
PROC [self: Ref, action:
PROC [Imager.Context], scale:
REAL ← 1] ~ {
data: Data ~ self.data;
stream: STREAM ~ data.stream;
pageBody:
PROC ~ {
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, makevec];
};
FGet:
PROC [stream:
STREAM, index:
INT] ~ {
PutInt[stream, index]; PutOp[stream, fget];
};
FSet:
PROC [stream:
STREAM, index:
INT] ~ {
PutInt[stream, index]; PutOp[stream, fset];
};
IGet:
PROC [stream:
STREAM, v: ImagerVariable] ~ {
PutInt[stream, ORD[v]]; PutOp[stream, iget];
};
ISet:
PROC [stream:
STREAM, v: ImagerVariable] ~ {
PutInt[stream, ORD[v]]; PutOp[stream, iset];
};
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];
MakeFont:
PROC [data: Data, font: Font] ~ {
stream: STREAM ~ data.stream;
PutName[stream, font.name];
PutOp[stream, findfont];
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;
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];
};
rgbLinear: Imager.ColorOperator ~ ImagerColorOperator.RGBLinearColorModel[1000];
MakeColorFromRGB:
PROC [data: Data, rgb: ImagerColor.
RGB] ~ {
stream: STREAM ~ data.stream;
PutInt[stream, Real.Round[rgb.R*1000]];
PutInt[stream, Real.Round[rgb.G*1000]];
PutInt[stream, Real.Round[rgb.B*1000]];
MakeVec[stream, 3];
FGet[stream, FetchColorOperator[data, rgbLinear]];
PutReal[stream, 1000];
MakeVec[stream, 1];
PutName[stream, "Xerox/Research/RGBLinear"];
PutOp[stream, findcolormodeloperator];
PutOp[stream, do];
PutOp[stream, do];
};
MakeColor:
PROC [data: Data, color: Color] ~ {
stream: STREAM ~ data.stream;
WITH color
SELECT
FROM
color: ConstantColor => {
impl: ConstantColorImpl ~ color.impl;
WITH impl: impl
SELECT
FROM
rgb => {MakeColorFromRGB[data, impl.val]};
gray => {
PutReal[stream, impl.f];
PutOp[stream, makegray];
};
cie => {MakeColorFromRGB[data, ImagerColor.RGBFromCIE[impl.val]]};
ENDCASE => {
PutReal[stream, 1-impl.Y]; -- ought to check for other variants
PutOp[stream, makegray];
};
};
color: SampledColor => {
opClass: ATOM ~ ImagerColorOperator.GetColorOperatorClass[color.colorOperator];
IF opClass = $SampledBlack
OR opClass = $SampledBlackClear
THEN {
FGet[stream, FetchPixelArray[data, color.pa]];
PutTransformation[stream, color.um];
PutInt[stream, IF opClass = $SampledBlackClear THEN 1 ELSE 0]; -- clear
PutOp[stream, makesampledblack];
}
ELSE {
FGet[stream, FetchPixelArray[data, color.pa]];
PutTransformation[stream, color.um];
FGet[stream, FetchColorOperator[data, color.colorOperator]];
PutOp[stream, makesampledcolor];
};
};
ENDCASE => ERROR;
};
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];
};
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];
};
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];
};
IPDoSave:
PROC [context: Context, action:
PROC, all:
BOOL] ~ {
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
getTDone: BOOL ~ data.getTDone;
IF all
THEN {
PutOp[stream, makesimpleco];
DoBody[data, action];
PutOp[stream, dosaveall];
}
ELSE {
PutOp[stream, dosavesimplebody];
DoBody[data, action];
};
data.getTDone ← FALSE;
};
IPSetInt:
PROC [context: Context, key: IntKey, val:
INT] ~ {
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
SELECT key
FROM
priorityImportant => { PutInt[stream, val]; ISet[stream, priorityImportant] };
noImage => { PutInt[stream, val]; ISet[stream, noImage] };
strokeEnd => { PutInt[stream, val]; ISet[stream, strokeEnd] };
strokeJoint => { PutInt[stream, FixJoint[val]]; ISet[stream, strokeJoint] };
ENDCASE => ERROR Imager.Error[[$unimplemented, "Unimplemented key for SetInt"]];
};
oldRound: [1..1] ~ ORD[Imager.StrokeJoint.round];
FixJoint:
PROC [i:
INT]
RETURNS [
INT] ~ {
Crock for compatibility between 6.0 Imager and 3.0 Interpress standard.
IF i = oldRound THEN i ← 2;
RETURN [i];
};
IPSetReal:
PROC [context: Context, key: RealKey, val:
REAL] ~ {
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
SELECT key
FROM
strokeWidth => { PutReal[stream, val]; ISet[stream, strokeWidth] };
underlineStart => { PutReal[stream, val]; ISet[stream, underlineStart] };
amplifySpace => { PutReal[stream, val]; ISet[stream, amplifySpace] };
correctShrink => { PutReal[stream, val]; ISet[stream, correctShrink] };
ENDCASE => ERROR Imager.Error[[$unimplemented, "Unimplemented key for SetReal"]];
};
IPSetFont:
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]
};
IPSetColor:
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: ConstantColor => {
impl: ConstantColorImpl ~ color.impl;
WITH impl: impl
SELECT
FROM
gray => { PutReal[stream, impl.f]; PutOp[stream, setgray]; RETURN };
rgb => {MakeColorFromRGB[data, impl.val]; ISet[stream, color]; RETURN };
ENDCASE;
};
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];
IPSetSampledColor[context, color.pa, um, color.colorOperator];
RETURN;
};
};
ENDCASE;
FGet[stream, FetchColor[data, color]];
ISet[stream, color];
};
IPSetT:
PROC [context: Context, m: Transformation] ~ {
Imager.Error[[$unimplemented, "SetT not implemented"]];
};
IPSetClipper:
PROC [context: Context, clipper: Clipper] ~ {
Imager.Error[[$unimplemented, "SetClipper not implemented"]];
};
IPSetStrokeDashes:
PROC [context: Context, strokeDashes: StrokeDashes] ~ {
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
PutDashPattern:
PROC [stream:
STREAM, pattern: DashPattern] ~ {
n: INT ← 0;
FOR list:
LIST
OF DashSpec ← pattern, list.rest
UNTIL list=
NIL
DO
PutInt[stream, ORD[list.first.end]];
PutInt[stream, ORD[list.first.joint]];
PutReal[stream, list.first.width];
PutReal[stream, list.first.length];
PutReal[stream, list.first.stretch];
PutInt[stream, 4];
PutOp[stream, makevec];
n ← n+1;
ENDLOOP;
PutInt[stream, n];
PutOp[stream, makevec];
};
PutDashPattern[stream, strokeDashes.begin];
PutDashPattern[stream, strokeDashes.repeat];
PutDashPattern[stream, strokeDashes.end];
PutInt[stream, 3];
PutOp[stream, makevec];
ISet[stream, strokeDashes];
};
IPGetStrokeDashes:
PROC [context: Context]
RETURNS[StrokeDashes] ~ {
Imager.Error[[$unimplemented, "Not implemented"]];
};
IPGetInt:
PROC [context: Context, key: IntKey]
RETURNS[
INT] ~ {
Imager.Error[[$unimplemented, "Not implemented"]];
};
IPGetReal:
PROC [context: Context, key: RealKey]
RETURNS[
REAL] ~ {
Imager.Error[[$unimplemented, "Not implemented"]];
};
IPGetT:
PROC [context: Context]
RETURNS[Transformation] ~ {
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) = endIPForm THEN data.getTForm ← firstIPForm;
};
m.form ← data.getTForm;
RETURN [m];
};
IPGetClipper:
PROC [context: Context]
RETURNS[Clipper] ~ {
Imager.Error[[$unimplemented, "Not implemented"]];
};
IPGetFont:
PROC [context: Context]
RETURNS[Font] ~ {
Imager.Error[[$unimplemented, "Not implemented"]];
};
IPGetColor:
PROC [context: Context]
RETURNS[Color] ~ {
Imager.Error[[$unimplemented, "Not implemented"]];
};
IPGetDashes:
PROC [context: Context]
RETURNS[StrokeDashes] ~ {
Imager.Error[[$unimplemented, "Not implemented"]];
};
IPConcatT:
PROC [context: Context, m: Transformation] ~ {
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
PutTransformation[stream, m];
PutOp[stream, concatt];
data.getTDone ← FALSE;
};
IPScale2T:
PROC [context: Context, s:
VEC] ~ {
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
IF s.x=s.y THEN { PutReal[stream, s.x]; PutOp[stream, scale] }
ELSE { PutVec[stream, s]; PutOp[stream, scale2] };
PutOp[stream, concatt];
data.getTDone ← FALSE;
};
IPRotateT:
PROC [context: Context, a:
REAL] ~ {
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
PutReal[stream, a]; PutOp[stream, rotate];
PutOp[stream, concatt];
data.getTDone ← FALSE;
};
IPTranslateT:
PROC [context: Context, t:
VEC] ~ {
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
PutVec[stream, t]; PutOp[stream, translate];
PutOp[stream, concatt];
data.getTDone ← FALSE;
};
IPMove:
PROC [context: Context, rounded:
BOOL] ~ {
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
PutOp[stream, IF rounded THEN trans ELSE move];
data.getTDone ← FALSE;
};
IPSetXY:
PROC [context: Context, p:
VEC] ~ {
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
PutVec[stream, p];
PutOp[stream, setxy];
};
IPSetXYRel:
PROC [context: Context, v:
VEC] ~ {
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
IF v.y=0 THEN { PutReal[stream, v.x]; PutOp[stream, setxrel] }
ELSE IF v.x=0 THEN { PutReal[stream, v.y]; PutOp[stream, setyrel] }
ELSE { PutVec[stream, v]; PutOp[stream, setxyrel] };
};
IPShow:
PROC [context: Context, string: XStringProc, xrel:
BOOL] ~ {
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];
PutOp[stream, IF xrel THEN showandxrel ELSE show];
};
IPShowText:
PROC [context: Context, text:
REF
READONLY
TEXT, start, len:
NAT, xrel:
BOOL] ~ {
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
PutSequenceText[stream, $sequenceString, text, start, len];
PutOp[stream, IF xrel THEN showandxrel ELSE show];
};
IPStartUnderline:
PROC [context: Context] ~ {
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
PutOp[stream, startunderline];
};
IPMaskUnderline:
PROC [context: Context, dy, h:
REAL] ~ {
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
PutReal[stream, dy];
PutReal[stream, h];
PutOp[stream, maskunderline];
};
IPCorrectMask:
PROC [context: Context] ~ {
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
PutOp[stream, correctmask];
};
IPCorrectSpace:
PROC [context: Context, v:
VEC] ~ {
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
PutVec[stream, v];
PutOp[stream, correctspace];
};
IPSpace:
PROC [context: Context, x:
REAL] ~ {
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
PutReal[stream, x];
PutOp[stream, space];
};
IPSetCorrectMeasure:
PROC [context: Context, v:
VEC] ~ {
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
PutVec[stream, v];
PutOp[stream, setcorrectmeasure];
};
IPSetCorrectTolerance:
PROC [context: Context, v:
VEC] ~ {
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
PutVec[stream, v];
PutOp[stream, setcorrecttolerance];
};
IPCorrect:
PROC [context: Context, action:
PROC] ~ {
data: Data ~ NARROW[context.data];
PutOp[data.stream, correct];
DoBody[data, action];
};
IPDontCorrect:
PROC [context: Context, action:
PROC, saveCP:
BOOL] ~ {
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];
};
IPSetGray:
PROC [context: Context, f:
REAL] ~ {
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
PutReal[stream, f];
PutOp[stream, setgray];
};
IPSetSampledColor:
PROC [context: Context,
pa: PixelArray, m: Transformation, colorOperator: ColorOperator] ~ {
opClass: ATOM ~ ImagerColorOperator.GetColorOperatorClass[colorOperator];
IF opClass = $SampledBlack
OR opClass = $SampledBlackClear
THEN {
IPSetSampledBlack[context, pa, m, opClass=$SampledBlackClear];
}
ELSE {
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
FGet[stream, FetchPixelArray[data, pa]]; -- pa
PutTransformation[stream, m];
PutInt[stream, ORD[ImagerVariable[T]]];
PutOp[stream, iget];
PutOp[stream, concat]; -- um = <m 4 IGET CONCAT>
FGet[stream, FetchColorOperator[data, colorOperator]]; -- colorOperator
PutOp[stream, makesampledcolor];
PutInt[stream, ORD[ImagerVariable[color]]];
PutOp[stream, iset];
};
};
IPSetSampledBlack:
PROC [context: Context,
pa: PixelArray, m: Transformation, clear:
BOOL] ~ {
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
FGet[stream, FetchPixelArray[data, pa]]; -- pa
PutTransformation[stream, m];
PutInt[stream, ORD[ImagerVariable[T]]];
PutOp[stream, iget];
PutOp[stream, concat]; -- um = <m 4 IGET CONCAT>
PutInt[stream, IF clear THEN 1 ELSE 0]; -- clear
PutOp[stream, makesampledblack];
PutInt[stream, ORD[ImagerVariable[color]]];
PutOp[stream, iset];
};
IPMaskFill:
PROC [context: Context, path: PathProc, parity:
BOOL] ~ {
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
depth: INT ← 0; count: PROC ~ { depth ← depth+1 };
PutPath[stream, path, count];
PutInt[stream, depth];
PutOp[stream, makeoutline];
PutOp[stream, IF parity THEN maskfillparity ELSE maskfill];
};
IPMaskRectangle:
PROC [context: Context, r: Rectangle] ~ {
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
PutRectangle[stream, r];
PutOp[stream, maskrectangle];
};
IPMaskRectangleI:
PROC [context: Context, x, y, w, h:
INTEGER] ~ {
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
PutRectangleI[stream, x, y, w, h];
PutOp[stream, maskrectangle];
};
IPMaskStroke:
PROC [context: Context, path: PathProc, closed:
BOOL] ~ {
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
stroke: PROC ~ { PutOp[stream, IF closed THEN maskstrokeclosed ELSE maskstroke] };
PutPath[stream, path, stroke];
};
IPMaskVector:
PROC [context: Context, p1, p2:
VEC] ~ {
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
PutVec[stream, p1];
PutVec[stream, p2];
PutOp[stream, maskvector];
};
IPMaskPixel:
PROC [context: Context, pa: PixelArray] ~ {
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
MakePixelArray[data, pa];
PutOp[stream, maskpixel];
};
rMinus90: Transformation ~ ImagerTransformation.Rotate[-90];
IPMaskBits:
PROC [context: Context, base:
LONG
POINTER, wordsPerLine:
NAT,
sMin, fMin, sSize, fSize:
NAT, tx, ty:
INTEGER] ~
TRUSTED {
data: Data ~ NARROW[context.data];
pm: ImagerPixelMap.PixelMap ← ImagerPixelMap.CreateFrameBuffer[pointer: base, words: Basics.LongMult[wordsPerLine, sMin+sSize], lgBitsPerPixel: 0, rast: wordsPerLine, lines: sMin+sSize, ref: NIL].Clip[[sMin, fMin, sSize, fSize]].ShiftMap[-sMin, -fMin];
m: Transformation ~ ImagerTransformation.PostTranslate[rMinus90, [tx, ty]];
pa: PixelArray ~ ImagerOps.PixelArrayFromPixelMaps[LIST[pm] ,m];
Imager.MaskPixel[context: context, pa: pa];
};
IPClip:
PROC [context: Context, path: PathProc, parity:
BOOL, exclude:
BOOL] ~ {
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
depth: INT ← 0; count: PROC ~ { depth ← depth+1 };
PutPath[stream, path, count];
PutInt[stream, depth];
PutOp[stream, makeoutline];
IF parity THEN ERROR Imager.Error[[$unimplemented, "Clip with parity not implemented."]];
PutOp[stream, IF exclude THEN excludeoutline ELSE clipoutline];
};
IPClipRectangle:
PROC [context: Context, r: Rectangle, exclude:
BOOL] ~ {
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
PutRectangle[stream, r];
PutOp[stream, IF exclude THEN excluderectangle ELSE cliprectangle];
};
IPClipRectangleI:
PROC [context: Context, x, y, w, h:
INTEGER, exclude:
BOOL] ~ {
data: Data ~ NARROW[context.data];
stream: STREAM ~ data.stream;
PutRectangleI[stream, x, y, w, h];
PutOp[stream, IF exclude THEN excluderectangle ELSE cliprectangle];
};
IPGetCP:
PROC [context: Context, rounded:
BOOL]
RETURNS [
VEC] ~ {
Imager.Error[[$unimplemented, "GetCP not implemented"]];
};
IPGetBoundingRectangle:
PROC [context: Context]
RETURNS [Rectangle] ~ {
Imager.Error[[$unimplemented, "GetBoundingRectangle not implemented"]];
};
ipClass: Class ~
NEW[ClassRep ← [
type: $Interpress,
DoSave: IPDoSave,
SetInt: IPSetInt,
SetReal: IPSetReal,
SetT: IPSetT,
SetFont: IPSetFont,
SetColor: IPSetColor,
SetClipper: IPSetClipper,
SetStrokeDashes: IPSetStrokeDashes,
GetInt: IPGetInt,
GetReal: IPGetReal,
GetT: IPGetT,
GetFont: IPGetFont,
GetColor: IPGetColor,
GetClipper: IPGetClipper,
GetStrokeDashes: IPGetStrokeDashes,
ConcatT: IPConcatT,
Scale2T: IPScale2T,
RotateT: IPRotateT,
TranslateT: IPTranslateT,
Move: IPMove,
SetXY: IPSetXY,
SetXYRel: IPSetXYRel,
Show: IPShow,
ShowText: IPShowText,
StartUnderline: IPStartUnderline,
MaskUnderline: IPMaskUnderline,
CorrectMask: IPCorrectMask,
CorrectSpace: IPCorrectSpace,
Space: IPSpace,
SetCorrectMeasure: IPSetCorrectMeasure,
SetCorrectTolerance: IPSetCorrectTolerance,
Correct: IPCorrect,
DontCorrect: IPDontCorrect,
SetGray: IPSetGray,
SetSampledColor: IPSetSampledColor,
SetSampledBlack: IPSetSampledBlack,
MaskFill: IPMaskFill,
MaskRectangle: IPMaskRectangle,
MaskRectangleI: IPMaskRectangleI,
MaskStroke: IPMaskStroke,
MaskVector: IPMaskVector,
MaskPixel: IPMaskPixel,
MaskBits: IPMaskBits,
Clip: IPClip,
ClipRectangle: IPClipRectangle,
ClipRectangleI: IPClipRectangleI,
GetCP: IPGetCP,
GetBoundingRectangle: NIL
]];
END.