📄 lin07.c
字号:
/*************************************************************************/
/* */
/* Copyright (c) 1997 - 1999 Accelerated Technology, Inc. */
/* */
/* PROPRIETARY RIGHTS of Accelerated Technology are involved in the */
/* subject matter of this material. All manufacturing, reproduction, */
/* use, and sales rights pertaining to this subject matter are governed */
/* by the license agreement. The recipient of this software implicitly */
/* accepts the terms of the license. */
/* */
/*************************************************************************/
/*************************************************************************/
/* */
/* FILE NAME VERSION */
/* */
/* LIN07.C 1.9 */
/* */
/* COMPONENT */
/* */
/* All */
/* */
/* DESCRIPTION */
/* */
/* This file contains the mwLIT and mwLID functions. */
/* */
/* AUTHOR */
/* */
/* Giac Dinh, Accelerated Technology, Inc. */
/* */
/* DATA STRUCTURES */
/* */
/* None */
/* */
/* FUNCTIONS */
/* */
/* None */
/* */
/* DEPENDENCIES */
/* */
/* None */
/* */
/* HISTORY */
/* */
/* NAME DATE REMARKS */
/* */
/* BobB 2/18/99 Corrected lsSkipStat type */
/* BobB 3/10/99 Corrected dashed count */
/* BobB 4/23/99 Corrected dashed line rect count */
/* */
/*************************************************************************/
#include "meta_wnd.h"
#include "metconst.h" /* MetaWINDOW Constant & Stucture Definitions */
#include "metports.h" /* MetaWINDOW Port & Bitmap Definitions */
#include "grafdata.h"
#include "metmacs3.h"
#include "lines.h"
/* LIN07 is a special-case optimization for patterned and dashed thin and square
pen line drawing to all types of bitmaps.
Note: Dashed lines get the patterns and dashing info from the current port,
rather than from the blitRcd. This module isn't a primitive, so it can
actually get any info it wants from the current port. (This is necessary for
the background pattern, at least, because there is no such blitRcd field.)
Therefore, the blitRcd passed in must agree with the port's default blitRcd,
or unexpected results may occur (like the first fg double-dash being in the
blitRcd's pen color, and the rest of the fg double-dashes being in the
current port's pen color).
Note: Clipped dashed lines could be drawn much faster with high-level
clipping than with the current low-level pixel-by-pixel clipping; even
unclipped lines would be faster. However, this requires bottom->top clip
handling and jumping dashes ahead to the clip, neither of which is trivial.
*/
struct _lineState lineState;
dashPoly dashPoly1;
dashPoly dashPoly2;
blitVect *vListPtr;
void DoCapPoints(rect *rlistPtr, dashPoly *dashPolyPtr, int capStl, int capNd);
void DoubleDash(void);
void HandleWideSq(void);
//void (*optPtr)();
void ProcessDashesSq(rect *rlistPtr, dashPoly *dashPolyPtr);
void ProcessDashes(rect *rlistPtr);
void HandlePattSq(void);
int _mwLLSetup(rect *rlistPtr);
void _mwLL(void);
void mwFC(byte *lclScratchBufferPtr, long lclScratchBufferSize,
point * points, int npoints, int mode,
long lclXAdjust, long lclYAdjust);
void mwLIT(blitRcd *LINEREC)
{
void SetUpCommon(blitRcd *LINEREC);
rect *rlistPtr;
/* BobB 4/23/99 - corrected dashed line rect count */
int lRectCnt;
SetUpCommon(LINEREC);
/* BobB 4/23/99 - corrected dashed line rect count */
lRectCnt = rectCnt;
if((grafPort.pnFlags & pnSizeFlg) != 0)
{
HandlePattSq();
return;
}
lineState.lsMaxRects = MAX_RECTS; /* Buffer size */
/* Main drawing looping */
/* BobB 4/23/99 - corrected dashed line rect count
while(rectCnt-- > 0) */
while(lRectCnt-- > 0)
{
/* Setup the line start for this line */
/* Get draw first and last status */
/* BobB 2/18/99 - corrected lsSkipStat type
lineState.lsSkipStat = (byte) vListPtr->skipStat; */
lineState.lsSkipStat = (signed char) vListPtr->skipStat;
rlistPtr = (rect *) ((long) vListPtr++);
if(_mwLLSetup(rlistPtr)) continue;
do{
_mwLL();
lclblitRec->blitDmap->prFill(lclblitRec);
}while(lineState.lsMajorAxisLengthM1 >= 0);
}
return;
}
/* Handle patterned/solid quare pen wide lines */
void HandlePattSq(void)
{
void DoSquareAsPoly(rect *rlistPtr);
short tem; long check;
rect listRect, *rlistPtr;
/* BobB 4/23/99 - corrected dashed line rect count */
int lRectCnt;
lRectCnt = rectCnt;
halfHeightUp = grafPort.pnSize.Y >> 1;
halfHeightDownRoDn = halfHeightUp;
halfHeightDownRoUp = (grafPort.pnSize.Y + 1) >> 1;
halfHeightDown = halfHeightDownRoUp;
halfWidthLeft = grafPort.pnSize.X >> 1;
halfWidthRightRoDn = halfWidthLeft;
halfWidthRightRoUp = (grafPort.pnSize.X + 1) >> 1;
halfWidthRight = halfWidthRightRoUp;
oddPenSizeFlag = grafPort.pnSize.X | grafPort.pnSize.Y;
lclblitRec->blitCnt = 1; /* Draw one rectangle at at time */
rlistPtr = (rect *) lclblitRec->blitList;
/* Main loop for drawgin solid/patterned square pen line */
/* BobB 4/23/99 - corrected dashed line rect count
while(rectCnt-- > 0) */
while(lRectCnt-- > 0)
{
/* Build a fill record for the square pen wide line and call the
convex polygon filler (or the rectangle filler , for horizontal
and vertical lines) */
/* See if this is a horizontal or vertical line, and use the
rectangle filler if so for maximum speed */
listRect = vListPtr->VectData;
vListPtr++;
if(listRect.Xmin == listRect.Xmax)
goto DoSquareAsRectV;
if(listRect.Ymin != listRect.Ymax)
{
DoSquareAsPoly(&listRect);
continue;
}
if(listRect.Xmin >= listRect.Xmax)
{
tem = listRect.Xmin;
listRect.Xmin = listRect.Xmax;
listRect.Xmax = tem;
}
goto DSARP1;
DoSquareAsRectV:
if(listRect.Ymin >= listRect.Ymax)
{
tem = listRect.Ymin;
listRect.Ymin = listRect.Ymax;
listRect.Ymax = tem;
}
DSARP1:
check = listRect.Xmin - halfWidthLeft;
if(check < -32768) check = -32768;
listRect.Xmin = (short) check;
check = listRect.Xmax + halfWidthRight;
if(check > 0x7FFF) check = 0x7FFF;
listRect.Xmax = (short) check;
check = listRect.Ymin - halfHeightUp;
if(check < -32768) check = -32768;
listRect.Ymin = (short) check;
check = listRect.Ymax + halfHeightDown;
if(check > 0x7FFF) check = 0x7FFF;
listRect.Ymax = (short) check;
*rlistPtr = listRect;
lclblitRec->blitDmap->prFill(lclblitRec);
}
return;
}
/* Not horizontal or vertical, so draw square pen wide line as a poly */
void DoSquareAsPoly(rect *rlistPtr)
{
long tem;
short majorMove,deltaX;
/* Check and swap between min and max coord */
if(rlistPtr->Ymin > rlistPtr->Ymax)
{
tem = rlistPtr->Xmin;
rlistPtr->Xmin = rlistPtr->Xmax;
rlistPtr->Xmax = (short) tem;
tem = rlistPtr->Ymin;
rlistPtr->Ymin = rlistPtr->Ymax;
rlistPtr->Ymax = (short) tem;
}
/* Check for the size if 1x1 */
if(oddPenSizeFlag == 1)
{
deltaX = rlistPtr->Xmin - rlistPtr->Xmax;
if(deltaX < 0) deltaX = -deltaX;
majorMove = deltaX - rlistPtr->Ymax + rlistPtr->Ymin;
if(majorMove >= 0)
{
halfWidthRight = halfWidthRightRoDn;
halfHeightDown = halfHeightDownRoUp;
}
else
{
halfHeightDown = halfHeightDownRoDn;
halfWidthRight = halfWidthRightRoUp;
}
}
/* Set up the vertex list. For odd deminsions, bias the extra pixel down or
to the right, becuase the polygon filler biases in favor of the top and left.
Check for vertices that overflow out of the coordinate systems; such vertices
are simply forced back to the edge of coordinate system. This can distort the
edges of the wide lin; no attempt is make to clip such vertices properly,
they're just make valid so there's no gabarge or crash */
/*
;set all vertices that don't vary
; with line X direction:
;
; 5 0 5 0
; X---X or X---X
; | \ / |
; o \ / o
; 4 \ \ / / 1
; \ \ 1 4 / /
; \ o o /
; \ | | /
; X---X X---X
; 3 2 3 2 */
tem = halfWidthRight + rlistPtr->Xmin;
if(tem > 0x7FFF) tem = 0x7FFF;
/* dashPoly1 is the buffer which points to dashPoly struct */
dashPoly1.FirstVert[0].X = (short) tem;
tem = rlistPtr->Ymin - halfHeightUp;
if(tem < -32768) tem = -32768;
dashPoly1.FirstVert[0].Y = (short) tem; /* Y coord of upper right */
dashPoly1.FirstVert[5].Y = (short) tem; /* Y coordinate upper left */
tem = halfWidthRight + rlistPtr->Xmax;
if(tem > 0x7FFF) tem = 0x7FFF;
dashPoly1.FirstVert[2].X = (short) tem; /* X coord of lower right */
tem = halfHeightDown + rlistPtr->Ymax;
if(tem > 0x7FFF) tem = 0x7FFF;
dashPoly1.FirstVert[2].Y = (short) tem; /* Y coord of lower right */
dashPoly1.FirstVert[3].Y = (short) tem; /* Y coord of lower left */
tem = rlistPtr->Xmax - halfWidthLeft;
if(tem < -32768) tem = -32768;
dashPoly1.FirstVert[3].X = (short) tem; /* X coord of lower left */
tem = rlistPtr->Xmin - halfWidthLeft;
if(tem < -32768) tem = -32768;
dashPoly1.FirstVert[5].X = (short) tem; /* X coord of upper left */
if(rlistPtr->Xmin > rlistPtr->Xmax)
{/* ;goes left; set vertices for:
;
; 5 0
; o---o
; / |
; / X
; / / 1
; 4 / /
; X /
; | /
; o---o
; 3 2 */
dashPoly1.FirstVert[1].X = dashPoly1.FirstVert[0].X;
dashPoly1.FirstVert[4].X = dashPoly1.FirstVert[3].X;
tem = rlistPtr->Ymin + halfHeightDown;
if(tem > 0x7FFF) tem = 0x7FFF; /* Force to larget valid value */
dashPoly1.FirstVert[1].Y = (short) tem;
tem = rlistPtr->Ymax - halfHeightUp;
if(tem < -32768) tem = -32768;
dashPoly1.FirstVert[4].Y = (short) tem;
}
else
{/* ;goes right; set vertices for:
;
; 5 0
; o---o
; | \
; X \
; 4 \ \
; \ \ 1
; \ X
; \ |
; o---o
; 3 2 */
dashPoly1.FirstVert[4].X = (short) tem; /* X coord of middle left */
dashPoly1.FirstVert[1].X = dashPoly1.FirstVert[2].X;
tem = rlistPtr->Ymax - halfHeightUp;
if(tem < -32768) tem = -32768; /* Force to smallest valid value */
dashPoly1.FirstVert[1].Y = (short) tem; /* Y coord of middle right */
tem = rlistPtr->Ymin + halfHeightDown;
if(tem > 0x7FFF) tem = 0x7FFF; /* Force to largest valid value */
dashPoly1.FirstVert[4].Y = (short) tem;
}
tem = MAX_RECTS*sizeof(rect) + sizeof(blitRcd);
mwFC((unsigned char *)lclblitRec,tem,dashPoly1.FirstVert,6,coordModeOrigin,0,0);
return;
}
/*======================================================================
Sets up the drawing parameters for the specified line.
Expects dest rect to be in (AE, BE) (start point) and (CE, DE) (end point).
This routine performs skipLast by cutting the length and skipFirst by
advancing the Bresenham's variables by one point, and will reject the line
if zero points are left after skipping. The calling routine need not worry
about skipFirst/skipLast, and in fact should pay no attention to
lsSkipStat after the clipping call, because all skipping will already have
been performed.
This routine returns Carry set if the line is not visible at all and
therefore cannot be drawn. Otherwise, it sets the lsDXmin, lsDYmin,
initial lsErrTerm, lsMajorAxisLengthM1, lsLineDir, lsErrTermAdjUp, and
lsErrTermAdjDown variables appropriately for the line.
Line directions here are different from in general line drawing, because
horizontal, vertical, and diagonal lines aren't special-cased, and because
lines aren't forced to top->bottom (I'd like to force them to be top->
bottom, but if they were, dashes wouldn't flow properly). lsLineDir
settings are:
0 = r->l, t->b Ymajor
1 = l->r, t->b Ymajor
2 = l->r, t->b Xmajor
3 = r->l, t->b Xmajor
4 = r->l, b->t Ymajor
5 = l->r, b->t Ymajor
6 = l->r, b->t Xmajor
7 = r->l, b->t Xmajor
*/
int _mwLLSetup(rect *rlistPtr)
{
void nuGrafErr(short);
short grafErrValue;
short tem = 0;
long check,deltaX,deltaY,temdelta;
lineState.lsDXmin = rlistPtr->Xmin;
lineState.lsDXmax = rlistPtr->Xmax;
lineState.lsDYmin = rlistPtr->Ymin;
lineState.lsDYmax = rlistPtr->Ymax;
deltaX = rlistPtr->Xmax - rlistPtr->Xmin;
deltaY = rlistPtr->Ymax - rlistPtr->Ymin;
if((deltaX > 0x7FFF || deltaX < -32768) ||
(deltaY > 0x7FFF || deltaY < -32768))
{
grafErrValue = c_LineTo + c_OfloLine;
nuGrafErr(grafErrValue);
return(1);
}
if(deltaX < 0)
goto RToL;
if(deltaY < 0)
goto LToRBToT;
if(deltaX < deltaY)
{
lineState.lsLineDir = 1;
temdelta = deltaX;
deltaX = deltaY;
deltaY = temdelta;
goto SetInitialVars;
}
lineState.lsLineDir = 2; /* 2*SIZEOFF */
goto SetInitialVars;
RToL:
deltaX = -deltaX;
if(deltaY < 0)
goto RToLBToT;
if(deltaX < deltaY)
{
lineState.lsLineDir = 0;
temdelta = deltaX;
deltaX = deltaY;
deltaY = temdelta;
goto SetInitialVars;
}
lineState.lsLineDir = 3;
goto SetInitialVars;
RToLBToT:
tem++;
deltaY = -deltaY;
if(deltaX < deltaY)
goto RToLBToTYMajor;
lineState.lsLineDir = 7;
goto SetInitialVars;
LToRBToT:
rlistPtr++;
deltaY = -deltaY;
if(deltaX < deltaY)
goto LToRBToTYMajor;
lineState.lsLineDir = 6;
goto SetInitialVars;
LToRBToTYMajor:
lineState.lsLineDir = 5;
temdelta = deltaX;
deltaX = deltaY;
deltaY = temdelta;
goto SetInitialVars;
RToLBToTYMajor:
lineState.lsLineDir = 4;
temdelta = deltaX;
deltaX = deltaY;
deltaY = temdelta;
/* Enter here to se tup inital line-drawing variable */
SetInitialVars:
lineState.lsMajorAxisLengthM1 = (short) deltaX;
lineState.lsErrTermAdjDown = (short) (deltaX << 1);
deltaX = -deltaX;
deltaX -= tem;
lineState.lsErrTerm = (short) deltaX;
lineState.lsErrTermAdjUp = (short) (deltaY << 1);
/* Finally, do first/last skipping, as needed */
if(lineState.lsSkipStat < 0)
{
switch(lineState.lsLineDir)
{
/* r->l, t->b Ymajor */
case 0:
check = lineState.lsErrTerm + lineState.lsErrTermAdjUp;
lineState.lsErrTerm = (short) check;
if(check > 0x7FFF)
{
lineState.lsDXmin--;
lineState.lsErrTerm -= lineState.lsErrTermAdjDown;
}
lineState.lsDYmin++;
lineState.lsMajorAxisLengthM1--;
break;
/* l->r, t->b Ymajor */
case 1:
lineState.lsDYmin++;
check = lineState.lsErrTerm + lineState.lsErrTermAdjUp;
lineState.lsErrTerm = (short) check;
if(check > 0x7FFF)
{
lineState.lsDXmin++;
lineState.lsErrTerm -= lineState.lsErrTermAdjDown;
}
lineState.lsMajorAxisLengthM1--;
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -