-- GraphicsImpl.mesa
-- Last edited by Doug Wyatt, December 1, 1983 1:09 pm

DIRECTORY
  CGArea USING [New, Ref],
  CGBitmapDevice USING [New],
  CGBitmapDeviceExtras USING [UnsafeNew],
  CGClipper USING [Assign, Bounds, Copy, New, Ref, Rep, SetBox, TestPoint],
  CGContext USING [Ref, Rep, TouchClipper, TouchMatrix],
  CGDevice USING [Ref, Rep],
  CGFont USING [New, Ref, Rep],
  CGMatrix USING [Assign, Copy, Inv, Map, Ref, Rep],
  CGPath USING [CurveTo, LastPoint, LineTo, MoveTo, New, Rectangle, Reset],
  CGPrivate, -- USING almost everything
  CGReducer USING [New, Ref],
  CGSource USING [Ref, Rep],
  CGStorage USING [qZone],
  Graphics USING [black, Context, ContextRep, ErrorType, GraphicsProcs, WarningType],
  GraphicsBasic USING [Box, Color, FontRef, ImageRef, Mark, PaintMode, Path, Vec, YMode],
  GraphicsExtras USING [],
  GraphicsOps USING [BitmapRef],
  RealFns USING [CosDeg, SinDeg];

GraphicsImpl: CEDAR PROGRAM
IMPORTS CGArea, CGBitmapDevice, CGBitmapDeviceExtras, CGClipper, CGContext, CGFont,
  CGMatrix, CGPath, CGPrivate, CGReducer, CGStorage, RealFns
