ImagerFontWorksImpl.mesa
Copyright Ó 1990, 1991 by Xerox Corporation. All rights reserved.
Michael Plass, December 21, 1990 2:29 pm PST
DIRECTORY
Imager,
ImagerBackdoor,
ImagerDevice USING [Device, DeviceClass, DeviceClassRep, DeviceParm, MakeDeviceParm],
ImagerFont USING [Font, Modify, XChar],
ImagerFontWorks,
ImagerMaskCache USING [Parameters, ParametersRep],
ImagerPath USING [ArcTo, ArcToProc, ConicTo, ConicToProc, CurveTo, CurveToProc, LineTo, LineToProc, MapTrajectoryList, MoveTo, MoveToProc, PathProc, TrajectoryList, Transform],
ImagerPrivate USING [Class, DefaultMaskDashedStroke],
ImagerRaster USING [Create, CreateClass, GetDevice],
ImagerSample USING [SampleMap],
ImagerTransformation USING [ApplyInvert, Destroy, Scale, ScanMode, Transformation],
ImagerTypeface USING [Typeface, TypefaceFromFont],
SF USING [Box, BoxGenerator, Vec],
Vector2 USING [VEC];
ImagerFontWorksImpl: CEDAR MONITOR
IMPORTS Imager, ImagerBackdoor, ImagerDevice, ImagerFont, ImagerPath, ImagerPrivate, ImagerRaster, ImagerTransformation, ImagerTypeface
EXPORTS ImagerFontWorks
,ImagerTypeface -- Export MaskChar here also (for compatibility)
~ BEGIN
Types
Context: TYPE = Imager.Context;
Device: TYPE = ImagerDevice.Device;
Font: TYPE = ImagerFont.Font;
Parameters: TYPE = ImagerMaskCache.Parameters;
SampleMap: TYPE = ImagerSample.SampleMap;
ScanMode: TYPE = ImagerTransformation.ScanMode;
TrajectoryList: TYPE = ImagerPath.TrajectoryList;
Transformation: TYPE = ImagerTransformation.Transformation;
Typeface: TYPE = ImagerTypeface.Typeface;
VEC: TYPE = Vector2.VEC;
XChar: TYPE = ImagerFont.XChar;
MaskChar
GetClientToDevice: PROC [context: Imager.Context] RETURNS [Transformation] ~ {
m: Transformation ¬ NIL;
m ¬ ImagerBackdoor.GetTransformation[context: context, from: client, to: device ! Imager.Error => { m ¬ ImagerTransformation.Scale[1/4096.0] }];
RETURN [m]
};
MaskChar: PUBLIC -- ImagerFontWorks-- PROC [font: Font, char: XChar, context: Imager.Context] ~ {
N.B. Also exported to ImagerTypeface (for compatibility)
typeface: Typeface ~ ImagerTypeface.TypefaceFromFont[font];
Action: PROC ~ {
IF (typeface.class.Mask = NIL) AND (typeface.class.MapChar # NIL)
THEN {
m: Transformation ¬ GetClientToDevice[context];
f: Font ~ ImagerFont.Modify[font, m];
Path: ImagerPath.PathProc ~ {
[] ¬ typeface.class.MapChar[font: f, char: char, parameters: NIL,
moveTo: moveTo, lineTo: lineTo, curveTo: curveTo, arcTo: arcTo, conicTo: conicTo];
};
ImagerTransformation.ApplyInvert[m];
Imager.ConcatT[context, m];
{ImagerTransformation.Destroy[m]; m ¬ NIL};
Imager.MaskFill[context: context, path: Path];
}
ELSE {
Imager.ConcatT[context, font.charToClient];
typeface.class.Mask[typeface, char, context];
}
};
Imager.DoSaveAll[context, Action];
};
MapChar
MapChar: PUBLIC ImagerFontWorks.MapCharProc = {
typeface: Typeface = ImagerTypeface.TypefaceFromFont[font];
success ¬ FALSE;
IF typeface.class.MapChar # NIL THEN {
success ¬ typeface.class.MapChar[font: font, char: char, parameters: parameters, moveTo: moveTo, lineTo: lineTo, curveTo: curveTo, arcTo: arcTo, conicTo: conicTo];
Issue: should we return here?
};
IF NOT success AND typeface.class.Mask # NIL THEN {
myContext: Context ¬ GetContext[parameters];
data: Data = NARROW[myContext.data];
Inner: PROC ~ {
Imager.ConcatT[myContext, font.charToClient];
typeface.class.Mask[typeface, char, myContext];
};
Imager.DoSaveAll[myContext, Inner];
success ¬ NOT data.failed;
IF success THEN ImagerPath.MapTrajectoryList[data.list, moveTo, lineTo, curveTo, conicTo, arcTo];
FreeContext[myContext];
};
};
Capturing character outlines
Wrap: TYPE ~ { unknown, nz, eo };
Data: TYPE = REF DataRep ¬ NIL;
DataRep: TYPE = RECORD [
wrap: Wrap ¬ unknown,
failed: BOOL,
list: TrajectoryList -- captured outline
];
CreateContext: PROC RETURNS [Context] = {
deviceParm: ImagerDevice.DeviceParm ¬ ImagerDevice.MakeDeviceParm[
class: mapCharDeviceClass, sSize: INTEGER.LAST, fSize: INTEGER.LAST,
scanMode: [slow: right, fast: up], surfaceUnitsPerInch: [1, 1]];
data: Data = NEW[DataRep ¬ [failed: FALSE, list: NIL]];
context: Context = ImagerRaster.Create[
class: mapCharContextClass, deviceParm: deviceParm,
deviceClass: mapCharDeviceClass, data: NIL, pixelUnits: TRUE];
context.data ¬ data; -- context.data is used instead of device.data because these procs capture at the context class level
RETURN[context];
};
defaultParameters: Parameters ¬ NEW[ImagerMaskCache.ParametersRep ¬ []];
GetContext: PROC [parameters: Parameters] RETURNS [context: Context] = {
context ¬ TryGetContext[];
IF context = NIL THEN context ¬ CreateContext[];
IF parameters = NIL THEN parameters ¬ defaultParameters;
ImagerRaster.GetDevice[context].parm.parameters ¬ parameters;
};
c1: Context ¬ NIL;
c2: Context ¬ NIL;
TryGetContext: ENTRY PROC RETURNS [context: Context] = INLINE {
ENABLE UNWIND => NULL;
IF c1 # NIL THEN {context ¬ c1; c1 ¬ NIL}
ELSE IF c2 # NIL THEN {context ¬ c2; c2 ¬ NIL} ELSE context ¬ NIL;
}; -- Be sure to call FreeContext when you are done.
FreeContext: ENTRY PROC [context: Context] = INLINE {
ENABLE UNWIND => NULL;
data: Data = NARROW[context.data];
data.wrap ¬ unknown;
data.failed ¬ FALSE;
data.list ¬ NIL;
IF c1 = NIL THEN {c1 ¬ context}
ELSE {c2 ¬ context; };
};
Capture class procs
MyMaskFill: PROC [context: Context, path: ImagerPath.PathProc, oddWrap: BOOL] = {
data: Data = NARROW[context.data];
m: Transformation ~ ImagerBackdoor.GetT[context];
wrap: Wrap ~ IF oddWrap THEN eo ELSE nz;
myMoveTo: ImagerPath.MoveToProc = {
data.list ¬ CONS[ImagerPath.MoveTo[p], data.list];
};
myLineTo: ImagerPath.LineToProc = {
data.list.first ¬ ImagerPath.LineTo[data.list.first, p1]; };
myCurveTo: ImagerPath.CurveToProc = {
data.list.first ¬ ImagerPath.CurveTo[data.list.first, p1, p2, p3];
};
myConicTo: ImagerPath.ConicToProc = {
data.list.first ¬ ImagerPath.ConicTo[data.list.first, p1, p2, r];
};
myArcTo: ImagerPath.ArcToProc = {
data.list.first ¬ ImagerPath.ArcTo[data.list.first, p1, p2];
};
ImagerPath.Transform[path, m, myMoveTo, myLineTo, myCurveTo, myConicTo, myArcTo];
IF data.wrap = unknown THEN data.wrap ¬ wrap;
IF data.wrap # wrap THEN data.failed ¬ TRUE;
ImagerTransformation.Destroy[m];
};
MyMaskRectangle: PROC [context: Context, r: Imager.Rectangle] = {
Path: Imager.PathProc ~ {
moveTo[[r.x, r.y]];
lineTo[[r.x+r.w, r.y]];
lineTo[[r.x+r.w, r.y+r.h]];
lineTo[[r.x, r.y+r.h]];
};
Imager.MaskFill[context: context, path: Path, oddWrap: TRUE];
};
MyMaskStroke: PROC [context: Context, path: ImagerPath.PathProc, closed: BOOL] = {
data: Data = NARROW[context.data];
data.failed ¬ TRUE;
};
MyMaskPixel: PROC [context: Context, pa: Imager.PixelArray] = {
data: Data = NARROW[context.data];
data.failed ¬ TRUE;
};
MyMaskVector: PROC [context: Context, p1, p2: VEC] = {
data: Data = NARROW[context.data];
data.failed ¬ TRUE;
};
MyMaskBitmap: PROC [context: Context, bitmap: SampleMap, referencePoint: SF.Vec,
scanMode: ScanMode, position: VEC] = {
data: Data = NARROW[context.data];
data.failed ¬ TRUE;
};
MyDrawBitmap: PROC [context: Context, bitmap: SampleMap, referencePoint: SF.Vec,
scanMode: ScanMode, position: VEC] = {
data: Data = NARROW[context.data];
data.failed ¬ TRUE;
};
MyDrawPixels: PROC [context: Context, pixelMap: Imager.PixelMap,
colorOperator: Imager.ColorOperator, referencePoint: SF.Vec, scanMode: ScanMode, position: VEC] = {
data: Data = NARROW[context.data];
data.failed ¬ TRUE;
};
mapCharContextClass: ImagerPrivate.Class = InitMapCharContextClass[];
InitMapCharContextClass: PROC RETURNS [ImagerPrivate.Class] = {
new: ImagerPrivate.Class = ImagerRaster.CreateClass[type: $MapChar];
new.MaskFill ¬ MyMaskFill;
new.MaskRectangle ¬ MyMaskRectangle;
new.MaskStroke ¬ MyMaskStroke;
new.MaskPixel ¬ MyMaskPixel;
new.MaskVector ¬ MyMaskVector;
new.MaskDashedStroke ¬ ImagerPrivate.DefaultMaskDashedStroke;
new.MaskBitmap ¬ MyMaskBitmap;
new.DrawPixels ¬ MyDrawPixels;
RETURN[new];
};
Capture device class procs
MySetColor: PROC [device: Device, color: Imager.Color, viewToDevice: Transformation] = {NULL};
MyMaskBoxes: PROC [device: Device, bounds: SF.Box, boxes: SF.BoxGenerator] = {NULL};
mapCharDeviceClass: ImagerDevice.DeviceClass = InitMapCharDeviceClass[];
InitMapCharDeviceClass: PROC RETURNS [ImagerDevice.DeviceClass] = {
RETURN[NEW[ImagerDevice.DeviceClassRep ¬ [
SetColor
: MySetColor, MaskBoxes: MyMaskBoxes]]]};
END.