Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
Source/BlendUtils.c
/*-------------------------------------------------------------------------------------- |
// |
// File: BlendProcs.c |
// |
// Contents: Procedures that render blended fills. |
// |
// |
// By Georgiann ("George") Delaney |
// ©Ê1989 - 1990, Apple Computer, Inc. |
// |
//--------------------------------------------------------------------------------------*/ |
#pragma segment BlendSeg |
#include "MacHeaders.h" |
/*--------------------------------------------------------------------------------------*/ |
/* Constants */ |
#define kGrayPatternRsrc 50 |
#define kNumGrayPatterns 50 |
/*--------------------------------------------------------------------------------------*/ |
/* Macro definitions */ |
#define RECT_BLEND_BAND_COUNT(span,bandWidth) (((span-bandWidth)/2)/bandWidth) |
#define RECT_BLEND_BAND_INC(span,bandCount,bandWidth) (((span-bandWidth)/2)/bandCount) |
#define RECT_BLEND_STEP(span,bandWidth) (65535/(((span/2)-(bandWidth/2))/bandWidth)) |
#define LINEAR_BLEND_BAND_COUNT(span,bandWidth) (span/bandWidth) |
#define LINEAR_BLEND_STEP(span,bandWidth) (65535/(span/bandWidth)) |
#define MIN(x,y) (((x) < (y)) ? (x) : (y)) |
#define MAX(x,y) (((x) > (y)) ? (x) : (y)) |
/*--------------------------------------------------------------------------------------*/ |
void HLSRectBlend(Rect *boundRect, short saturation) |
/* |
// This procedure fills the specified rect with a concentric rectangular HLS blend |
// at the specified saturation. The band size used for this fill is 1 pixel. It is |
// assumed that the desired port as well as any desired clipping has already been set. |
*/ |
{ |
RGBColor holdRGB,theRGB; |
HSVColor theHSV; |
short blendStep; |
short i; |
short span; |
Rect tempRect; |
tempRect = *boundRect; |
/* calculate the diameter of the specified rect */ |
span = MIN((tempRect.right-tempRect.left)/2, (tempRect.bottom - tempRect.top)/2); |
/* calculate the color increment for each band */ |
blendStep = 65536 / span; |
/* save off the current RGB */ |
GetForeColor(&holdRGB); |
/* set the initial color */ |
theHSV.value = 65535; |
theHSV.saturation = saturation; |
theHSV.hue = 0; |
/* Generate the blend by converting the hls (hsv in mac terms) to |
its RGB equivalent. Set the forecolor to this RGB value. Paint |
the rect. Then increment the HLS value and band rect for the next |
iteration |
*/ |
for (i=0; i<span; i++) { |
HSV2RGB(&theHSV,&theRGB); |
RGBForeColor(&theRGB); |
PaintRect(&tempRect); |
theHSV.hue += blendStep; |
tempRect.top +=1; |
tempRect.left +=1; |
tempRect.right -=1; |
tempRect.bottom -=1; |
} |
/* restore the original RGB */ |
RGBForeColor(&holdRGB); |
} |
/*--------------------------------------------------------------------------------------*/ |
void HLSVLinearBlend(Rect *boundRect, short saturation) |
/* |
// This procedure fills the specified rect with a vertical HLS blend |
// at the specified saturation. The band size used for this fill is 1 pixel. It is |
// assumed that the desired port as well as any desired clipping has already been set. |
*/ |
{ |
RGBColor holdRGB,theRGB; |
HSVColor theHSV; |
short blendStep; |
short height; |
Rect tempRect; |
short i; |
tempRect = *boundRect; |
/* calculate the vertical distance the blend is to cover */ |
height = tempRect.bottom - tempRect.top; |
/* calculate the color increment for each band */ |
blendStep = 65535 / height; |
/* save off the current RGB */ |
GetForeColor(&holdRGB); |
/* set the initial color */ |
theHSV.value = 65535; |
theHSV.saturation = saturation; |
theHSV.hue = 0; |
/* Initialize the rectangle that specifies the first band of the blend */ |
tempRect.bottom = tempRect.top + 1; |
/* Generate the blend by converting the hls (hsv in mac terms) to |
its RGB equivalent. Set the forecolor to this RGB value. Paint |
the rect. Then increment the HLS value and offset the band rect for |
the next iteration |
*/ |
for (i=0; i<height; i++) { |
HSV2RGB(&theHSV,&theRGB); |
RGBForeColor(&theRGB); |
PaintRect(&tempRect); |
theHSV.hue += blendStep; |
tempRect.top +=1; |
tempRect.bottom +=1; |
} |
/* restore the original RGB */ |
RGBForeColor(&holdRGB); |
} |
/*--------------------------------------------------------------------------------------*/ |
void HLSHLinearBlend(Rect *boundRect, short saturation) |
/* |
// This procedure fills the specified rect with a horizontal HLS blend |
// at the specified saturation. The band size used for this fill is 1 pixel. It is |
// assumed that the desired port as well as any desired clipping has already been set. |
*/ |
{ |
RGBColor holdRGB,theRGB; |
HSVColor theHSV; |
short blendStep; |
short width; |
Rect tempRect; |
short i; |
tempRect = *boundRect; |
/* calculate the horizontal distance the blend is to cover */ |
width = tempRect.right-tempRect.left; |
/* calculate the color increment for each band */ |
blendStep = 65535 / width; |
/* save off the current RGB */ |
GetForeColor(&holdRGB); |
/* set the initial color */ |
theHSV.value = 65535; |
theHSV.saturation = saturation; |
theHSV.hue = 0; |
/* Initialize the rectangle that specifies the first band of the blend */ |
tempRect.right = tempRect.left + 1; |
/* Generate the blend by converting the hls (hsv in mac terms) to |
its RGB equivalent. Set the forecolor to this RGB value. Paint |
the rect. Then increment the HLS value and offset the band rect for |
the next iteration |
*/ |
for (i=0; i<width; i++) { |
HSV2RGB(&theHSV,&theRGB); |
RGBForeColor(&theRGB); |
PaintRect(&tempRect); |
theHSV.hue += blendStep; |
tempRect.left +=1; |
tempRect.right +=1; |
} |
/* restore the original RGB */ |
RGBForeColor(&holdRGB); |
} |
/*--------------------------------------------------------------------------------------*/ |
void GrayRectBlend(Rect *boundRect) |
/* |
// This procedure fills the specified rect with a concentric rectangular gray scale blend |
// from black to white. The band size used for this fill is 1 pixel. It is |
// assumed that the desired port as well as any desired clipping has already been set. |
*/ |
{ |
RGBColor holdRGB,theRGB; |
short blendStep; |
short i; |
short span; |
Rect tempRect; |
tempRect = *boundRect; |
/* calculate the diameter of the specified rect */ |
span = MIN((tempRect.right-tempRect.left)/2, (tempRect.bottom - tempRect.top)/2); |
/* calculate the color increment for each band */ |
blendStep = 65536 / span; |
/* save off the current RGB color */ |
GetForeColor(&holdRGB); |
/* set the initial color */ |
theRGB.red = theRGB.green = theRGB.blue = 0; |
/* Generate the blend by seting the forecolor to the RGB value. Paint |
the rect. Then increment the RGB value and band rect for the next |
iteration |
*/ |
for (i=0; i<span; i++) { |
RGBForeColor(&theRGB); |
PaintRect(&tempRect); |
theRGB.red = theRGB.green = theRGB.blue = theRGB.red + blendStep; |
tempRect.top +=1; |
tempRect.left +=1; |
tempRect.right -=1; |
tempRect.bottom -=1; |
} |
/* restore the original RGB */ |
RGBForeColor(&holdRGB); |
} |
/*--------------------------------------------------------------------------------------*/ |
void GrayVLinearBlend(Rect *boundRect) |
/* |
// This procedure fills the specified rect with a vertical gray scale blend |
// from black to white. The band size used for this fill is 1 pixel. It is |
// assumed that the desired port as well as any desired clipping has already been set. |
*/ |
{ |
RGBColor holdRGB,theRGB; |
short blendStep; |
short i; |
short height; |
Rect tempRect; |
tempRect = *boundRect; |
/* calculate the vertical distance the blend is to cover */ |
height = tempRect.bottom - tempRect.top; |
/* calculate the color increment for each band */ |
blendStep = 65535 / height; |
/* save off the current RGB color */ |
GetForeColor(&holdRGB); |
/* set the initial color */ |
theRGB.red = theRGB.green = theRGB.blue = 0; |
/* Initialize the rectangle that specifies the first band of the blend */ |
tempRect.bottom = tempRect.top + 1; |
/* Generate the blend by setting the forecolor to this RGB value. Paint |
the rect. Then increment the RGB value and offset the band rect for |
the next iteration |
*/ |
for (i=0; i<height; i++) { |
RGBForeColor(&theRGB); |
PaintRect(&tempRect); |
theRGB.red = theRGB.green = theRGB.blue = theRGB.red + blendStep; |
tempRect.top +=1; |
tempRect.bottom +=1; |
} |
/* restore the original RGB */ |
RGBForeColor(&holdRGB); |
} |
/*--------------------------------------------------------------------------------------*/ |
void GrayHLinearBlend(Rect *boundRect) |
/* |
// This procedure fills the specified rect with a horizontal gray scale blend |
// from black to white. The band size used for this fill is 1 pixel. It is |
// assumed that the desired port as well as any desired clipping has already been set. |
*/ |
{ |
RGBColor holdRGB,theRGB; |
short blendStep; |
short i; |
short width; |
Rect tempRect; |
tempRect = *boundRect; |
/* calculate the horizontal distance the blend is to cover */ |
width = tempRect.right-tempRect.left; |
/* calculate the color increment for each band */ |
blendStep = 65535 / width; |
/* save off the current RGB color */ |
GetForeColor(&holdRGB); |
/* set the initial color */ |
theRGB.red = theRGB.green = theRGB.blue = 0; |
/* Initialize the rectangle that specifies the first band of the blend */ |
tempRect.right = tempRect.left + 1; |
/* Generate the blend by setting the forecolor to this RGB value. Paint |
the rect. Then increment the RGB value and offset the band rect for |
the next iteration |
*/ |
for (i=0; i<width; i++) { |
RGBForeColor(&theRGB); |
PaintRect(&tempRect); |
theRGB.red = theRGB.green = theRGB.blue = theRGB.red + blendStep; |
tempRect.left +=1; |
tempRect.right +=1; |
} |
/* restore the original RGB */ |
RGBForeColor(&holdRGB); |
} |
/*--------------------------------------------------------------------------------------*/ |
void GrayPatRectBlend(Rect *boundRect) |
/* |
// This procedure fills the specified rect with a concentric rectangular gray scale pattern blend |
// from black to white. The band size used for this fill is calculated by dividing the shorter |
// the horizontal and vertical diameters of the specified rect by the number of gray patterns in |
// the gray pattern resource. It is assumed that the desired port as well as any desired clipping |
// has already been set. |
*/ |
{ |
register i; |
double bandWidth; |
double distance; |
Rect origRect,tempRect; |
Pattern thePat; |
origRect = tempRect = *boundRect; |
/* calculate the width of each band */ |
bandWidth = (double)(MIN((tempRect.right-tempRect.left)/2, (tempRect.bottom-tempRect.top)/2)) / (double)(kNumGrayPatterns+1); |
distance = bandWidth; |
/* There is a pattern resource consisting of 64 shades of gray in MacLib.rsrc |
// that gives a pretty good approximation of a gray ramp from white to black. |
// The following loop performs the actual imaging of the ramp's 64 gray bands. |
*/ |
for (i=kNumGrayPatterns; i>=1; i--) { |
GetIndPattern(&thePat, kGrayPatternRsrc, i); |
FillRect(&tempRect,thePat); |
distance += bandWidth; |
tempRect.top = origRect.top + distance; |
tempRect.left = origRect.left + distance; |
tempRect.right = origRect.right - distance; |
tempRect.bottom = origRect.bottom - distance; |
} |
} |
/*--------------------------------------------------------------------------------------*/ |
void GrayPatVLinearBlend(Rect *boundRect) |
/* |
// This procedure fills the specified rect with a vertical gray scale pattern blend |
// from black to white. The band size used for this fill is calculated by dividing the width |
// of the specified blend by the number of gray patterns in the gray pattern resource. It is |
// assumed that the desired port as well as any desired clipping has already been set. |
*/ |
{ |
register i; |
double theTop; |
double bandHeight; |
double distance; |
Rect tempRect; |
Pattern thePat; |
tempRect = *boundRect; |
/* silly, but saves a pointer dereference in the blend loop */ |
theTop = (double)tempRect.top; |
/* calculate the width of each band */ |
bandHeight = ((double)(tempRect.bottom-tempRect.top)) / (double)kNumGrayPatterns; |
/* Initialize the rectangle that specifies the first band of the blend */ |
tempRect.bottom = tempRect.top + bandHeight; |
distance = bandHeight; |
/* There is a pattern resource consisting of 64 shades of gray in MacLib.rsrc |
// that gives a pretty good approximation of a gray ramp from white to black. |
// The following loop performs the actual imaging of the ramp's 64 gray bands. |
*/ |
for (i=kNumGrayPatterns; i>1; i--) { |
GetIndPattern(&thePat, kGrayPatternRsrc, i); |
FillRect(&tempRect,thePat); |
distance += bandHeight; |
tempRect.top = tempRect.bottom; |
tempRect.bottom = (short)(theTop + distance); |
} |
tempRect.bottom = boundRect->bottom; |
GetIndPattern(&thePat,kGrayPatternRsrc,1); |
FillRect(&tempRect,thePat); |
} |
/*--------------------------------------------------------------------------------------*/ |
void GrayPatHLinearBlend(Rect *boundRect) |
/* |
// This procedure fills the specified rect with a horizontal gray scale pattern blend |
// from black to white. The band size used for this fill is calculated by dividing the width |
// of the specified blend by the number of gray patterns in the gray pattern resource. It is |
// assumed that the desired port as well as any desired clipping has already been set. |
*/ |
{ |
register i; |
double farLeft; |
double bandWidth; |
double distance; |
Rect tempRect; |
Pattern thePat; |
tempRect = *boundRect; |
/* silly, but saves a pointer dereference in the blend loop */ |
farLeft = (double)tempRect.left; |
/* calculate the width of each band */ |
bandWidth = ((double)(tempRect.right-tempRect.left)) / (double)kNumGrayPatterns; |
/* Initialize the rectangle that specifies the first band of the blend */ |
tempRect.right = tempRect.left + bandWidth; |
distance = bandWidth; |
/* There is a pattern resource consisting of 64 shades of gray in MacLib.rsrc |
// that gives a pretty good approximation of a gray ramp from white to black. |
// The following loop performs the actual imaging of the ramp's 64 gray bands. |
*/ |
for (i=kNumGrayPatterns; i>1; i--) { |
GetIndPattern(&thePat, kGrayPatternRsrc, i); |
FillRect(&tempRect,thePat); |
distance += bandWidth; |
tempRect.left = tempRect.right; |
tempRect.right = (short)(farLeft + distance); |
} |
tempRect.right = boundRect->right; |
GetIndPattern(&thePat,kGrayPatternRsrc,1); |
FillRect(&tempRect,thePat); |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-10-10