EXPORTS Graphics, GraphicsBasic, GraphicsOps, GraphicsExtras = { OPEN GraphicsBasic;

DeviceObject: PUBLIC TYPE = CGDevice.Rep; -- export to GraphicsBasic
FontObject: PUBLIC TYPE = CGFont.Rep; -- export to GraphicsBasic

Context: TYPE = Graphics.Context;
ContextData: TYPE = CGContext.Ref;

repZone: ZONE = CGStorage.qZone;
srcZone: ZONE = CGStorage.qZone;

procs: REF Graphics.GraphicsProcs _ repZone.NEW[Graphics.GraphicsProcs _ [
  GetCP: CGPrivate.GetCP,
  SetCP: CGPrivate.SetCP,
  DrawTo: CGPrivate.DrawTo,
  DrawStroke: CGPrivate.DrawStroke,
  DrawArea: CGPrivate.DrawArea,
  DrawBox: CGPrivate.DrawBox,
  DrawImage: CGPrivate.DrawImage,
  Translate: CGPrivate.Translate,
  Concat: CGPrivate.Concat,
  WorldToUser: CGPrivate.WorldToUser,
  UserToWorld: CGPrivate.UserToWorld,
  SetColor: CGPrivate.SetColor,
  GetColor: CGPrivate.GetColor,
  SetPaintMode: CGPrivate.SetPaintMode,
  SetFat: CGPrivate.SetFat,
  GetDefaultFont: CGPrivate.GetDefaultFont,
  SetDefaultFont: CGPrivate.SetDefaultFont,
  DrawChars: CGPrivate.DrawChars,
  ClipArea: CGPrivate.ClipArea,
  ClipBox: CGPrivate.ClipBox,
  IsPointVisible: CGPrivate.IsPointVisible,
  IsRectangular: CGPrivate.IsRectangular,
  GetBounds: CGPrivate.GetBounds,
  Visible: CGPrivate.Visible,
  Save: CGPrivate.Save,
  Restore: CGPrivate.Restore,
  DrawBits: CGPrivate.DrawBits,
  UserToDevice: CGPrivate.UserToDevice,
  DeviceToUser: CGPrivate.DeviceToUser,
  GetYMode: CGPrivate.GetYMode,
  SetYMode: CGPrivate.SetYMode,
  DrawTexturedBox: CGPrivate.DrawTexturedBox,
  Disable: CGPrivate.Disable,
  MoveDeviceRectangle: CGPrivate.MoveDeviceRectangle
  ]];

-- Signals --

Warning: PUBLIC SIGNAL[type: Graphics.WarningType] = CODE;
Error: PUBLIC ERROR[type: Graphics.ErrorType] = CODE;

-- Creating new contexts --

NewContext: PUBLIC PROC[device: CGDevice.Ref] RETURNS[Context] = {
  d: ContextData _ repZone.NEW[CGContext.Rep _ [
    device: NIL, -- output device
    cp: [0,0], -- current position
    matrix: NIL, -- current matrix
    clipper: NIL, -- current clipper
    reducer: NIL, -- reducer
    area: NIL,
    src: NIL, -- current source
    haveRaster: FALSE,
    boxing: FALSE, newbox: FALSE, -- boxing state
    bbox: NIL
    ]];
  m: CGMatrix.Ref _ NIL;
  dbase: LONG POINTER _ NIL;
  drast: CARDINAL _ 0;
  IF device=NIL THEN device _ CGBitmapDevice.New[NIL,0,0]; -- the screen
  m _ device.GetMatrix[device]; -- world to device transformation
  d.device _ device;
  d.cp _ CGMatrix.Map[m,[0,0]];
  d.matrix _ CGMatrix.Copy[m];
  d.clipper _ CGClipper.New[1];
  d.reducer _ CGReducer.New[8];
  d.area _ CGArea.New[4];
  CGClipper.SetBox[d.clipper,device.GetBounds[device]];
  d.src _ srcZone.NEW[CGSource.Rep _ [type: const, fat: FALSE, mode: opaque,
    bps: 0, color: Graphics.black, xbase: NIL, xrast: 0, Get: NIL]];
  IF device.GetRaster#NIL THEN { [dbase,drast] _ device.GetRaster[device] };
  IF dbase#NIL THEN { d.dbase _ dbase; d.drast _ drast; d.haveRaster _ TRUE };
  RETURN[repZone.NEW[Graphics.ContextRep _ [procs, d]]];
  };

CopyContext: PUBLIC PROC[self: Context] RETURNS[Context] = {
  d: ContextData _ NARROW[self.data];
  device: CGDevice.Ref _ d.device;
  copy: ContextData _ repZone.NEW[CGContext.Rep _ [
    device: device, -- output device
    cp: d.cp, -- current position
    matrix: NIL, -- current matrix
    clipper: NIL, -- current clipper
    reducer: NIL, -- reducer
    area: NIL,
    src: NIL, -- current source
    boxing: FALSE, newbox: FALSE, -- boxing state
    bbox: NIL,
    haveRaster: d.haveRaster,
    dbase: d.dbase,
    drast: d.drast
    ]];
  copy.matrix _ CGMatrix.Copy[d.matrix];
  copy.clipper _ CGClipper.Copy[d.clipper];
  copy.reducer _ CGReducer.New[8];
  copy.area _ CGArea.New[4];
  copy.src _ srcZone.NEW[CGSource.Rep _ d.src^];
  RETURN[repZone.NEW[Graphics.ContextRep _ [self.procs, copy]]];
  };

-- Procedures independent of data representation --

minPathSize: NAT = 4;

NewPath: PUBLIC PROC[initialSize: INT _ 0] RETURNS[Path] = {
  size: NAT _ MIN[MAX[initialSize, minPathSize], LAST[NAT]];
  path: Path _ CGPath.New[size];
  RETURN[path]
  };

LastPoint: PUBLIC PROC[self: Path] RETURNS[x, y: REAL] = {
  v: Vec _ CGPath.LastPoint[self]; RETURN[v.x, v.y];
  };

FlushPath: PUBLIC PROC[self: Path] = {
  CGPath.Reset[self];
  };

MoveTo: PUBLIC PROC[self: Path, x, y: REAL, flush: BOOLEAN _ TRUE] = {
  IF flush THEN CGPath.Reset[self];
  CGPath.MoveTo[self, [x, y]];
  };

LineTo: PUBLIC PROC[self: Path, x, y: REAL] = {
  CGPath.LineTo[self, [x, y]];
  };

CurveTo: PUBLIC PROC[self: Path, x1, y1, x2, y2, x3, y3: REAL] = {
  CGPath.CurveTo[self, [x1, y1], [x2, y2], [x3, y3]];
  };

Rectangle: PUBLIC PROC[self: Path, x0, y0, x1, y1: REAL] = {
  CGPath.Rectangle[self, [x0, y0], [x1, y1]];
  };


Rotate: PUBLIC PROC[self: Context, angle: REAL] = {
  cos, sin: REAL;
  eps: REAL = 1E-6;
  TRUSTED { cos _ RealFns.CosDeg[angle]; sin _ RealFns.SinDeg[angle] };
  IF ABS[sin]<eps THEN { sin _ 0; cos _ (IF cos>0 THEN 1 ELSE -1) };
  IF ABS[cos]<eps THEN { cos _ 0; sin _ (IF sin>0 THEN 1 ELSE -1) };
  self.procs.Concat[self, cos,sin,-sin,cos];
  };

Map: PUBLIC PROC[sc,dc: Context, sx,sy: REAL] RETURNS[dx,dy: REAL] = {
  wx, wy: REAL;
  [wx, wy] _ sc.procs.UserToWorld[sc, sx, sy];
  [dx, dy] _ dc.procs.WorldToUser[dc, wx, wy];
  };

BitmapRef: TYPE = GraphicsOps.BitmapRef;

DrawBitmap: PUBLIC PROC[self: Context, bitmap: BitmapRef,
  w, h: CARDINAL, x, y: CARDINAL, xorigin, yorigin: INTEGER] = {
  w _ MIN[w, bitmap.width-(x _ MIN[x, bitmap.width])];
  h _ MIN[h, bitmap.height-(y _ MIN[y, bitmap.height])];
  TRUSTED { self.procs.DrawBits[self,
    LOOPHOLE[bitmap.base], bitmap.raster, 0, x, y, w, h, xorigin, yorigin] };
  };

NewContextFromBitmap: PUBLIC PROC[bitmap: BitmapRef] RETURNS[Context] = TRUSTED {
  dev: CGDevice.Ref _ CGBitmapDevice.New[
    base: LOOPHOLE[bitmap.base], raster: bitmap.raster, height: bitmap.height];
  RETURN[NewContext[dev]];
  };

UnsafeNewContextFromBitmap: PUBLIC UNSAFE PROC[base: LONG POINTER, raster, height: CARDINAL] RETURNS[Context] = UNCHECKED {
  dev: CGDevice.Ref _ CGBitmapDeviceExtras.UnsafeNew[base: base, raster: raster, height: height];
  RETURN[NewContext[dev]];
  };


MapperObject: PUBLIC TYPE = CGMatrix.Rep; -- export to GraphicsBasic
ClipperObject: PUBLIC TYPE = CGClipper.Rep; -- export to GraphicsBasic

GetMapper: PUBLIC PROC[self: Context] RETURNS[CGMatrix.Ref] = {
  ctx: ContextData _ NARROW[self.data];
  m: CGMatrix.Ref _ ctx.matrix;
  RETURN[CGMatrix.Copy[m]];
  };
SetMapper: PUBLIC PROC[self: Context, mapper: CGMatrix.Ref] = {
  ctx: ContextData _ NARROW[self.data];
  m: CGMatrix.Ref _ ctx.matrix;
  CGContext.TouchMatrix[ctx];
  CGMatrix.Assign[m,mapper];
  };

GetClipper: PUBLIC PROC[self: Context] RETURNS[CGClipper.Ref] = {
  ctx: ContextData _ NARROW[self.data];
  clipper: CGClipper.Ref _ ctx.clipper;
  RETURN[CGClipper.Copy[clipper]];
  };
SetClipper: PUBLIC PROC[self: Context, clipper: CGClipper.Ref] = {
  ctx: ContextData _ NARROW[self.data];
  CGContext.TouchClipper[ctx];
  CGClipper.Assign[ctx.clipper,clipper];
  };

TestVisible: PUBLIC PROC[mapper: CGMatrix.Ref, clipper: CGClipper.Ref, x,y: REAL]
  RETURNS[BOOLEAN] = {
  p: Vec _ CGMatrix.Map[mapper,[x,y]];
  RETURN[CGClipper.TestPoint[clipper,p]];
  };

TestBounds: PUBLIC PROC[mapper: CGMatrix.Ref, clipper: CGClipper.Ref]
  RETURNS[Box] = {
  box: Box _ CGClipper.Bounds[clipper];
  m: CGMatrix.Ref _ mapper;
  result: Box;
  a,b,c,d: Vec;
  IF m.rectangular THEN {
    a _ CGMatrix.Inv[m,[box.xmin,box.ymin]];
    c _ CGMatrix.Inv[m,[box.xmax,box.ymax]];
    result.xmin _ MIN[a.x,c.x];
    result.xmax _ MAX[a.x,c.x];
    result.ymin _ MIN[a.y,c.y];
    result.ymax _ MAX[a.y,c.y];
    }
  ELSE {
    a _ CGMatrix.Inv[m,[box.xmin,box.ymin]];
    b _ CGMatrix.Inv[m,[box.xmax,box.ymin]];
    c _ CGMatrix.Inv[m,[box.xmax,box.ymax]];
    d _ CGMatrix.Inv[m,[box.xmin,box.ymax]];
    result.xmin _ MIN[a.x,b.x,c.x,d.x];
    result.xmax _ MAX[a.x,b.x,c.x,d.x];
    result.ymin _ MIN[a.y,b.y,c.y,d.y];
    result.ymax _ MAX[a.y,b.y,c.y,d.y];
    };
  RETURN[result];
  };

BeginBox: PUBLIC PROC[self: Context] = {
  ctx: ContextData _ NARROW[self.data];
  SIGNAL Warning[notImplemented];
  ctx.boxing _ ctx.newbox _ TRUE;
  };

EndBox: PUBLIC PROC[self: Context] RETURNS[Box] = {
  ctx: ContextData _ NARROW[self.data];
  box: Box _ [0,0,0,0];
  SIGNAL Warning[notImplemented];
  ctx.boxing _ FALSE;
  RETURN[box];
  };

UnsafeNewFont: PUBLIC UNSAFE PROC[lp: LONG POINTER]
  RETURNS[CGFont.Ref] = UNCHECKED { RETURN[CGFont.New[lp]] };

}.

