|
|
/**************************************************************************\
* * Copyright (c) 1998 Microsoft Corporation * * Abstract: * * Implementation of GpBrush class * * Revision History: * * 12/09/1998 davidx * Flesh out brush interfaces. * * 12/08/1998 andrewgo * Initial placeholders. * \**************************************************************************/
#include "precomp.hpp"
// For GetData and SetData methods
#define GDIP_BRUSHFLAGS_PATH 0x00000001
#define GDIP_BRUSHFLAGS_TRANSFORM 0x00000002
#define GDIP_BRUSHFLAGS_PRESETCOLORS 0x00000004
#define GDIP_BRUSHFLAGS_BLENDFACTORS 0x00000008
#define GDIP_BRUSHFLAGS_BLENDFACTORSH GDIP_BRUSHFLAGS_BLENDFACTORS
#define GDIP_BRUSHFLAGS_BLENDFACTORSV 0x00000010
#define GDIP_BRUSHFLAGS_BLENDFACTORS0 GDIP_BRUSHFLAGS_BLENDFACTORSH
#define GDIP_BRUSHFLAGS_BLENDFACTORS1 GDIP_BRUSHFLAGS_BLENDFACTORSV
#define GDIP_BRUSHFLAGS_BLENDFACTORS2 0x00000020
#define GDIP_BRUSHFLAGS_FOCUSSCALES 0x00000040
#define GDIP_BRUSHFLAGS_ISGAMMACORRECTED 0x00000080
// Defined in path.cpp
extern BOOL IsRectanglePoints( const GpPointF* points, INT count, const GpMatrix * matrix, GpRectF * transformedBounds );
GpStatus GpElementaryBrush::MultiplyTransform(const GpMatrix& matrix, GpMatrixOrder order) { GpStatus status = Ok;
if (matrix.IsInvertible()) { if (order == MatrixOrderPrepend) { DeviceBrush.Xform.Prepend(matrix); } else { DeviceBrush.Xform.Append(matrix); } UpdateUid(); } else status = InvalidParameter;
return status; }
/**************************************************************************\
* * Function Description: * * Calculate the brush transform from a starting point and two directions. * * Arguments: * * [OUT] m - matrix coefficients * [OUT] width - width (the length of dP1) * [OUT] height - height (the length of dP2) * [IN] p0 - the starting point of the brush. * [IN] dP1 - the vector to represent the transformed x-direction. * [IN] dP2 - the vector to represent the transformed y-direction. * * Return Vaule: * * TRUE if the transform matrix is non-degenerate. * Otherwise returns FALSE. * * History: * * 06/03/1999 ikkof * Created it. * \**************************************************************************/
BOOL getLineGradientTransform( REAL* m, REAL* width, REAL* height, const GpPointF& p0, const GpPointF& dP1, const GpPointF& dP2 ) { // Make sure the flat API has correctly set the FPU.
FPUStateSaver::AssertMode();
REAL l1 = dP1.X*dP1.X + dP1.Y*dP1.Y; REAL l2 = dP2.X*dP2.X + dP2.Y*dP2.Y; REAL test = dP1.X*dP2.Y - dP1.Y*dP2.X;
if(l1 == 0 || l2 == 0 || test == 0) return FALSE;
l1 = REALSQRT(l1); l2 = REALSQRT(l2); m[0] = TOREAL(dP1.X/l1); // M11
m[1] = TOREAL(dP1.Y/l1); // M12
m[2] = TOREAL(dP2.X/l2); // M21
m[3] = TOREAL(dP2.Y/l2); // M22
m[4] = TOREAL(p0.X - p0.X*m[0] - p0.Y*m[2]); // Dx
m[5] = TOREAL(p0.Y - p0.X*m[1] - p0.Y*m[3]); // Dy
*width = l1; *height = l2;
return TRUE; }
static GpStatus LinearGradientRectFromPoints( const GpPointF& point1, const GpPointF& point2, GpRectF & rect ) { // If the API specifies two coincident points, we
// can't get information for the gradient, so we
// fail the construction here.
if( IsClosePointF(point1, point2) ) { return InvalidParameter; }
// Compute the bounding rectangle of the two input points.
rect.X = min(point1.X, point2.X); rect.Y = min(point1.Y, point2.Y); rect.Width = REALABS(point1.X-point2.X); rect.Height = REALABS(point1.Y-point2.Y);
// eliminate degenerate rectangles when the two
// input points form a horizontal or vertical line.
// This is a very odd way of coercing a 1d linear gradient
// into a rect gradient and avoiding later matrix computation error
// when we try get an affine warp between this rectangle and a
// reference rectangle.
if( IsCloseReal(point1.X, point2.X) ) { rect.X -= rect.Height/2; rect.Width = rect.Height; }
if( IsCloseReal(point1.Y, point2.Y) ) { rect.Y -= rect.Width/2; rect.Height = rect.Width; } return Ok; }
static GpStatus CalcLinearGradientXform( REAL angle, BOOL isAngleScalable, const GpRectF& rect, GpMatrix& xform ) { GpPointF p0, dP1, dP2;
angle = GpModF(angle, 360);
INT zone; REALD deltaTheta; const REALD degreeToRadian = 3.1415926535897932/180;
if(angle < 90) { zone = 0; deltaTheta = angle; } else if(angle < 180) { zone = 1; deltaTheta = 180 - angle; } else if(angle < 270) { zone = 2; deltaTheta = angle - 180; } else { zone = 3; deltaTheta = 360 - angle; }
REALD s, c;
deltaTheta *= degreeToRadian;
s = sin(deltaTheta); c = cos(deltaTheta);
// d0 is the distance between p0 and the starting corner of the
// original rectangle.
// d1 and d2 is the length of dP1 and dP2, respectively.
REALD top, left, w, h, d0, d1, d2; REALD x0, y0; // Starting corner of the original rectangle.
GpPointD norm; // Direction of dP1.
// Direction of dP2 = (-norm.Y, norm.X) which is 90 degree rotation
// of dP1.
if(!isAngleScalable) { left = rect.X; top = rect.Y; w = rect.Width; h = rect.Height; } else { // Scale to (0, 0, 1, 1) rectangle.
top = 0.0; left = 0.0; w = 1.0; h = 1.0; }
switch(zone) { case 0: d0 = w*s; norm.X = c; norm.Y = s;
x0 = left; y0 = top; break;
case 1: d0 = h*c; norm.X = - c; norm.Y = s;
x0 = left + w; y0 = top; break;
case 2: d0 = w*s; norm.X = - c; norm.Y = - s;
x0 = left + w; y0 = top + h; break;
case 3: d0 = h*c; norm.X = c; norm.Y = - s;
x0 = left; y0 = top + h; break; }
d2 = w*s + h*c; d1 = w*c + h*s; p0.X = TOREAL(x0 + d0*norm.Y); p0.Y = TOREAL(y0 - d0*norm.X); dP1.X = TOREAL(d1*norm.X); dP1.Y = TOREAL(d1*norm.Y); dP2.X = TOREAL(- d2*norm.Y); dP2.Y = TOREAL(d2*norm.X);
if(isAngleScalable) { // Scale back.
p0.X = rect.Width*p0.X + rect.X; p0.Y = rect.Height*p0.Y + rect.Y;
dP1.X *= rect.Width; dP1.Y *= rect.Height; dP2.X *= rect.Width; dP2.Y *= rect.Height; }
// Set up the transform.
GpPointF points[3];
points[0] = p0; points[1].X = p0.X + dP1.X; points[1].Y = p0.Y + dP1.Y; points[2].X = p0.X + dP2.X; points[2].Y = p0.Y + dP2.Y;
GpStatus status;
if(xform.InferAffineMatrix(&points[0], rect) == Ok) { return Ok; } return InvalidParameter; }
GpStatus GpLineGradient::ChangeLinePoints( const GpPointF& point1, const GpPointF& point2, BOOL isAngleScalable ) { GpStatus status; GpRectF rect; if ((status = LinearGradientRectFromPoints(point1, point2, rect)) != Ok) { return status; }
REAL angle = GetAngleFromPoints(point1, point2); GpMatrix xform;
if ((status = CalcLinearGradientXform(angle, isAngleScalable, rect, xform)) == Ok) { DeviceBrush.Xform = xform; DeviceBrush.Rect = rect; DeviceBrush.IsAngleScalable = isAngleScalable; DeviceBrush.Points[0] = point1; DeviceBrush.Points[1] = point2; return Ok; } return status; }
GpLineGradient::GpLineGradient( const GpPointF& point1, const GpPointF& point2, const GpColor& color1, const GpColor& color2, GpWrapMode wrapMode ) { // Make sure the flat API has correctly set the FPU.
FPUStateSaver::AssertMode();
REAL angle; GpRectF rect;
if (LinearGradientRectFromPoints(point1, point2, rect) != Ok) { SetValid(FALSE); return; }
// Compute the angle of the line formed by point1 and point2.
// Note atan2 is only undefined if dP.Y == 0.0 and dP.X == 0.0
// and then it returns 0 radians. We take care of that case separately
// (above).
// Also, atan2 correctly computes the quadrant from the two input points.
GpPointF dP = point2 - point1; double rad = atan2((double)(dP.Y), (double)(dP.X));
SetLineGradient( point1, point2, rect, color1, color2,
// why aren't we working in radians???
(REAL)(rad*180.0/3.1415926535897932), FALSE, wrapMode ); }
/**************************************************************************\
* * Function Description: * * Creates a LineGradient which is defined by the rectangle. * * Arguments: * * [IN] rect - the rectangle to define this gradient. * [IN] color1 - the color of the start point. * [IN] color2 - the color of the end point. * [IN] mode - the line gradient mode * [IN] wrapMode - the wrap mode of this brush. * * The start and end points of this gradient is defined as follows * according to the line gradient mode: * * mode start point end point * ------------------------------------------------------------- * LineGradientHorizontal top-left top-right * LineGradientVertical top-right bottom-right * LineGradientForwardDiagonal top-left bottom-right * LineGradientBackwardDiagonal bottom-left top-right * * * History: * * 06/03/1999 ikkof * Created it. * \**************************************************************************/
GpLineGradient::GpLineGradient( const GpRectF& rect, const GpColor& color1, const GpColor& color2, LinearGradientMode mode, GpWrapMode wrapMode ) { // Make sure the flat API has correctly set the FPU.
FPUStateSaver::AssertMode();
BOOL isAngleScalable = TRUE; REAL angle = 0; GpPointF point1; GpPointF point2;
switch(mode) { case LinearGradientModeHorizontal: angle = 0; point1.X = rect.X; point1.Y = (rect.Y + rect.GetBottom()) / 2.0f; point2.X = rect.GetRight(); point2.Y = point1.Y; break;
case LinearGradientModeVertical: angle = 90; point1.X = (rect.X + rect.GetRight()) / 2.0f; point1.Y = rect.Y; point2.X = point1.X; point2.Y = rect.GetBottom(); break;
case LinearGradientModeForwardDiagonal: angle = 45; point1.X = rect.X; point1.Y = rect.Y; point2.X = rect.GetRight(); point2.Y = rect.GetBottom(); break;
case LinearGradientModeBackwardDiagonal: angle = 135; point1.X = rect.GetRight(); point1.Y = rect.Y; point2.X = rect.X; point2.Y = rect.GetBottom(); break;
default: // No such a case.
ASSERT(0);
SetValid(FALSE); return; }
SetLineGradient( point1, point2, rect, color1, color2, angle, isAngleScalable, wrapMode); }
/**************************************************************************\
* * Function Description: * * Creates a LineGradient which is defined by the rectangle. * * Arguments: * * [IN] rect - the rectangle to define this gradient. * [IN] color1 - the color of the start point. * [IN] color2 - the color of the end point. * [IN] angle - the angle of the gradient * [IN] isAngleScalable - TRUE if 45 degree is corner to corner. * The default value is FALSE. * [IN] wrapMode - the wrap mode of this brush. * * * * History: * * 10/06/1999 ikkof * Created it. * \**************************************************************************/
GpLineGradient::GpLineGradient( const GpRectF& rect, const GpColor& color1, const GpColor& color2, REAL angle, BOOL isAngleScalable, GpWrapMode wrapMode ) { // Make sure the flat API has correctly set the FPU.
FPUStateSaver::AssertMode(); GpPointF point1; GpPointF point2; // Not an Office scenario, but need to fix at some point
// so we can print to PCL better.
point1.X = point1.Y = point2.X = point2.Y = 0;
SetLineGradient( point1, point2, rect, color1, color2, angle, isAngleScalable, wrapMode); }
GpStatus GpLineGradient::SetLineGradient( const GpPointF& point1, const GpPointF& point2, const GpRectF& rect, const GpColor& color1, const GpColor& color2, REAL angle, BOOL isAngleScalable, GpWrapMode wrapMode ) { // Make sure the flat API has correctly set the FPU.
FPUStateSaver::AssertMode();
DeviceBrush.Wrap = wrapMode; DeviceBrush.Colors[0] = color1; DeviceBrush.Colors[1] = color2; DeviceBrush.Colors[2] = color1; DeviceBrush.Colors[3] = color2;
DeviceBrush.BlendCounts[0] = DeviceBrush.BlendCounts[1] = 1; DeviceBrush.BlendFactors[0] = DeviceBrush.BlendFactors[1] = NULL; DeviceBrush.Falloffs[0] = DeviceBrush.Falloffs[1] = 1;
GpStatus status; if (CalcLinearGradientXform(angle, isAngleScalable, rect, DeviceBrush.Xform) == Ok) { SetValid(TRUE); DeviceBrush.Rect = rect; DeviceBrush.IsAngleScalable = isAngleScalable; DeviceBrush.Points[0] = point1; DeviceBrush.Points[1] = point2; status = Ok; } else { SetValid(FALSE); GpMemset(&DeviceBrush.Rect, 0, sizeof(DeviceBrush.Rect)); GpMemset(DeviceBrush.Points, 0, sizeof(DeviceBrush.Points[0]) * 2); DeviceBrush.IsAngleScalable = FALSE; status = InvalidParameter; }
return status; }
GpStatus GpLineGradient::SetLinePoints( const GpPointF& point1, const GpPointF& point2 ) { // Make sure the flat API has correctly set the FPU.
FPUStateSaver::AssertMode();
GpPointF p0, dP1, dP2;
p0 = point1; dP1.X = point2.X - point1.X; dP1.Y = point2.Y - point1.Y; dP2.X = - dP1.Y; dP2.Y = dP1.X;
REAL m[6]; REAL width, height;
if(getLineGradientTransform(&m[0], &width, &height, p0, dP1, dP2)) { SetValid(TRUE);
DeviceBrush.Rect.X = p0.X; DeviceBrush.Rect.Y = p0.Y; DeviceBrush.Rect.Width = width; DeviceBrush.Rect.Height = height; } else { // Don't change the current state.
return GenericError; }
DeviceBrush.Xform.SetMatrix(m); UpdateUid(); return Ok; }
GpStatus GpLineGradient::GetLinePoints(GpPointF* points) { // Make sure the flat API has correctly set the FPU.
FPUStateSaver::AssertMode();
ASSERT(points); points[0].X = DeviceBrush.Rect.X; points[0].Y = DeviceBrush.Rect.Y; points[1].X = DeviceBrush.Rect.X + DeviceBrush.Rect.Width; points[1].Y = DeviceBrush.Rect.Y + DeviceBrush.Rect.Height; DeviceBrush.Xform.Transform(points, 2);
return Ok; }
INT GpLineGradient::GetPresetBlendCount() { if(DeviceBrush.UsesPresetColors) return DeviceBrush.BlendCounts[0]; else return 0; }
/*
** This returns the premultiplied colors */
GpStatus GpLineGradient::GetPresetBlend( GpColor* blendColors, REAL* blendPositions, INT count) { // Make sure the flat API has correctly set the FPU.
FPUStateSaver::AssertMode();
if(!blendColors || !blendPositions || count <= 1) return InvalidParameter;
if(DeviceBrush.UsesPresetColors && DeviceBrush.PresetColors && DeviceBrush.BlendPositions[0]) { for(INT i = 0; i < count; i++) { blendColors[i].SetColor(DeviceBrush.PresetColors[i]); } GpMemcpy(blendPositions, DeviceBrush.BlendPositions[0], count*sizeof(REAL));
return Ok; } else return GenericError; }
GpStatus GpLineGradient::SetPresetBlend( const GpColor* blendColors, const REAL* blendPositions, INT count) { // Make sure the flat API has correctly set the FPU.
FPUStateSaver::AssertMode();
if(!blendColors || !blendPositions || count <= 1) return InvalidParameter;
ARGB* newColors = (ARGB*) GpRealloc(DeviceBrush.PresetColors, count*sizeof(ARGB));
if (newColors != NULL) { DeviceBrush.PresetColors = newColors; } else { return OutOfMemory; }
REAL* newPositions = (REAL*) GpRealloc(DeviceBrush.BlendPositions[0], count*sizeof(REAL));
if (newPositions != NULL) { DeviceBrush.BlendPositions[0] = newPositions; } else { return OutOfMemory; }
GpFree(DeviceBrush.BlendFactors[0]);
// DeviceBrush.BlendFactors[1] is always NULL for LineGradient.
DeviceBrush.BlendFactors[0] = NULL;
DeviceBrush.UsesPresetColors = TRUE;
for(INT i = 0; i < count; i++) { newColors[i] = blendColors[i].GetValue(); } GpMemcpy(newPositions, blendPositions, count*sizeof(REAL)); DeviceBrush.BlendCounts[0] = count; UpdateUid(); return Ok; }
/**************************************************************************\
* * Function Description: * * Blend any transparent colors in this brush with white. Note that * colors are premultiplied, since they will become fully opaque. * * Arguments: * * Return Value: * * GpStatus - Ok or failure status * \**************************************************************************/
GpStatus GpLineGradient::BlendWithWhite() { if (DeviceBrush.UsesPresetColors) { GpColor color; for (INT i=0; i<DeviceBrush.BlendCounts[0]; i++) { color.SetValue(GpColor::ConvertToPremultiplied(DeviceBrush.PresetColors[i])); color.BlendOpaqueWithWhite(); DeviceBrush.PresetColors[i] = color.GetValue(); } return Ok; } else { return GpRectGradient::BlendWithWhite(); } }
BOOL GpPathGradient::IsRectangle() const { BOOL result = FALSE;
if (DeviceBrush.PointsPtr != NULL) result = IsRectanglePoints(DeviceBrush.PointsPtr, DeviceBrush.Count, NULL, NULL); else { GpPath* path = static_cast<GpPath*> (DeviceBrush.Path); if(path) result = path->IsRectangle(NULL); }
return result; }
INT GpPathGradient::GetPresetBlendCount() const { if(DeviceBrush.UsesPresetColors) return DeviceBrush.BlendCounts[0]; else return 0; }
/*
** This returns the premultiplied colors */
GpStatus GpPathGradient::GetPresetBlend( GpColor* blendColors, REAL* blendPositions, INT count) const { if(!blendColors || !blendPositions || count <= 1) return InvalidParameter;
if(DeviceBrush.UsesPresetColors && DeviceBrush.PresetColors && DeviceBrush.BlendPositions[0]) { // Users will obtain the preset colors as radial blend colors.
// 0 position means the center location and 1 position means the
// the outer edge. In order to convert those colors and position arrays
// from the weight factor arrays in PathGradient,
// we must invert the order of the returned arrays.
for(INT i = 0; i < count; i++) { blendColors[count - 1 -i].SetColor(DeviceBrush.PresetColors[i]); blendPositions[count - 1 -i] = TOREAL(1.0 - DeviceBrush.BlendPositions[0][i]); }
return Ok; } else return GenericError; }
GpStatus GpPathGradient::SetPresetBlend( const GpColor* blendColors, const REAL* blendPositions, INT count) { if(!blendColors || !blendPositions || count <= 1) return InvalidParameter;
ARGB* newColors = (ARGB*) GpRealloc(DeviceBrush.PresetColors, count*sizeof(ARGB));
if (newColors != NULL) { DeviceBrush.PresetColors = newColors; } else { return OutOfMemory; }
REAL* newPositions = (REAL*) GpRealloc(DeviceBrush.BlendPositions[0], count*sizeof(REAL));
if (newPositions != NULL) { DeviceBrush.BlendPositions[0] = newPositions; } else { return OutOfMemory; }
GpFree(DeviceBrush.BlendFactors[0]); DeviceBrush.BlendFactors[0] = NULL;
DeviceBrush.UsesPresetColors = TRUE;
// Users will supply the preset colors as radial blend colors.
// 0 position means the center location and 1 position means the
// the outer edge. In order to convert those colors and position arrays
// to the weight factor arrays in PathGradient,
// we must invert the order of the given arrays.
for(INT i = 0; i < count; i++) { // PresetColors are stored non-premultiplied.
newColors[count - 1 - i] = blendColors[i].GetValue(); newPositions[count - 1 - i] = TOREAL(1.0 - blendPositions[i]); }
DeviceBrush.BlendCounts[0] = count; UpdateUid(); return Ok; }
//==================================================================
// Copy constructors
//==================================================================
GpElementaryBrush::GpElementaryBrush(const GpElementaryBrush *brush) { if(brush && brush->IsValid()) { // !!! [asecchia] we should really be asking the DeviceBrush to
// copy it's members instead of duplicating the code all over
// the place. Current code is error prone - each subclass is has to
// know all about how to copy and what has or hasn't been updated on
// the chain down to it's ancestor.
DeviceBrush.Xform = brush->DeviceBrush.Xform; DeviceBrush.Wrap = brush->DeviceBrush.Wrap; DeviceBrush.IsGammaCorrected = brush->DeviceBrush.IsGammaCorrected; SetValid(brush->IsValid()); } else SetValid(FALSE); }
GpTexture::GpTexture( const GpTexture *brush ) : GpElementaryBrush(brush) { if(brush && brush->IsValid()) { const DpBrush* devBrush = &(brush->DeviceBrush);
InitializeBrush(brush->Image, devBrush->Wrap, NULL); SetTransform(devBrush->Xform); } else SetValid(FALSE); }
GpRectGradient::GpRectGradient( const GpRectGradient *brush ) : GpGradientBrush(brush) { if(brush && brush->IsValid()) { const DpBrush* devBrush = &(brush->DeviceBrush);
InitializeBrush( devBrush->Rect, &(devBrush->Colors[0]), devBrush->Wrap );
SetTransform(devBrush->Xform);
SetHorizontalBlend( devBrush->BlendFactors[0], devBrush->BlendPositions[0], devBrush->BlendCounts[0] );
SetVerticalBlend( devBrush->BlendFactors[1], devBrush->BlendPositions[1], devBrush->BlendCounts[1] );
} else SetValid(FALSE); }
GpLineGradient::GpLineGradient( const GpLineGradient *brush ) : GpRectGradient(brush) { if(brush && brush->IsValid()) { // Copy the preset colors.
// !!! [asecchia] why isn't this handled in a uniform way?
const DpBrush* devBrush = &(brush->DeviceBrush);
DeviceBrush.Points[0] = devBrush->Points[0]; DeviceBrush.Points[1] = devBrush->Points[1]; DeviceBrush.IsAngleScalable = devBrush->IsAngleScalable;
if(devBrush->UsesPresetColors) { SetPresetBlend( (GpColor*)(devBrush->PresetColors), (REAL*)(devBrush->BlendPositions[0]), devBrush->BlendCounts[0] ); } } }
GpPathGradient::GpPathGradient( const GpPathGradient *brush ) : GpGradientBrush(brush) { if(brush && brush->IsValid()) { const DpBrush* devBrush = &(brush->DeviceBrush);
// If a path exists for the brush, use that for initialization.
// Otherwise, use the points collection.
if (devBrush->Path != NULL) { DefaultBrush(); DeviceBrush.Wrap = devBrush->Wrap; DeviceBrush.Path = devBrush->Path->ClonePath(); PrepareBrush(); } else { InitializeBrush(devBrush->PointsPtr, devBrush->Count, devBrush->Wrap); }
if(IsValid()) { SetTransform(devBrush->Xform);
SetCenterPoint(devBrush->Points[0]); SetCenterColor(devBrush->Colors[0]); SetSurroundColors(devBrush->ColorsPtr); DeviceBrush.Falloffs[0] = devBrush->Falloffs[0]; DeviceBrush.FocusScaleX = devBrush->FocusScaleX; DeviceBrush.FocusScaleY = devBrush->FocusScaleY; DeviceBrush.UsesPresetColors = devBrush->UsesPresetColors; INT blendCount = devBrush->BlendCounts[0]; DeviceBrush.BlendCounts[0] = blendCount;
// If we're cloning a brush with preset colors, copy preset colors
// and blend positions. Otherwise, copy the blend factors and
// blend positions.
if (devBrush->UsesPresetColors) { ARGB* newColors = (ARGB*) GpRealloc(DeviceBrush.PresetColors, blendCount*sizeof(ARGB)); if (newColors != NULL) { DeviceBrush.PresetColors = newColors;
REAL* newPositions = (REAL*) GpRealloc(DeviceBrush.BlendPositions[0], blendCount*sizeof(REAL));
if (newPositions != NULL) { DeviceBrush.BlendPositions[0] = newPositions; GpFree(DeviceBrush.BlendFactors[0]); DeviceBrush.BlendFactors[0] = NULL; memcpy(DeviceBrush.PresetColors, devBrush->PresetColors, blendCount*sizeof(ARGB)); memcpy(DeviceBrush.BlendPositions[0], devBrush->BlendPositions[0], blendCount*sizeof(REAL)); } else { SetValid(FALSE); } } else { SetValid(FALSE); } } else if (devBrush->BlendFactors[0] && devBrush->BlendPositions[0]) { REAL* newFactors = (REAL*) GpRealloc(DeviceBrush.BlendFactors[0], blendCount*sizeof(REAL)); if (newFactors != NULL) { DeviceBrush.BlendFactors[0] = newFactors;
REAL* newPositions = (REAL*) GpRealloc(DeviceBrush.BlendPositions[0], blendCount*sizeof(REAL));
if (newPositions != NULL) { DeviceBrush.BlendPositions[0] = newPositions; memcpy(DeviceBrush.BlendFactors[0], devBrush->BlendFactors[0], blendCount*sizeof(REAL)); memcpy(DeviceBrush.BlendPositions[0], devBrush->BlendPositions[0], blendCount*sizeof(REAL)); } else { SetValid(FALSE); } } else { SetValid(FALSE); } } } } else SetValid(FALSE); }
GpHatch::GpHatch(const GpHatch* brush) { if(brush && brush->IsValid()) { const DpBrush* devBrush = &(brush->DeviceBrush);
InitializeBrush(devBrush->Style, devBrush->Colors[0], devBrush->Colors[1]); } else SetValid(FALSE); }
/**************************************************************************\
* * Function Description: * * Getting horizontal falloff / blend-factors for * a rectangular gradient brush object * * Arguments: * * [OUT] blendFactors - Buffer for returning the horizontal * falloff or blend-factors. * count - Size of the buffer (in number of REAL elements) * * Return Value: * * Status code * \**************************************************************************/
GpStatus GpRectGradient::GetHorizontalBlend( REAL* blendFactors, REAL* blendPositions, INT count ) { if(!blendFactors || !blendPositions || count < 1) return InvalidParameter;
// Check if the input buffer is big enough
if (count < DeviceBrush.BlendCounts[0]) return InsufficientBuffer;
if (DeviceBrush.BlendCounts[0] == 1) { // Return falloff parameter
blendFactors[0] = DeviceBrush.Falloffs[0]; } else { // Return blend factors
GpMemcpy( blendFactors, DeviceBrush.BlendFactors[0], DeviceBrush.BlendCounts[0]*sizeof(REAL) ); GpMemcpy( blendPositions, DeviceBrush.BlendPositions[0], DeviceBrush.BlendCounts[0]*sizeof(REAL) ); }
return Ok; }
/**************************************************************************\
* * Function Description: * * Setting horizontal falloff / blend-factors for * a rectangular gradient brush object * * Arguments: * * [IN] blendFactors - Specify the new blend factors * count - Number of elements in the blend factor array * * Return Value: * * Status code * \**************************************************************************/
GpStatus GpRectGradient::SetHorizontalBlend( const REAL* blendFactors, const REAL* blendPositions, INT count ) { if(!blendFactors || !blendPositions || count < 1) return InvalidParameter;
if (count == 1) { // Setting falloff parameter
GpFree(DeviceBrush.BlendFactors[0]); DeviceBrush.BlendFactors[0] = NULL; GpFree(DeviceBrush.BlendPositions[0]); DeviceBrush.BlendPositions[0] = NULL;
if (blendFactors == NULL) DeviceBrush.Falloffs[0] = 1; else DeviceBrush.Falloffs[0] = blendFactors[0];
DeviceBrush.BlendCounts[0] = 1; } else { ASSERT(blendFactors != NULL && blendPositions != NULL); // blend positions must start at 0.0 and end at 1.0
if (REALABS(blendPositions[0]) > REAL_EPSILON || REALABS(1.0f - blendPositions[count-1]) > REAL_EPSILON) { return InvalidParameter; }
// Setting blend factors
REAL* newFactors; REAL* newPositions;
newFactors = (REAL*) GpRealloc(DeviceBrush.BlendFactors[0], count*sizeof(REAL));
if (newFactors != NULL) { DeviceBrush.BlendFactors[0] = newFactors; } else { return OutOfMemory; }
newPositions = (REAL*) GpRealloc(DeviceBrush.BlendPositions[0], count*sizeof(REAL));
if (newPositions != NULL) { DeviceBrush.BlendPositions[0] = newPositions; } else { return OutOfMemory; }
if (newFactors == NULL || newPositions == NULL) return OutOfMemory;
GpMemcpy(newFactors, blendFactors, count*sizeof(REAL)); GpMemcpy(newPositions, blendPositions, count*sizeof(REAL)); DeviceBrush.BlendCounts[0] = count; }
DeviceBrush.UsesPresetColors = FALSE; GpFree(DeviceBrush.PresetColors); DeviceBrush.PresetColors = NULL; UpdateUid(); return Ok; }
/**************************************************************************\
* * Function Description: * * Getting vertical falloff / blend-factors for * a rectangular gradient brush object * * Arguments: * * [OUT] blendFactors - Buffer for returning the vertical * falloff or blend-factors. * count - Size of the buffer (in number of REAL elements) * * Return Value: * * Status code * \**************************************************************************/
GpStatus GpRectGradient::GetVerticalBlend( REAL* blendFactors, REAL* blendPositions, INT count ) { if(!blendFactors || !blendPositions || count < 1) return InvalidParameter;
// Check if the input buffer is big enough
if (count < DeviceBrush.BlendCounts[1]) return InsufficientBuffer;
if (DeviceBrush.BlendCounts[1] == 1) { // Return falloff parameter
blendFactors[0] = DeviceBrush.Falloffs[1]; } else { // Return blend factors
GpMemcpy( blendFactors, DeviceBrush.BlendFactors[1], DeviceBrush.BlendCounts[1]*sizeof(REAL)); GpMemcpy( blendPositions, DeviceBrush.BlendPositions[1], DeviceBrush.BlendCounts[1]*sizeof(REAL)); }
return Ok; }
/**************************************************************************\
* * Function Description: * * Setting vertical falloff / blend-factors for * a rectangular gradient brush object * * Arguments: * * [IN] blendFactors - Specify the new blend factors * count - Number of elements in the blend factor array * * Return Value: * * Status code * \**************************************************************************/
GpStatus GpRectGradient::SetVerticalBlend( const REAL* blendFactors, const REAL* blendPositions, INT count ) { if(!blendFactors || !blendPositions || count < 1) return InvalidParameter;
if (count == 1) { // Setting falloff parameter
GpFree(DeviceBrush.BlendFactors[1]); DeviceBrush.BlendFactors[1] = NULL; GpFree(DeviceBrush.BlendPositions[1]); DeviceBrush.BlendPositions[1] = NULL;
if (blendFactors == NULL) DeviceBrush.Falloffs[1] = 1; else DeviceBrush.Falloffs[1] = blendFactors[0];
DeviceBrush.BlendCounts[1] = 1; } else { ASSERT(blendFactors != NULL && blendPositions != NULL);
// Setting blend factors
REAL* newFactors; REAL* newPositions;
newFactors = (REAL*) GpRealloc(DeviceBrush.BlendFactors[1], count*sizeof(REAL));
if (newFactors != NULL) { DeviceBrush.BlendFactors[1] = newFactors; } else { return OutOfMemory; }
newPositions = (REAL*) GpRealloc(DeviceBrush.BlendPositions[1], count*sizeof(REAL));
if (newPositions != NULL) { DeviceBrush.BlendPositions[1] = newPositions; } else { return OutOfMemory; }
GpMemcpy(newFactors, blendFactors, count*sizeof(REAL)); GpMemcpy(newPositions, blendPositions, count*sizeof(REAL)); DeviceBrush.BlendCounts[1] = count; }
DeviceBrush.UsesPresetColors = FALSE; GpFree(DeviceBrush.PresetColors); DeviceBrush.PresetColors = NULL; UpdateUid();
return Ok; }
/**************************************************************************\
* * Function Description: * * Blend any transparent colors in this brush with white. Note that colors * are converted to premultiplied first, since they will become fully opaque. * * Arguments: * * Return Value: * * GpStatus - Ok or failure status * \**************************************************************************/
GpStatus GpRectGradient::BlendWithWhite() { GpColor color; for (INT i=0; i<4; i++) { color.SetValue(DeviceBrush.Colors[i].GetPremultipliedValue()); color.BlendOpaqueWithWhite(); DeviceBrush.Colors[i] = color.GetValue(); }
return Ok; }
//--------------------------------------------------------------------------
// Path Gradient
//--------------------------------------------------------------------------
VOID GpPathGradient::PrepareBrush() { GpPath* path = static_cast<GpPath*> (DeviceBrush.Path);
if (path) { DeviceBrush.Count = path->Points.GetCount(); GpPointF* points = path->Points.GetDataBuffer();
if(!DeviceBrush.ColorsPtr) { DeviceBrush.ColorsPtr = (GpColor*)GpMalloc(DeviceBrush.Count*sizeof(GpColor));
if (DeviceBrush.ColorsPtr != NULL) GpMemset(&DeviceBrush.ColorsPtr[0], 255, DeviceBrush.Count*sizeof(GpColor)); }
REAL xmin, xmax, ymin, ymax, x0, y0;
x0 = xmin = xmax = points[0].X; y0 = ymin = ymax = points[0].Y;
for(INT i = 1; i < DeviceBrush.Count; i++) { x0 += points[i].X; y0 += points[i].Y; xmin = min(xmin, points[i].X); xmax = max(xmax, points[i].X); ymin = min(ymin, points[i].Y); ymax = max(ymax, points[i].Y); }
DeviceBrush.Rect.X = xmin; DeviceBrush.Rect.Width = xmax - xmin; DeviceBrush.Rect.Y = ymin; DeviceBrush.Rect.Height = ymax - ymin;
if(!WrapModeIsValid(DeviceBrush.Wrap) || DeviceBrush.Rect.Width <= 0 || DeviceBrush.Rect.Height <= 0) return;
DeviceBrush.Points[0].X = x0/DeviceBrush.Count; DeviceBrush.Points[0].Y = y0/DeviceBrush.Count;
SetValid(TRUE); } }
GpStatus GpPathGradient::Flatten(GpMatrix* matrix) const { GpPath* path = static_cast<GpPath*> (DeviceBrush.Path);
if(!path) return Ok;
if(path->HasCurve()) { INT origCount = DeviceBrush.Count;
GpStatus status = path->Flatten( const_cast<DynByteArray*>(&FlattenTypes), const_cast<DynPointFArray*> (&FlattenPoints), matrix);
if(status == Ok) { DeviceBrush.Count = FlattenPoints.GetCount(); DeviceBrush.PointsPtr = FlattenPoints.GetDataBuffer(); if ((DeviceBrush.Count > origCount) && (DeviceBrush.ColorsPtr != NULL)) { // The colors array is no longer the proper size. Adjust the
// size and copy up the last color. It is the apps responsibility
// to estimate and specify the correct number of flattened points.
const_cast<GpColor*>(DeviceBrush.ColorsPtr) = (GpColor*) GpRealloc((VOID*)DeviceBrush.ColorsPtr, sizeof(GpColor)*DeviceBrush.Count);
if (DeviceBrush.ColorsPtr != NULL) { GpColor copyColor = (origCount > 1) ? DeviceBrush.ColorsPtr[origCount-1] : GpColor(0xFFFFFFFF);
for (INT i=origCount; i<DeviceBrush.Count; i++) { DeviceBrush.ColorsPtr[i] = copyColor; } } else { return OutOfMemory; } } } } else { DeviceBrush.Count = path->GetPointCount(); DeviceBrush.PointsPtr = const_cast<GpPointF*> (path->GetPathPoints()); }
return Ok; }
GpStatus GpPathGradient::GetBlend( REAL* blendFactors, REAL* blendPositions, INT count ) const { if(!blendFactors || !blendPositions || count < 1) return InvalidParameter;
// Check if the input buffer is big enough
if (count < DeviceBrush.BlendCounts[0]) return InsufficientBuffer;
if (DeviceBrush.BlendCounts[0] == 1) { // Return falloff parameter
blendFactors[0] = DeviceBrush.Falloffs[0]; } else { // Return blend factors
// Users want to obtain the blend factor as radial blend factors.
// 0 blend factor means 100 % center color and 0 position means
// the center location. In order to return those factor and
// position arrays, we must invert the weight and position factor
// arrays stored in this PathGradient class.
for(INT i = 0; i < DeviceBrush.BlendCounts[0]; i++) { blendFactors[DeviceBrush.BlendCounts[0] - 1 - i] = TOREAL(1.0 - DeviceBrush.BlendFactors[0][i]); blendPositions[DeviceBrush.BlendCounts[0] - 1 - i] = TOREAL(1.0 - DeviceBrush.BlendPositions[0][i]); } }
return Ok; }
GpStatus GpPathGradient::SetBlend( const REAL* blendFactors, const REAL* blendPositions, INT count ) { if(!blendFactors || !blendPositions || count < 1) return InvalidParameter;
if (count == 1) { // Setting falloff parameter
GpFree(DeviceBrush.BlendFactors[0]); DeviceBrush.BlendFactors[0] = NULL; GpFree(DeviceBrush.BlendPositions[0]); DeviceBrush.BlendPositions[0] = NULL;
if (blendFactors == NULL) DeviceBrush.Falloffs[0] = 1; else DeviceBrush.Falloffs[0] = blendFactors[0];
DeviceBrush.BlendCounts[0] = 1; } else { // blend positions must start at 0.0 and end at 1.0
if (REALABS(blendPositions[0]) > REAL_EPSILON || REALABS(1.0f - blendPositions[count-1]) > REAL_EPSILON) { return InvalidParameter; }
// Setting blend factors
REAL* newFactors; REAL* newPositions;
newFactors = (REAL*) GpRealloc(DeviceBrush.BlendFactors[0], count*sizeof(REAL));
if (newFactors != NULL) { DeviceBrush.BlendFactors[0] = newFactors; } else { return OutOfMemory; }
newPositions = (REAL*) GpRealloc(DeviceBrush.BlendPositions[0], count*sizeof(REAL));
if (newPositions != NULL) { DeviceBrush.BlendPositions[0] = newPositions; } else { return OutOfMemory; }
// Users will supply the blend factor as radial blend factors.
// 0 blend factor means 100 % center color and 0 position means
// the center location. In order to convert those factor and position arrays
// to the weight and position factor arrays in PathGradient,
// we must invert the given arrays.
for(INT i = 0; i < count; i++) { newFactors[count - 1 - i] = TOREAL(1.0 - blendFactors[i]); newPositions[count - 1 - i] = TOREAL(1.0 - blendPositions[i]); } DeviceBrush.BlendCounts[0] = count; }
DeviceBrush.UsesPresetColors = FALSE; GpFree(DeviceBrush.PresetColors); DeviceBrush.PresetColors = NULL; UpdateUid();
return Ok; }
GpStatus GpGradientBrush::GetSigmaBlendArray( REAL focus, REAL scale, INT* count, REAL* blendFactors, REAL* blendPositions) { // Make sure the FPU is set correctly.
FPUStateSaver::AssertMode();
if(!blendFactors || !blendPositions || !count) return InvalidParameter;
// This gives 1/4 of the Sigma array.
static REAL factors[] = { 0, 59, 120, 182, 247, 314, 383, 454, 527, 602, 680, 759, 841, 926, 1013, 1102, 1194, 1288, 1385, 1485, 1587, 1692, 1800, 1911, 2024, 2141, 2260, 2383, 2508, 2637, 2769, 2904, 3042, 3183, 3328, 3477, 3628, 3783, 3942, 4104, 4270, 4439, 4612, 4789, 4969, 5153, 5341, 5533, 5728, 5928, 6131, 6338, 6549, 6764, 6983, 7206, 7434, 7665, 7900, 8139, 8382, 8630, 8881, 9136, 9396, 9660, 9927, 10199, 10475, 10755, 11039, 11327, 11619, 11916, 12216, 12520, 12828, 13140, 13456, 13776, 14099, 14427, 14758, 15093, 15431, 15774, 16119, 16469, 16822, 17178, 17538, 17901, 18267, 18637, 19009, 19385, 19764, 20146, 20530, 20918, 21308, 21701, 22096, 22494, 22894, 23297, 23702, 24109, 24518, 24929, 25342, 25756, 26173, 26591, 27010, 27431, 27853, 28276, 28701, 29126, 29552, 29979, 30407, 30836, 31264, 31694, 32123, 32553 };
if(focus < 0 || focus > 1 || scale < 0 || scale > 1) return InvalidParameter;
if(blendFactors && blendPositions) { INT i, n; scale /= 65536; REAL one = 65536;
if(focus > 0 && focus < 1) { for(i = 0; i < 128; i++) { blendFactors[i] = factors[i]; blendPositions[i] = focus*i/255; } for(i = 128; i < 256; i++) { blendFactors[i] = one - factors[255 - i]; blendPositions[i] = focus*i/255; }
// skip i = 256 since this gives the same data.
for(i = 257; i < 384; i++) { blendFactors[i - 1] = one - factors[i - 256]; blendPositions[i - 1] = TOREAL(focus + (1.0 - focus)*(i - 256)/255); } for(i = 384; i < 512; i++) { blendFactors[i - 1] = factors[511 - i]; blendPositions[i - 1] = TOREAL(focus + (1.0 - focus)*(i - 256)/255); }
// Set n to 511 because we skipped index 256 above to avoid
// the duplicate 1 entry in the ramp from 0 to 1 to 0.
n = 511; } else if(focus == 1) { for(i = 0; i < 128; i++) { blendFactors[i] = factors[i]; blendPositions[i] = TOREAL(i)/255; } for(i = 128; i < 256; i++) { blendFactors[i] = one - factors[255 - i]; blendPositions[i] = TOREAL(i)/255; }
n = 256; } else // focus == 0
{ for(i = 256; i < 384; i++) { blendFactors[i - 256] = one - factors[i - 256]; blendPositions[i - 256] = TOREAL(i - 256)/255; } for(i = 384; i < 512; i++) { blendFactors[i - 256] = factors[511 - i]; blendPositions[i - 256] = TOREAL(i - 256)/255; }
n = 256; }
for(i = 0; i < n; i++) blendFactors[i] *= scale;
*count = n; return Ok; } else return InvalidParameter; }
GpStatus GpGradientBrush::GetLinearBlendArray( REAL focus, REAL scale, INT* count, REAL* blendFactors, REAL* blendPositions) { if(!blendFactors || !blendPositions || !count) return InvalidParameter;
if(focus < 0 || focus > 1 || scale < 0 || scale > 1) return InvalidParameter;
if(blendFactors && blendPositions) { if(focus > 0 && focus < 1) { blendFactors[0] = 0.0f; blendFactors[1] = scale; blendFactors[2] = 0.0f;
blendPositions[0] = 0.0f; blendPositions[1] = focus; blendPositions[2] = 1.0f;
*count = 3; } else if(focus == 1) { blendFactors[0] = 0.0f; blendFactors[1] = scale;
blendPositions[0] = 0.0f; blendPositions[1] = 1.0f;
*count = 2; } else // focus == 0
{ blendFactors[0] = scale; blendFactors[1] = 0.0f;
blendPositions[0] = 0.0f; blendPositions[1] = 1.0f;
*count = 2; }
return Ok; } else return InvalidParameter; }
GpStatus GpGradientBrush::SetSigmaBlend( REAL focus, REAL scale) { REAL* blendFactors = (REAL*) GpMalloc(512*sizeof(REAL)); REAL* blendPositions = (REAL*) GpMalloc(512*sizeof(REAL)); INT count; GpStatus status;
if(blendFactors && blendPositions) { status = GetSigmaBlendArray(focus, scale, &count, blendFactors, blendPositions);
if(status == Ok) status = SetBlend(&blendFactors[0], &blendPositions[0], count); } else status = OutOfMemory;
GpFree(blendFactors); GpFree(blendPositions);
return status; }
GpStatus GpGradientBrush::SetLinearBlend( REAL focus, REAL scale) { REAL blendFactors[3]; REAL blendPositions[3]; INT count;
GpStatus status = GetLinearBlendArray(focus, scale, &count, &blendFactors[0], &blendPositions[0]);
if(status != Ok) return status;
return SetBlend(&blendFactors[0], &blendPositions[0], count); }
//--------------------------------------------------------------------------
// Hatch Brush
//--------------------------------------------------------------------------
const BYTE GdipHatchPatterns8bpp[HatchStyleTotal][64] = { { // HatchStyleHorizontal, 0
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, { // HatchStyleVertical, 1
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, { // HatchStyleForwardDiagonal, 2
0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, }, { // HatchStyleBackwardDiagonal, 3
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, }, { // HatchStyleCross, 4
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, { // HatchStyleDiagonalCross 5
0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0x80, 0xff, 0x80, 0x00, 0x00, 0x80, 0xff, 0x80, 0x00, 0x80, 0xff, 0x80, 0x80, 0xff, 0x80, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x80, 0xff, 0x80, 0x80, 0xff, 0x80, 0x00, 0x80, 0xff, 0x80, 0x00, 0x00, 0x80, 0xff, 0x80, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, }, { // HatchStyle05Percent, 6
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, { // HatchStyle10Percent, 7
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, { // HatchStyle20Percent, 8
0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, { // HatchStyle25Percent, 9
0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, }, { // HatchStyle30Percent, 10
0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, }, { // HatchStyle40Percent, 11
0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, }, { // HatchStyle50Percent, 12
0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, }, { // HatchStyle60Percent, 13
0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, }, { // HatchStyle70Percent, 14
0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, }, { // HatchStyle75Percent, 15
0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, }, { // HatchStyle80Percent, 16
0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, }, { // HatchStyle90Percent, 17
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, }, { // HatchStyleLightDownwardDiagonal, 18
0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, }, { // HatchStyleLightUpwardDiagonal, 19
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, }, { // HatchStyleDarkDownwardDiagonal, 20
0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, }, { // HatchStyleDarkUpwardDiagonal, 21
0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, }, { // HatchStyleWideDownwardDiagonal, 22
0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, }, { // HatchStyleWideUpwardDiagonal, 23
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, }, { // HatchStyleLightVertical, 24
0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, }, { // HatchStyleLightHorizontal, 25
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, { // HatchStyleNarrowVertical, 26
0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, }, { // HatchStyleNarrowHorizontal, 27
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, { // HatchStyleDarkVertical, 28
0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, }, { // HatchStyleDarkHorizontal, 29
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, { // HatchStyleDashedDownwardDiagonal, 30
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, { // HatchStyleDashedUpwardDiagonal, 31
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, { // HatchStyleDashedHorizontal, 32
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, { // HatchStyleDashedVertical, 33
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, }, { // HatchStyleSmallConfetti, 34
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, }, { // HatchStyleLargeConfetti, 35
0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, }, { // HatchStyleZigZag, 36
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, }, { // HatchStyleWave, 37
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, { // HatchStyleDiagonalBrick, 38
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, }, { // HatchStyleHorizontalBrick, 39
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, }, { // HatchStyleWeave, 40
0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, }, { // HatchStylePlaid, 41
0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, }, { // HatchStyleDivot, 42
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, { // HatchStyleDottedGrid, 43
0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, { // HatchStyleDottedDiamond, 44
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, { // HatchStyleShingle, 45
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, }, { // HatchStyleTrellis, 46
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, }, { // HatchStyleSphere, 47
0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, }, { // HatchStyleSmallGrid, 48
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, }, { // HatchStyleSmallCheckerBoard, 49
0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, }, { // HatchStyleLargeCheckerBoard, 50
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, }, { // HatchStyleOutlinedDiamond, 51
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, }, { // HatchStyleSolidDiamond, 52
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, };
VOID GpHatch::InitializeData() { if ((DeviceBrush.Style >= HatchStyleMin) && (DeviceBrush.Style <= HatchStyleMax)) { GpMemcpy(DeviceBrush.Data, GdipHatchPatterns8bpp[DeviceBrush.Style], 64); } else { WARNING1("Bad Hatch Style Value"); GpMemset(DeviceBrush.Data, 0x00, 64); // make it transparent
} }
/***************************************************************************\
* * Equivalence comparsion functions * \***************************************************************************/
/**************************************************************************\
* * Function Description: * * Answer TRUE if brush and the receiver are equivalent (i.e. - they will * render indentically) * * Arguments: * * [IN] brush - GpBrush, or subclass, to compare this against. * * Return Value: * * TRUE if equivalent * * Created - 5/28/99 peterost * \**************************************************************************/
BOOL GpHatch::IsEqual(const GpBrush * brush) const { if(!brush) return FALSE;
if (brush == this) return TRUE;
if (GpBrush::IsEqual(brush)) { const GpHatch * hbrush = static_cast<const GpHatch *>(brush); return hbrush->DeviceBrush.Style == DeviceBrush.Style && hbrush->DeviceBrush.Colors[0].IsEqual(DeviceBrush.Colors[0]) && hbrush->DeviceBrush.Colors[1].IsEqual(DeviceBrush.Colors[1]); } else { return FALSE; } }
/**************************************************************************\
* * Function Description: * * Answer TRUE if brush and the receiver are equivalent (i.e. - they will * render indentically). RectGradient brushes require all four colors and * blend factors to be equal. * * Arguments: * * [IN] brush - GpBrush, or subclass, to compare this against. * * Return Value: * * TRUE if equivalent * * Created - 5/28/99 peterost * \**************************************************************************/
BOOL GpRectGradient::IsEqual(const GpBrush * brush) const { if(!brush) return FALSE;
if (brush == this) return TRUE;
if (GpGradientBrush::IsEqual(brush)) { const GpRectGradient * rbrush = static_cast<const GpRectGradient *>(brush);
if (rbrush->DeviceBrush.UsesPresetColors == DeviceBrush.UsesPresetColors && rbrush->DeviceBrush.BlendCounts[0] == DeviceBrush.BlendCounts[0] && rbrush->DeviceBrush.BlendCounts[1] == DeviceBrush.BlendCounts[1]) { INT i;
if (DeviceBrush.UsesPresetColors) { // For preset colors, only the horizontal blend variables are used.
for (INT i=0; i<DeviceBrush.BlendCounts[0]; i++) { if (rbrush->DeviceBrush.PresetColors[i] != DeviceBrush.PresetColors[i] || rbrush->DeviceBrush.BlendPositions[0][i] != DeviceBrush.BlendPositions[0][i]) return FALSE; }
} else { for (i=0; i<4; i++) { if (!rbrush->DeviceBrush.Colors[i].IsEqual(DeviceBrush.Colors[i])) return FALSE; }
if (DeviceBrush.BlendCounts[0] > 1) { for (i=0; i<DeviceBrush.BlendCounts[0]; i++) { if (rbrush->DeviceBrush.BlendFactors[0][i] != DeviceBrush.BlendFactors[0][i] || rbrush->DeviceBrush.BlendPositions[0][i] != DeviceBrush.BlendPositions[0][i]) return FALSE; } } else if (rbrush->DeviceBrush.Falloffs[0] != DeviceBrush.Falloffs[0]) { return FALSE; }
if (DeviceBrush.BlendCounts[1] > 1) { for (i=0; i<DeviceBrush.BlendCounts[1]; i++) { if (rbrush->DeviceBrush.BlendFactors[1][i] != DeviceBrush.BlendFactors[1][i] || rbrush->DeviceBrush.BlendPositions[1][i] != DeviceBrush.BlendPositions[1][i]) return FALSE; } } else if (rbrush->DeviceBrush.Falloffs[1] != DeviceBrush.Falloffs[1]) { return FALSE; } }
return TRUE;
} else { return FALSE; } } else { return FALSE; }
}
/**************************************************************************\
* * Function Description: * * Answer TRUE if brush and the receiver are equivalent (i.e. - they will * render indentically). * * Arguments: * * [IN] brush - GpBrush, or subclass, to compare this against. * * Return Value: * * TRUE if equivalent * * Created - 6/2/99 peterost * \**************************************************************************/ #if 0
BOOL GpRadialGradient::IsEqual(const GpBrush * brush) const { if(!brush) return FALSE;
if (brush == this) return TRUE;
if (GpGradientBrush::IsEqual(brush)) { const GpRadialGradient * rbrush = static_cast<const GpRadialGradient *>(brush); if (rbrush->DeviceBrush.UsesPresetColors == DeviceBrush.UsesPresetColors && rbrush->DeviceBrush.BlendCounts[0] == DeviceBrush.BlendCounts[0]) { if (DeviceBrush.UsesPresetColors) { for (INT i=0; i<DeviceBrush.BlendCounts[0]; i++) { if (rbrush->DeviceBrush.PresetColors[i] != DeviceBrush.PresetColors[i] || rbrush->DeviceBrush.BlendPositions[0][i] != DeviceBrush.BlendPositions[0][i]) return FALSE; } } else { if (rbrush->DeviceBrush.Colors[0].IsEqual(DeviceBrush.Colors[0]) && rbrush->DeviceBrush.Colors[1].IsEqual(DeviceBrush.Colors[1])) { if (DeviceBrush.BlendCounts[0] > 1) { for (INT i=0; i<DeviceBrush.BlendCounts[0]; i++) { if (rbrush->DeviceBrush.BlendFactors[0][i] != DeviceBrush.BlendFactors[0][i] || rbrush->DeviceBrush.BlendPositions[0][i] != DeviceBrush.BlendPositions[0][i]) return FALSE; } } else if (rbrush->DeviceBrush.Falloffs[0] != DeviceBrush.Falloffs[0]) { return FALSE; } } else { return FALSE; } }
return TRUE; } else { return FALSE; } } else { return FALSE; }
}
/**************************************************************************\
* * Function Description: * * Answer TRUE if brush and the receiver are equivalent (i.e. - they will * render indentically). * * Arguments: * * [IN] brush - GpBrush, or subclass, to compare this against. * * Return Value: * * TRUE if equivalent * * Created - 6/7/99 peterost * \**************************************************************************/
BOOL GpTriangleGradient::IsEqual(const GpBrush * brush) const { if(!brush) return FALSE;
if (brush == this) return TRUE;
if (GpGradientBrush::IsEqual(brush)) { const GpTriangleGradient * tbrush = static_cast<const GpTriangleGradient *>(brush); if (tbrush->DeviceBrush.BlendCounts[0] == DeviceBrush.BlendCounts[0] && tbrush->DeviceBrush.BlendCounts[1] == DeviceBrush.BlendCounts[1] && tbrush->DeviceBrush.BlendCounts[2] == DeviceBrush.BlendCounts[2] && tbrush->DeviceBrush.Rect.Equals(DeviceBrush.Rect)) { INT i; for (i=0; i<3; i++) { if (tbrush->DeviceBrush.Points[i].X != DeviceBrush.Points[i].X || tbrush->DeviceBrush.Points[i].Y != DeviceBrush.Points[i].Y || !(tbrush->DeviceBrush.Colors[i].IsEqual(DeviceBrush.Colors[i]))) return FALSE; }
if (DeviceBrush.BlendCounts[0] > 1) { for (i=0; i<DeviceBrush.BlendCounts[0]; i++) { if (tbrush->DeviceBrush.BlendFactors[0][i] != DeviceBrush.BlendFactors[0][i] || tbrush->DeviceBrush.BlendPositions[0][i] != DeviceBrush.BlendPositions[0][i]) return FALSE; } } else if (tbrush->DeviceBrush.Falloffs[0] != DeviceBrush.Falloffs[0]) { return FALSE; }
if (DeviceBrush.BlendCounts[1] > 1) { for (i=0; i<DeviceBrush.BlendCounts[1]; i++) { if (tbrush->DeviceBrush.BlendFactors[1][i] != DeviceBrush.BlendFactors[1][i] || tbrush->DeviceBrush.BlendPositions[1][i] != DeviceBrush.BlendPositions[1][i]) return FALSE; } } else if (tbrush->DeviceBrush.Falloffs[1] != DeviceBrush.Falloffs[1]) { return FALSE; }
if (DeviceBrush.BlendCounts[2] > 1) { for (i=0; i<DeviceBrush.BlendCounts[2]; i++) { if (tbrush->DeviceBrush.BlendFactors[2][i] != DeviceBrush.BlendFactors[2][i] || tbrush->DeviceBrush.BlendPositions[2][i] != DeviceBrush.BlendPositions[2][i]) return FALSE; } } else if (tbrush->DeviceBrush.Falloffs[2] != DeviceBrush.Falloffs[2]) { return FALSE; }
return TRUE; } else { return FALSE; } } else { return FALSE; } } #endif
/**************************************************************************\
* * Function Description: * * Answer TRUE if brush and the receiver are equivalent (i.e. - they will * render indentically). * * Arguments: * * [IN] brush - GpBrush, or subclass, to compare this against. * * Return Value: * * TRUE if equivalent * * Created - 6/7/99 peterost * \**************************************************************************/
BOOL GpPathGradient::IsEqual(const GpBrush * brush) const { if(!brush) return FALSE;
if (brush == this) return TRUE;
if (GpGradientBrush::IsEqual(brush)) { const GpPathGradient * pbrush = static_cast<const GpPathGradient *>(brush); if (pbrush->DeviceBrush.BlendCounts[0] == DeviceBrush.BlendCounts[0] && pbrush->DeviceBrush.Count == DeviceBrush.Count && pbrush->DeviceBrush.OneSurroundColor == DeviceBrush.OneSurroundColor && pbrush->DeviceBrush.UsesPresetColors == DeviceBrush.UsesPresetColors && pbrush->DeviceBrush.Points[0].X == DeviceBrush.Points[0].X && pbrush->DeviceBrush.Points[0].Y == DeviceBrush.Points[0].Y && pbrush->DeviceBrush.Rect.Equals(DeviceBrush.Rect) && pbrush->DeviceBrush.Colors[0].IsEqual(DeviceBrush.Colors[0]) ) { INT i; for (i=0; i<DeviceBrush.Count; i++) { if (pbrush->DeviceBrush.PointsPtr[i].X != DeviceBrush.PointsPtr[i].X || pbrush->DeviceBrush.PointsPtr[i].Y != DeviceBrush.PointsPtr[i].Y || !(pbrush->DeviceBrush.ColorsPtr[i].IsEqual(DeviceBrush.ColorsPtr[i]))) return FALSE; }
if (DeviceBrush.UsesPresetColors) { for (i=0; i<DeviceBrush.BlendCounts[0]; i++) { if (pbrush->DeviceBrush.PresetColors[i] != DeviceBrush.PresetColors[i] || pbrush->DeviceBrush.BlendPositions[0][i] != DeviceBrush.BlendPositions[0][i]) return FALSE; } } else { if (DeviceBrush.BlendCounts[0] > 1) { for (i=0; i<DeviceBrush.BlendCounts[0]; i++) { if (pbrush->DeviceBrush.BlendFactors[0][i] != DeviceBrush.BlendFactors[0][i] || pbrush->DeviceBrush.BlendPositions[0][i] != DeviceBrush.BlendPositions[0][i]) return FALSE; } } else if (pbrush->DeviceBrush.Falloffs[0] != DeviceBrush.Falloffs[0]) { return FALSE; } } }
return TRUE; } else { return FALSE; }
}
DpOutputSpan* GpSolidFill::CreateOutputSpan( DpScanBuffer * scan, DpContext *context, const GpRect *drawBounds) { return new DpOutputSolidColorSpan( DeviceBrush.SolidColor.GetPremultipliedValue(), scan ); }
DpOutputSpan* GpRectGradient::CreateOutputSpan( DpScanBuffer * scan, DpContext *context, const GpRect *drawBounds) { DpOutputSpan* span = NULL;
ARGB argb[4];
for(INT i = 0; i < 4; i++) { argb[i] = DeviceBrush.Colors[i].GetValue(); }
BOOL isHorizontal = FALSE; BOOL isVertical = FALSE;
if(HasPresetColors() && DeviceBrush.BlendCounts[0] > 1) isHorizontal = TRUE;
if(!isHorizontal && argb[0] == argb[2] && argb[1] == argb[3]) isHorizontal = TRUE;
if(!isHorizontal && argb[0] == argb[1] && argb[2] == argb[3]) isVertical = TRUE;
if(!isHorizontal && !isVertical) { span = new DpOutputGradientSpan(this, scan, context); } else { // !!![andrewgo] Not sure why a LinearGradient is coming down to us
// as BrushRectGrad - if it comes down as a BrushTypeLinearGradient
// (as it should) then we don't have to do any of the
// above 'isHorizontal', 'isVertical' stuff
FPUStateSaver fpuState; // Set the rounding mode.
if ((GetBrushType() == BrushTypeLinearGradient) /*|| (GetBrushType() == BrushRectGrad)*/) { if (OSInfo::HasMMX) { span = new DpOutputLinearGradientSpan_MMX(this, scan, context); } else { span = new DpOutputLinearGradientSpan(this, scan, context); } } else { span = new DpOutputOneDGradientSpan(this, scan, context, isHorizontal, isVertical); } }
if (span && !span->IsValid()) { delete span; span = NULL; }
return span; }
#if 0
DpOutputSpan* GpRadialGradient::CreateOutputSpan( DpScanBuffer * scan, DpContext *context, const GpRect *drawBounds) { return new DpOutputOneDGradientSpan( this, scan, context ); }
DpOutputSpan* GpTriangleGradient::CreateOutputSpan( DpScanBuffer * scan, DpContext *context, const GpRect *drawBounds) { return new DpOutputTriangleGradientSpan( this, scan, context ); } #endif
DpOutputSpan* GpPathGradient::CreateOutputSpan( DpScanBuffer * scan, DpContext *context, const GpRect *drawBounds) { FPUStateSaver::AssertMode();
DpOutputSpan* span = NULL; WrapMode wrap = DeviceBrush.Wrap;
// Check to see if a tiled gradient is really needed. It
// is not necessary if the transformed drawbounds fit
// entirely within the bounds of the brush rectangle.
if (drawBounds && wrap != WrapModeClamp) { GpMatrix inverseXForm = context->WorldToDevice; if (Ok == inverseXForm.Invert()) { GpRectF brushRect = DeviceBrush.Rect; GpRectF transformRect; TransformBounds( &inverseXForm, (REAL)drawBounds->GetLeft(), (REAL)drawBounds->GetTop(), (REAL)drawBounds->GetRight(), (REAL)drawBounds->GetBottom(), &transformRect );
if (brushRect.Contains(transformRect)) { wrap = WrapModeClamp; } } }
if(wrap == WrapModeClamp) { if(!DeviceBrush.OneSurroundColor) { span = new DpOutputPathGradientSpan( this, scan, context );
} else { span = new DpOutputOneDPathGradientSpan( this, scan, context ); } } else { INT width, height, ix, iy;
GpRectF brushRect = DeviceBrush.Rect;
// Create a texture brush to represent this path gradient brush.
// We do this by creating a texture as close to device resolution
// as we can and computing the transform (brush to world) for the
// texture brush decomposed into two transforms that take the
// brush via device space. The texture brush transform
// usually works out to be the inverse of the world to device, so
// the final texture brush draws with a resultant identity transform
// regardless of the world to device matrix. (exception when there is
// a rotation in the w2d).
GpPointF worldDestPoints[3]; worldDestPoints[0].X = brushRect.X ; worldDestPoints[0].Y = brushRect.Y; worldDestPoints[1].X = worldDestPoints[0].X + brushRect.Width; worldDestPoints[1].Y = worldDestPoints[0].Y; worldDestPoints[2].X = worldDestPoints[0].X; worldDestPoints[2].Y = worldDestPoints[0].Y + brushRect.Height;
// Take into account transformation by both the brush xform and
// the world to device. This will handle transforms such as
// UnitInch and w2d scales.
// First get the destination points in world space by applying the
// brush transform.
DeviceBrush.Xform.Transform(worldDestPoints, 3); GpPointF deviceDestPoints[3]; GpMemcpy(deviceDestPoints, worldDestPoints, sizeof(worldDestPoints)); // Now get the device space destination points by applying the
// world to device transform.
context->WorldToDevice.Transform(deviceDestPoints, 3); // Compute the bounds in device space.
REAL xmin, xmax, ymin, ymax, nextX, nextY; xmin = xmax = deviceDestPoints[1].X + deviceDestPoints[2].X - deviceDestPoints[0].X; ymin = ymax = deviceDestPoints[1].Y + deviceDestPoints[2].Y - deviceDestPoints[0].Y; for(INT i = 0; i < 3; i++) { nextX = deviceDestPoints[i].X; nextY = deviceDestPoints[i].Y;
if(nextX < xmin) xmin = nextX; else if(nextX > xmax) xmax = nextX; if(nextY < ymin) ymin = nextY; else if(nextY > ymax) ymax = nextY; }
// Set the optimal bitmap bounds.
ix = GpRound(xmin); iy = GpRound(ymin); width = GpRound(xmax) - ix; height = GpRound(ymax) - iy; GpRectF bitmapBounds(0, 0, TOREAL(width), TOREAL(height));
// Decompose brushRect --> worldDestPoints transform into two matrix.
// mat1: brushRect --> bitmapBounds (device space)
// mat2: bitmapBounds --> worldDestPoints
GpMatrix mat1, mat2; mat1.InferAffineMatrix(bitmapBounds, brushRect); mat2.InferAffineMatrix(worldDestPoints, bitmapBounds);
if(width <= 0 || height <= 0) return NULL;
// Create a bitmap which the gradient will be drawn onto.
// Make it the full width and height of the gradient, even
// though only a small portion may be used to simplify
// handling by downstream functions.
GpBitmap* bitmap = new GpBitmap(width, height, PixelFormat32bppARGB);
if(bitmap) { GpGraphics* g = bitmap->GetGraphicsContext(); if(g) { GpLock lock(g->GetObjectLock()); // Set the transform to brushRect --> bitmapBounds.
g->MultiplyWorldTransform(mat1);
WrapMode savedWrapMode = DeviceBrush.Wrap; DeviceBrush.Wrap = WrapModeClamp; GpMatrix savedMat = DeviceBrush.Xform; DeviceBrush.Xform.Reset();
g->FillRect(this, brushRect.X, brushRect.Y, brushRect.Width, brushRect.Height); DeviceBrush.Wrap = savedWrapMode; DeviceBrush.Xform = savedMat;
if(MorphedBrush) delete MorphedBrush;
// Create a texuture with a unit tile and set the
// brush transform to bitmapBounds --> worldDestPoints.
GpTexture* texture = new GpTexture(bitmap, savedWrapMode); // span must be NULL at this point. If it's not, we're going
// to leak memory when we create it below, or in the case of
// an error out, we may end up with uninitialized memory
// being returned to the caller.
ASSERT(span == NULL); if(texture) { texture->MultiplyTransform(mat2); span = texture->CreateOutputSpan(scan, context, drawBounds); } // Even if we failed to create the texture, we still want to
// set a reasonable (NULL) value for MorphedBrush so that we
// don't have a dangling pointer.
MorphedBrush = texture; } // We're done with this graphics.
// NOTE: this is explicitly done outside of the scope of the
// GpLock object, so that the GpLock (which modifies the graphics
// in its destructor) doesn't touch freed memory.
delete g;
bitmap->Dispose(); } }
return span; }
DpOutputSpan* GpTexture::CreateOutputSpan( DpScanBuffer *scan, DpContext *context, const GpRect *drawBounds) { DpOutputBilinearSpan *textureSpan = NULL; GpMatrix brushTransform; GpMatrix worldToDevice;
// Figure out the world-to-device transform:
worldToDevice = context->WorldToDevice; this->GetTransform(&brushTransform); worldToDevice.Prepend(brushTransform);
// Go through our heirarchy of scan drawers:
if (worldToDevice.IsIntegerTranslate() && ((this->GetWrapMode() == WrapModeTile) || (this->GetWrapMode() == WrapModeClamp))) { textureSpan = new DpOutputBilinearSpan_Identity(this, scan, &worldToDevice, context); } else if (OSInfo::HasMMX && GpValidFixed16(DeviceBrush.Rect.Width) && GpValidFixed16(DeviceBrush.Rect.Height)) { textureSpan = new DpOutputBilinearSpan_MMX(this, scan, &worldToDevice, context); }
// Scan drawer creation may fail, so clean up and try one last time
if ((textureSpan) && !textureSpan->IsValid()) { delete textureSpan; textureSpan = NULL; }
if (!textureSpan) { textureSpan = new DpOutputBilinearSpan(this, scan, &worldToDevice, context); }
if ((textureSpan) && !textureSpan->IsValid()) { delete textureSpan; textureSpan = NULL; }
return textureSpan; }
DpOutputSpan* GpHatch::CreateOutputSpan( DpScanBuffer * scan, DpContext *context, const GpRect *drawBounds) { if (StretchFactor == 1) { return new DpOutputHatchSpan( this, scan, context ); } else { return new DpOutputStretchedHatchSpan( this, scan, context, StretchFactor ); } }
class SolidBrushData : public ObjectTypeData { public: ARGB SolidColor; };
/**************************************************************************\
* * Function Description: * * Get the brush data. * * Arguments: * * [IN] dataBuffer - fill this buffer with the data * [IN/OUT] size - IN - size of buffer; OUT - number bytes written * * Return Value: * * GpStatus - Ok or error code * * Created: * * 9/13/1999 DCurtis * \**************************************************************************/ GpStatus GpSolidFill::GetData( IStream * stream ) const { ASSERT (stream != NULL);
SolidBrushData brushData; brushData.Type = DeviceBrush.Type; brushData.SolidColor = DeviceBrush.SolidColor.GetValue(); stream->Write(&brushData, sizeof(brushData), NULL); return Ok; }
UINT GpSolidFill::GetDataSize() const { return sizeof(SolidBrushData); }
/**************************************************************************\
* * Function Description: * * Read the brush object from memory. * * Arguments: * * [IN] dataBuffer - the data that was read from the stream * [IN] size - the size of the data * * Return Value: * * GpStatus - Ok or failure status * * Created: * * 4/26/1999 DCurtis * \**************************************************************************/ GpStatus GpSolidFill::SetData( const BYTE * dataBuffer, UINT size ) { ASSERT ((GpBrushType)(((SolidBrushData *)dataBuffer)->Type) == BrushTypeSolidColor);
if (dataBuffer == NULL) { WARNING(("dataBuffer is NULL")); return InvalidParameter; }
if (size < sizeof(SolidBrushData)) { WARNING(("size too small")); return InvalidParameter; }
if (!((SolidBrushData *)dataBuffer)->MajorVersionMatches()) { WARNING(("Version number mismatch")); return InvalidParameter; }
SetColor(GpColor(((SolidBrushData *)dataBuffer)->SolidColor));
return Ok; }
GpStatus GpSolidFill::ColorAdjust( GpRecolor * recolor, ColorAdjustType type ) { if(!recolor) return InvalidParameter;
if (type == ColorAdjustTypeDefault) { type = ColorAdjustTypeBrush; }
ARGB solidColor32 = Color.GetValue();
recolor->ColorAdjust(&solidColor32, 1, type);
this->SetColor(GpColor(solidColor32)); return Ok; }
class TextureBrushData : public ObjectTypeData { public: INT32 Flags; INT32 Wrap; };
/**************************************************************************\
* * Function Description: * * Get the brush data. * * Arguments: * * [IN] dataBuffer - fill this buffer with the data * [IN/OUT] size - IN - size of buffer; OUT - number bytes written * * Return Value: * * GpStatus - Ok or error code * * Created: * * 9/13/1999 DCurtis * \**************************************************************************/ GpStatus GpTexture::GetData( IStream * stream ) const { ASSERT (stream != NULL);
if (Image == NULL) { WARNING(("Image is NULL")); return Ok; }
INT flags = 0;
if (DeviceBrush.IsGammaCorrected) { flags |= GDIP_BRUSHFLAGS_ISGAMMACORRECTED; }
if (!DeviceBrush.Xform.IsIdentity()) { flags |= GDIP_BRUSHFLAGS_TRANSFORM; }
TextureBrushData brushData; brushData.Type = DeviceBrush.Type; brushData.Flags = flags; brushData.Wrap = DeviceBrush.Wrap; stream->Write(&brushData, sizeof(brushData), NULL);
if (flags & GDIP_BRUSHFLAGS_TRANSFORM) { DeviceBrush.Xform.WriteMatrix(stream); }
return Image->GetData(stream); }
UINT GpTexture::GetDataSize() const { if (Image == NULL) { WARNING(("Image is NULL")); return 0; }
UINT size = sizeof(TextureBrushData);
if (!DeviceBrush.Xform.IsIdentity()) { size += GDIP_MATRIX_SIZE; }
size += Image->GetDataSize();
return size; }
/**************************************************************************\
* * Function Description: * * Read the brush object from memory. * * Arguments: * * [IN] dataBuffer - the data that was read from the stream * [IN] size - the size of the data * * Return Value: * * GpStatus - Ok or failure status * * Created: * * 4/26/1999 DCurtis * \**************************************************************************/ GpStatus GpTexture::SetData( const BYTE * dataBuffer, UINT size ) { ASSERT ((GpBrushType)(((TextureBrushData *)dataBuffer)->Type) == BrushTypeTextureFill);
if (dataBuffer == NULL) { WARNING(("dataBuffer is NULL")); return InvalidParameter; }
if (size < sizeof(TextureBrushData)) { WARNING(("size too small")); return InvalidParameter; }
const TextureBrushData * brushData;
brushData = reinterpret_cast<const TextureBrushData *>(dataBuffer);
if (!brushData->MajorVersionMatches()) { WARNING(("Version number mismatch")); return InvalidParameter; }
DeviceBrush.Type = BrushTypeTextureFill; DeviceBrush.Wrap = (GpWrapMode) brushData->Wrap; DeviceBrush.IsGammaCorrected = ((brushData->Flags & GDIP_BRUSHFLAGS_ISGAMMACORRECTED) != 0);
dataBuffer += sizeof(TextureBrushData); size -= sizeof(TextureBrushData);
if (brushData->Flags & GDIP_BRUSHFLAGS_TRANSFORM) { if (size < GDIP_MATRIX_SIZE) { WARNING(("size too small")); return InvalidParameter; } DeviceBrush.Xform.SetMatrix((REAL *)dataBuffer); dataBuffer += GDIP_MATRIX_SIZE; size -= GDIP_MATRIX_SIZE; } if (Image != NULL) { Image->Dispose(); Image = NULL; }
if (size >= sizeof(ObjectTypeData)) { Image = (GpImage *)GpObject::Factory(ObjectTypeImage, (const ObjectData *)dataBuffer, size);
if (Image != NULL) { if ((Image->SetData(dataBuffer, size) == Ok) && Image->IsValid() && ((ImageType = Image->GetImageType()) == ImageTypeBitmap)) { GpPageUnit unit; Image->GetBounds(&DeviceBrush.Rect, &unit); SetValid(TRUE); UpdateUid(); return Ok; } Image->Dispose(); Image = NULL; } } WARNING(("Failure getting image")); GpMemset(&DeviceBrush.Rect, 0, sizeof(DeviceBrush.Rect)); SetValid(FALSE); return GenericError; }
GpStatus GpTexture::ColorAdjust( GpRecolor * recolor, ColorAdjustType type ) { if (type == ColorAdjustTypeDefault) { type = ColorAdjustTypeBrush; }
if (Image != NULL) { Image->ColorAdjust(recolor, type); UpdateUid(); }
return Ok; }
VOID GpTexture::InitializeBrush( GpImage* image, GpWrapMode wrapMode, const GpRectF* rect, const GpImageAttributes *imageAttributes) { ASSERT(image && image->IsValid());
if (!WrapModeIsValid(wrapMode)) { WARNING(("bad wrap mode")); goto Failure; }
GpImageType imageType;
imageType = image->GetImageType();
if (imageType == ImageTypeBitmap) { InitializeBrushBitmap( static_cast<GpBitmap*>(image), wrapMode, rect, imageAttributes ); } else if (imageType == ImageTypeMetafile) { // For now, convert the metafile into a bitmap image and use that to
// create the brush.
GpBitmap * bitmapImage;
if (rect != NULL) { // !!! we don't handle this case yet
if ((rect->X != 0) || (rect->Y != 0)) { WARNING(("No handling for non-zero start in metafiles")); } // Don't apply the imageAttributes now, because WMF/EMF rendering
// doesn't support alpha. So wait until it's been converted to
// a bitmap to apply the imageAttributes.
bitmapImage = ((GpMetafile *)image)->GetBitmap( GpRound(rect->Width), GpRound(rect->Height), NULL); } else { // Let the metafile decide how big the bitmap should be
// Don't apply the imageAttributes now, because WMF/EMF rendering
// doesn't support alpha. So wait until it's been converted to
// a bitmap to apply the imageAttributes.
bitmapImage = ((GpMetafile *)image)->GetBitmap(0, 0, NULL); }
if (bitmapImage != NULL) { ASSERT (bitmapImage->IsValid());
InitializeBrushBitmap(bitmapImage, wrapMode, NULL, imageAttributes, TRUE); return; } goto Failure; } else // unknown image type
{ WARNING(("unknown image type")); Failure: Image = NULL; SetValid(FALSE); } }
VOID GpTexture::InitializeBrushBitmap( GpBitmap* bitmap, GpWrapMode wrapMode, const GpRectF* rect, const GpImageAttributes *imageAttributes, BOOL useBitmap) { DeviceBrush.Type = BrushTypeTextureFill; DeviceBrush.Wrap = wrapMode;
ImageType = ImageTypeBitmap;
Image = NULL;
FPUStateSaver fpState; // Setup the fpu state.
if (bitmap && bitmap->IsValid()) { GpRect *pRectI = NULL; GpRect recti; if(rect) { recti.X = GpRound(rect->X); recti.Y = GpRound(rect->Y); recti.Width = GpRound(rect->Width); recti.Height = GpRound(rect->Height); pRectI = &recti; }
if(imageAttributes) { GpBitmap *dst = NULL;
if (bitmap->Recolor( imageAttributes->recolor, &dst, NULL, NULL, pRectI ) == Ok) { Image = dst; // If useBitmap is TRUE that means the caller has transferred
// ownership of bitmap to us. In this case, Recolor makes
// a clone of the bitmap that we're going to use, so we have
// to free the bitmap passed in and use the clone instead,
// otherwise we leak.
if(useBitmap) { bitmap->Dispose(); } } }
// !!! note that this should be non-premultiplied ARGB.
// we'll fix this when we drop premultiplied data [asecchia]
// also note that the output of RecolorImage is 32BPP_ARGB
// if it's not NULL it's because the RecolorImage code cloned it already
if (Image == NULL) { if (useBitmap) { // This is for the case where we constructed a bitmap
// from a metafile image.
Image = bitmap; } else { #ifdef NO_PREMULTIPLIED_ALPHA
Image = bitmap->Clone(pRectI, PIXFMT_32BPP_ARGB); #else
Image = bitmap->Clone(pRectI, PIXFMT_32BPP_PARGB); #endif
} } }
if (Image && Image->IsValid()) { SetValid(TRUE);
// Rect is given as a pixel unit in bitmap.
GpPageUnit unit; Image->GetBounds(&DeviceBrush.Rect, &unit); } else { SetValid(FALSE);
GpMemset(&DeviceBrush.Rect, 0, sizeof(DeviceBrush.Rect)); } }
// See if this texture fill is really a picture fill (with a bitmap,
// not a metafile).
BOOL GpTexture::IsPictureFill( const GpMatrix * worldToDevice, const GpRect * drawBounds ) const { ASSERT ((drawBounds->Width > 0) && (drawBounds->Height > 0));
BOOL isPictureFill = FALSE; GpMatrix newBrushMatrix; this->GetTransform(&newBrushMatrix);
if (worldToDevice != NULL) { newBrushMatrix.Append(*worldToDevice); }
newBrushMatrix.Translate( (REAL)-(drawBounds->X), (REAL)-(drawBounds->Y), MatrixOrderAppend );
// See if the texture is supposed to fill the drawBounds.
// If so, this is a picture fill.
if (newBrushMatrix.IsTranslateScale()) { Size size;
// If the texture is not a bitmap, this returns InvalidParameter.
if (this->GetBitmapSize(&size) == Ok) { GpRectF transformedRect(0.0f, 0.0f, (REAL)size.Width, (REAL)size.Height); newBrushMatrix.TransformRect(transformedRect);
// get the transformed width
INT deltaValue = abs(GpRound(transformedRect.Width) - drawBounds->Width); // We might be off a little because of the pixel offset mode
// or a matrix that isn't quite right for whatever reason.
if (deltaValue <= 2) { // get the transformed height
deltaValue = abs(GpRound(transformedRect.Height) - drawBounds->Height);
if (deltaValue <= 2) { if ((abs(GpRound(transformedRect.X)) <= 2) && (abs(GpRound(transformedRect.Y)) <= 2)) { isPictureFill = TRUE; } } } } } return isPictureFill; }
class RectGradientBrushData : public ObjectTypeData { public: INT32 Flags; INT32 Wrap; GpRectF Rect; UINT32 Color0; UINT32 Color1; UINT32 Color2; UINT32 Color3; };
/**************************************************************************\
* * Function Description: * * Get the brush data. * * Arguments: * * [IN] dataBuffer - fill this buffer with the data * [IN/OUT] size - IN - size of buffer; OUT - number bytes written * * Return Value: * * GpStatus - Ok or error code * * Created: * * 9/13/1999 DCurtis * \**************************************************************************/ GpStatus GpRectGradient::GetData( IStream * stream ) const { ASSERT (stream != NULL);
INT flags = 0;
if (DeviceBrush.IsGammaCorrected) { flags |= GDIP_BRUSHFLAGS_ISGAMMACORRECTED; }
if (!DeviceBrush.Xform.IsIdentity()) { flags |= GDIP_BRUSHFLAGS_TRANSFORM; }
// Note: can't have both blendFactors and presetColors at the same time
// PresetColors used for GpLineGradient, but not for GpRectGradient.
if (DeviceBrush.UsesPresetColors && (DeviceBrush.BlendCounts[0] > 1) && (DeviceBrush.PresetColors != NULL) && (DeviceBrush.BlendPositions[0] != NULL) && (DeviceBrush.BlendFactors[0] == NULL)) { flags |= GDIP_BRUSHFLAGS_PRESETCOLORS; }
if ((DeviceBrush.BlendCounts[0] > 1) && (DeviceBrush.BlendFactors[0] != NULL) && (DeviceBrush.BlendPositions[0] != NULL)) { flags |= GDIP_BRUSHFLAGS_BLENDFACTORSH; }
if ((DeviceBrush.BlendCounts[1] > 1) && (DeviceBrush.BlendFactors[1] != NULL) && (DeviceBrush.BlendPositions[1] != NULL)) { flags |= GDIP_BRUSHFLAGS_BLENDFACTORSV; }
RectGradientBrushData brushData; brushData.Type = DeviceBrush.Type; brushData.Flags = flags; brushData.Wrap = DeviceBrush.Wrap; brushData.Rect = DeviceBrush.Rect; brushData.Color0 = DeviceBrush.Colors[0].GetValue(); brushData.Color1 = DeviceBrush.Colors[1].GetValue(); brushData.Color2 = DeviceBrush.Colors[2].GetValue(); brushData.Color3 = DeviceBrush.Colors[3].GetValue(); stream->Write(&brushData, sizeof(brushData), NULL);
if (flags & GDIP_BRUSHFLAGS_TRANSFORM) { DeviceBrush.Xform.WriteMatrix(stream); }
if (flags & GDIP_BRUSHFLAGS_PRESETCOLORS) { INT realSize = DeviceBrush.BlendCounts[0] * sizeof(REAL); INT argbSize = DeviceBrush.BlendCounts[0] * sizeof(ARGB);
stream->Write(&DeviceBrush.BlendCounts[0], sizeof(INT32), NULL); stream->Write(DeviceBrush.BlendPositions[0], realSize, NULL); stream->Write(DeviceBrush.PresetColors, argbSize, NULL); }
if (flags & GDIP_BRUSHFLAGS_BLENDFACTORSH) { INT realSize = DeviceBrush.BlendCounts[0] * sizeof(REAL);
stream->Write(&DeviceBrush.BlendCounts[0], sizeof(INT32), NULL); stream->Write(DeviceBrush.BlendPositions[0], realSize, NULL); stream->Write(DeviceBrush.BlendFactors[0], realSize, NULL); }
if (flags & GDIP_BRUSHFLAGS_BLENDFACTORSV) { INT realSize = DeviceBrush.BlendCounts[1] * sizeof(REAL);
stream->Write(&DeviceBrush.BlendCounts[1], sizeof(INT32), NULL); stream->Write(DeviceBrush.BlendPositions[1], realSize, NULL); stream->Write(DeviceBrush.BlendFactors[1], realSize, NULL); }
return Ok; }
UINT GpRectGradient::GetDataSize() const { UINT size = sizeof(RectGradientBrushData);
if (!DeviceBrush.Xform.IsIdentity()) { size += GDIP_MATRIX_SIZE; }
// Note: can't have both blendFactors and presetColors at the same time
// PresetColors used for GpLineGradient, but not for GpRectGradient.
if (DeviceBrush.UsesPresetColors && (DeviceBrush.BlendCounts[0] > 1) && (DeviceBrush.PresetColors != NULL) && (DeviceBrush.BlendPositions[0] != NULL) && (DeviceBrush.BlendFactors[0] == NULL)) { size += sizeof(INT32) + ((sizeof(ARGB) + sizeof(REAL)) * DeviceBrush.BlendCounts[0]); }
if ((DeviceBrush.BlendCounts[0] > 1) && (DeviceBrush.BlendFactors[0] != NULL) && (DeviceBrush.BlendPositions[0] != NULL)) { size += sizeof(INT32) + ((sizeof(REAL) + sizeof(REAL)) * DeviceBrush.BlendCounts[0]); }
if ((DeviceBrush.BlendCounts[1] > 1) && (DeviceBrush.BlendFactors[1] != NULL) && (DeviceBrush.BlendPositions[1] != NULL)) { size += sizeof(INT32) + ((sizeof(REAL) + sizeof(REAL)) * DeviceBrush.BlendCounts[1]); }
return size; }
/**************************************************************************\
* * Function Description: * * Read the brush object from memory. * * Arguments: * * [IN] dataBuffer - the data that was read from the stream * [IN] size - the size of the data * * Return Value: * * GpStatus - Ok or failure status * * Created: * * 4/26/1999 DCurtis * \**************************************************************************/ GpStatus GpRectGradient::SetData( const BYTE * dataBuffer, UINT size ) { ASSERT ((GpBrushType)(((RectGradientBrushData *)dataBuffer)->Type) == BrushTypeLinearGradient);
if (dataBuffer == NULL) { WARNING(("dataBuffer is NULL")); return InvalidParameter; }
if (size < sizeof(RectGradientBrushData)) { WARNING(("size too small")); return InvalidParameter; }
const RectGradientBrushData * brushData; GpColor colors[4];
brushData = reinterpret_cast<const RectGradientBrushData *>(dataBuffer);
if (!brushData->MajorVersionMatches()) { WARNING(("Version number mismatch")); return InvalidParameter; }
colors[0].SetValue(brushData->Color0); colors[1].SetValue(brushData->Color1); colors[2].SetValue(brushData->Color2); colors[3].SetValue(brushData->Color3);
InitializeBrush(brushData->Rect, colors, (GpWrapMode) brushData->Wrap);
DeviceBrush.IsGammaCorrected = ((brushData->Flags & GDIP_BRUSHFLAGS_ISGAMMACORRECTED) != 0);
dataBuffer += sizeof(RectGradientBrushData); size -= sizeof(RectGradientBrushData);
if (brushData->Flags & GDIP_BRUSHFLAGS_TRANSFORM) { if (size < GDIP_MATRIX_SIZE) { WARNING(("size too small")); return InvalidParameter; } DeviceBrush.Xform.SetMatrix((REAL *)dataBuffer); dataBuffer += GDIP_MATRIX_SIZE; size -= GDIP_MATRIX_SIZE; }
if (brushData->Flags & GDIP_BRUSHFLAGS_PRESETCOLORS) { if (size < sizeof(INT32)) { WARNING(("size too small")); return InvalidParameter; }
UINT count = ((INT32 *)dataBuffer)[0]; dataBuffer += sizeof(INT32); size -= sizeof(INT32);
UINT realSize = count * sizeof(REAL); UINT argbSize = count * sizeof(ARGB);
if (size < (realSize + argbSize)) { WARNING(("size too small")); return InvalidParameter; }
ARGB* newColors = (ARGB*) GpRealloc(DeviceBrush.PresetColors, argbSize);
if (newColors != NULL) { // We have to just copy in the ARGB values, because they've already
// been premultiplied.
// Actually PresetColors is NON-premultiplied, but this code should
// still be right because we write them out non-premultiplied too.
GpMemcpy(newColors, dataBuffer + realSize, argbSize); DeviceBrush.PresetColors = newColors;
REAL* newPositions = (REAL*) GpRealloc(DeviceBrush.BlendPositions[0], realSize);
if (newPositions != NULL) { GpMemcpy(newPositions, dataBuffer, realSize); DeviceBrush.BlendPositions[0] = newPositions;
GpFree(DeviceBrush.BlendFactors[0]); DeviceBrush.BlendFactors[0] = NULL; DeviceBrush.UsesPresetColors = TRUE; DeviceBrush.BlendCounts[0] = count; } }
dataBuffer += (realSize + argbSize); size -= (realSize + argbSize); }
if (brushData->Flags & GDIP_BRUSHFLAGS_BLENDFACTORSH) { if (size < sizeof(INT32)) { WARNING(("size too small")); return InvalidParameter; }
UINT count = ((INT32 *)dataBuffer)[0]; dataBuffer += sizeof(INT32); size -= sizeof(INT32);
UINT realSize = count * sizeof(REAL);
if (size < (2 * realSize)) { WARNING(("size too small")); return InvalidParameter; }
this->SetHorizontalBlend((REAL *)(dataBuffer + realSize),(REAL *)dataBuffer, count); dataBuffer += (2 * realSize); size -= (2 * realSize); }
if (brushData->Flags & GDIP_BRUSHFLAGS_BLENDFACTORSV) { if (size < sizeof(INT32)) { WARNING(("size too small")); return InvalidParameter; }
UINT count = ((INT32 *)dataBuffer)[0]; dataBuffer += sizeof(INT32); size -= sizeof(INT32);
UINT realSize = count * sizeof(REAL);
if (size < (2 * realSize)) { WARNING(("size too small")); return InvalidParameter; }
this->SetVerticalBlend((REAL *)(dataBuffer + realSize), (REAL *)dataBuffer, count); dataBuffer += (2 * realSize); size -= (2 * realSize); } UpdateUid(); return Ok; }
GpStatus GpRectGradient::ColorAdjust( GpRecolor * recolor, ColorAdjustType type ) { if(!recolor) return InvalidParameter;
if (type == ColorAdjustTypeDefault) { type = ColorAdjustTypeBrush; }
ARGB solidColor32[4];
solidColor32[0] = DeviceBrush.Colors[0].GetValue(); solidColor32[1] = DeviceBrush.Colors[1].GetValue(); solidColor32[2] = DeviceBrush.Colors[2].GetValue(); solidColor32[3] = DeviceBrush.Colors[3].GetValue();
recolor->ColorAdjust(solidColor32, 4, type);
DeviceBrush.Colors[0].SetValue(solidColor32[0]); DeviceBrush.Colors[1].SetValue(solidColor32[1]); DeviceBrush.Colors[2].SetValue(solidColor32[2]); DeviceBrush.Colors[3].SetValue(solidColor32[3]);
if (DeviceBrush.UsesPresetColors && (DeviceBrush.BlendCounts[0] > 1) && (DeviceBrush.PresetColors != NULL)) { recolor->ColorAdjust(DeviceBrush.PresetColors, DeviceBrush.BlendCounts[0], type); }
UpdateUid(); return Ok; }
#if 0
class RadialGradientBrushData : public ObjectTypeData { public: INT32 Flags; INT32 Wrap; GpRectF Rect; UINT32 CenterColor; UINT32 BoundaryColor; };
/**************************************************************************\
* * Function Description: * * Get the brush data. * * Arguments: * * [IN] dataBuffer - fill this buffer with the data * [IN/OUT] size - IN - size of buffer; OUT - number bytes written * * Return Value: * * GpStatus - Ok or error code * * Created: * * 9/13/1999 DCurtis * \**************************************************************************/ GpStatus GpRadialGradient::GetData( IStream * stream ) const { ASSERT (stream != NULL);
INT flags = 0;
if (DeviceBrush.IsGammaCorrected) { flags |= GDIP_BRUSHFLAGS_ISGAMMACORRECTED; }
if (!DeviceBrush.Xform.IsIdentity()) { flags |= GDIP_BRUSHFLAGS_TRANSFORM; }
// Note: can't have both blendFactors and presetColors at the same time
if (DeviceBrush.UsesPresetColors && (DeviceBrush.BlendCounts[0] > 1) && (DeviceBrush.PresetColors != NULL) && (DeviceBrush.BlendPositions[0] != NULL) && (DeviceBrush.BlendFactors[0] == NULL)) { flags |= GDIP_BRUSHFLAGS_PRESETCOLORS; }
if ((DeviceBrush.BlendCounts[0] > 1) && (DeviceBrush.BlendFactors[0] != NULL) && (DeviceBrush.BlendPositions[0] != NULL)) { flags |= GDIP_BRUSHFLAGS_BLENDFACTORS; }
RadialGradientBrushData brushData; brushData.Type = DeviceBrush.Type; brushData.Flags = flags; brushData.Wrap = DeviceBrush.Wrap; brushData.Rect = DeviceBrush.Rect; brushData.CenterColor = DeviceBrush.Colors[0].GetValue(); brushData.BoundaryColor = DeviceBrush.Colors[1].GetValue(); stream->Write(&brushData, sizeof(brushData), NULL);
if (flags & GDIP_BRUSHFLAGS_TRANSFORM) { DeviceBrush.Xform.WriteMatrix(stream); }
if (flags & GDIP_BRUSHFLAGS_PRESETCOLORS) { INT realSize = DeviceBrush.BlendCounts[0] * sizeof(REAL); INT argbSize = DeviceBrush.BlendCounts[0] * sizeof(ARGB);
stream->Write(&DeviceBrush.BlendCounts[0], sizeof(INT32), NULL); stream->Write(DeviceBrush.BlendPositions[0], realSize, NULL); stream->Write(DeviceBrush.PresetColors, argbSize, NULL); }
if (flags & GDIP_BRUSHFLAGS_BLENDFACTORS) { INT realSize = DeviceBrush.BlendCounts[0] * sizeof(REAL);
stream->Write(&DeviceBrush.BlendCounts[0], sizeof(INT32), NULL); stream->Write(DeviceBrush.BlendPositions[0], realSize, NULL); stream->Write(DeviceBrush.BlendFactors[0], realSize, NULL); }
return Ok; }
UINT GpRadialGradient::GetDataSize() const { UINT size = sizeof(RadialGradientBrushData);
if (!DeviceBrush.Xform.IsIdentity()) { size += GDIP_MATRIX_SIZE; }
// Note: can't have both blendFactors and presetColors at the same time
if (DeviceBrush.UsesPresetColors && (DeviceBrush.BlendCounts[0] > 1) && (DeviceBrush.PresetColors != NULL) && (DeviceBrush.BlendPositions[0] != NULL) && (DeviceBrush.BlendFactors[0] == NULL)) { size += sizeof(INT32) + ((sizeof(ARGB) + sizeof(REAL)) * DeviceBrush.BlendCounts[0]); }
if ((DeviceBrush.BlendCounts[0] > 1) && (DeviceBrush.BlendFactors[0] != NULL) && (DeviceBrush.BlendPositions[0] != NULL)) { size += sizeof(INT32) + ((sizeof(REAL) + sizeof(REAL)) * DeviceBrush.BlendCounts[0]); }
return size; }
/**************************************************************************\
* * Function Description: * * Read the brush object from memory. * * Arguments: * * [IN] dataBuffer - the data that was read from the stream * [IN] size - the size of the data * * Return Value: * * GpStatus - Ok or failure status * * Created: * * 4/26/1999 DCurtis * \**************************************************************************/ GpStatus GpRadialGradient::SetData( const BYTE * dataBuffer, UINT size ) { // ASSERT ((GpBrushType)(((RadialGradientBrushData *)dataBuffer)->Type) == BrushTypeRadialGradient);
if (dataBuffer == NULL) { WARNING(("dataBuffer is NULL")); return InvalidParameter; }
if (size < sizeof(RadialGradientBrushData)) { WARNING(("size too small")); return InvalidParameter; }
const RadialGradientBrushData * brushData; GpColor centerColor; GpColor boundaryColor;
brushData = reinterpret_cast<const RadialGradientBrushData *>(dataBuffer);
if (!brushData->MajorVersionMatches()) { WARNING(("Version number mismatch")); return InvalidParameter; }
centerColor.SetValue(brushData->CenterColor); boundaryColor.SetValue(brushData->BoundaryColor);
InitializeBrush( brushData->Rect, centerColor, boundaryColor, (GpWrapMode) brushData->Wrap );
DeviceBrush.IsGammaCorrected = ((brushData->Flags & GDIP_BRUSHFLAGS_ISGAMMACORRECTED) != 0);
dataBuffer += sizeof(RadialGradientBrushData); size -= sizeof(RadialGradientBrushData);
if (brushData->Flags & GDIP_BRUSHFLAGS_TRANSFORM) { if (size < GDIP_MATRIX_SIZE) { WARNING(("size too small")); return InvalidParameter; }
DeviceBrush.Xform.SetMatrix((REAL *)dataBuffer); dataBuffer += GDIP_MATRIX_SIZE; size -= GDIP_MATRIX_SIZE; }
if (brushData->Flags & GDIP_BRUSHFLAGS_PRESETCOLORS) { if (size < sizeof(INT32)) { WARNING(("size too small")); return InvalidParameter; }
UINT count = ((INT32 *)dataBuffer)[0]; dataBuffer += sizeof(INT32); size -= sizeof(INT32);
UINT realSize = count * sizeof(REAL); UINT argbSize = count * sizeof(ARGB);
if (size < (realSize + argbSize)) { WARNING(("size too small")); return InvalidParameter; }
ARGB* newColors = (ARGB*) GpRealloc(DeviceBrush.PresetColors, argbSize);
if (newColors != NULL) { // We have to just copy in the ARGB values, because they've already
// been premultiplied.
GpMemcpy(newColors, dataBuffer + realSize, argbSize); DeviceBrush.PresetColors = newColors;
REAL* newPositions = (REAL*) GpRealloc(DeviceBrush.BlendPositions[0], realSize);
if (newPositions != NULL) { GpMemcpy(newPositions, dataBuffer, realSize); DeviceBrush.BlendPositions[0] = newPositions;
GpFree(DeviceBrush.BlendFactors[0]); DeviceBrush.BlendFactors[0] = NULL; DeviceBrush.UsesPresetColors = TRUE; DeviceBrush.BlendCounts[0] = count; } }
dataBuffer += (realSize + argbSize); size -= (realSize + argbSize); }
if (brushData->Flags & GDIP_BRUSHFLAGS_BLENDFACTORS) { if (size < sizeof(INT32)) { WARNING(("size too small")); return InvalidParameter; }
UINT count = ((INT32 *)dataBuffer)[0]; dataBuffer += sizeof(INT32); size -= sizeof(INT32);
UINT realSize = count * sizeof(REAL);
if (size < (2 * realSize)) { WARNING(("size too small")); return InvalidParameter; }
this->SetBlend((REAL *)(dataBuffer + realSize), (REAL *)dataBuffer, count); dataBuffer += (2 * realSize); size -= (2 * realSize); }
UpdateUid(); return Ok; }
GpStatus GpRadialGradient::ColorAdjust( GpRecolor * recolor, ColorAdjustType type ) { if(!recolor) return InvalidParameter;
if (type == ColorAdjustTypeDefault) { type = ColorAdjustTypeBrush; }
ARGB solidColor32[2];
solidColor32[0] = DeviceBrush.Colors[0].GetValue(); solidColor32[1] = DeviceBrush.Colors[1].GetValue();
recolor->ColorAdjust(solidColor32, 2, type);
DeviceBrush.Colors[0].SetValue(solidColor32[0]); DeviceBrush.Colors[1].SetValue(solidColor32[1]);
if (DeviceBrush.UsesPresetColors && (DeviceBrush.BlendCounts[0] > 1) && (DeviceBrush.PresetColors != NULL)) { recolor->ColorAdjust(DeviceBrush.PresetColors, DeviceBrush.BlendCounts[0], type); }
UpdateUid(); return Ok; }
class TriangleGradientBrushData : public ObjectTypeData { public: INT32 Flags; INT32 Wrap; GpPointF Points[3]; UINT32 Color0; UINT32 Color1; UINT32 Color2; };
/**************************************************************************\
* * Function Description: * * Get the brush data. * * Arguments: * * [IN] dataBuffer - fill this buffer with the data * [IN/OUT] size - IN - size of buffer; OUT - number bytes written * * Return Value: * * GpStatus - Ok or error code * * Created: * * 9/13/1999 DCurtis * \**************************************************************************/ GpStatus GpTriangleGradient::GetData( IStream * stream ) const { ASSERT (stream != NULL);
INT flags = 0;
if (DeviceBrush.IsGammaCorrected) { flags |= GDIP_BRUSHFLAGS_ISGAMMACORRECTED; }
if (!DeviceBrush.Xform.IsIdentity()) { flags |= GDIP_BRUSHFLAGS_TRANSFORM; }
if ((DeviceBrush.BlendCounts[0] > 1) && (DeviceBrush.BlendFactors[0] != NULL) && (DeviceBrush.BlendPositions[0] != NULL)) { flags |= GDIP_BRUSHFLAGS_BLENDFACTORS0; }
if ((DeviceBrush.BlendCounts[1] > 1) && (DeviceBrush.BlendFactors[1] != NULL) && (DeviceBrush.BlendPositions[1] != NULL)) { flags |= GDIP_BRUSHFLAGS_BLENDFACTORS1; }
if ((DeviceBrush.BlendCounts[2] > 1) && (DeviceBrush.BlendFactors[2] != NULL) && (DeviceBrush.BlendPositions[2] != NULL)) { flags |= GDIP_BRUSHFLAGS_BLENDFACTORS2; }
TriangleGradientBrushData brushData; brushData.Type = DeviceBrush.Type; brushData.Flags = flags; brushData.Wrap = DeviceBrush.Wrap; brushData.Points[0] = DeviceBrush.Points[0]; brushData.Points[1] = DeviceBrush.Points[1]; brushData.Points[2] = DeviceBrush.Points[2]; brushData.Color0 = DeviceBrush.Colors[0].GetValue(); brushData.Color1 = DeviceBrush.Colors[1].GetValue(); brushData.Color2 = DeviceBrush.Colors[2].GetValue(); stream->Write(&brushData, sizeof(brushData), NULL);
if (flags & GDIP_BRUSHFLAGS_TRANSFORM) { DeviceBrush.Xform.WriteMatrix(stream); }
if (flags & GDIP_BRUSHFLAGS_BLENDFACTORS0) { INT realSize = DeviceBrush.BlendCounts[0] * sizeof(REAL);
stream->Write(&DeviceBrush.BlendCounts[0], sizeof(INT32), NULL); stream->Write(DeviceBrush.BlendPositions[0], realSize, NULL); stream->Write(DeviceBrush.BlendFactors[0], realSize, NULL); }
if (flags & GDIP_BRUSHFLAGS_BLENDFACTORS1) { INT realSize = DeviceBrush.BlendCounts[1] * sizeof(REAL);
stream->Write(&DeviceBrush.BlendCounts[1], sizeof(INT32), NULL); stream->Write(DeviceBrush.BlendPositions[1], realSize, NULL); stream->Write(DeviceBrush.BlendFactors[1], realSize, NULL); }
if (flags & GDIP_BRUSHFLAGS_BLENDFACTORS2) { INT realSize = DeviceBrush.BlendCounts[2] * sizeof(REAL);
stream->Write(&DeviceBrush.BlendCounts[2], sizeof(INT32), NULL); stream->Write(DeviceBrush.BlendPositions[2], realSize, NULL); stream->Write(DeviceBrush.BlendFactors[2], realSize, NULL); }
return Ok; }
UINT GpTriangleGradient::GetDataSize() const { UINT size = sizeof(RectGradientBrushData);
if (!DeviceBrush.Xform.IsIdentity()) { size += GDIP_MATRIX_SIZE; }
if ((DeviceBrush.BlendCounts[0] > 1) && (DeviceBrush.BlendFactors[0] != NULL) && (DeviceBrush.BlendPositions[0] != NULL)) { size += sizeof(INT32) + ((sizeof(REAL) + sizeof(REAL)) * DeviceBrush.BlendCounts[0]); }
if ((DeviceBrush.BlendCounts[1] > 1) && (DeviceBrush.BlendFactors[1] != NULL) && (DeviceBrush.BlendPositions[1] != NULL)) { size += sizeof(INT32) + ((sizeof(REAL) + sizeof(REAL)) * DeviceBrush.BlendCounts[1]); }
if ((DeviceBrush.BlendCounts[2] > 1) && (DeviceBrush.BlendFactors[2] != NULL) && (DeviceBrush.BlendPositions[2] != NULL)) { size += sizeof(INT32) + ((sizeof(REAL) + sizeof(REAL)) * DeviceBrush.BlendCounts[2]); }
return size; }
/**************************************************************************\
* * Function Description: * * Read the brush object from memory. * * Arguments: * * [IN] dataBuffer - the data that was read from the stream * [IN] size - the size of the data * * Return Value: * * GpStatus - Ok or failure status * * Created: * * 4/26/1999 DCurtis * \**************************************************************************/ GpStatus GpTriangleGradient::SetData( const BYTE * dataBuffer, UINT size ) { // ASSERT ((GpBrushType)(((TriangleGradientBrushData *)dataBuffer)->Type) == BrushTypeTriangleGradient);
if (dataBuffer == NULL) { WARNING(("dataBuffer is NULL")); return InvalidParameter; }
if (size < sizeof(TriangleGradientBrushData)) { WARNING(("size too small")); return InvalidParameter; }
const TriangleGradientBrushData * brushData; GpColor colors[3];
brushData = reinterpret_cast<const TriangleGradientBrushData *>(dataBuffer);
if (!brushData->MajorVersionMatches()) { WARNING(("Version number mismatch")); return InvalidParameter; }
colors[0].SetValue(brushData->Color0); colors[1].SetValue(brushData->Color1); colors[2].SetValue(brushData->Color2);
InitializeBrush(brushData->Points, colors, (GpWrapMode) brushData->Wrap);
DeviceBrush.IsGammaCorrected = ((brushData->Flags & GDIP_BRUSHFLAGS_ISGAMMACORRECTED) != 0);
dataBuffer += sizeof(TriangleGradientBrushData); size -= sizeof(TriangleGradientBrushData);
if (brushData->Flags & GDIP_BRUSHFLAGS_TRANSFORM) { if (size < GDIP_MATRIX_SIZE) { WARNING(("size too small")); return InvalidParameter; }
DeviceBrush.Xform.SetMatrix((REAL *)dataBuffer); dataBuffer += GDIP_MATRIX_SIZE; size -= GDIP_MATRIX_SIZE; }
if (brushData->Flags & GDIP_BRUSHFLAGS_BLENDFACTORS0) { if (size < sizeof(INT32)) { WARNING(("size too small")); return InvalidParameter; }
UINT count = ((INT32 *)dataBuffer)[0]; dataBuffer += sizeof(INT32); size -= sizeof(INT32);
UINT realSize = count * sizeof(REAL);
if (size < (2 * realSize)) { WARNING(("size too small")); return InvalidParameter; }
this->SetBlend0((REAL *)(dataBuffer + realSize), (REAL *)dataBuffer, count); dataBuffer += (2 * realSize); size -= (2 * realSize); }
if (brushData->Flags & GDIP_BRUSHFLAGS_BLENDFACTORS1) { if (size < sizeof(INT32)) { WARNING(("size too small")); return InvalidParameter; }
UINT count = ((INT32 *)dataBuffer)[0]; dataBuffer += sizeof(INT32); size -= sizeof(INT32);
UINT realSize = count * sizeof(REAL);
if (size < (2 * realSize)) { WARNING(("size too small")); return InvalidParameter; }
this->SetBlend1((REAL *)(dataBuffer + realSize), (REAL *)dataBuffer, count); dataBuffer += (2 * realSize); size -= (2 * realSize); }
if (brushData->Flags & GDIP_BRUSHFLAGS_BLENDFACTORS2) { if (size < sizeof(INT32)) { WARNING(("size too small")); return InvalidParameter; }
UINT count = ((INT32 *)dataBuffer)[0]; dataBuffer += sizeof(INT32); size -= sizeof(INT32);
UINT realSize = count * sizeof(REAL);
if (size < (2 * realSize)) { WARNING(("size too small")); return InvalidParameter; }
this->SetBlend2((REAL *)(dataBuffer + realSize), (REAL *)dataBuffer, count); dataBuffer += (2 * realSize); size -= (2 * realSize); }
UpdateUid(); return Ok; }
GpStatus GpTriangleGradient::ColorAdjust( GpRecolor * recolor, ColorAdjustType type ) { if(!recolor) return InvalidParameter;
if (type == ColorAdjustTypeDefault) { type = ColorAdjustTypeBrush; }
ARGB solidColor32[3];
solidColor32[0] = DeviceBrush.Colors[0].GetValue(); solidColor32[1] = DeviceBrush.Colors[1].GetValue(); solidColor32[2] = DeviceBrush.Colors[2].GetValue();
recolor->ColorAdjust(solidColor32, 3, type);
DeviceBrush.Colors[0].SetValue(solidColor32[0]); DeviceBrush.Colors[1].SetValue(solidColor32[1]); DeviceBrush.Colors[2].SetValue(solidColor32[2]);
UpdateUid(); return Ok; } #endif
class PathGradientBrushData : public ObjectTypeData { public: INT32 Flags; INT32 Wrap; UINT32 CenterColor; GpPointF CenterPoint; UINT32 SurroundingColorCount; };
/**************************************************************************\
* * Function Description: * * Get the brush data. * * Arguments: * * [IN] dataBuffer - fill this buffer with the data * [IN/OUT] size - IN - size of buffer; OUT - number bytes written * * Return Value: * * GpStatus - Ok or error code * * Created: * * 9/13/1999 DCurtis * \**************************************************************************/ GpStatus GpPathGradient::GetData( IStream * stream ) const { ASSERT (stream != NULL);
UINT pathSize = 0; UINT surroundingColorCount = DeviceBrush.OneSurroundColor ? 1 : DeviceBrush.Count; INT flags = 0; GpPath * path = GpPath::GetPath(DeviceBrush.Path);
if (DeviceBrush.IsGammaCorrected) { flags |= GDIP_BRUSHFLAGS_ISGAMMACORRECTED; }
if ((DeviceBrush.PointsPtr == NULL) && (path != NULL)) { flags |= GDIP_BRUSHFLAGS_PATH; pathSize = path->GetDataSize(); ASSERT((pathSize & 0x03) == 0); }
if (!DeviceBrush.Xform.IsIdentity()) { flags |= GDIP_BRUSHFLAGS_TRANSFORM; }
// Note: can't have both blendFactors and presetColors at the same time
if (DeviceBrush.UsesPresetColors && (DeviceBrush.BlendCounts[0] > 1) && (DeviceBrush.PresetColors != NULL) && (DeviceBrush.BlendPositions[0] != NULL) && (DeviceBrush.BlendFactors[0] == NULL)) { flags |= GDIP_BRUSHFLAGS_PRESETCOLORS; }
if ((DeviceBrush.BlendCounts[0] > 1) && (DeviceBrush.BlendFactors[0] != NULL) && (DeviceBrush.BlendPositions[0] != NULL)) { flags |= GDIP_BRUSHFLAGS_BLENDFACTORS; }
if((DeviceBrush.FocusScaleX != 0) || (DeviceBrush.FocusScaleY != 0)) { flags |= GDIP_BRUSHFLAGS_FOCUSSCALES; }
PathGradientBrushData brushData; brushData.Type = DeviceBrush.Type; brushData.Flags = flags; brushData.Wrap = DeviceBrush.Wrap; brushData.CenterColor = DeviceBrush.Colors[0].GetValue(); brushData.CenterPoint = DeviceBrush.Points[0]; brushData.SurroundingColorCount = surroundingColorCount; stream->Write(&brushData, sizeof(brushData), NULL);
ARGB argb;
for (UINT i = 0; i < surroundingColorCount; i++) { argb = DeviceBrush.ColorsPtr[i].GetValue(); stream->Write(&argb, sizeof(argb), NULL); }
if (flags & GDIP_BRUSHFLAGS_PATH) { stream->Write(&pathSize, sizeof(INT32), NULL); path->GetData(stream); } else { INT count = DeviceBrush.Count;
if (DeviceBrush.PointsPtr == NULL) { count = 0; } stream->Write(&count, sizeof(INT32), NULL); if (count > 0) { INT pointsSize = count * sizeof(DeviceBrush.PointsPtr[0]); stream->Write(DeviceBrush.PointsPtr, pointsSize, NULL); } }
if (flags & GDIP_BRUSHFLAGS_TRANSFORM) { DeviceBrush.Xform.WriteMatrix(stream); }
if (flags & GDIP_BRUSHFLAGS_PRESETCOLORS) { INT count = DeviceBrush.BlendCounts[0]; INT realSize = count * sizeof(REAL); INT argbSize = count * sizeof(ARGB);
REAL *newPositions = (REAL*) GpMalloc(realSize);
if (newPositions == NULL ) { return OutOfMemory; }
ARGB *newARGB = (ARGB*) GpMalloc(argbSize);
if (newARGB == NULL ) { GpFree(newPositions); return OutOfMemory; }
GpColor *newPresetColors = new GpColor[count];
if (newPresetColors == NULL) { GpFree(newPositions); GpFree (newARGB); return OutOfMemory; }
// Users will supply the preset colors as radial blend colors.
// 0 position means the center location and 1 position means the
// the outer edge. These are stored inverted internally, so to get back
// to the original user values, invert again.
GetPresetBlend(newPresetColors, newPositions, count);
for (INT i = 0; i < count; i++) { newARGB[i] = newPresetColors[i].GetValue(); }
stream->Write(&count, sizeof(INT32), NULL); stream->Write(newPositions, realSize, NULL); stream->Write(newARGB, argbSize, NULL);
GpFree(newPositions); GpFree(newARGB); delete newPresetColors; }
if (flags & GDIP_BRUSHFLAGS_BLENDFACTORS) { INT count = DeviceBrush.BlendCounts[0]; INT realSize = count * sizeof(REAL);
// Users will supply the blend factor as radial blend factors, and these are stored
// with inverted values. To get back the original user specified blend factors to
// store, they must be inverted again.
REAL *newFactors = (REAL*) GpMalloc(realSize);
if (newFactors == NULL ) { return OutOfMemory; }
REAL *newPositions = (REAL*) GpMalloc(realSize);
if (newPositions == NULL ) { GpFree(newFactors); return OutOfMemory; }
GetBlend(newFactors, newPositions, count);
stream->Write(&count, sizeof(INT32), NULL); stream->Write(newPositions, realSize, NULL); stream->Write(newFactors, realSize, NULL);
GpFree(newPositions); GpFree(newFactors); }
if (flags & GDIP_BRUSHFLAGS_FOCUSSCALES) { INT count = 2; REAL focusScale[2];
focusScale[0] = DeviceBrush.FocusScaleX; focusScale[1] = DeviceBrush.FocusScaleY;
stream->Write(&count, sizeof(INT32), NULL); stream->Write(focusScale, 2 * sizeof(REAL), NULL); }
return Ok; }
UINT GpPathGradient::GetDataSize() const { UINT pathSize; UINT surroundingColorCount = DeviceBrush.OneSurroundColor ? 1 : DeviceBrush.Count; UINT size = sizeof(PathGradientBrushData) + (surroundingColorCount * sizeof(ARGB));
GpPath* path = static_cast<GpPath*> (DeviceBrush.Path);
if (DeviceBrush.PointsPtr != NULL) { size += sizeof(INT32) + (DeviceBrush.Count * sizeof(DeviceBrush.PointsPtr[0])); } else if (path != NULL) { pathSize = path->GetDataSize(); ASSERT((pathSize & 0x03) == 0); size += sizeof(INT32) + pathSize; }
if (!DeviceBrush.Xform.IsIdentity()) { size += GDIP_MATRIX_SIZE; }
// Note: can't have both blendFactors and presetColors at the same time
if (DeviceBrush.UsesPresetColors && (DeviceBrush.BlendCounts[0] > 1) && (DeviceBrush.PresetColors != NULL) && (DeviceBrush.BlendPositions[0] != NULL) && (DeviceBrush.BlendFactors[0] == NULL)) { size += sizeof(INT32) + ((sizeof(ARGB) + sizeof(REAL)) * DeviceBrush.BlendCounts[0]); }
if ((DeviceBrush.BlendCounts[0] > 1) && (DeviceBrush.BlendFactors[0] != NULL) && (DeviceBrush.BlendPositions[0] != NULL)) { size += sizeof(INT32) + ((sizeof(REAL) + sizeof(REAL)) * DeviceBrush.BlendCounts[0]); }
if((DeviceBrush.FocusScaleX != 0) || (DeviceBrush.FocusScaleY != 0)) { size += sizeof(INT32) + 2*sizeof(REAL); }
return size; }
/**************************************************************************\
* * Function Description: * * Read the brush object from memory. * * Arguments: * * [IN] dataBuffer - the data that was read from the stream * [IN] size - the size of the data * * Return Value: * * GpStatus - Ok or failure status * * Created: * * 4/26/1999 DCurtis * \**************************************************************************/ GpStatus GpPathGradient::SetData( const BYTE * dataBuffer, UINT size ) { ASSERT ((GpBrushType)(((PathGradientBrushData *)dataBuffer)->Type) == BrushTypePathGradient);
if (dataBuffer == NULL) { WARNING(("dataBuffer is NULL")); return InvalidParameter; }
if (size < sizeof(PathGradientBrushData)) { WARNING(("size too small")); return InvalidParameter; }
if (DeviceBrush.PointsPtr != NULL) { GpFree(DeviceBrush.PointsPtr); DeviceBrush.PointsPtr = NULL; }
GpPath* path = static_cast<GpPath*> (DeviceBrush.Path);
if (path != NULL) { delete path; path = NULL; }
const PathGradientBrushData * brushData; ARGB * surroundingColors;
brushData = reinterpret_cast<const PathGradientBrushData *>(dataBuffer);
if (!brushData->MajorVersionMatches()) { WARNING(("Version number mismatch")); return InvalidParameter; }
dataBuffer += sizeof(PathGradientBrushData); size -= sizeof(PathGradientBrushData);
if (size < (brushData->SurroundingColorCount * sizeof(ARGB))) { WARNING(("size too small")); return InvalidParameter; }
surroundingColors = (ARGB *)dataBuffer;
dataBuffer += (brushData->SurroundingColorCount * sizeof(ARGB)); size -= (brushData->SurroundingColorCount * sizeof(ARGB));
if (brushData->Flags & GDIP_BRUSHFLAGS_PATH) { if (size < sizeof(INT32)) { WARNING(("size too small")); return InvalidParameter; }
UINT pathSize = ((INT32 *)dataBuffer)[0]; dataBuffer += sizeof(INT32); size -= sizeof(INT32);
DefaultBrush(); DeviceBrush.Wrap = (GpWrapMode) brushData->Wrap;
if (size < pathSize) { WARNING(("size too small")); return InvalidParameter; }
path = new GpPath(); if (path) { path->SetData(dataBuffer, pathSize); }
DeviceBrush.Path = path; PrepareBrush(); dataBuffer += pathSize; size -= pathSize; } else { if (size < sizeof(INT32)) { WARNING(("size too small")); return InvalidParameter; }
INT count = ((INT32 *)dataBuffer)[0]; dataBuffer += sizeof(INT32); size -= sizeof(INT32);
if (size < (count * sizeof(GpPointF))) { WARNING(("size too small")); return InvalidParameter; }
InitializeBrush((GpPointF *)dataBuffer, count, (GpWrapMode) brushData->Wrap); dataBuffer += (count * sizeof(GpPointF)); size -= (count * sizeof(GpPointF)); }
DeviceBrush.IsGammaCorrected = ((brushData->Flags & GDIP_BRUSHFLAGS_ISGAMMACORRECTED) != 0);
SetCenterPoint(brushData->CenterPoint); SetCenterColor(GpColor(brushData->CenterColor));
DeviceBrush.OneSurroundColor = (brushData->SurroundingColorCount == 1);
if (DeviceBrush.ColorsPtr != NULL) { for (UINT32 i = 0; i < brushData->SurroundingColorCount; i++) { SetSurroundColor(GpColor(surroundingColors[i]), i); } // OneSurroundColor requires n colors and they are all set to the
// same value. This is a very weird requirement, but that's the way
// it was written. One color simply isn't enough.
if (i == 1) { for (i = 1; (INT)i < DeviceBrush.Count; i++) { DeviceBrush.ColorsPtr[i] = GpColor(surroundingColors[0]); } } } if (brushData->Flags & GDIP_BRUSHFLAGS_TRANSFORM) { if (size < GDIP_MATRIX_SIZE) { WARNING(("size too small")); return InvalidParameter; }
DeviceBrush.Xform.SetMatrix((REAL *)dataBuffer); dataBuffer += GDIP_MATRIX_SIZE; size -= GDIP_MATRIX_SIZE; }
if (brushData->Flags & GDIP_BRUSHFLAGS_PRESETCOLORS) { if (size < sizeof(INT32)) { WARNING(("size too small")); return InvalidParameter; }
UINT count = ((INT32 *)dataBuffer)[0]; dataBuffer += sizeof(INT32); size -= sizeof(INT32);
UINT realSize = count * sizeof(REAL); UINT argbSize = count * sizeof(ARGB);
if (size < (realSize + argbSize)) { WARNING(("size too small")); return InvalidParameter; }
ARGB *argbBuffer = (ARGB*)(dataBuffer + realSize); GpColor *colors = new GpColor[count];
if (colors == NULL) { return OutOfMemory; }
for (UINT i = 0; i < count; i++) { colors[i].SetValue(argbBuffer[i]); }
this->SetPresetBlend(colors, (REAL *)dataBuffer, count);
dataBuffer += (realSize + argbSize); size -= (realSize + argbSize);
delete colors; }
if (brushData->Flags & GDIP_BRUSHFLAGS_BLENDFACTORS) { if (size < sizeof(INT32)) { WARNING(("size too small")); return InvalidParameter; }
UINT count = ((INT32 *)dataBuffer)[0]; dataBuffer += sizeof(INT32); size -= sizeof(INT32);
UINT realSize = count * sizeof(REAL);
if (size < (2 * realSize)) { WARNING(("size too small")); return InvalidParameter; }
this->SetBlend((REAL *)(dataBuffer + realSize), (REAL *)dataBuffer, count); dataBuffer += (2 * realSize); size -= (2 * realSize); }
if (brushData->Flags & GDIP_BRUSHFLAGS_FOCUSSCALES) { if (size < sizeof(INT32)) { WARNING(("size too small")); return InvalidParameter; }
INT count = ((INT32 *)dataBuffer)[0]; dataBuffer += sizeof(INT32); size -= sizeof(INT32);
if (size < (2 * sizeof(REAL))) { WARNING(("size too small")); return InvalidParameter; }
DeviceBrush.FocusScaleX = ((REAL *) dataBuffer)[0]; DeviceBrush.FocusScaleY = ((REAL *) dataBuffer)[1];
dataBuffer += (2 * sizeof(REAL)); size -= (2 * sizeof(REAL)); }
UpdateUid(); return Ok; }
/**************************************************************************\
* * Function Description: * * Blend any transparent colors in this brush with white. Note that * colors are premultiplied, since they will become fully opaque. * * Arguments: * * Return Value: * * GpStatus - Ok or failure status * \**************************************************************************/
GpStatus GpPathGradient::BlendWithWhite() { DeviceBrush.Colors[0].SetValue( GpColor::ConvertToPremultiplied(DeviceBrush.Colors[0].GetValue())); DeviceBrush.Colors[0].BlendOpaqueWithWhite(); if (DeviceBrush.UsesPresetColors) { GpColor color; for (INT i=0; i<DeviceBrush.BlendCounts[0]; i++) { color.SetValue(GpColor::ConvertToPremultiplied(DeviceBrush.PresetColors[i])); color.BlendOpaqueWithWhite(); DeviceBrush.PresetColors[i] = color.GetValue(); } } else { for (INT i=0; i<DeviceBrush.Count; i++) { DeviceBrush.ColorsPtr[i].SetValue( GpColor::ConvertToPremultiplied(DeviceBrush.ColorsPtr[i].GetValue())); DeviceBrush.ColorsPtr[i].BlendOpaqueWithWhite(); } } return Ok; }
/**************************************************************************\
* * Function Description: * * Set the surround color. * * Arguments: * * [IN] color - the color to set. * [IN] index - which color to set. * * Return Value: * * GpStatus - Ok or failure status * \**************************************************************************/
GpStatus GpPathGradient::SetSurroundColor(GpColor& color, INT index) { if(index >= 0 && index < DeviceBrush.Count) { if(DeviceBrush.OneSurroundColor) { if(index == 0) { DeviceBrush.ColorsPtr[0] = color; // OneSurroundColor requires n colors and they are all set to the
// same value. This is a very weird requirement, but that's the way
// it was written. One color simply isn't enough.
for (INT i = 1; i < DeviceBrush.Count; i++) { DeviceBrush.ColorsPtr[i] = GpColor(DeviceBrush.ColorsPtr[0]); } UpdateUid(); } else { if(DeviceBrush.ColorsPtr[0].GetValue() != color.GetValue()) { DeviceBrush.OneSurroundColor = FALSE; DeviceBrush.ColorsPtr[index] = color; UpdateUid(); } } } else { DeviceBrush.ColorsPtr[index] = color; UpdateUid(); }
return Ok; } else return InvalidParameter; }
/**************************************************************************\
* * Function Description: * * Set the surround colors. * * Arguments: * * [IN] color - the color to set. * * Return Value: * * GpStatus - Ok or failure status * \**************************************************************************/
GpStatus GpPathGradient::SetSurroundColors(const GpColor* colors) { GpStatus status = InvalidParameter;
ASSERT(DeviceBrush.Count > 0);
if(IsValid() && colors && DeviceBrush.Count > 0) { GpMemcpy( DeviceBrush.ColorsPtr, colors, DeviceBrush.Count*sizeof(GpColor) );
DeviceBrush.OneSurroundColor = TRUE; INT i = 1; ARGB value = colors[0].GetValue();
while((i < DeviceBrush.Count) && (DeviceBrush.OneSurroundColor)) { if(colors[i].GetValue() != value) { DeviceBrush.OneSurroundColor = FALSE; }
i++; }
UpdateUid(); status = Ok; }
return status; }
GpStatus GpPathGradient::ColorAdjust( GpRecolor * recolor, ColorAdjustType type ) { if(!recolor) return InvalidParameter;
if (type == ColorAdjustTypeDefault) { type = ColorAdjustTypeBrush; }
INT surroundingColorCount = DeviceBrush.OneSurroundColor ? 1 : DeviceBrush.Count;
if ((surroundingColorCount > 0) && (DeviceBrush.ColorsPtr != NULL)) { ARGB solidColor32[32]; ARGB * color32 = solidColor32;
if (surroundingColorCount > 32) { color32 = new ARGB[surroundingColorCount]; if (color32 == NULL) { return OutOfMemory; } } INT i;
for (i = 0; i < surroundingColorCount; i++) { color32[i] = DeviceBrush.ColorsPtr[i].GetValue(); }
recolor->ColorAdjust(color32, surroundingColorCount, type);
for (i = 0; i < surroundingColorCount; i++) { DeviceBrush.ColorsPtr[i].SetValue(color32[i]); }
if (color32 != solidColor32) { delete[] color32; } }
if (DeviceBrush.UsesPresetColors && (DeviceBrush.BlendCounts[0] > 1) && (DeviceBrush.PresetColors != NULL)) { recolor->ColorAdjust(DeviceBrush.PresetColors, DeviceBrush.BlendCounts[0], type); }
UpdateUid(); return Ok; }
class HatchBrushData : public ObjectTypeData { public: INT32 Style; UINT32 ForeColor; UINT32 BackColor; };
/**************************************************************************\
* * Function Description: * * Get the brush data. * * Arguments: * * [IN] dataBuffer - fill this buffer with the data * [IN/OUT] size - IN - size of buffer; OUT - number bytes written * * Return Value: * * GpStatus - Ok or error code * * Created: * * 9/13/1999 DCurtis * \**************************************************************************/ GpStatus GpHatch::GetData( IStream * stream ) const { ASSERT (stream != NULL);
HatchBrushData brushData; brushData.Type = DeviceBrush.Type; brushData.Style = DeviceBrush.Style; brushData.ForeColor = DeviceBrush.Colors[0].GetValue(); brushData.BackColor = DeviceBrush.Colors[1].GetValue(); stream->Write(&brushData, sizeof(brushData), NULL);
return Ok; }
UINT GpHatch::GetDataSize() const { return sizeof(HatchBrushData); }
/**************************************************************************\
* * Function Description: * * Read the brush object from memory. * * Arguments: * * [IN] dataBuffer - the data that was read from the stream * [IN] size - the size of the data * * Return Value: * * GpStatus - Ok or failure status * * Created: * * 4/26/1999 DCurtis * \**************************************************************************/ GpStatus GpHatch::SetData( const BYTE * dataBuffer, UINT size ) { ASSERT ((GpBrushType)(((HatchBrushData *)dataBuffer)->Type) == BrushTypeHatchFill);
if (dataBuffer == NULL) { WARNING(("dataBuffer is NULL")); return InvalidParameter; }
if (size < sizeof(HatchBrushData)) { WARNING(("size too small")); return InvalidParameter; }
const HatchBrushData * brushData;
brushData = reinterpret_cast<const HatchBrushData *>(dataBuffer);
if (!brushData->MajorVersionMatches()) { WARNING(("Version number mismatch")); return InvalidParameter; }
InitializeBrush(static_cast<GpHatchStyle>(brushData->Style), GpColor(brushData->ForeColor), GpColor(brushData->BackColor));
UpdateUid(); return Ok; }
GpStatus GpHatch::ColorAdjust( GpRecolor * recolor, ColorAdjustType type ) { ASSERT(recolor != NULL); if (type == ColorAdjustTypeDefault) { type = ColorAdjustTypeBrush; }
ARGB solidColor32[2];
solidColor32[0] = DeviceBrush.Colors[0].GetValue();
//!!! bhouse: bug?
// seems that this should be BackColor ... I'm making the
// change!
// solidColor32[1] = ForeColor.GetValue();
solidColor32[1] = DeviceBrush.Colors[1].GetValue();
recolor->ColorAdjust(solidColor32, 2, type);
DeviceBrush.Colors[0].SetValue(solidColor32[0]); DeviceBrush.Colors[1].SetValue(solidColor32[1]); UpdateUid(); return Ok; }
static COLORREF AverageColors( const GpColor * colors, INT count ) { REAL r = 0; REAL g = 0; REAL b = 0;
if (count > 0) { for (INT i = 0; i < count; i++) { r += colors->GetRed(); g += colors->GetGreen(); b += colors->GetBlue(); }
r /= count; g /= count; b /= count; }
INT red = GpRound(r); INT green = GpRound(g); INT blue = GpRound(b);
return RGB(red, green, blue); }
static COLORREF AverageColors( const GpColor & color1, const GpColor & color2 ) { REAL r = ((REAL)((INT)color1.GetRed() + (INT)color2.GetRed())) / 2.0f; REAL g = ((REAL)((INT)color1.GetGreen()+ (INT)color2.GetGreen())) / 2.0f; REAL b = ((REAL)((INT)color1.GetBlue() + (INT)color2.GetBlue())) / 2.0f;
INT red = GpRound(r); INT green = GpRound(g); INT blue = GpRound(b);
return RGB(red, green, blue); }
COLORREF ToCOLORREF( const DpBrush * deviceBrush ) { switch (deviceBrush->Type) { default: ASSERT(0); // FALLTHRU
case BrushTypeSolidColor: return deviceBrush->SolidColor.ToCOLORREF();
case BrushTypeHatchFill: return AverageColors(deviceBrush->Colors[0], deviceBrush->Colors[1]);
case BrushTypeTextureFill: return RGB(0x80, 0x80, 0x80);
// case BrushRectGrad:
case BrushTypeLinearGradient: return AverageColors(deviceBrush->Colors, 4); #if 0
case BrushRadialGrad: return AverageColors(deviceBrush->Colors[0], deviceBrush->Colors[1]);
case BrushTriangleGrad: return AverageColors(deviceBrush->Colors, 3); #endif
case BrushTypePathGradient: return AverageColors(deviceBrush->Colors[0], deviceBrush->ColorsPtr[0]); } }
|