Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

782 lines
21 KiB

/**************************************************************************\
*
* Copyright (c) 1999-2000 Microsoft Corporation
*
* Module Name:
*
* Output.hpp
*
* Abstract:
*
* Classes to output a span for a particular brush type
*
* Created:
*
* 2/24/1999 DCurtis
*
\**************************************************************************/
#ifndef _OUTPUT_HPP
#define _OUTPUT_HPP
void ApplyWrapMode(INT WrapMode, INT &x, INT &y, INT w, INT h);
//--------------------------------------------------------------------------
// Solid color output
//--------------------------------------------------------------------------
class DpOutputSolidColorSpan : public DpOutputSpan
{
public:
ARGB Argb;
DpScanBuffer * Scan;
public:
DpOutputSolidColorSpan(ARGB argb, DpScanBuffer * scan)
{
Argb = argb;
Scan = scan;
}
GpStatus OutputSpan(
INT y,
INT xMin,
INT xMax
);
virtual BOOL IsValid() const { return TRUE; }
virtual DpScanBuffer* GetScanBuffer(){ return Scan; }
};
//--------------------------------------------------------------------------
// Gradient output base class
//--------------------------------------------------------------------------
class DpOutputGradientSpan : public DpOutputSpan
{
private:
// We now use an ObjectTag to determine if the object is valid
// instead of using a BOOL. This is much more robust and helps
// with debugging. It also enables us to version our objects
// more easily with a version number in the ObjectTag.
ObjectTag Tag; // Keep this as the 1st value in the object!
protected:
VOID SetValid(BOOL valid)
{
Tag = valid ? ObjectTagOutputGradientSpan : ObjectTagInvalid;
}
public:
virtual BOOL IsValid() const
{
ASSERT((Tag == ObjectTagOutputGradientSpan) || (Tag == ObjectTagInvalid));
#if DBG
if (Tag == ObjectTagInvalid)
{
WARNING1("Invalid OutputGradientSpan");
}
#endif
return (Tag == ObjectTagOutputGradientSpan);
}
public:
DpScanBuffer * Scan;
const GpBrush* Brush;
INT BrushType;
INT WrapMode;
INT CompositingMode;
GpRectF BrushRect;
GpMatrix WorldToDevice;
GpMatrix DeviceToWorld;
REAL A[4], R[4], G[4], B[4];
public:
DpOutputGradientSpan() { SetValid (TRUE); }
DpOutputGradientSpan(
const GpElementaryBrush *brush,
DpScanBuffer * scan,
DpContext* context
);
~DpOutputGradientSpan()
{
SetValid(FALSE); // so we don't use a deleted object
}
virtual GpStatus OutputSpan(
INT y,
INT xMin,
INT xMax
);
DpScanBuffer* GetScanBuffer(){ return Scan; }
protected:
VOID InitDefaultColorArrays(const GpElementaryBrush* brush)
{
const GpGradientBrush *gradBrush
= static_cast<const GpGradientBrush*> (brush);
if(gradBrush->UsesDefaultColorArray())
{
GpColor colors[4]; // Default array is up to
// 4 colors.
gradBrush->GetColors(colors);
INT num = gradBrush->GetNumberOfColors();
for(INT i = 0; i < num; i++)
{
ARGB argb = colors[i].GetPremultipliedValue();
A[i] = (REAL)GpColor::GetAlphaARGB(argb);
R[i] = (REAL)GpColor::GetRedARGB(argb);
G[i] = (REAL)GpColor::GetGreenARGB(argb);
B[i] = (REAL)GpColor::GetBlueARGB(argb);
}
}
}
};
//--------------------------------------------------------------------------
// Handle one-dimension gradients (we call 'em 'textures' for reasons that
// should be obvious)
//--------------------------------------------------------------------------
class DpOutputOneDGradientSpan : public DpOutputGradientSpan
{
protected:
INT OneDDataMultiplier;
INT OneDDataCount;
ARGB* OneDData;
BOOL IsHorizontal;
BOOL IsVertical;
public:
DpOutputOneDGradientSpan()
{
Initialize();
}
DpOutputOneDGradientSpan(
const GpElementaryBrush *brush,
DpScanBuffer *scan,
DpContext *context,
BOOL isHorizontal = TRUE,
BOOL isVertical = FALSE
);
~DpOutputOneDGradientSpan();
virtual GpStatus OutputSpan(
INT y,
INT xMin,
INT xMax
);
protected:
VOID Initialize()
{
OneDDataMultiplier = 1;
OneDDataCount = 0;
OneDData = NULL;
IsHorizontal = FALSE;
IsVertical = FALSE;
SetValid(FALSE);
}
GpStatus AllocateOneDData(BOOL isHorizontal,BOOL isVertical);
VOID SetupRectGradientOneDData();
VOID SetupRadialGradientOneDData();
};
//--------------------------------------------------------------------------
// Linear gradients
//--------------------------------------------------------------------------
// The AGRB64TEXEL structure is sort of funky in order to optimize the
// inner loop of our C-code linear gradient routine.
struct AGRB64TEXEL // Note that it's 'AGRB', not 'ARGB'
{
UINT32 A00rr00bb; // Texel's R and B components
UINT32 A00aa00gg; // Texel's A and G components
};
// # of pixels in our 1-D texture:
//#define ONEDMAXIMUMTEXELS 32
#define ONEDMAXIMUMTEXELS 1024
// # of fractional bits that we iterate across the texture with:
#define ONEDNUMFRACTIONALBITS 16
// Get the integer portion of our fixed point texture coordinate, using
// a floor function:
#define ONEDGETINTEGERBITS(x) ((x) >> ONEDNUMFRACTIONALBITS)
// Get the 8-bit fractional portion of our fixed point texture coordinate.
// We could round, but I can't be bothered:
#define ONEDGETFRACTIONAL8BITS(x) ((x) >> ((ONEDNUMFRACTIONALBITS - 8)) & 0xff)
class DpOutputLinearGradientSpan : public DpOutputGradientSpan
{
protected:
GpMatrix DeviceToNormalized; // Transforms from the device-space brush
// parallogram to fixed-point-scaled
// brush texture coordinates
INT32 M11; // Fixed point representation of
// M11 element of DeviceToNormalized
INT32 M21; // Fixed point representation of
// M21 element of DeviceToNormalized
INT32 Dx; // Fixed point representation of
// Dx element of DeviceToNormalized
INT32 XIncrement; // Fixed point increment (in format
// defined by ONEDNUMFRACTIONALBITS)
// representing texture x-distance
// traveled for every x pixel increment
// in device space
UINT32 IntervalMask; // One less than the number of texels in
// our texture
UINT32 NumberOfIntervalBits; // log2 of the number of texels
union
{
ULONGLONG StartTexelArgb[ONEDMAXIMUMTEXELS];
// Array of colors (at 16-bits per channel,
// with zeroes in the significant bytes)
// representing the start color of the
// linear approximation at interval 'x'
// (in A-R-G-B format)
AGRB64TEXEL StartTexelAgrb[ONEDMAXIMUMTEXELS];
// Similarly, but for the non-MMX renderer
// (in A-G-R-B format)
};
union
{
ULONGLONG EndTexelArgb[ONEDMAXIMUMTEXELS];
// End color for the interval (in A-R-G-B
// format)
AGRB64TEXEL EndTexelAgrb[ONEDMAXIMUMTEXELS];
// Similarly, but for the non-MMX renderer
// (in A-G-R-B format)
};
public:
DpOutputLinearGradientSpan(
const GpElementaryBrush *brush,
DpScanBuffer *scan,
DpContext *context
);
virtual GpStatus OutputSpan(
INT y,
INT xMin,
INT xMax
);
};
//--------------------------------------------------------------------------
// Gradient special case - MMX
//--------------------------------------------------------------------------
class DpOutputLinearGradientSpan_MMX : public DpOutputLinearGradientSpan
{
public:
DpOutputLinearGradientSpan_MMX(
const GpElementaryBrush *brush,
DpScanBuffer *scan,
DpContext *context
);
virtual GpStatus OutputSpan(
INT y,
INT xMin,
INT xMax
);
};
//--------------------------------------------------------------------------
// Path gradients
//--------------------------------------------------------------------------
class DpOutputOneDPathGradientSpan : public DpOutputOneDGradientSpan
{
public:
DpOutputOneDPathGradientSpan()
{
BLTransforms = NULL;
Count = 0;
}
~DpOutputOneDPathGradientSpan()
{
if(BLTransforms)
delete[] BLTransforms;
}
DpOutputOneDPathGradientSpan(
const GpElementaryBrush *brush,
DpScanBuffer * scan,
DpContext* context,
BOOL isHorizontal = TRUE,
BOOL isVertical = FALSE
);
virtual GpStatus OutputSpan(
INT y,
INT xMin,
INT xMax
);
protected:
VOID SetupPathGradientOneDData(BOOL gammaCorrect);
protected:
GpBilinearTransform* BLTransforms;
INT Count;
};
class DpTriangleData
{
friend class DpOutputTriangleGradientSpan;
friend class DpOutputPathGradientSpan;
private:
// We now use an ObjectTag to determine if the object is valid
// instead of using a BOOL. This is much more robust and helps
// with debugging. It also enables us to version our objects
// more easily with a version number in the ObjectTag.
ObjectTag Tag; // Keep this as the 1st value in the object!
protected:
VOID SetValid(BOOL valid)
{
Tag = valid ? ObjectTagTriangleData : ObjectTagInvalid;
}
virtual BOOL IsValid() const
{
ASSERT((Tag == ObjectTagTriangleData) || (Tag == ObjectTagInvalid));
#if DBG
if (Tag == ObjectTagInvalid)
{
WARNING1("Invalid TriangleData");
}
#endif
return (Tag == ObjectTagTriangleData);
}
public:
DpTriangleData();
~DpTriangleData()
{
SetValid(FALSE); // so we don't use a deleted object
}
VOID SetTriangle(
GpPointF& pt0,
GpPointF& pt1,
GpPointF& pt2,
GpColor& color0,
GpColor& color1,
GpColor& color2,
BOOL isPolygonMode = FALSE,
BOOL isGammaCorrected = FALSE
);
GpStatus OutputSpan(ARGB* buffer, INT compositingMode,
INT y, INT &xMin, INT &xMax);
private:
BOOL GetXSpan(REAL y, REAL xmin, REAL xmax, REAL* x, GpPointF* s);
BOOL SetXSpan(REAL y, REAL xmin, REAL xmax, REAL* x);
private:
BOOL IsPolygonMode;
BOOL GammaCorrect;
INT Index[3];
REAL X[3];
REAL Y[3];
GpFColor128 Color[3];
REAL Falloff0;
REAL Falloff1;
REAL Falloff2;
INT BlendCount0;
INT BlendCount1;
INT BlendCount2;
REAL* BlendFactors0;
REAL* BlendFactors1;
REAL* BlendFactors2;
REAL* BlendPositions0;
REAL* BlendPositions1;
REAL* BlendPositions2;
ARGB* PresetColors;
BOOL UsesPresetColors;
REAL Xmin, Xmax;
REAL M[3]; // dx/dy
REAL DeltaY[3]; // Inverse of dy.
PointF STGradient[2]; // Cached starting and ending fractional values of
// the color gradients for the current XSpan
REAL XSpan[2]; // Cached X range covered by this triangle for
// the current value of Y being output
};
//--------------------------------------------------------------------------
// Triangle Gradients
//--------------------------------------------------------------------------
class DpOutputTriangleGradientSpan : public DpOutputGradientSpan
{
public:
DpOutputTriangleGradientSpan() {}
DpOutputTriangleGradientSpan(
const GpElementaryBrush *brush,
DpScanBuffer * scan,
DpContext* context
);
virtual GpStatus OutputSpan(
INT y,
INT xMin,
INT xMax
);
DpScanBuffer* GetScanBuffer(){ return Scan; }
private:
DpTriangleData Triangle;
};
//--------------------------------------------------------------------------
// Path Gradients
//--------------------------------------------------------------------------
class DpOutputPathGradientSpan : public DpOutputGradientSpan
{
public:
INT Count;
DpTriangleData** Triangles;
public:
DpOutputPathGradientSpan()
{
Count = 0;
Triangles = NULL;
SetValid(FALSE);
}
DpOutputPathGradientSpan(
const GpElementaryBrush *brush,
DpScanBuffer * scan,
DpContext* context
);
virtual ~DpOutputPathGradientSpan();
virtual GpStatus OutputSpan(
INT y,
INT xMin,
INT xMax
);
DpScanBuffer* GetScanBuffer(){ return Scan; }
protected:
VOID FreeData();
};
//--------------------------------------------------------------------------
// Textures
//--------------------------------------------------------------------------
class DpOutputBilinearSpan : public DpOutputSpan
{
protected:
const GpBitmap *Bitmap;
const DpBitmap *dBitmap;
BitmapData BmpData;
DpScanBuffer *Scan;
WrapMode BilinearWrapMode;
ARGB ClampColor;
BOOL SrcRectClamp;
GpRectF SrcRect;
GpMatrix WorldToDevice;
GpMatrix DeviceToWorld;
public:
DpOutputBilinearSpan(
const GpTexture *textureBrush,
DpScanBuffer *scan,
GpMatrix *worldToDevice,
DpContext *context
);
DpOutputBilinearSpan(
const DpBitmap *bitmap,
DpScanBuffer *scan,
GpMatrix *worldToDevice,
DpContext *context,
DpImageAttributes *imageAttributes
);
DpOutputBilinearSpan(
DpBitmap* bitmap,
DpScanBuffer * scan,
DpContext* context,
DpImageAttributes imageAttributes,
INT numPoints,
const GpPointF *dstPoints,
const GpRectF *srcRect
);
virtual ~DpOutputBilinearSpan();
virtual GpStatus OutputSpan(
INT y,
INT xMin,
INT xMax
);
virtual BOOL IsValid() const
{
return ((dBitmap != NULL) || (Bitmap != NULL));
}
DpScanBuffer* GetScanBuffer()
{
return Scan;
}
};
//--------------------------------------------------------------------------
// Textures - MMX
//
// The MMX code uses the same setup as the non-MMX, hence the reason
// we're derived from it.
//--------------------------------------------------------------------------
class DpOutputBilinearSpan_MMX : public DpOutputBilinearSpan
{
protected:
BOOL TranslateMatrixValid; // TRUE if Dx, and Dy are valid
BOOL ScaleMatrixValid; // TRUE if M11-M22 are valid
INT M11; // 16.16 fixed point representation of the
INT M12; // device-to-world transform
INT M21;
INT M22;
INT Dx;
INT Dy;
INT UIncrement; // Increment in texture space for every one-
INT VIncrement; // pixel-to-the-right in device space
INT ModulusWidth; // Modulus value for doing tiling
INT ModulusHeight;
INT XEdgeIncrement; // Edge condition increments.
INT YEdgeIncrement;
public:
VOID InitializeFixedPointState();
DpOutputBilinearSpan_MMX(
const GpTexture *textureBrush,
DpScanBuffer *scan,
GpMatrix *worldToDevice,
DpContext *context
) : DpOutputBilinearSpan(textureBrush, scan, worldToDevice, context)
{
InitializeFixedPointState();
}
DpOutputBilinearSpan_MMX(
const DpBitmap *bitmap,
DpScanBuffer *scan,
GpMatrix *worldToDevice,
DpContext *context,
DpImageAttributes *imageAttributes
) : DpOutputBilinearSpan(
bitmap,
scan,
worldToDevice,
context,
imageAttributes
)
{
InitializeFixedPointState();
}
virtual GpStatus OutputSpan(
INT y,
INT xMin,
INT xMax
);
virtual BOOL IsValid() const
{
return (ScaleMatrixValid && DpOutputBilinearSpan::IsValid());
}
};
//--------------------------------------------------------------------------
// Textures - Identity transform
//
// Actually, this object handles texture output for any translating
// transform, so long as the translate is integer.
//
//--------------------------------------------------------------------------
class DpOutputBilinearSpan_Identity : public DpOutputBilinearSpan
{
protected:
INT Dx;
INT Dy;
BOOL PowerOfTwo; // True if both texture dimensions power of two
public:
DpOutputBilinearSpan_Identity(
const GpTexture *textureBrush,
DpScanBuffer * scan,
GpMatrix *worldToDevice,
DpContext *context
) : DpOutputBilinearSpan(textureBrush, scan, worldToDevice, context)
{
PowerOfTwo = !(BmpData.Width & (BmpData.Width - 1)) &&
!(BmpData.Height & (BmpData.Height - 1));
// Compute the device-to-world transform (easy, eh?):
Dx = -GpRound(worldToDevice->GetDx());
Dy = -GpRound(worldToDevice->GetDy());
}
DpOutputBilinearSpan_Identity(
const DpBitmap *bitmap,
DpScanBuffer * scan,
GpMatrix *worldToDevice,
DpContext *context,
DpImageAttributes *imageAttributes
) : DpOutputBilinearSpan(
bitmap,
scan,
worldToDevice,
context,
imageAttributes
)
{
PowerOfTwo = !(BmpData.Width & (BmpData.Width - 1)) &&
!(BmpData.Height & (BmpData.Height - 1));
// Compute the device-to-world transform (easy, eh?):
Dx = -GpRound(worldToDevice->GetDx());
Dy = -GpRound(worldToDevice->GetDy());
}
virtual GpStatus OutputSpan(
INT y,
INT xMin,
INT xMax
);
};
//--------------------------------------------------------------------------
// Hatch brushes
//--------------------------------------------------------------------------
class DpOutputHatchSpan : public DpOutputSpan
{
public:
DpScanBuffer * Scan;
ARGB ForeARGB;
ARGB BackARGB;
ARGB AverageARGB;
BYTE Data[8][8];
protected:
INT m_BrushOriginX;
INT m_BrushOriginY;
public:
DpOutputHatchSpan(
const GpHatch *hatchBrush,
DpScanBuffer * scan,
DpContext* context
);
virtual ~DpOutputHatchSpan()
{
}
virtual GpStatus OutputSpan(
INT y,
INT xMin,
INT xMax
);
virtual BOOL IsValid() const { return TRUE; }
DpScanBuffer* GetScanBuffer(){ return Scan; }
};
class DpOutputStretchedHatchSpan : public DpOutputHatchSpan
{
public:
DpOutputStretchedHatchSpan(
const GpHatch *hatchBrush,
DpScanBuffer * scan,
DpContext* context,
INT scaleFactor
) : DpOutputHatchSpan(hatchBrush,
scan,
context)
{
ScaleFactor = scaleFactor;
}
virtual GpStatus OutputSpan(
INT y,
INT xMin,
INT xMax
);
private:
INT ScaleFactor;
};
#endif // _OUTPUT_HPP