�����Ê¬��–"Mesa" style˜�Iprocš¸ÏcLœÏk	œ
žœžœžœžœGžœ3žœžœžœ.žœKœžœžœžœžœVžœVžœžœžœ"žœžœžœŠžœ:žœžœžœœžœžœœ
žœ"žœžœžœžœ"žœº	
œžœžœžœ	žœžœžœœÏn
œžœžœžœ)žœžœœœžœœ
žœœ
žœœ
žœžœœžœžœ
žœœ
žœžœžœžœžœžœžœžœžœžœœ "œøžœ#žœ:žœžœžœžœžœ1žœžœžœ4žœžœ	žœ+Ÿœžœžœžœ!žœNžœ'œœžœœ
žœœ
žœœ
žœžœœžœ
žœœ
žœùžœžœ	žœ33œžœŸœžœžœžœžœžœžœžœžœžœ'žœ
Ÿ	œžœžœ
žœžœ)žœŸ	œžœžœ-Ÿœžœžœžœ	žœžœžœžœ:Ÿœžœžœžœ+Ÿœžœžœ%žœBŸ	œžœžœžœ;Ÿœžœžœžœžœ	žœžœAžœžœ
žœžœžœžœ
žœžœ
žœžœžœžœ;ŸœžœžœžœžœžœžœqžœŸ
œžœžœ+žœžœžœžœžœžœžœžœ!žœHŸœžœžœžœžœ7žœ@žœŸœžœžœžœžœžœžœž
œfžœ(žœžœœžœžœœŸ	œžœžœžœ(žœ/žœŸ	œžœžœ?žœnŸ
œžœžœžœ)žœ7žœ Ÿ
œžœžœAžœ[Ÿœžœžœ4žœžœžœ/žœ(Ÿ
œžœžœ1žœožœžœožœžœžœžœžœÉžœ%žœ%žœ%žœžœŸœžœžœ)žœžœ6žœŸœžœžœžœžœ'žœ)žœžœ
Ÿ
œžœžœžœžœžœžœž	œžœ˜‚K—�…—����%„��*6��