📄 line.c
字号:
//
// Permedia3 Sample Display Driver
// line.c
//
// Copyright (c) 2000 Microsoft Corporation. All rights reserved.
//
// This file contains the GDI entry points for drawing lines, or unfilled
// shapes given as a set of edges. It currently does not hardware accelerate
// this operation, rather, it relies on the software graphics library's
// SoftwareLine routine.
#include "pch.h" // Precompiled header support.
#include "debug.h"
#include "struct.h"
#include "proto.h"
// This is a dumb little helper macro.
#define Swap(a,b) \
{ \
(a) = (a) ^ (b); \
(b) = (a) ^ (b); \
(a) = (a) ^ (b); \
}
// These constants are used as flags for storing line information.
#define FL_H_ROUND_DOWN 0x00000080 // .... .... 1... ....
#define FL_V_ROUND_DOWN 0x00008000 // 1... .... .... ....
#define FL_FLIP_D 0x00000005 // .... .... .... .1.1
#define FL_FLIP_V 0x00000008 // .... .... .... 1...
#define FL_FLIP_SLOPE_ONE 0x00000010 // .... .... ...1 ....
#define FL_FLIP_HALF 0x00000002 // .... .... .... ..1.
#define FL_FLIP_H 0x00000200 // .... ..1. .... ....
#define FL_ROUND_MASK 0x0000001C // .... .... ...1 11..
#define FL_ROUND_SHIFT 2
#define FL_RECTLCLIP_MASK 0x0000000C // .... .... .... 11..
#define FL_RECTLCLIP_SHIFT 2
#define FL_STRIP_MASK 0x00000003 // .... .... .... ..11
#define FL_STRIP_SHIFT 0
#define FL_SIMPLE_CLIP 0x00000020 // .... .... ..1. ....
#define FL_COMPLEX_CLIP 0x00000040 // .... .... .1.. ....
#define FL_CLIP (FL_SIMPLE_CLIP | FL_COMPLEX_CLIP)
#define FL_STYLED 0x00000400 // .... .1.. .... ....
#define FL_ALTERNATESTYLED 0x00001000 // ...1 .... .... ....
#define FL_STYLE_MASK 0x00000400
#define FL_STYLE_SHIFT 10
#define FL_LAST_PEL_INCLUSIVE 0x00002000 // ..1. .... .... ....
const ULONG RoundLookup[] = {
FL_H_ROUND_DOWN | FL_V_ROUND_DOWN, // no flips
FL_H_ROUND_DOWN | FL_V_ROUND_DOWN, // FL_FLIP_D
FL_H_ROUND_DOWN, // FL_FLIP_V
FL_V_ROUND_DOWN, // FL_FLIP_V | FL_FLIP_D
FL_V_ROUND_DOWN, // FL_FLIP_SLOPE_ONE
0xbaadf00d, // FL_FLIP_SLOPE_ONE | FL_FLIP_D
FL_H_ROUND_DOWN, // FL_FLIP_SLOPE_ONE | FL_FLIP_V
0xbaadf00d // FL_FLIP_SLOPE_ONE | FL_FLIP_V | FL_FLIP_D
};
BOOL
DrvStrokePath(
SURFOBJ * DestSurface,
PATHOBJ * Path,
CLIPOBJ * Clipper,
XFORMOBJ * Xform,
BRUSHOBJ * Brush,
POINTL * BrushOrigin,
LINEATTRS * Attributes,
MIX Mix
)
{
// DrvStrokePath
// This function is called by GDI when it needs to draw the outline of a
// geometric shape, defined by a list of edges. ("Stroke a path" in GDI's
// parlance.)
// Local variables.
BOOL FnRetVal = TRUE;
LINE_PARAM Parameters;
PERM3_SURFACE Dest;
LONG DashNum;
LONG DashPixel;
LONG BitNum;
LONG BitVal;
RECT * ClipRect;
BOOL MoreClipRects;
ENUMRECTS ClipEnum;
RECT OreintedClipRect[8];
RECT * CurOreintedClipRect;
BOOL MorePathData;
PATHDATA PathData;
ULONG Point;
ULONG PointCount;
POINTFIX StartPoint;
POINTFIX LastPoint;
POINTFIX * PreviousPoint;
POINTFIX * CurrentPoint;
ULONG x, y;
FIX x1, y1, x2, y2;
FIX M1, M2;
FIX N1, N2;
FIX dN, dM;
ULONG Flags;
LONG Gamma;
LONG Beta;
LONG Left, Right, Top, Bottom;
LONG ErrorTerm;
LONG StylePixels;
LONG xStart, yStart;
LONG Direction;
LONG PixelCount;
// Check parameters.
// !TODO!
Enter(L"DrvStrokePath");
Assert(Brush->iSolidColor != 0xFFFFFFFF);
memset(&Parameters, 0, sizeof(LINE_PARAM));
// Fill in all of the line parameters that are constant along the path.
Parameters.FillValue = Brush->iSolidColor;
Parameters.Mix = (USHORT)Mix;
SurfobjToPerm3Surface(&Dest,
DestSurface,
NULL,
FALSE);
Parameters.Destination = (const SURFACE *)&Dest;
// Work out the line style. Windows CE only draws single pixel wide
// lines, hence we do not worry about mitering, endcaps, and joining.
Parameters.Style = 0;
if (Attributes && (((Mix >> 8) & 0x00FF) != (Mix & 0x00FF))) {
if (Attributes->fl & LA_ALTERNATE) {
// Special case style, every other pixel on.
Parameters.Style = 0xAAAAAAAA;
}
else if (Attributes->pstyle != NULL &&
Attributes->cstyle != 0) {
// Use the given style array to work out the style dword for the
// software line rasterizer.
for (DashNum = 0, BitNum = 0, BitVal = 0;
BitNum < 32;
DashNum++) {
DashNum %= Attributes->cstyle;
for (DashPixel = 0;
(DashPixel < Attributes->pstyle[DashNum].l) && (BitNum < 32);
DashPixel++, BitNum++) {
Parameters.Style |= (BitVal << BitNum);
}
BitVal ^= 1;
if (DashNum == 64) {
// All segments have 0 length
Parameters.Style = 0;
break;
}
}
}
if (Attributes->fl & LA_STARTGAP) {
// First dash is actually a gap.
Parameters.Style = ~Parameters.Style;
}
}
// Deal with the line clipping.
if ((Clipper == NULL) || (Clipper->iDComplexity == DC_TRIVIAL)) {
ClipRect = NULL;
MoreClipRects = FALSE;
}
else if (Clipper->iDComplexity == DC_RECT) {
ClipRect = (RECT *)&(Clipper->rclBounds);
MoreClipRects = FALSE;
}
else {
MoreClipRects = TRUE;
}
// Iterate over the clip rectangles. (Just once if no list.)
for (ClipEnum.c = 1 - (MoreClipRects ? 1 : 0);
(ClipEnum.c != 0) || (MoreClipRects);
ClipRect++, ClipEnum.c--) {
if (ClipEnum.c == 0) {
// Get the next rectangle from the clipper.
MoreClipRects = CLIPOBJ_bEnum(Clipper,
sizeof(ClipEnum),
(ULONG *)&ClipEnum);
ClipRect = (RECT *)ClipEnum.arcl;
if (ClipEnum.c == 0) {
continue;
}
}
Parameters.StyleState = 0;
// Now, fill out the OreintedClipRect array by precomputing all
// possible flips and/or rotations.
memcpy(&(OreintedClipRect[0]), ClipRect, sizeof(RECT));
// FL_FLIP_D
OreintedClipRect[1].top = ClipRect->left;
OreintedClipRect[1].left = ClipRect->top;
OreintedClipRect[1].bottom = ClipRect->right;
OreintedClipRect[1].right = ClipRect->bottom;
// FL_FLIP_V
OreintedClipRect[2].top = -ClipRect->bottom + 1;
OreintedClipRect[2].left = ClipRect->left;
OreintedClipRect[2].bottom = -ClipRect->top + 1;
OreintedClipRect[2].right = ClipRect->right;
// FL_FLIP_V | FL_FLIP_D
OreintedClipRect[3].top = ClipRect->left;
OreintedClipRect[3].left = -ClipRect->bottom + 1;
OreintedClipRect[3].bottom = ClipRect->right;
OreintedClipRect[3].right = -ClipRect->top + 1;
// FL_FLIP_H
OreintedClipRect[4].top = ClipRect->top;
OreintedClipRect[4].left = -ClipRect->right + 1;
OreintedClipRect[4].bottom = ClipRect->bottom;
OreintedClipRect[4].right = -ClipRect->left + 1;
// FL_FLIP_H | FL_FLIP_D
OreintedClipRect[5].top = -ClipRect->right + 1;
OreintedClipRect[5].left = ClipRect->top;
OreintedClipRect[5].bottom = -ClipRect->left + 1;
OreintedClipRect[5].right = ClipRect->bottom;
// FL_FLIP_H | FL_FLIP_V
OreintedClipRect[6].top = -ClipRect->bottom + 1;
OreintedClipRect[6].left = -ClipRect->right + 1;
OreintedClipRect[6].bottom = -ClipRect->top + 1;
OreintedClipRect[6].right = -ClipRect->left + 1;
// FL_FLIP_H | FL_FLIP_V | FL_FLIP_D
OreintedClipRect[7].top = -ClipRect->right + 1;
OreintedClipRect[7].left = -ClipRect->bottom + 1;
OreintedClipRect[7].bottom = -ClipRect->left + 1;
OreintedClipRect[7].right = -ClipRect->top + 1;
// Loop through the line segments in the path.
PATHOBJ_vEnumStart(Path);
do {
MorePathData = PATHOBJ_bEnum(Path, &PathData);
PointCount = PathData.count;
if (PointCount == 0) {
break;
}
if (PathData.flags & PD_BEGINSUBPATH) {
StartPoint = *PathData.pptfx;
PreviousPoint = PathData.pptfx;
CurrentPoint = PathData.pptfx + 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -