-- Copyright (C) 1983 by Xerox Corporation. All rights reserved.
-- DisplayImplC.mesa - last edited by
-- Rick 29-Nov-83 11:51:53
-- Bruce 25-Feb-83 10:35:50
DIRECTORY
BitBlt USING [BitBltFlags],
Display USING [paintGrayFlags],
DisplayFormat USING [CircleType],
DisplayOps USING [LogError],
DisplayInternal USING [SpecialCircle],
SpecialDisplay USING [defaultContext, LineStyle, solid, Special],
Window USING [Box, BoxHandle, nullBox, Place],
WindowOps USING [AbsoluteBoxHandle, Bounds, Object, ScreenBox];
DisplayImplC: PROGRAM
IMPORTS DisplayInternal, DisplayOps, SpecialDisplay, WindowOps
EXPORTS Display, DisplayInternal, SpecialDisplay, Window =
BEGIN
-- exported types
Handle: TYPE = LONG POINTER TO Object;
Object: PUBLIC TYPE = WindowOps.Object;
-- copied types because John doesn't like them
Special: TYPE = SpecialDisplay.Special;
Arc: PUBLIC PROC [
window: Handle, place: Window.Place, radius: INTEGER,
startSector, stopSector: CARDINAL, start, stop: Window.Place,
bounds: Window.BoxHandle ← NIL] = {
IF ~window.inTree THEN RETURN;
[] ← SpArcInternal[
window, FALSE, place, radius, startSector, stopSector, start, stop,
ALL[FALSE], bounds, SpecialDisplay.solid, Display.paintGrayFlags]};
SpArc: PUBLIC PROC [
window: Handle, place: Window.Place, radius: INTEGER,
startSector, stopSector: CARDINAL, start, stop: Window.Place,
bounds: Window.BoxHandle, dashes: SpecialDisplay.LineStyle,
flags: BitBlt.BitBltFlags, context: Special←SpecialDisplay.defaultContext] = {
ENABLE UNWIND => NULL;
filled: BOOLEAN = context.alloc # NIL;
SpArcInternal[
window, filled, place, radius, startSector, stopSector, start, stop,
ALL[FALSE], bounds, dashes, flags, context]};
SpArcInternal: PROC [
window: Handle, filled: BOOLEAN, place: Window.Place, radius: INTEGER,
startSector, stopSector: CARDINAL, start, stop: Window.Place,
circleType: DisplayFormat.CircleType, bounds: Window.BoxHandle,
dashes: SpecialDisplay.LineStyle,
flags: BitBlt.BitBltFlags, context: Special ← SpecialDisplay.defaultContext]={
box1, box2, box3: Window.Box ← Window.nullBox;
boundsBox: WindowOps.ScreenBox =
IF bounds = NIL THEN WindowOps.Bounds[window]
ELSE WindowOps.AbsoluteBoxHandle[window, bounds];
IF filled THEN FillArcBoxes[
@box1, @box2, @box3, start, stop, place, radius, boundsBox.top,
boundsBox.bottom]
ELSE DisplayArcBoxes[
@box1, @box2, @box3, start, stop, place, radius, dashes.thickness,
(startSector-1)*8+(stopSector-1)]; -- octants are now 0..7
IF box1 # Window.nullBox THEN DisplayInternal.SpecialCircle[
window: window, place: place, radius: radius, circleType: circleType,
bounds: @box1, dashes: dashes, flags: flags, context: context];
IF box2 # Window.nullBox THEN DisplayInternal.SpecialCircle[
window: window, place: place, radius: radius, circleType: circleType,
bounds: @box2, dashes: dashes, flags: flags, context: context];
IF box3 # Window.nullBox THEN DisplayInternal.SpecialCircle[
window: window, place: place, radius: radius, circleType: circleType,
bounds: @box3, dashes: dashes, flags: flags, context: context] };
DisplayArcBoxes: PUBLIC PROC [
b1, b2, b3: Window.BoxHandle, start,stop,center:Window.Place,
radius, thickness, sum: CARDINAL] = {
box1, box2, box3: WindowOps.ScreenBox ← [left:0,right:0,top:0,bottom:0];
bigBox: WindowOps.ScreenBox ← [
left: center.x - radius - 1, right: center.x + radius + 1,
top: center.y - radius - 1, bottom: center.y + radius + 1];
littleBox: WindowOps.ScreenBox ← [
left: MIN[start.x, stop.x], right: MAX[start.x, stop.x],
top: MIN[start.y, stop.y], bottom: MAX[start.y, stop.y]];
IF thickness > 2 THEN {
bigBox.left ← bigBox.left - 1;
bigBox.right ← bigBox.right + 1;
bigBox.top ← bigBox.top - 1;
bigBox.bottom ← bigBox.bottom + 1;
IF littleBox.left < center.x THEN littleBox.left ← littleBox.left - 1;
IF littleBox.top < center.y THEN littleBox.top ← littleBox.top - 1;
IF littleBox.right > center.x THEN littleBox.right ← littleBox.right + 1;
IF littleBox.bottom > center.y THEN littleBox.bottom ← littleBox.bottom+1};
--sum ← begin*8 + end; 0 to 65, could be passed from the graphic object
-- convert sum to octal to get start and stop octants
-- (eg. 14 = 16 octal or start octant 1 stop octant 6)
SELECT sum FROM
0 => -- both in octant 0
IF start.y > stop.y OR start.x > stop.x THEN box1 ← littleBox
ELSE {
box1 ← box2 ← box3 ← bigBox;
box1.top ← box2.bottom ← box3.bottom ← center.y;
box2.right ← start.x;
box3.left ← stop.x};
1, 2, 57, 58 => { -- 0 to 1, 0 to 2
box1 ← box2 ← bigBox;
box1.right ← box2.left ← start.x;
box2.top ← stop.y};
3, 4, 59, 60 => {-- 0 to 3, 0 to 4
box1 ← box2 ← bigBox;
box1.bottom ← box2.top ← center.y;
box1.right ← start.x;
box2.right ← stop.x};
9 => -- both in octant 1
IF start.y > stop.y OR start.x > stop.x THEN box1 ← littleBox
ELSE {
box1 ← box2 ← box3 ← bigBox;
box1.right ← box2.left ← box3.left ← center.x;
box2.bottom ← start.y;
box3.top ← stop.y};
10 => {-- 1 to 2
box1 ← box2 ← box3 ← bigBox;
box1.right ← box2.left ← box3.left ← center.x;
box2.bottom ← start.y;
box3.top ← stop.y};
11, 12, 19, 20 => {
box1 ← box2 ← bigBox;
box1.right ← box2.left ← stop.x;
box2.bottom ← start.y};
13, 14, 21, 22 => {-- 1 to 5
box1 ← box2 ← bigBox;
box1.right ← box2.left ← center.x;
box1.bottom ← stop.y;
box2.bottom ← start.y};
18 => -- both in octant 2
IF start.y > stop.y OR start.x < stop.x THEN box1 ← littleBox
ELSE {
box1 ← box2 ← box3 ← bigBox;
box1.right ← box2.left ← box3.left ← center.x;
box2.bottom ← start.y;
box3.top ← stop.y};
24, 31, 32, 39 => {
box1 ← box2 ← bigBox;
box1.top ← box2.bottom ← center.y;
box1.left ← start.x;
box2.left ← stop.x};
27 => -- both in octant 3
IF start.y > stop.y OR start.x < stop.x THEN box1 ← littleBox
ELSE {
box1 ← box2 ← box3 ← bigBox;
box1.bottom ← box2.top ← box3.top ← center.y;
box2.left ← start.x;
box3.right ← stop.x};
28 => {
box1 ← box2 ← box3 ← bigBox;
box1.bottom ← box2.top ← box3.top ← center.y;
box2.left ← start.x;
box3.right ← stop.x};
29, 30, 37, 38 => {
box1 ← box2 ← bigBox;
box1.left ← box2.right ← start.x;
box2.bottom ← stop.y};
36 => -- both in octant 4
IF start.y < stop.y OR start.x < stop.x THEN box1 ← littleBox
ELSE {
box1 ← box2 ← box3 ← bigBox;
box1.bottom ← box2.top ← box3.top ← center.y;
box2.left ← start.x;
box3.right ← stop.x};
40, 47, 48, 55 => {
box1 ← box2 ← bigBox;
box1.left ← box2.right ← stop.x;
box2.top ← start.y};
41, 42, 49, 50 => {
box1 ← box2 ← bigBox;
box1.left ← box2.right ← center.x;
box2.top ← start.y;
box1.top ← stop.y};
45 => -- both in octant 5
IF start.y < stop.y OR start.x < stop.x THEN box1 ← littleBox
ELSE {
box1 ← box2 ← box3 ← bigBox;
box1.left ← box2.right ← box3.right ← center.x;
box2.top ← start.y;
box3.bottom ← stop.y};
46 => {
box1 ← box2 ← box3 ← bigBox;
box1.left ← box2.right ← box3.right ← center.x;
box2.top ← start.y;
box3.bottom ← stop.y};
54 => -- both in octant 6
IF start.y < stop.y OR start.x > stop.x THEN box1 ← littleBox
ELSE {
box1 ← box2 ← box3 ← bigBox;
box1.left ← box2.right ← box3.right ← center.x;
box2.top ← start.y;
box3.bottom ← stop.y};
56 => {
box1 ← box2 ← box3 ← bigBox;
box1.top ← box2.bottom ← box3.bottom ← center.y;
box2.right ← start.x;
box3.left ← stop.x};
63 => -- both in octant 7
IF start.y < stop.y OR start.x > stop.x THEN box1 ← littleBox
ELSE {
box1 ← box2 ← box3 ← bigBox;
box1.top ← box2.bottom ← box3.bottom ← center.y;
box2.right ← start.x;
box3.left ← stop.x};
5, 61 => {
box1 ← bigBox;
box1.right ← start.x;
box1.bottom ← stop.y};
6, 7, 15 => {
box1 ← littleBox;
box1.top ← bigBox.top};
23 => {
box1 ← bigBox;
box1.left ← stop.x;
box1.bottom ← start.y};
16, 17, 25 => {
box1 ← littleBox;
box1.right ← bigBox.right};
33, 34 => {
box1 ← littleBox;
box1.right ← bigBox.right;
box1.bottom ← bigBox.bottom};
35, 43 => {
box1 ← littleBox;
box1.bottom ← bigBox.bottom};
51, 52 => {
box1 ← littleBox;
box1.left ← bigBox.left;
box1.bottom ← bigBox.bottom};
53 => {
box1 ← littleBox;
box1.left ← bigBox.left};
ENDCASE => box1 ← littleBox; --8, 26, 44, 62
IF box1.top < box1.bottom AND box1.left < box1.right THEN b1↑ ← [
place: [x: box1.left, y: box1.top],
dims: [w: box1.right - box1.left + 1, h: box1.bottom - box1.top + 1]];
IF box2.top < box2.bottom AND box2.left < box2.right THEN b2↑ ← [
place: [x: box2.left, y: box2.top],
dims: [w: box2.right - box2.left + 1, h: box2.bottom - box2.top + 1]];
IF box3.top < box3.bottom AND box3.left < box3.right THEN b3↑ ← [
place: [x: box3.left, y: box3.top],
dims: [w: box3.right - box3.left + 1, h: box3.bottom - box3.top + 1]]};
FillArcBoxes: PUBLIC PROC [
b1, b2, b3: Window.BoxHandle, startPlace, stopPlace, centerPlace:
Window.Place, screenRadius, top, bottom: INTEGER] = {
left: INTEGER = centerPlace.x - screenRadius - 1;
right: INTEGER = centerPlace.x + screenRadius + 1;
sum: CARDINAL ← (SELECT TRUE FROM
startPlace.x < centerPlace.x => 0,
startPlace.x = centerPlace.x AND startPlace.y > centerPlace.y => 1,
startPlace.x = centerPlace.x AND startPlace.y < centerPlace.y => 2,
ENDCASE => 3) +
(SELECT TRUE FROM
stopPlace.x < centerPlace.x => 0,
stopPlace.x = centerPlace.x AND stopPlace.y > centerPlace.y => 4,
stopPlace.x = centerPlace.x AND stopPlace.y < centerPlace.y => 8,
ENDCASE => 12);
IF startPlace.y > stopPlace.y THEN sum ← sum + 16;
SELECT sum FROM
0, 2, 4, 6 => b1↑ ← [place: [x: left, y: startPlace.y],
dims: [w: centerPlace.x - left + 1, h: stopPlace.y - startPlace.y + 1]];
11, 13, 25, 27, 29, 31 => b1↑ ← [place: [x: centerPlace.x, y:stopPlace.y],
dims: [w: right - centerPlace.x + 1, h:startPlace.y - stopPlace.y + 1]]; 8, 10, 12, 14, 24, 28 => {
b1↑ ← [place: [x: left, y: startPlace.y],
dims: [w: centerPlace.x - left + 1, h: bottom - startPlace.y + 1]];
b2↑ ← [place: [x: centerPlace.x, y: stopPlace.y],
dims: [w: right - centerPlace.x + 1, h: bottom - stopPlace.y + 1]]};
1, 3, 5, 7, 17, 19 => {
b1↑ ← [place: [x: left, y: top],
dims: [w: centerPlace.x - left + 1, h: stopPlace.y - top + 1]];
b2↑ ← [place: [x: centerPlace.x, y: top],
dims: [w: right - centerPlace.x + 1, h: startPlace.y - top + 1]]};
15 => {
b1↑ ← [place: [x: left, y: top],
dims: [w: centerPlace.x - left + 1, h: bottom - top + 1]];
b2↑ ← [place: [x: centerPlace.x, y: top],
dims: [w: right - centerPlace.x + 1, h: startPlace.y - top + 1]];
b3↑ ← [place: [x: centerPlace.x, y: stopPlace.y],
dims: [w: right - centerPlace.x + 1, h: bottom - stopPlace.y + 1]]};
16 => {
b1↑ ← [place: [x: centerPlace.x, y: top],
dims: [w: right - centerPlace.x + 1, h: bottom - top + 1]];
b2↑ ← [place: [x: left, y: startPlace.y],
dims: [w: centerPlace.x - left + 1, h: bottom - startPlace.y + 1]];
b3↑ ← [place: [x: left, y: top],
dims: [w: centerPlace.x - left + 1, h: stopPlace.y - top + 1]]};
ENDCASE => {
DisplayOps.LogError[];
RETURN};
IF b1↑ # Window.nullBox AND b1.dims.h = 1 AND
(b2↑ # Window.nullBox OR b3↑ # Window.nullBox) THEN
b1↑ ← Window.nullBox;
IF b2↑ # Window.nullBox AND b2.dims.h = 1 AND
(b1↑ # Window.nullBox OR b3↑ # Window.nullBox) THEN
b2↑ ← Window.nullBox;
IF b3↑ # Window.nullBox AND b3↑.dims.h = 1 AND
(b1↑ # Window.nullBox OR b2↑ # Window.nullBox) THEN
b3↑ ← Window.nullBox};
END.