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
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
|