DIRECTORY Basics USING [BITAND, bitsPerWord, LongMult], FunctionCache USING [Cache, CompareProc, Create, Insert, Lookup], Imager USING [ClassRep, Context, SetXYRel, StateRep], ImagerCache USING [Fetch, GetNamedCache, Ref], ImagerDevice USING [CharMaskRep, Device], ImagerDeviceBitmapPrivate USING [Data], ImagerFastShow USING [], ImagerFont USING [Font, XChar, XStringProc], ImagerFontPrivate USING [FontAtom], ImagerPrivate USING [ClassRep], ImagerRaster USING [Create, CreateClass, FontTuner, NewBitmapDevice], ImagerRasterPrivate USING [AndFlags, Data, Flags, NoteStateChanges, RasterShow, ValidateIfNeeded], ImagerSample USING [SampleMap], ImagerState USING [notChanged, State, StateRep], ImagerTransformation USING [InverseTransform, Transform, Transformation], PrincOps USING [BBTableSpace, BitBltFlags, BitBltTablePtr], PrincOpsUtils USING [AlignedBBTable, BITBLT], Real, Scaled USING [Float, FromReal, half, MINUS, PLUS, Value, zero], SF USING [Box, SizeS], Vector2 USING [Mul, VEC]; ImagerFastShowImpl: CEDAR PROGRAM IMPORTS Basics, FunctionCache, Imager, ImagerCache, ImagerRaster, ImagerRasterPrivate, ImagerTransformation, PrincOpsUtils, Real, Scaled, SF, Vector2 EXPORTS Imager, ImagerFastShow ~ BEGIN OPEN ImagerRasterPrivate; bitsPerWord: NAT ~ Basics.bitsPerWord; ClassRep: PUBLIC TYPE ~ ImagerPrivate.ClassRep; -- export to Imager.ClassRep Context: TYPE ~ Imager.Context; Device: TYPE ~ ImagerDevice.Device; Box: TYPE ~ SF.Box; Font: TYPE ~ ImagerFont.Font; FontAtom: TYPE ~ ImagerFontPrivate.FontAtom; RasterMask: TYPE ~ REF ImagerDevice.CharMaskRep.raster; State: TYPE ~ ImagerState.State; StateRep: PUBLIC TYPE ~ ImagerState.StateRep; -- export to Imager.StateRep Transformation: TYPE ~ ImagerTransformation.Transformation; VEC: TYPE ~ Vector2.VEC; XChar: TYPE ~ ImagerFont.XChar; XStringProc: TYPE ~ ImagerFont.XStringProc; fastShowClass: REF Imager.ClassRep ~ FastShowClass[]; FastShowClass: PROC RETURNS [c: REF ImagerPrivate.ClassRep] ~ { c _ ImagerRaster.CreateClass[$FastShowBitmap]; IF c.Show # ImagerRasterPrivate.RasterShow THEN ERROR; c.Show _ FastShow; }; rastWeight: REAL _ 2.0; Create: PUBLIC PROC [bitmap: ImagerSample.SampleMap, pixelsPerInch: REAL _ 72, pixelUnits: BOOL, fontTuner: ImagerRaster.FontTuner] RETURNS [Context] ~ { device: ImagerDevice.Device ~ ImagerRaster.NewBitmapDevice[ frame: bitmap, pixelsPerInch: pixelsPerInch]; bitmapFontCache: ImagerCache.Ref ~ ImagerCache.GetNamedCache[ atom: $Bitmap, createSize: 4000]; RETURN[ImagerRaster.Create[device: device, pixelUnits: pixelUnits, fontCache: bitmapFontCache, rastWeight: rastWeight, fontTuner: fontTuner, class: fastShowClass]]; }; Validate: PROC [data: ImagerRasterPrivate.Data, state: State, needs: ImagerRasterPrivate.Flags] RETURNS [BOOL] ~ INLINE { IF state.changed#ImagerState.notChanged THEN ImagerRasterPrivate.NoteStateChanges[data, state]; IF ImagerRasterPrivate.AndFlags[data.valid, needs]#needs THEN ImagerRasterPrivate.ValidateIfNeeded[data, state, needs]; RETURN [TRUE] }; showNeeds: ImagerRasterPrivate.Flags ~ [clientClipper: TRUE, deviceColor: TRUE, devicePriority: TRUE, clientToDevice: TRUE, fontInfo: TRUE]; worryNat: NAT ~ NAT.LAST/2-1; worryReal: REAL _ worryNat; space: XChar ~ [0, ORD[' ]]; Trust: UNSAFE PROC [INTEGER] RETURNS [NAT] ~ UNCHECKED MACHINE CODE {}; ContainingBox: PROC [s, f: INTEGER, boxes: LIST OF Box] RETURNS [Box] ~ { FOR p: LIST OF Box _ boxes, p.rest UNTIL p=NIL DO b: Box ~ p.first; IF s IN [b.min.s..b.max.s) AND f IN [b.min.f..b.max.f) THEN RETURN[b]; ENDLOOP; RETURN[[[0,0],[0,0]]] }; sSizeBoxMin: NAT _ 4; CommonChar: TYPE ~ [32..127]; charArrayCache: FunctionCache.Cache _ FunctionCache.Create[maxEntries: 24]; GetCharArray: PROC [fontAtom: REF] RETURNS [r: REF ARRAY CommonChar OF RasterMask] ~ { compare: FunctionCache.CompareProc ~ {RETURN [argument = fontAtom]}; r _ NARROW[FunctionCache.Lookup[charArrayCache, compare].value]; IF r = NIL THEN { r _ NEW[ARRAY CommonChar OF RasterMask _ ALL[NIL]]; [] _ FunctionCache.Insert[charArrayCache, fontAtom, r, SIZE[ARRAY CommonChar OF RasterMask]]; }; }; Ord: PROC [char: XChar] RETURNS [CARDINAL] ~ INLINE {RETURN [LOOPHOLE[char]]}; FastShow: PROC [context: Context, string: XStringProc, xrel: BOOL] ~ { state: State ~ context.state; rasterData: Data ~ NARROW[context.data]; device: Device ~ rasterData.device; bitmapData: ImagerDeviceBitmapPrivate.Data ~ NARROW[device.data]; cache: ImagerCache.Ref ~ rasterData.fontCache; font: Font ~ state.font; valid: BOOL _ Validate[rasterData, state, showNeeds]; scaledCPValid: BOOL _ FALSE; sCP: Scaled.Value; -- device coordinates, offset by 1/2 pixel fCP: Scaled.Value; -- ditto box: Box; UpdateCP: PROC ~ { IF scaledCPValid THEN state.p.cp _ rasterData.viewToDevice.InverseTransform[ [sCP.MINUS[Scaled.half].Float, fCP.MINUS[Scaled.half].Float] ]; }; TryScaledCP: PROC RETURNS [BOOL]~ { cp: VEC _ rasterData.viewToDevice.Transform[state.p.cp]; IF ABS[cp.x] < worryReal AND ABS[cp.y] < worryReal THEN { sCP _ Scaled.FromReal[cp.x].PLUS[Scaled.half]; fCP _ Scaled.FromReal[cp.y].PLUS[Scaled.half]; scaledCPValid _ TRUE; } ELSE scaledCPValid _ FALSE; IF scaledCPValid THEN box _ ContainingBox[s: sCP.integerPart, f: fCP.integerPart, boxes: rasterData.clientClipMask]; RETURN [scaledCPValid] }; charArray: REF ARRAY CommonChar OF RasterMask _ GetCharArray[rasterData.fontAtom]; Lookup: PROC [char: XChar] RETURNS [m: RasterMask _ NIL] ~ { WITH ImagerCache.Fetch[cache, rasterData.fontAtom, char] SELECT FROM r: RasterMask => { IF MAX[r.sSizeBB, r.fSizeBB, ABS[r.sEscapement.integerPart], ABS[r.fEscapement.integerPart]] < worryNat THEN { m _ r; IF Ord[char] IN CommonChar THEN { charArray[Ord[char]] _ m; }; }; }; ENDCASE => NULL; }; lastAmplified: RasterMask _ NIL; sCPAmp: Scaled.Value _ Scaled.zero; fCPAmp: Scaled.Value _ Scaled.zero; Amplify: PROC [m: RasterMask] ~ { IF m # lastAmplified THEN { IF state.np.amplifySpace = 1.0 THEN { sCPAmp _ m.sEscapement; fCPAmp _ m.fEscapement; } ELSE { escapement: VEC ~ Vector2.Mul[[m.sEscapement.Float, m.fEscapement.Float], state.np.amplifySpace]; IF MAX[ABS[escapement.x], ABS[escapement.y]] < worryReal THEN { sCPAmp _ Scaled.FromReal[escapement.x]; fCPAmp _ Scaled.FromReal[escapement.y]; } ELSE { UpdateCP[]; Imager.SetXYRel[context, escapement]; [] _ TryScaledCP[]; RETURN; }; }; lastAmplified _ m; }; sCP _ sCP.PLUS[sCPAmp]; fCP _ fCP.PLUS[fCPAmp]; }; IF NOT xrel AND bitmapData.case = fill AND (state.np.correctPass = 0 OR (state.np.correctPass = 2 AND state.p.correctMask.x=0.0 AND state.p.correctMask.y=0.0 AND state.p.correctSpace.x=0.0 AND state.p.correctSpace.y=0.0)) AND state.np.noImage = 0 AND cache # NIL AND TryScaledCP[] AND SF.SizeS[box] > sSizeBoxMin THEN TRUSTED { dstBase: LONG POINTER ~ bitmapData.frame.pointer; dstWpl: NAT ~ bitmapData.frame.rast; bbspace: PrincOps.BBTableSpace; bbPtr: PrincOps.BitBltTablePtr ~ InitBITBLT[]; InitBITBLT: PROC RETURNS [PrincOps.BitBltTablePtr] ~ TRUSTED { bb: PrincOps.BitBltTablePtr ~ PrincOpsUtils.AlignedBBTable[@bbspace]; flags: PrincOps.BitBltFlags _ bitmapData.maskBitsFlags; flags.gray _ FALSE; flags.disjoint _ TRUE; bb.dst _ [word: NIL, bit: 0]; bb.dstBpl _ dstWpl*bitsPerWord; bb.src _ [word: NIL, bit: 0]; bb.flags _ flags; RETURN [bb]; }; FastCharAction: PROC [char: XChar] ~ TRUSTED { bb: PrincOps.BitBltTablePtr ~ bbPtr; m: RasterMask _ NIL; QuickLook: PROC RETURNS [ok: BOOL] ~ CHECKED INLINE { IF Ord[char] IN CommonChar THEN { m _ charArray[Ord[char]]; IF m # NIL THEN RETURN [TRUE]; }; m _ Lookup[char]; RETURN [m#NIL] }; s0, f0: INTEGER; sSize, fSize: NAT; fast: BOOL ~ ( scaledCPValid AND QuickLook[] AND (s0 _ sCP.integerPart + m.sMinBB) >= box.min.s AND (f0 _ fCP.integerPart + m.fMinBB) >= box.min.f AND (s0 + (sSize _ LOOPHOLE[m.sSizeBB])) <= box.max.s AND (f0 + (fSize _ LOOPHOLE[m.fSizeBB])) <= box.max.f ); IF fast THEN { IF sSize # 0 THEN { bplMask: CARDINAL ~ LAST[CARDINAL]-(bitsPerWord-1); bb.dst.word _ dstBase + Basics.LongMult[Trust[s0], dstWpl] + Trust[f0]/bitsPerWord; bb.dst.bit _ Trust[f0] MOD bitsPerWord; bb.height _ sSize; bb.width _ fSize; bb.src.word _ @m[0]; bb.srcDesc _ [srcBpl[LOOPHOLE[Basics.BITAND[fSize+(bitsPerWord-1), bplMask]]]]; PrincOpsUtils.BITBLT[bb]; }; IF NOT m.amplified THEN { fCP _ fCP.PLUS[m.fEscapement]; sCP _ sCP.PLUS[m.sEscapement]; } ELSE IF m = lastAmplified THEN { sCP _ sCP.PLUS[sCPAmp]; fCP _ fCP.PLUS[fCPAmp]; } ELSE Amplify[m]; } ELSE { oneChar: XStringProc ~ CHECKED {charAction[char]}; UpdateCP[]; ImagerRasterPrivate.RasterShow[context, oneChar, FALSE]; [] _ TryScaledCP[]; }; }; string[FastCharAction]; UpdateCP[]; } ELSE ImagerRasterPrivate.RasterShow[context, string, xrel]; }; END. ImagerFastShowImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Michael Plass, November 19, 1985 3:17:29 pm PST Doug Wyatt, March 20, 1986 2:30:54 pm PST N.B. Uses the fact that ref assignment is atomic to avoid the need for a monitor. Κ ε˜code™Kšœ Οmœ1™KšœE˜EKšœ7˜7Kšœ žœžœ˜*Kšœžœ ˜Kšœ˜Kšœžœ ˜Kšœ˜Kšžœ˜ Kšœ˜—š‘œžœžœ˜.Kšœ$˜$Kšœžœ˜š ‘ œžœžœžœžœžœ˜5šžœ žœ žœ˜!Kšœ˜Kš žœžœžœžœžœ˜Kšœ˜—Kšœ˜Kšžœžœ˜Kšœ˜—Kšœžœ˜Kšœžœ˜šœžœ˜Kšœ ˜ Kšžœ ˜Kšžœ/˜2Kšžœ/˜2Kšžœžœ˜5Kšžœžœ˜5K˜—šžœžœ˜šžœ žœ˜Kšœ žœžœžœ˜3KšœS˜SKšœžœ ˜'Kšœ˜Kšœ˜Kšœ˜Kšœžœžœ$˜OKšœžœ˜Kšœ˜—šžœžœ žœ˜Kšœ žœ˜Kšœ žœ˜Kšœ˜—šžœžœžœ˜ Kšœ žœ ˜Kšœ žœ ˜Kšœ˜—Kšžœ ˜Kšœ˜—šžœ˜Kšœžœ˜2Kšœ ˜ Kšœ1žœ˜8Kšœ˜Kšœ˜—Kšœ˜—Kšœ˜Kšœ ˜ Kšœ˜—Kšžœ7˜;—Kšœ˜——K˜Kšžœ˜—…—!Ί.§