BSOne.SFC/EM.Lib/ImageEn_SRC/Source/ieXCanvasUtils.pas

2504 lines
101 KiB
Plaintext

(* ImageEn Build 7.0.0.06.2637 @ 7-4-17 14:58:42.679 *)
(*
Copyright (c) 1998-2017 by Carlotta Calandra. All rights reserved.
Copyright (c) 2011-2017 by Xequte Software.
This software comes without express or implied warranty.
In no case shall the author be liable for any damage or unwanted behavior of any
computer hardware and/or software.
Author grants you the right to include the component
in your application, whether COMMERCIAL, SHAREWARE, or FREEWARE.
ImageEn, IEvolution and ImageEn ActiveX may not be included in any
commercial, shareware or freeware libraries or components.
www.ImageEn.com
*)
unit iexCanvasUtils;
(*
File version 1006
*)
{$I ie.inc}
interface
uses
Windows, Messages, SysUtils, Classes, {$ifdef IEHASTYPES}Types,{$endif} Graphics, Controls, stdctrls, hyiedefs,
iegdiplus;
type
{!!
<FS>TIEBooleanEx
<FM>Declaration<FC>
}
TIEBooleanEx = (iebFalse, iebTrue, iebDefault);
{!!}
{!!
<FS>TWallpaperEffect
<FM>Declaration<FC>
}
TWallpaperEffect = (
wpSolid, // A color fill
wpLeftLine, // A single line on left
wpTopLine, // A single line along top
wpDoubleLeftLines, // Two lines on left
wpDoubleTopLines, // Two lines along top
wpDoubleVariedLeftLines, // Two lines of decreasing widths on left
wpDoubleVariedTopLines, // Two lines of decreasing widths along top
wpTripleLeftLines, // Three lines on left
wpTripleTopLines, // Three lines along top
wpTripleVariedLeftLines, // Three lines of decreasing widths on left
wpTripleVariedTopLines, // Three lines of decreasing widths along top
wpLeftDashes, // Short lines of a uniform sizes on left
wpTopDashes, // Short lines of a uniform sizes along top
wpDoubleLeftDashes, // Short lines of two sizes on left
wpDoubleTopDashes, // Short lines of two sizes along top
wpTripleLeftDashes, // Short lines of three sizes on left
wpTripleTopDashes, // Short lines of three sizes along top
wpLeftZigZag, // Shark tooth pattern on left
wpTopZigZag, // Shark tooth pattern along top
wpLeftGradient, // Color gradient on left
wpTopGradient, // Color gradient along top
wpHorzPinStripe, // Horizontal lines across image
wpVertPinStripe, // Vertical lines down image
wpDiagPinStripe, // Diagonal lines across image
wpDiagPinStripe2, // Diagonal lines across image (alternative direction)
wpCrossHatch, // Horizontal and vertical lines
wpDiagCrossHatch, // Diagonal lines in two directions
wpHorzStripes, // Horizontal stripes across image
wpVertStripes, // Vertical stripes down image
wpDiagStripes, // Diagonal stripes down image
wpDiagStripes2, // Diagonal stripes down image (alternative direction)
wpCheckers, // Alternativing blocks of color
wpDiagCheckers, // Alternativing diagonal blocks of color
wpRain, // Diagonal dashes
wpRain2, // Diagonal dashes (alternative direction)
wpRivets, // Circles over page
wpHearts, // Hearts over page
wpStars, // Stars over page
wpLightning, // Lightning over page
wpRuledPage); // Similar to standard ruled page (with red line along side)
{!!}
procedure IEDrawShape(Canvas: TCanvas; Shape: TIEShape; iLeft, iTop, iWidth, iHeight: Integer; MaintainAspect: TIEBooleanEx = iebDefault); overload;
procedure IEDrawShape(Canvas: TCanvas; Shape: TIEShape;
iLeft, iTop, iWidth, iHeight: Integer; MaintainAspect: TIEBooleanEx;
BorderColor: TColor; BorderWidth: Integer;
FillColor: TColor; FillColor2: TColor = clNone; GradientDir: TIEGradientDir = gdVertical;
Angle: Integer = 0; ShapeModifier: Integer = 0); overload;
{$ifdef IEIncludeDeprecatedInV6}
// Deprecated in 7.0.0 (2016-11-1)
type TXCustomShape = (xcsStar5, xcsStar6, xcsArrowNW, xcsArrowNE, xcsArrowSW, xcsArrowSE, xcsLightningLeft, xcsLightningRight,
xcsExplosion, xcsExplosion_2, xcsCross, xcsArrowNW2, xcsArrowNE2, xcsArrowSW2, xcsArrowSE2, xcsHeart, xcsDoubleHeart);
procedure DrawCustomShape(Canvas: TCanvas; Shape: TXCustomShape; iLeft, iTop, iWidth, iHeight: Integer); {$ifdef IEWarningForDeprecated} deprecated {$ifdef IESupportDeprecatedDescription} 'Use IEDrawShape instead - http://imageen.com/help/Compatibility.html' {$endif}; {$endif}
function CreateCustomShapeRegion(Shape: TXCustomShape; iLeft, iTop, iWidth, iHeight: Integer): Hrgn; {$ifdef IEWarningForDeprecated} deprecated {$ifdef IESupportDeprecatedDescription} 'Use IECreateShapeRegion instead - http://imageen.com/help/Compatibility.html' {$endif}; {$endif}
{$endif}
function IEShapePreferredAspectRatio(Shape: TIEShape): Double;
function IECreateShapeRegion(Shape: TIEShape; iLeft, iTop, iWidth, iHeight: Integer; MaintainAspect: TIEBooleanEx = iebDefault;
Angle: Integer = 0; ShapeModifier: Integer = 0): Hrgn; overload;
function IECreateShapeRegion(Shape: TIEShape; ARect: TRect; MaintainAspect: TIEBooleanEx = iebDefault;
Angle: Integer = 0; ShapeModifier: Integer = 0): HRgn; overload;
function CreateWallpaperBitmap(Effect : TWallpaperEffect; Color1 : TColor; Color2 : TColor; iSize : Integer = -1; iSpacing : integer = -1; iThickness: Integer = -1) : TBitmap;
Procedure TileBitmapOntoCanvas(Canvas : TCanvas; iWidth, iHeight : Integer; Bitmap : TBitmap); overload;
Procedure TileBitmapOntoCanvas(Canvas : TCanvas; iWidth, iHeight : Integer; Graphic : TGraphic); overload;
// Pass PointArray as "Array[ 0 .. Shape_Array_Max_Points ] of TPoint;"
procedure IEGenerateShapePoints(out PointArray: Array of TPoint; out PointArrayCount: Integer;
Shape: TIEShape; iLeft, iTop, iWidth, iHeight: Integer;
Angle: Integer = 0; MaintainAROnRotate: Boolean = False;
ShapeModifier: Integer = 0);
function ShapeToString(Shape: TIEShape): string;
procedure IEDrawShapeToComboListBoxItem(ControlCanvas : TCanvas;
CanvasRect : TRect;
ControlEnabled : Boolean;
Shape: TIEShape;
Color: TColor;
ShowText : Boolean= True);
const
Shape_Array_Max_Points = 102;
{!!
<FS>Supported_Generate_Points_Shapes
<FM>Declaration<FC>
}
Supported_Generate_Points_Shapes = [ iesRectangle, iesTriangle, iesCorner, iesDiamond, iesStar5, iesStar6, iesArrowLeft, iesArrowRight,
iesArrowUp, iesArrowDown, iesFatArrowUp, iesFatArrowLeft, iesFatArrowRight, iesFatArrowDown,
iesArrowLeftRight, iesArrowUpDown, iesArrowNW, iesArrowNE, iesArrowSW, iesArrowSE,
iesShootingArrowNW, iesShootingArrowNE, iesShootingArrowSW, iesShootingArrowSE, iesLightningLeft,
iesLightningRight, iesExplosion, iesCross, iesShield, iesBadge, iesNamePlate, iesPentagon,
iesHexagon, iesHeptagon, iesOctagon, iesCustomShape, iesCustomStar, iesCustomExplosion ];
{!!}
implementation
uses
Math, iesettings, iexHelperFunctions, hyieutils;
// Returns closest of 0, 90, 180, 270
function RoundTo90(value: Integer) : integer;
begin
Result := 90 * Round( value / 90 );
if Result = 360 then
Result := 0;
end;
// Create square canvas to maintain the Aspect Ratio of the shape
procedure KeepAspectRatioForDimensions(var iLeft, iTop, iWidth, iHeight: integer);
var
iShortSide: Integer;
begin
if iWidth < iHeight then
iShortSide := iWidth
else
iShortSide := iHeight;
Inc(iLeft, (iWidth - iShortSide) div 2);
Inc(iTop, (iHeight - iShortSide) div 2);
iWidth := iShortSide;
iHeight := iShortSide;
end;
// Note: Angle is rounded to nearest 90
function CreateHeartRegion(iLeft, iTop, iWidth, iHeight: Integer; Angle: Integer = 0): Hrgn;
const
Triangle_Start_Point_On_Circle = 0.69; // start trinagle 62% down the circle
Top_Circle_Bulge = 2; // two pixels bigger
LHS_Circle_Intersect_Deg = 233.14; // Start triangle 1.5% in from edge
RHS_Circle_Intersect_Deg = 360 - LHS_Circle_Intersect_Deg; //126.86;
LHS_Circle_Middle_Touch_Deg = 83;
RHS_Circle_Middle_Touch_Deg = 360 - LHS_Circle_Middle_Touch_Deg;
var
origWidth, origHeight, origLeft, origTop : Integer;
Function FindPointOnCircleEdge(Center: Tpoint; Angle: Real; Radius: Word): TPoint;
Begin
Result.X := Round(center.x + Radius*cos((angle-90)*pi/180));
Result.Y := round(center.y + Radius*sin((angle-90)*pi/180));
End;
function _FlipVert(value: Integer): integer;
begin
if ( Angle = 180 ) or ( Angle = 90 ) then
Result := origHeight - Value
else
Result := Value;
end;
var
rgn1, rgn2, rgn3, rgn4 : Hrgn;
iCircleSize: Integer;
poly: array[0..2] of TPoint;
iCircleRadius: Integer;
LeftCircleIntersectPt: TPoint;
RightCircleIntersectPt: TPoint;
iHalfWidth: Integer;
iQuarterWidth: Integer;
invertDir: Boolean;
begin
Angle := RoundTo90( Angle );
origLeft := iLeft;
origTop := iTop;
origHeight := iHeight;
origWidth := iWidth;
iLeft := 0;
iTop := 0;
// Must maintain the Aspect Ratio of the Heart!
KeepAspectRatioForDimensions( iLeft, iTop, iWidth, iHeight );
invertDir := ( Angle = 90 ) or ( Angle = 270 );
if invertDir then
begin
IESwap( iWidth, iHeight );
IESwap( iLeft, iTop );
origHeight := origWidth;
end;
iHalfWidth := iWidth div 2;
iQuarterWidth := iWidth div 4;
iCircleSize := iHalfWidth + Top_Circle_Bulge;
iCircleRadius := iCircleSize div 2;
LeftCircleIntersectPt := FindPointOnCircleEdge( Point( iQuarterWidth, iQuarterWidth), LHS_Circle_Intersect_Deg, iCircleRadius - 1 );
RightCircleIntersectPt := FindPointOnCircleEdge( Point( iWidth - iQuarterWidth, iQuarterWidth), RHS_Circle_Intersect_Deg, iCircleRadius - 1 );
if invertDir then
begin
Result := CreateEllipticRgn( iTop, iLeft, iHeight, iWidth ); // Not used
// Circles
rgn1 := CreateEllipticRgn( origLeft + _FlipVert( iTop ),
origTop + iLeft,
origLeft + _FlipVert( iTop + iCircleSize ),
origTop + iLeft + iCircleSize );
rgn2 := CreateEllipticRgn( origLeft + _FlipVert( iTop ),
origTop + iLeft + iWidth - iCircleSize,
origLeft + _FlipVert( iTop + iCircleSize ),
origTop + iLeft + iWidth );
CombineRgn( Result, rgn1, rgn2, RGN_OR );
// Bottom Triangle
poly[0] := point( origLeft + _FlipVert( iTop + LeftCircleIntersectPt.Y ), origTop + iLeft + LeftCircleIntersectPt.X );
poly[1] := point( origLeft + _FlipVert( iTop + RightCircleIntersectPt.Y ), origTop + iLeft + RightCircleIntersectPt.X );
poly[2] := point( origLeft + _FlipVert( iTop + iHeight ), origTop + iLeft + iHalfWidth ); // Bottom point
rgn3 := Windows.CreatePolygonRgn( poly, 3, WINDING );
CombineRgn( Result, Result, rgn3, RGN_OR );
// Fill Hole
rgn4 := Windows.CreateRectRgn( origLeft + _FlipVert( iTop + iCircleRadius ), origTop + iLeft + iCircleRadius,
origLeft + _FlipVert( iTop + iCircleSize ), origTop + iLeft + iWidth - iCircleRadius );
CombineRgn( Result, Result, rgn4, RGN_OR );
end
else
begin
Result := CreateEllipticRgn( iLeft, iTop, iWidth, iHeight ); // Not used
// Circles
rgn1 := CreateEllipticRgn( origLeft + iLeft,
origTop + _FlipVert( iTop ),
origLeft + iLeft + iCircleSize,
origTop + _FlipVert( iTop + iCircleSize ));
rgn2 := CreateEllipticRgn( origLeft + iLeft + iWidth - iCircleSize ,
origTop + _FlipVert( iTop ),
origLeft + iLeft + iWidth,
origTop + _FlipVert( iTop + iCircleSize ));
CombineRgn( Result, rgn1, rgn2, RGN_OR );
// Bottom Triangle
poly[0] := point( origLeft + iLeft + LeftCircleIntersectPt.X, origTop + _FlipVert( iTop + LeftCircleIntersectPt.Y ));
poly[1] := point( origLeft + iLeft + RightCircleIntersectPt.X, origTop + _FlipVert( iTop + RightCircleIntersectPt.Y ));
poly[2] := point( origLeft + iLeft + iHalfWidth, origTop + _FlipVert( iTop + iHeight )); // Bottom point
rgn3 := Windows.CreatePolygonRgn( poly, 3, WINDING );
CombineRgn( Result, Result, rgn3, RGN_OR );
// Fill Hole
rgn4 := Windows.CreateRectRgn( origLeft + iLeft + iCircleRadius, origTop + _FlipVert( iTop + iCircleRadius ),
origLeft + iLeft + iWidth - iCircleRadius, origTop + _FlipVert( iTop + iCircleSize ));
CombineRgn( Result, Result, rgn4, RGN_OR );
end;
DeleteObject(rgn4);
DeleteObject(rgn3);
DeleteObject(rgn2);
DeleteObject(rgn1);
end;
// Note: Angle is rounded to nearest 90
function CreateDoubleHeartRegion(iLeft, iTop, iWidth, iHeight: Integer; Angle: Integer = 0): Hrgn;
const
Dbl_Heart_Size = 66;
Dbl_Heart_Offset = 5;
var
Rgn2 : Hrgn;
begin
Angle := RoundTo90( Angle );
if ( Angle = 90 ) or ( Angle = 270 ) then
begin
// Left heart - Lower
Result := CreateHeartRegion(iLeft + MulDiv(iWidth, 100 - Dbl_Heart_Size, 100),
iTop + MulDiv(iHeight, Dbl_Heart_Offset, 100) - MulDiv(iHeight, Dbl_Heart_Offset, 100),
MulDiv(iWidth, Dbl_Heart_Size, 100),
MulDiv(iHeight, Dbl_Heart_Size, 100),
Angle);
// Right heart - Higher
Rgn2 := CreateHeartRegion(iLeft,
iTop + MulDiv(iHeight, 100 - Dbl_Heart_Size, 100),
MulDiv(iWidth, Dbl_Heart_Size, 100),
MulDiv(iHeight, Dbl_Heart_Size, 100),
Angle);
end
else
begin
// Left heart - Higher
Result := CreateHeartRegion(iLeft,
iTop + MulDiv(iHeight, Dbl_Heart_Offset, 100),
MulDiv(iWidth, Dbl_Heart_Size, 100),
MulDiv(iHeight, Dbl_Heart_Size, 100),
Angle);
// Right heart - Lower
Rgn2 := CreateHeartRegion(iLeft + MulDiv(iWidth, 100 - Dbl_Heart_Size, 100),
iTop + MulDiv(iHeight, 100 - Dbl_Heart_Size, 100) - MulDiv(iHeight, Dbl_Heart_Offset, 100),
MulDiv(iWidth, Dbl_Heart_Size, 100),
MulDiv(iHeight, Dbl_Heart_Size, 100),
Angle);
end;
CombineRgn(Result, Result, Rgn2, RGN_OR);
DeleteObject(Rgn2);
end;
const
Max_Custom_Polygon_Points = 102;
// Supported range for PointCount is 3 .. 50
procedure GetCustomPolygonPoints(out PointArray: Array of TPoint; out PointArrayCount: Integer;
iLeft, iTop, iWidth, iHeight: Integer; Shape: TIEShape; PointCount : Integer;
Angle: Integer = 0);
const
Random_Nrs: array[0 .. 29] of Double = ( 0.82, 0.74, 0.62, 0.99, 0.52, 0.43, 0.99, 0.46, 0.98, 0.70,
0.56, 0.76, 0.95, 0.59, 0.35, 0.98, 0.84, 0.44, 0.72, 0.79,
0.17, 0.96, 0.07, 0.84, 0.35, 0.58, 0.39, 0.55, 0.27, 0.62 );
var
xCenter, yCenter,
xRadius, yRadius,
I : Integer;
CurrAngle : Double;
rotation: Double;
begin
if PointCount <= 3 then
begin
if Shape = iesCustomExplosion then
PointCount := 12
else
PointCount := 10;
end;
if PointCount > 50 then
PointCount := 50;
xCenter := iWidth div 2;
yCenter := iHeight div 2;
rotation := 360 / PointCount;
case Shape of
iesCustomExplosion : PointArrayCount := 2 * PointCount + 1;
iesCustomStar : PointArrayCount := 2 * PointCount;
else PointArrayCount := PointCount;
end;
for I := 0 to PointArrayCount - 1 do
begin
if ( Shape in [ iesCustomStar, iesCustomExplosion ]) and (( I mod 2 ) = 0 ) then
begin
// Inner point
xRadius := Round( xCenter / 2 );
yRadius := Round( yCenter / 2 );
end
else
if ( Shape = iesCustomExplosion ) and (( I mod 4 ) = 3 ) then
begin
// High outer point
xRadius := Round( xCenter / 2 + 1.000 * xCenter / 2 - Random_Nrs[ I mod 30 ] * xCenter / 20 );
yRadius := Round( yCenter / 2 + 1.000 * yCenter / 2 - Random_Nrs[ I mod 30 ] * yCenter / 20 );
end
else
if Shape = iesCustomExplosion then
begin
// Low outer point
xRadius := Round( xCenter / 2 + 0.7 * xCenter / 2 - Random_Nrs[ I mod 30 ] * xCenter / 10 );
yRadius := Round( yCenter / 2 + 0.7 * yCenter / 2 - Random_Nrs[ I mod 30 ] * yCenter / 10 );
end
else
begin
// Outer point
xRadius := xCenter;
yRadius := yCenter;
end;
if Shape in [ iesCustomStar, iesCustomExplosion ] then
CurrAngle := (( I * rotation / 2 ) + 270 - Angle) * PI / 180
else
CurrAngle := ((I * rotation) + 90 - Angle) * PI / 180;
PointArray[I].X := iLeft + xCenter + Round(cos(CurrAngle) * xRadius);
PointArray[I].Y := iTop + yCenter - Round(sin(CurrAngle) * yRadius);
end;
end;
// Note: Angle is rounded to nearest 90
function CreateHalfCircleRegion(iLeft, iTop, iWidth, iHeight: Integer; MoonShape: Boolean= False; Angle: Integer = 0): Hrgn;
var
rgn2, rgn3: Hrgn;
adjLeft, adjTop, adjWidth, adjHeight: integer;
moonLeft, moonTop: integer;
begin
Angle := RoundTo90( Angle );
adjLeft := iLeft;
if Angle = 0 then
dec( adjLeft, iWidth );
adjTop := iTop;
if Angle = 90 then
dec( adjTop, iHeight );
adjWidth := iWidth ;
if ( Angle = 0 ) or ( Angle = 180 ) then
inc( adjWidth, iWidth );
adjHeight := iHeight ;
if ( Angle = 90 ) or ( Angle = 270 ) then
inc( adjHeight, iHeight );
Result := CreateEllipticRgn( adjLeft, adjTop, adjLeft + adjWidth, adjTop + adjHeight );
rgn2 := CreateRectRgn(iLeft, iTop, iLeft + iWidth, iTop + iHeight);
combineRgn(Result, Result, rgn2, RGN_AND);
DeleteObject( rgn2 );
if MoonShape then
begin
moonLeft := adjLeft;
if ( Angle = 0 ) or ( Angle = 180 ) then
inc( moonLeft, iWidth div 2 );
moonTop := adjTop;
if ( Angle = 90 ) or ( Angle = 270 ) then
inc( moonTop, iHeight div 2 );
// Take bite out of it
rgn3 := CreateEllipticRgn(moonLeft, moonTop, moonLeft + iWidth, moonTop + iHeight);
combineRgn(Result, Result, rgn3, RGN_DIFF);
DeleteObject( rgn3 );
end;
end;
// SegmentWidth must be <= 90
function CreateQuarterCircleRegion(iLeft, iTop, iWidth, iHeight: Integer; Angle: Integer; SegmentWidth: Integer): Hrgn;
var
rgn2: Hrgn;
adjWidth, adjHeight, centerX, centerY: Integer;
largeSide, adjLargeSide, NewWidth, NewHeight: integer;
needL, needR, needT, needB: Boolean;
Poly : Array[ 0 .. 8 ] of TPoint;
PointCount: Integer;
rgnRect: TRect ;
px, py: double;
procedure _AddPoint(X, Y: Integer);
begin
poly[ PointCount ] := point( X, Y );
inc( PointCount );
end;
begin
if SegmentWidth <= 0 then
SegmentWidth := 45
else
if SegmentWidth > 90 then
SegmentWidth := 90;
if iWidth > iHeight then
largeSide := iWidth
else
largeSide := iHeight;
if ( Angle mod 90 = 0 ) or ( Angle mod 90 + SegmentWidth < 90 ) then
adjLargeSide := largeSide
else
begin
px := largeSide;
py := 0;
IEDRotatePoint( px, py, - SegmentWidth, 0, 0 );
IECalcRotatedBitmapSizes( largeSide, Round( Max( px, py )), IE2DPoint( 0, 0 ), ( Angle mod 90 ), NewWidth, NewHeight );
adjLargeSide := Max( NewWidth, NewHeight );
end;
needL := ( Angle >= 180 ) or ( Angle + SegmentWidth > 180 );
needR := ( Angle < 180 ) or ( Angle + SegmentWidth > 360 );
needT := (( Angle >= 270 ) or ( Angle < 90 )) or
( Angle + SegmentWidth > 270 );
needB := (( Angle >= 90 ) and ( Angle < 180 )) or
(( Angle < 270 ) and ( Angle + SegmentWidth > 90 ));
adjWidth := Round( iWidth * 2 * largeSide / adjLargeSide );
adjHeight := Round( iHeight * 2 * largeSide / adjLargeSide );
centerX := adjWidth div 2;
centerY := adjHeight div 2;
// Circle
Result := CreateEllipticRgn( 0, 0, adjWidth, adjHeight );
PointCount := 0;
// Center
_AddPoint( centerX, centerY );
// Start of slice
_AddPoint( Round( centerx - adjWidth / 2 * cos(( angle + 90) * pi / 180 )),
round( centery - adjHeight / 2 * sin(( angle + 90) * pi / 180 )));
// TR
if ( Angle <= 90 ) and needT and needR then
_AddPoint( adjWidth, 0 );
// BR
if needB and needR then
_AddPoint( adjWidth, adjHeight );
// BL
if needB and needL then
_AddPoint( 0, adjHeight );
// TL
if needT and needL then
_AddPoint( 0, 0 );
// TR #2
if ( Angle >= 270 ) and needT and needR then
_AddPoint( adjWidth, 0 );
// End of slice
_AddPoint( Round( centerx - adjWidth / 2 * cos(( Angle + SegmentWidth + 90) * pi / 180 )),
round( centery - adjHeight / 2 * sin(( Angle + SegmentWidth + 90) * pi / 180 )));
rgn2 := Windows.CreatePolygonRgn( poly, PointCount, WINDING );
combineRgn( Result, Result, rgn2, RGN_AND );
// Center the region
GetRgnBox( Result, rgnRect );
iLeft := iLeft + ( iWidth - rgnRect.Right + rgnRect.Left ) div 2;
iTop := iTop + ( iHeight - rgnRect.Bottom + rgnRect.Top ) div 2;
OffsetRgn( Result, iLeft - rgnRect.Left, iTop - rgnRect.Top );
DeleteObject( rgn2 );
end;
// Note: Angle is rounded to nearest 90
function CreateSpeechBubbleRegion(iLeft, iTop, iWidth, iHeight: Integer; Shape: TIEShape; Angle: Integer = 0): Hrgn;
const
Long_Bubble_Bottom_Excl_Circle = 0.35;
Long_Bubble_Circle_Round = 0.1;
Short_Bubble_Bottom_Excl_Circle = 0.15;
Short_Bubble_Circle_Round = 0.45;
Triangle_Buffer = 0.05;
var
rgn1, rgn2, rgn3, rgn4, rgn5, rgn6, rgn7: Hrgn;
circleSz: integer;
halfCircleSz: integer;
bubbleHeight: integer;
poly: array [ 0 .. 2 ] of TPoint;
trianglePointLeft, triangleTopLeft, triangleTopRight: integer;
triangleBottom: integer;
invertDir, flipHorz: Boolean;
function _FlipVert(value: Integer): integer;
begin
if ( Angle = 180 ) or ( Angle = 90 ) then
Result := iHeight - Value
else
Result := Value;
end;
begin
Angle := RoundTo90( Angle );
flipHorz := ( Angle = 180 ) or ( Angle = 270 );
invertDir := ( Angle = 90 ) or ( Angle = 270 );
if flipHorz then
case Shape of
iesSpeechBubbleLeftInShort : Shape := iesSpeechBubbleRightInShort;
iesSpeechBubbleLeftOutShort : Shape := iesSpeechBubbleRightOutShort;
iesSpeechBubbleRightInShort : Shape := iesSpeechBubbleLeftInShort;
iesSpeechBubbleRightOutShort : Shape := iesSpeechBubbleLeftOutShort;
iesSpeechBubbleLeftInLong : Shape := iesSpeechBubbleRightInLong;
iesSpeechBubbleLeftOutLong : Shape := iesSpeechBubbleRightOutLong;
iesSpeechBubbleRightInLong : Shape := iesSpeechBubbleLeftInLong;
iesSpeechBubbleRightOutLong : Shape := iesSpeechBubbleLeftOutLong;
end;
if invertDir then
begin
IESwap( iWidth, iHeight );
IESwap( iLeft, iTop );
end;
if Shape in [ iesSpeechBubbleLeftInLong, iesSpeechBubbleLeftOutLong, iesSpeechBubbleRightInLong, iesSpeechBubbleRightOutLong ] then
begin
circleSz := round(iWidth * Long_Bubble_Circle_Round);
bubbleHeight := round(iHeight * Long_Bubble_Bottom_Excl_Circle) + circleSz
end
else
begin
circleSz := min(round(iWidth * Short_Bubble_Circle_Round), round(iHeight * Short_Bubble_Circle_Round));
bubbleHeight := round(iHeight * Short_Bubble_Bottom_Excl_Circle) + circleSz;
end;
halfcircleSz := circleSz div 2;
triangleBottom := iHeight - 1;
case Shape of
iesSpeechBubbleLeftInLong,
iesSpeechBubbleLeftInShort:
Begin
triangleTopLeft := round(iWidth * 0.18);
triangleTopRight := round(iWidth * 0.30);
trianglePointLeft := round(iWidth * 0.45);
end;
iesSpeechBubbleLeftOutLong,
iesSpeechBubbleLeftOutShort:
Begin
triangleTopLeft := round(iWidth * 0.18);
triangleTopRight := round(iWidth * 0.30);
trianglePointLeft := round(iWidth * 0.08);
end;
iesSpeechBubbleRightInLong,
iesSpeechBubbleRightInShort:
Begin
triangleTopLeft := round(iWidth * 0.70);
triangleTopRight := round(iWidth * 0.82);
trianglePointLeft := round(iWidth * 0.55);
end;
iesSpeechBubbleRightOutLong,
iesSpeechBubbleRightOutShort:
Begin
triangleTopLeft := round(iWidth * 0.70);
triangleTopRight := round(iWidth * 0.82);
trianglePointLeft := round(iWidth * 0.92);
end;
else
raise Exception.Create('Unknown shape');
end;
if invertDir then
begin
result := CreateEllipticRgn( _FlipVert( iTop ), iLeft, _FlipVert( iTop + iHeight ), iLeft + iWidth );
// Top Circles
rgn1 := CreateEllipticRgn( _FlipVert( iTop ), iLeft, _FlipVert( iTop + circleSz ), iLeft + circleSz );
rgn2 := CreateEllipticRgn( _FlipVert( iTop ), iLeft + iWidth - circleSz, _FlipVert( iTop + circleSz ), iLeft + iWidth );
combineRgn(result, rgn1, rgn2, RGN_OR);
// Bottom Circles
rgn3 := CreateEllipticRgn( _FlipVert( iTop + bubbleHeight - circleSz ), iLeft, _FlipVert( iTop + bubbleHeight ), iLeft + circleSz );
combineRgn(result, result, rgn3, RGN_OR);
rgn4 := CreateEllipticRgn( _FlipVert( iTop + bubbleHeight - circleSz ), iLeft + iWidth - circleSz, _FlipVert( iTop + bubbleHeight ), iLeft + iWidth );
combineRgn(result, result, rgn4, RGN_OR);
// Box fills
rgn5 := CreateRectRgn( _FlipVert( iTop ),
iLeft + halfCircleSz,
_FlipVert( iTop + bubbleHeight ),
iLeft + iWidth - halfCircleSz);
combineRgn(result, result, rgn5, RGN_OR);
rgn6 := CreateRectRgn( _FlipVert( iTop + halfCircleSz ),
iLeft,
_FlipVert( iTop + bubbleHeight - halfCircleSz ),
iLeft + iWidth);
combineRgn(result, result, rgn6, RGN_OR);
// Draw Triangle
poly[ 0 ] := point( _FlipVert( iTop + bubbleHeight - Round( Triangle_Buffer * iHeight )), iLeft + triangleTopLeft );
poly[ 1 ] := point( _FlipVert( iTop + bubbleHeight - Round( Triangle_Buffer * iHeight )), iLeft + triangleTopRight );
poly[ 2 ] := point( _FlipVert( iTop + triangleBottom ), iLeft + trianglePointLeft );
end
else
begin
result := CreateEllipticRgn( iLeft, _FlipVert( iTop ), iLeft + iWidth, _FlipVert( iTop + iHeight ));
// Top Circles
rgn1 := CreateEllipticRgn(iLeft, _FlipVert( iTop ), iLeft + circleSz, _FlipVert( iTop + circleSz ));
rgn2 := CreateEllipticRgn(iLeft + iWidth - circleSz, _FlipVert( iTop ), iLeft + iWidth, _FlipVert( iTop + circleSz ));
combineRgn(result, rgn1, rgn2, RGN_OR);
// Bottom Circles
rgn3 := CreateEllipticRgn(iLeft, _FlipVert( iTop + bubbleHeight - circleSz ), iLeft + circleSz, _FlipVert( iTop + bubbleHeight ));
combineRgn(result, result, rgn3, RGN_OR);
rgn4 := CreateEllipticRgn(iLeft + iWidth - circleSz, _FlipVert( iTop + bubbleHeight - circleSz ), iLeft + iWidth, _FlipVert( iTop + bubbleHeight ));
combineRgn(result, result, rgn4, RGN_OR);
// Box fills
rgn5 := CreateRectRgn( iLeft + halfCircleSz,
_FlipVert( iTop ),
iLeft + iWidth - halfCircleSz,
_FlipVert( iTop + bubbleHeight ));
combineRgn(result, result, rgn5, RGN_OR);
rgn6 := CreateRectRgn( iLeft,
_FlipVert( iTop + halfCircleSz ),
iLeft + iWidth,
_FlipVert( iTop + bubbleHeight - halfCircleSz ));
combineRgn(result, result, rgn6, RGN_OR);
// Draw Triangle
poly[ 0 ] := point( iLeft + triangleTopLeft, _FlipVert( iTop + bubbleHeight - Round( Triangle_Buffer * iHeight )));
poly[ 1 ] := point( iLeft + triangleTopRight, _FlipVert( iTop + bubbleHeight - Round( Triangle_Buffer * iHeight )));
poly[ 2 ] := point( iLeft + trianglePointLeft, _FlipVert( iTop + triangleBottom ));
end;
rgn7 := Windows.CreatePolygonRgn(poly, 3, WINDING);
combineRgn(Result, result, rgn7, RGN_OR);
DeleteObject(rgn1);
DeleteObject(rgn2);
DeleteObject(rgn3);
DeleteObject(rgn4);
DeleteObject(rgn5);
DeleteObject(rgn6);
DeleteObject(rgn7);
end;
// Note: Angle is rounded to nearest 90
function CreateThoughtBubbleRegion(iLeft, iTop, iWidth, iHeight: Integer; Shape: TIEShape; Angle: Integer = 0): Hrgn;
const
Max_X = 1000;
Thought_Bubble_Max_Y = 1000;
Cloud_Max_Y = 817;
Last_Cloud_Rect = 8;
Thought_Bubble_Ellipses : array[0 .. 11] of TRect = ( (Left: 160; Top: 142; Right: 845; Bottom: 718),
(Left: 0; Top: 229; Right: 323; Bottom: 573),
(Left: 160; Top: 73; Right: 482; Bottom: 404),
(Left: 411; Top: 0; Right: 743; Bottom: 431),
(Left: 630; Top: 133; Right: 942; Bottom: 460),
(Left: 776; Top: 351; Right: 1000; Bottom: 595),
(Left: 689; Top: 509; Right: 875; Bottom: 740),
(Left: 394; Top: 513; Right: 727; Bottom: 817),
(Left: 138; Top: 396; Right: 496; Bottom: 754),
(Left: 783; Top: 758; Right: 880; Bottom: 862),
(Left: 860; Top: 873; Right: 919; Bottom: 935),
(Left: 910; Top: 960; Right: 950; Bottom: 1000));
var
rgn2: Hrgn;
I, ellipseLeft, ellipseRight, ellipseTop, ellipseBottom, MaxY: integer;
invertDir, flipHorz, flipVert: Boolean;
function _FlipHorz(value: Integer): integer;
begin
if flipHorz then
Result := iWidth - Value
else
Result := Value;
end;
function _FlipVert(value: Integer): integer;
begin
if flipVert then
Result := iHeight - Value
else
Result := Value;
end;
begin
Result := 0;
Angle := RoundTo90( Angle );
invertDir := ( Angle = 90 ) or ( Angle = 270 );
if Shape = iesThoughtBubbleLeft then
begin
flipVert := ( Angle = 180 ) or ( Angle = 90 );
flipHorz := ( Angle = 0 ) or ( Angle = 90 );
end
else
begin
flipVert := ( Angle = 180 ) or ( Angle = 270 );
flipHorz := ( Angle = 180 ) or ( Angle = 90 );
end;
if Shape <> iesCloud then
MaxY := Thought_Bubble_Max_Y
else
begin
MaxY := Cloud_Max_Y;
flipVert := not flipVert;
end;
for I := Low( Thought_Bubble_Ellipses ) to High( Thought_Bubble_Ellipses ) do
begin
if invertDir then
begin
ellipseLeft := _FlipHorz( Round( iWidth * ( Thought_Bubble_Ellipses[ I ].Bottom / MaxY )));
ellipseTop := _FlipVert( Round( iHeight * ( Thought_Bubble_Ellipses[ I ].Left / Max_X )));
ellipseRight := _FlipHorz( Round( iWidth * ( Thought_Bubble_Ellipses[ I ].Top / MaxY )));
ellipseBottom := _FlipVert( Round( iHeight * ( Thought_Bubble_Ellipses[ I ].Right / Max_X )));
end
else
begin
ellipseLeft := _FlipHorz( Round( iWidth * ( Thought_Bubble_Ellipses[ I ].Left / Max_X )));
ellipseTop := _FlipVert( Round( iHeight * ( Thought_Bubble_Ellipses[ I ].Top / MaxY )));
ellipseRight := _FlipHorz( Round( iWidth * ( Thought_Bubble_Ellipses[ I ].Right / Max_X )));
ellipseBottom := _FlipVert( Round( iHeight * ( Thought_Bubble_Ellipses[ I ].Bottom / MaxY )));
end;
if I = Low( Thought_Bubble_Ellipses ) then
result := CreateEllipticRgn( iLeft + ellipseLeft, iTop + ellipseTop,
iLeft + ellipseRight, iTop + ellipseBottom )
else
begin
rgn2 := CreateEllipticRgn( iLeft + ellipseLeft, iTop + ellipseTop,
iLeft + ellipseRight, iTop + ellipseBottom );
combineRgn(result, result, rgn2, RGN_OR);
DeleteObject(rgn2);
if ( Shape = iesCloud ) and ( I = Last_Cloud_Rect ) then
Break;
end;
end;
end;
function CreateCircularFrameRegion(iLeft, iTop, iWidth, iHeight: Integer; Angle: Integer = 0): Hrgn;
var
rgn2: Hrgn;
begin
Result := CreateEllipticRgn(iLeft, iTop, iLeft + iWidth, iTop + iHeight);
rgn2 := CreateEllipticRgn(iLeft + iWidth div 8, iTop + iHeight div 8, iLeft + iWidth - iWidth div 8, iTop + iHeight - iHeight div 8);
combineRgn(Result, Result, rgn2, RGN_XOR);
DeleteObject(rgn2);
end;
// Note: Angle is not used
function CreateFrameRegion(iLeft, iTop, iWidth, iHeight: Integer; Shape: TIEShape; Angle: Integer = 0): Hrgn;
var
rgn2: Hrgn;
dw: integer;
begin
case Shape of
iesFatFrame : dw := min(iWidth div 4, iHeight div 4);
iesNarrowFrame : dw := min(iWidth div 16, iHeight div 16);
else { iesFrame } dw := min(iWidth div 8, iHeight div 8);
end;
result := CreateRectRgn(iLeft, iTop, iLeft + iWidth, iTop + iHeight );
rgn2 := CreateRectRgn(iLeft + dw, iTop + dw, iLeft + iWidth - dw, iTop + iHeight - dw);
combineRgn(result, result, rgn2, RGN_XOR);
DeleteObject(rgn2);
end;
{!!
<FS>IEShapePreferredAspectRatio
<FM>Declaration<FC>
function IEShapePreferredAspectRatio(Shape: <A TIEShape>): Double;
<FM>Description<FN>
Some shapes are best displayed at the ratio they were designed (typically 1:1). This method returns that preferred aspect ratio (equating to Height / Width ) or 0 if the shape has no preferred ratio.
Note: Defined in iexCanvasUtils unit
<FM>Example<FC>
aspectRatio := IEShapePreferredAspectRatio( iesHeart ); // Returns 1
!!}
function IEShapePreferredAspectRatio(Shape: TIEShape): Double;
begin
Result := 0;
if Shape in [ iesMoon ] then
Result := 0.5
else
if Shape in [ iesStar5 ,
iesStar6 ,
iesCustomStar,
iesArrowNW ,
iesArrowNE ,
iesArrowSW ,
iesArrowSE ,
iesShootingArrowNW,
iesShootingArrowNE,
iesShootingArrowSW,
iesShootingArrowSE,
iesHeart ,
iesDoubleHeart ,
iesLightningLeft,
iesLightningRight,
iesCustomStar ,
iesTriangle ,
iesCorner ,
iesDiamond,
iesPentagon ,
iesHexagon ,
iesHeptagon ,
iesOctagon ,
iesCustomShape ,
iesCross ] then
Result := 1;
end;
const
Max_Shape_Region_Points = 31;
Rect_Pts : array[0 .. 4] of TDPoint = ((X: 0; Y: 0), (X: 1; Y: 0), (X: 1; Y: 1), (X: 0; Y: 1), (X: 0; Y: 0));
Triangle_Pts : array[0 .. 3] of TDPoint = ((X: 0.5; Y: 0), (X: 1; Y: 1), (X: 0; Y: 1), (X: 0.5; Y: 0));
Corner_Pts : array[0 .. 3] of TDPoint = ((X: 0; Y: 0), (X: 1; Y: 0), (X: 0; Y: 1), (X: 0; Y: 0));
Star_5_Pts : array[0 .. 10] of TDPoint = ( (X: 0.5; Y: 0),
(X: 0.62; Y: 0.38),
(X: 1; Y: 0.38),
(X: 0.7; Y: 0.62),
(X: 0.81; Y: 1.00),
(X: 0.5; Y: 0.77),
(X: 0.19; Y: 1.00),
(X: 0.31; Y: 0.62),
(X: 0; Y: 0.38),
(X: 0.39; Y: 0.38),
(X: 0.5; Y: 0) );
Star_6_Pts : array[0 .. 12] of TDPoint = ((X: 0.5; Y: 0), (X: 0.625; Y: 0.25), (X: 0.9; Y: 0.25), (X: 0.75; Y: 0.5), (X: 0.9; Y: 0.75), (X: 0.625; Y: 0.75), (X: 0.5; Y: 1), (X: 0.375; Y: 0.75), (X: 0.1; Y: 0.75), (X: 0.25; Y: 0.5), (X: 0.1; Y: 0.25), (X: 0.375; Y: 0.25), (X: 0.5; Y: 0));
Arrow_NW_Pts : array[0 .. 7] of TDPoint = ((X: 0; Y: 0), (X: 0.4; Y: 0), (X: 0.3; Y: 0.1), (X: 1; Y: 0.8), (X: 0.8; Y: 1), (X: 0.1; Y: 0.3), (X: 0; Y: 0.4), (X: 0; Y: 0));
Shooting_Arrow_NW_Pts : array[0 .. 30] of TDPoint = ((X: 0.85; Y: 1), (X: 0.8; Y: 0.95), (X: 0.8; Y: 0.85), (X: 0.775; Y: 0.825), (X: 0.775; Y: 0.925), (X: 0.725; Y: 0.875), (X: 0.725; Y: 0.775), (X: 0.7; Y: 0.75), (X: 0.7; Y: 0.85), (X: 0.65; Y: 0.8), (X: 0.65; Y: 0.7), (X: 0.15; Y: 0.2), (X: 0.15; Y: 0.3), (X: 0; Y: 0.15), (X: 0; Y: 0), (X: 0.15; Y: 0), (X: 0.3; Y: 0.15), (X: 0.2; Y: 0.15), (X: 0.7; Y: 0.65), (X: 0.8; Y: 0.65), (X: 0.85; Y: 0.7), (X: 0.75; Y: 0.7), (X: 0.775; Y: 0.725), (X: 0.875; Y: 0.725), (X: 0.925; Y: 0.775), (X: 0.825; Y: 0.775), (X: 0.85; Y: 0.8), (X: 0.95; Y: 0.8), (X: 1; Y: 0.85), (X: 0.85; Y: 0.85), (X: 0.85; Y: 1));
Lightning_Left_Pts : array[0 .. 11] of TDPoint = ((X: 1; Y: 0.19), (X: 0.61; Y: 0.01), (X: 0.41; Y: 0.29), (X: 0.49; Y: 0.31), (X: 0.23; Y: 0.55), (X: 0.33; Y: 0.6), (X: 0; Y: 1), (X: 0.51; Y: 0.69), (X: 0.46; Y: 0.65), (X: 0.78; Y: 0.45), (X: 0.66; Y: 0.39), (X: 1; Y: 0.19));
Explosion_Pts : array[0 .. 24] of TDPoint = ((X: 0.33; Y: 0), (X: 0.5; Y: 0.26), (X: 0.62; Y: 0.11), (X: 0.67; Y: 0.28), (X: 0.99; Y: 0.1), (X: 0.78; Y: 0.35), (X: 1; Y: 0.39), (X: 0.84; Y: 0.54), (X: 0.99; Y: 0.66), (X: 0.75; Y: 0.64), (X: 0.78; Y: 0.81), (X: 0.65; Y: 0.71), (X: 0.61; Y: 1), (X: 0.51; Y: 0.69), (X: 0.38; Y: 0.89), (X: 0.35; Y: 0.66), (X: 0.17; Y: 0.83), (X: 0.22; Y: 0.59), (X: 0; Y: 0.61), (X: 0.19; Y: 0.48), (X: 0.04; Y: 0.37), (X: 0.22; Y: 0.34), (X: 0.16; Y: 0.2), (X: 0.35; Y: 0.25), (X: 0.33; Y: 0.01));
Badge_Pts : array[0 .. 5] of TDPoint = ( (X: 0.25; Y: 0),
(X: 0.75; Y: 0),
(X: 1.00; Y: 0.25),
(X: 0.50; Y: 1),
(X: 0.00; Y: 0.25),
(X: 0.25; Y: 0) );
Diamond_Pts : array[0 .. 4] of TDPoint = ( (X: 0.50; Y: 0.00),
(X: 1.00; Y: 0.50),
(X: 0.50; Y: 1.00),
(X: 0.00; Y: 0.50),
(X: 0.50; Y: 0.00) );
Arrow_Head_Size = 0.40;
Arrow_Offset = 0.33;
Arrow_Up_Pts : array[0 .. 6] of TDPoint = ( (X: Arrow_Offset; Y: 1.00),
(X: Arrow_Offset; Y: Arrow_Head_Size),
(X: 0.00; Y: Arrow_Head_Size),
(X: 0.50; Y: 0.00),
(X: 1.00; Y: Arrow_Head_Size),
(X: 1 - Arrow_Offset; Y: Arrow_Head_Size),
(X: 1 - Arrow_Offset; Y: 1.00) );
Double_Arrow_Head_Size = 0.30;
Double_Vert_Arrow_Pts : array[0 .. 9] of TDPoint = ( (X: 0.50; Y: 0.00), // Top point
(X: 0.00; Y: Double_Arrow_Head_Size),
(X: 0.33; Y: Double_Arrow_Head_Size),
(X: 0.33; Y: 1 - Double_Arrow_Head_Size),
(X: 0.00; Y: 1 - Double_Arrow_Head_Size),
(X: 0.50; Y: 1.00), // bottom point
(X: 1.00; Y: 1 - Double_Arrow_Head_Size),
(X: 0.67; Y: 1 - Double_Arrow_Head_Size),
(X: 0.67; Y: Double_Arrow_Head_Size),
(X: 1.00; Y: Double_Arrow_Head_Size) );
Fat_Arrow_Head_Size = 0.40;
Fat_Arrow_Offset = 0.16;
Fat_Arrow_Up_Pts : array[0 .. 6] of TDPoint = ( (X: Fat_Arrow_Offset; Y: 1.00),
(X: Fat_Arrow_Offset; Y: Fat_Arrow_Head_Size),
(X: 0.00; Y: Fat_Arrow_Head_Size),
(X: 0.50; Y: 0.00),
(X: 1.00; Y: Fat_Arrow_Head_Size),
(X: 1 - Fat_Arrow_Offset; Y: Fat_Arrow_Head_Size),
(X: 1 - Fat_Arrow_Offset; Y: 1.00) );
Shield_Pts : array[0 .. 15] of TDPoint = ( (X: 0.00; Y: 0.00),
(X: 0.25; Y: 0.125),
(X: 0.50; Y: 0.00),
(X: 0.75; Y: 0.125),
(X: 1.00; Y: 0.00),
(X: 0.875; Y: 0.25),
(X: 1.00; Y: 0.50),
(X: 0.875; Y: 0.75),
(X: 1.00; Y: 1.00),
(X: 0.75; Y: 0.875),
(X: 0.50; Y: 1.00),
(X: 0.25; Y: 0.875),
(X: 0.00; Y: 1.00),
(X: 0.125; Y: 0.75),
(X: 0.00; Y: 0.50),
(X: 0.125; Y: 0.25) );
Name_Plate_Corner_Width = 0.12;
Name_Plate_Pts : array[0 .. 20] of TDPoint = ( (X: 0.00; Y: 0.00 ),
(X: -(2 * Name_Plate_Corner_Width); Y: 0.00 ),
(X: -(2 * Name_Plate_Corner_Width); Y: -(Name_Plate_Corner_Width) ),
(X: -(1 - 2 * Name_Plate_Corner_Width); Y: -(Name_Plate_Corner_Width) ),
(X: -(1 - 2 * Name_Plate_Corner_Width); Y: 0.00 ),
(X: 1.00; Y: 0.00 ),
(X: 1.00; Y: -(2 * Name_Plate_Corner_Width) ),
(X: -(1 - Name_Plate_Corner_Width); Y: -(2 * Name_Plate_Corner_Width) ),
(X: -(1 - Name_Plate_Corner_Width); Y: -(1 - 2 * Name_Plate_Corner_Width) ),
(X: 1.00; Y: -(1 - 2 * Name_Plate_Corner_Width) ),
(X: 1.00; Y: 1.00 ),
(X: -(1 - 2 * Name_Plate_Corner_Width); Y: 1.00 ),
(X: -(1 - 2 * Name_Plate_Corner_Width); Y: -(1 - Name_Plate_Corner_Width) ),
(X: -(2 * Name_Plate_Corner_Width); Y: -(1 - Name_Plate_Corner_Width) ),
(X: -(2 * Name_Plate_Corner_Width); Y: 1.00 ),
(X: 0.00; Y: 1.00 ),
(X: 0.00; Y: -(1 - 2 * Name_Plate_Corner_Width) ),
(X: -(Name_Plate_Corner_Width); Y: -(1 - 2 * Name_Plate_Corner_Width) ),
(X: -(Name_Plate_Corner_Width); Y: -(2 * Name_Plate_Corner_Width) ),
(X: 0.00; Y: -(2 * Name_Plate_Corner_Width) ),
(X: 0.00; Y: 0.00 ) );
Cross_Inset_Width = 0.33;
Cross_Pts : array[0 .. 12] of TDPoint = ( (X: Cross_Inset_Width; Y: 0.00),
(X: 1.00 - Cross_Inset_Width; Y: 0.00),
(X: 1.00 - Cross_Inset_Width; Y: Cross_Inset_Width),
(X: 1.00; Y: Cross_Inset_Width),
(X: 1.00; Y: 1.00 - Cross_Inset_Width),
(X: 1.00 - Cross_Inset_Width; Y: 1.00 - Cross_Inset_Width),
(X: 1.00 - Cross_Inset_Width; Y: 1.00 ),
(X: Cross_Inset_Width; Y: 1.00),
(X: Cross_Inset_Width; Y: 1.00 - Cross_Inset_Width),
(X: 0.00; Y: 1.00 - Cross_Inset_Width ),
(X: 0.00; Y: Cross_Inset_Width),
(X: Cross_Inset_Width; Y: Cross_Inset_Width),
(X: Cross_Inset_Width; Y: 0.00) );
procedure IEGenerateShapePoints(out PointArray: Array of TPoint; out PointArrayCount: Integer;
Shape: TIEShape; iLeft, iTop, iWidth, iHeight: Integer;
Angle: Integer = 0; MaintainAROnRotate: Boolean = False;
ShapeModifier: Integer = 0);
var
flipHorz, flipVert, invertDir: Boolean;
procedure _GetShapePoints(SrcPointArray: array of TDPoint; bFlipHorz, bFlipVert, bInvertDir: Boolean);
var
i: Integer;
iShortSide: Integer;
iX, iY: Double;
begin
if (Shape in [ iesLightningLeft, iesLightningRight ]) and ( iWidth > iHeight ) then
begin
// Maintain the Aspect Ratio
iShortSide := iHeight;
Inc(iLeft, (iWidth - iShortSide) div 2);
iWidth := iShortSide;
end;
dec( iWidth );
dec( iHeight );
PointArrayCount := 1 + High(SrcPointArray) - Low(SrcPointArray);
for i := 0 to PointArrayCount - 1 do
begin
iX := abs( SrcPointArray[i].x );
// Negative values mean to average height and width
if iWidth > iHeight then
begin
if SrcPointArray[i].x < -0.50 then
iX := 1 - ( ( 1 - iX ) * iHeight / iWidth )
else
if SrcPointArray[i].x < -0.00 then
iX := iX * iHeight / iWidth;
end;
iY := abs( SrcPointArray[i].y );
// Negative values mean to average height and width
if iHeight > iWidth then
begin
if SrcPointArray[i].y < -0.50 then
iY := 1 - ( ( 1 - iY ) * iWidth / iHeight )
else
if SrcPointArray[i].y < -0.00 then
iY := iY * iWidth / iHeight;
end;
// FLIP HORZ
if bFlipHorz then
iX := 1 - iX;
// FLIP VERT
if bFlipVert then
iY := 1 - iY;
if bInvertDir then
begin
PointArray[i].x := iLeft + round(iY * (iWidth - 1));
PointArray[i].y := iTop + round(iX * (iHeight - 1));
end
else
begin
PointArray[i].x := iLeft + round(iX * (iWidth - 1));
PointArray[i].y := iTop + round(iY * (iHeight - 1));
end;
end;
if Angle mod 90 <> 0 then
begin
IERotatePoints( PointArray, PointArrayCount, - Angle, iLeft + iWidth div 2, iTop + iHeight div 2 );
IEScalePoints( PointArray, PointArrayCount, iLeft, iTop, iLeft + iWidth, iTop + iHeight, MaintainAROnRotate );
end;
end;
procedure _GetCustomPolygonPoints(Shape: TIEShape; PointCount : Integer);
begin
GetCustomPolygonPoints( PointArray, PointArrayCount, iLeft, iTop, iWidth, iHeight, Shape, PointCount, Angle );
end;
begin
// for 90 degree rotates, do flip/inversions for speed
flipHorz := ( Angle = 180 ) or ( Angle = 270 );
flipVert := ( Angle = 90 ) or ( Angle = 180 );
invertDir := (Angle = 90) or ( Angle = 270 );
// Note: Ensure aligns with Supported_Generate_Points_Shapes
case Shape of
iesRectangle,
iesRoundRect : _GetShapePoints( Rect_Pts, False, False, False );
iesTriangle : _GetShapePoints( Triangle_Pts, flipHorz, flipVert, invertDir );
iesCorner : _GetShapePoints( Corner_Pts, flipHorz, flipVert, invertDir );
iesDiamond : _GetShapePoints( Diamond_Pts, flipHorz, flipVert, invertDir );
iesStar5 : _GetShapePoints( Star_5_Pts, flipHorz, flipVert, invertDir );
iesStar6 : _GetShapePoints( Star_6_Pts, flipHorz, flipVert, invertDir );
iesArrowLeft : _GetShapePoints( Arrow_Up_Pts, flipHorz, flipVert, not invertDir );
iesArrowRight : _GetShapePoints( Arrow_Up_Pts, flipHorz, not flipVert, not invertDir );
iesArrowUp : _GetShapePoints( Arrow_Up_Pts, flipHorz, flipVert, invertDir );
iesArrowDown : _GetShapePoints( Arrow_Up_Pts, flipHorz, not flipVert, invertDir );
iesFatArrowUp : _GetShapePoints( Fat_Arrow_Up_Pts, flipHorz, flipVert, invertDir );
iesFatArrowLeft : _GetShapePoints( Fat_Arrow_Up_Pts, flipHorz, flipVert, not invertDir );
iesFatArrowRight : _GetShapePoints( Fat_Arrow_Up_Pts, flipHorz, not flipVert, not invertDir );
iesFatArrowDown : _GetShapePoints( Fat_Arrow_Up_Pts, flipHorz, not flipVert, invertDir );
iesArrowLeftRight : _GetShapePoints( Double_Vert_Arrow_Pts, flipHorz, flipVert, not invertDir );
iesArrowUpDown : _GetShapePoints( Double_Vert_Arrow_Pts, flipHorz, flipVert, invertDir );
iesArrowNW : _GetShapePoints( Arrow_NW_Pts, flipHorz, flipVert, invertDir );
iesArrowNE : _GetShapePoints( Arrow_NW_Pts, not flipHorz, flipVert, invertDir );
iesArrowSW : _GetShapePoints( Arrow_NW_Pts, flipHorz, not flipVert, invertDir );
iesArrowSE : _GetShapePoints( Arrow_NW_Pts, not flipHorz, not flipVert, invertDir );
iesShootingArrowNW : _GetShapePoints( Shooting_Arrow_NW_Pts, flipHorz, flipVert, invertDir );
iesShootingArrowNE : _GetShapePoints( Shooting_Arrow_NW_Pts, not flipHorz, flipVert, invertDir );
iesShootingArrowSW : _GetShapePoints( Shooting_Arrow_NW_Pts, flipHorz, not flipVert, invertDir );
iesShootingArrowSE : _GetShapePoints( Shooting_Arrow_NW_Pts, not flipHorz, not flipVert, invertDir );
iesLightningLeft : _GetShapePoints( Lightning_Left_Pts, flipHorz, flipVert, invertDir );
iesLightningRight : _GetShapePoints( Lightning_Left_Pts, not flipHorz, flipVert, invertDir );
iesExplosion : _GetShapePoints( Explosion_Pts, flipHorz, flipVert, invertDir );
iesCross : _GetShapePoints( Cross_Pts, flipHorz, flipVert, invertDir );
iesShield : _GetShapePoints( Shield_Pts, flipHorz, flipVert, invertDir );
iesBadge : _GetShapePoints( Badge_Pts, flipHorz, flipVert, invertDir );
iesNamePlate : _GetShapePoints( Name_Plate_Pts, flipHorz, flipVert, invertDir );
iesPentagon : _GetCustomPolygonPoints( iesCustomShape, 5 );
iesHexagon : _GetCustomPolygonPoints( iesCustomShape, 6 );
iesHeptagon : _GetCustomPolygonPoints( iesCustomShape, 7 );
iesOctagon : _GetCustomPolygonPoints( iesCustomShape, 8 );
iesCustomShape : _GetCustomPolygonPoints( iesCustomShape, ShapeModifier );
iesCustomStar : _GetCustomPolygonPoints( iesCustomStar, ShapeModifier );
iesCustomExplosion : _GetCustomPolygonPoints( iesCustomExplosion, ShapeModifier );
else raise EIEException.create( 'Unexpected Shape' );
end;
end;
{!!
<FS>IECreateShapeRegion
<FM>Declaration<FC>
function IECreateShapeRegion(Shape: <A TIEShape>; iLeft, iTop, iWidth, iHeight: Integer;
Angle: Integer = 0; ShapeModifier: Integer = 0): HRgn; overload;
function IECreateShapeRegion(Shape: <A TIEShape>; ARect: TRect; MaintainAspect: TIEBooleanEx = iebDefault;
Angle: Integer = 0; ShapeModifier: Integer = 0): HRgn; overload;
<FM>Description<FN>
Create an HRGN of a <A TIEShape> at the specified position and size.
If MaintainAspect is <FC>iebDefault<FN>, then shapes are output at the aspect ratio they were designed (if <FC>iebTrue<FN> then a 1:1 aspect ratio is enforced even if it was not designed with one).
<FC>Angle<FN> is the amount of rotation to apply (degrees counter-clockwise). The following shapes can only be rotated in 90 degree increments: iesHalfEllipse, iesRoundRect, iesHeart, iesDoubleHeart, iesCloud, iesMoon, iesSpeechBubble*, iesThoughtBubble*, iesFrame, iesNarrowFrame, iesFatFrame
<FC>ShapeModifier<FN> has the following effect:
<TABLE>
<R> <H>Shape</H> <H>Effect</H> <H>Range</H> <H>Default</H> </R>
<R> <C><FC>iesCustomShape<FN></C> <C> Specifies the number of sides of the shape </C> <C>3 - 50</C> <C>10</C> </R>
<R> <C><FC>iesCustomStar<FN></C> <C> Specifies the number of points of the star </C> <C>3 - 50</C> <C>10</C> </R>
<R> <C><FC>iesCustomExplosion<FN></C> <C> Specifies the number of points of the explosion </C> <C>3 - 50</C><C>12</C> </R>
<R> <C><FC>iesEllipseSegment<FN></C> <C> Specifies the width of the ellipse segment (in degrees) </C> <C>1 - 90</C> <C>45</C> </R>
</TABLE>
Note: Defined in iexCanvasUtils unit
<FM>Example<FC>
// Create a heart HRGN
aRgn := IECreateShapeRegion( iesExplosion, 0, 0, 200, 200 );
!!}
function IECreateShapeRegion(Shape: TIEShape; iLeft, iTop, iWidth, iHeight: Integer; MaintainAspect: TIEBooleanEx = iebDefault;
Angle: Integer = 0; ShapeModifier: Integer = 0): HRgn;
var
maintainAR: Boolean;
function _CreateCustomPolygonRegion(Shape: TIEShape; InPointCount : Integer): HRgn;
var
arPts : Array[ 0 .. Max_Custom_Polygon_Points ] of TPoint;
pts: Integer;
begin
GetCustomPolygonPoints( arPts, pts, iLeft, iTop, iWidth, iHeight, Shape, InPointCount, Angle );
Result := CreatePolygonRgn(arPts, pts, WINDING);
end;
function _CreateShapeRegionEx(): HRgn;
var
arPts : Array[ 0 .. Max_Shape_Region_Points ] of TPoint;
pts: Integer;
begin
IEGenerateShapePoints( arPts, pts, Shape, iLeft, iTop, iWidth, iHeight, Angle, maintainAr );
Result := CreatePolygonRgn(arPts, pts, WINDING);
end;
begin
// ImageEn angles are counter-clockwise
Angle := 360 - Angle;
while Angle >= 360 do
Dec( Angle, 360 );
while Angle < 0 do
Inc( Angle, 360 );
// Should object be drawn 1:1
maintainAR := MaintainAspect = iebTrue;
if MaintainAspect = iebDefault then
maintainAR := IEShapePreferredAspectRatio( Shape ) <> 0;
if maintainAR then
begin
KeepAspectRatioForDimensions( iLeft, iTop, iWidth, iHeight );
if Shape in [ iesHalfEllipse, iesMoon ] then
begin
// Moon needs to be scaled 1:2
if ( Angle = 90 ) or ( Angle = 270 ) then
begin
inc( iTop, iHeight div 4 );
iHeight := iHeight div 2;
end
else
begin
inc( iLeft, iWidth div 4 );
iWidth := iWidth div 2;
end;
end;
end;
case Shape of
iesEllipse : Result := CreateEllipticRgn( iLeft, iTop, iLeft + iWidth, iTop + iHeight );
iesHalfEllipse : Result := CreateHalfCircleRegion(iLeft, iTop, iWidth, iHeight, False, Angle);
iesQuarterEllipse : Result := CreateQuarterCircleRegion(iLeft, iTop, iWidth, iHeight, Angle, 90 );
iesEllipseSegment : Result := CreateQuarterCircleRegion(iLeft, iTop, iWidth, iHeight, Angle, ShapeModifier );
iesRectangle : if Angle mod 90 = 0 then
Result := CreateRectRgn( iLeft, iTop, iLeft + iWidth, iTop + iHeight )
else
Result := _CreateShapeRegionEx();
iesRoundRect : begin
// Note: Angle is not supported
Result := CreateRoundRectRgn( iLeft, iTop, iLeft + iWidth, iTop + iHeight, min( iWidth div 4, iHeight div 4 ), min( iWidth div 4, iHeight div 4 ));
end;
iesSpeechBubbleLeftInLong,
iesSpeechBubbleLeftOutLong,
iesSpeechBubbleRightInLong,
iesSpeechBubbleRightOutLong,
iesSpeechBubbleLeftInShort,
iesSpeechBubbleLeftOutShort,
iesSpeechBubbleRightInShort,
iesSpeechBubbleRightOutShort : Result := CreateSpeechBubbleRegion(iLeft, iTop, iWidth, iHeight, Shape, Angle);
iesCloud,
iesThoughtBubbleLeft,
iesThoughtBubbleRight : Result := CreateThoughtBubbleRegion(iLeft, iTop, iWidth, iHeight, Shape, Angle);
iesFrame,
iesNarrowFrame,
iesFatFrame : Result := CreateFrameRegion(iLeft, iTop, iWidth, iHeight, Shape, Angle);
iesCircularFrame : Result := CreateCircularFrameRegion(iLeft, iTop, iWidth, iHeight, Angle);
iesPentagon : Result := _CreateCustomPolygonRegion( iesCustomShape, 5 );
iesHexagon : Result := _CreateCustomPolygonRegion( iesCustomShape, 6 );
iesHeptagon : Result := _CreateCustomPolygonRegion( iesCustomShape, 7 );
iesOctagon : Result := _CreateCustomPolygonRegion( iesCustomShape, 8 );
iesCustomShape : Result := _CreateCustomPolygonRegion( iesCustomShape, ShapeModifier );
iesCustomStar : Result := _CreateCustomPolygonRegion( iesCustomStar, ShapeModifier );
iesCustomExplosion : Result := _CreateCustomPolygonRegion( iesCustomExplosion, ShapeModifier );
iesHeart : Result := CreateHeartRegion(iLeft, iTop, iWidth, iHeight, Angle);
iesDoubleHeart : Result := CreateDoubleHeartRegion(iLeft, iTop, iWidth, iHeight, Angle);
iesMoon : Result := CreateHalfCircleRegion(iLeft, iTop, iWidth, iHeight, True, Angle);
else Result := _CreateShapeRegionEx();
end;
end;
function IECreateShapeRegion(Shape: TIEShape; ARect: TRect; MaintainAspect: TIEBooleanEx = iebDefault;
Angle: Integer = 0; ShapeModifier: Integer = 0): HRgn;
var
iLeft, iTop, iWidth, iHeight: Integer;
begin
iLeft := ARect.Left;
iTop := ARect.Top;
iWidth := ARect.Right - ARect.Left;
iHeight := ARect.Bottom - ARect.Top;
Result := IECreateShapeRegion( Shape, iLeft, iTop, iWidth, iHeight, MaintainAspect, Angle, ShapeModifier );
end;
{$ifdef IEIncludeDeprecatedInV6}
function CreateCustomShapeRegion(Shape: TXCustomShape; iLeft, iTop, iWidth, iHeight: Integer): Hrgn;
begin
case Shape of
xcsStar5 : result := IECreateShapeRegion( iesStar5 , iLeft, iTop, iWidth, iHeight, iebTrue );
xcsStar6 : result := IECreateShapeRegion( iesStar6 , iLeft, iTop, iWidth, iHeight, iebTrue );
xcsArrowNW : result := IECreateShapeRegion( iesArrowNW , iLeft, iTop, iWidth, iHeight, iebTrue );
xcsArrowNE : result := IECreateShapeRegion( iesArrowNE , iLeft, iTop, iWidth, iHeight, iebTrue );
xcsArrowSW : result := IECreateShapeRegion( iesArrowSW , iLeft, iTop, iWidth, iHeight, iebTrue );
xcsArrowSE : result := IECreateShapeRegion( iesArrowSE , iLeft, iTop, iWidth, iHeight, iebTrue );
xcsLightningLeft : result := IECreateShapeRegion( iesLightningLeft , iLeft, iTop, iWidth, iHeight, iebTrue );
xcsLightningRight : result := IECreateShapeRegion( iesLightningRight, iLeft, iTop, iWidth, iHeight, iebTrue );
xcsExplosion : result := IECreateShapeRegion( iesExplosion , iLeft, iTop, iWidth, iHeight, iebTrue );
xcsExplosion_2 : result := IECreateShapeRegion( iesExplosion , iLeft, iTop, iWidth, iHeight, iebTrue, 180 );
xcsCross : result := IECreateShapeRegion( iesCross , iLeft, iTop, iWidth, iHeight, iebTrue );
xcsArrowNW2 : result := IECreateShapeRegion( iesShootingArrowNW, iLeft, iTop, iWidth, iHeight, iebTrue );
xcsArrowNE2 : result := IECreateShapeRegion( iesShootingArrowNE, iLeft, iTop, iWidth, iHeight, iebTrue );
xcsArrowSW2 : result := IECreateShapeRegion( iesShootingArrowSW, iLeft, iTop, iWidth, iHeight, iebTrue );
xcsArrowSE2 : result := IECreateShapeRegion( iesShootingArrowSE, iLeft, iTop, iWidth, iHeight, iebTrue );
xcsHeart : result := IECreateShapeRegion( iesHeart , iLeft, iTop, iWidth, iHeight, iebTrue );
xcsDoubleHeart : result := IECreateShapeRegion( iesDoubleHeart , iLeft, iTop, iWidth, iHeight, iebTrue );
else raise Exception.create( 'Unknown shape' );
end;
end;
{$endif}
{!!
<FS>IEDrawShape
<FM>Declaration<FC>
procedure IEDrawShape(Canvas: TCanvas; Shape: <A TIEShape>; iLeft, iTop, iWidth, iHeight: Integer; MaintainAspect: <A TIEBooleanEx> = iebDefault); overload;
procedure IEDrawShape(Canvas: TCanvas; Shape: <A TIEShape>;
iLeft, iTop, iWidth, iHeight: Integer; MaintainAspect: <A TIEBooleanEx>;
BorderColor: TColor; BorderWidth: Integer;
FillColor: TColor; FillColor2: TColor = clNone; GradientDir: <A TIEGradientDir> = gdVertical
Angle: Integer = 0; ShapeModifier: Integer = 0); overload;
<FM>Description<FN>
Draw a <A TIEShape> onto a canvas at the specified size and position.
If MaintainAspect is <FC>iebDefault<FN>, then shapes are output at the aspect ratio they were designed (if <FC>iebTrue<FN> then a 1:1 aspect ratio is enforced even if it was not designed with one).
For the first overload, the Canvas Brush is used for color and fill.
For the second, the colors you specify will override the canvas brush.
<FC>Angle<FN> is the amount of rotation to apply (degrees counter-clockwise). The following shapes can only be rotated in 90 degree increments: iesHalfEllipse, iesRoundRect, iesHeart, iesDoubleHeart, iesCloud, iesMoon, iesSpeechBubble*, iesThoughtBubble*, iesFrame, iesNarrowFrame, iesFatFrame
<FC>ShapeModifier<FN> has the following effect:
<TABLE>
<R> <H>Shape</H> <H>Effect</H> <H>Range</H> <H>Default</H> </R>
<R> <C><FC>iesCustomShape<FN></C> <C> Specifies the number of sides of the shape </C> <C>3 - 50</C> <C>10</C> </R>
<R> <C><FC>iesCustomStar<FN></C> <C> Specifies the number of points of the star </C> <C>3 - 50</C> <C>10</C> </R>
<R> <C><FC>iesCustomExplosion<FN></C> <C> Specifies the number of points of the explosion </C> <C>3 - 50</C><C>12</C> </R>
<R> <C><FC>iesEllipseSegment<FN></C> <C> Specifies the width of the ellipse segment (in degrees) </C> <C>1 - 90</C> <C>45</C> </R>
</TABLE>
Note: Defined in iexCanvasUtils unit
<FM>Example<FC>
// Draw a heart onto the centre of the current image
IEDrawShape( ImageEnView1.IEBitmap.Canvas, iesExplosion, Width div 2 - 100, Height div 2 - 100, 200, 200 );
ImageEnView1.Update;
!!}
procedure IEDrawShape(Canvas: TCanvas; Shape: TIEShape; iLeft, iTop, iWidth, iHeight: Integer; MaintainAspect: TIEBooleanEx = iebDefault);
var
rgnMain: HRGN;
begin
rgnMain := IECreateShapeRegion( Shape, iLeft, iTop, iWidth, iHeight, MaintainAspect );
try
SelectClipRgn(Canvas.handle, rgnMain);
Canvas.FillRect(Rect(iLeft, iTop, iLeft + iWidth, iTop + iHeight));
SelectClipRgn(Canvas.handle, 0);
finally
DeleteObject(rgnMain);
end;
end;
procedure IEDrawShape(Canvas: TCanvas; Shape: TIEShape;
iLeft, iTop, iWidth, iHeight: Integer; MaintainAspect: TIEBooleanEx;
BorderColor: TColor; BorderWidth: Integer;
FillColor: TColor; FillColor2: TColor = clNone; GradientDir: TIEGradientDir = gdVertical;
Angle: Integer = 0; ShapeModifier: Integer = 0);
var
rgnMain: HRGN;
begin
rgnMain := IECreateShapeRegion( Shape, iLeft, iTop, iWidth, iHeight, MaintainAspect, Angle, ShapeModifier );
try
SelectClipRgn( Canvas.handle, rgnMain );
// FILL
if ( FillColor2 <> clNone ) and ( FillColor <> FillColor2 ) then
IEDrawGradient(Rect(iLeft, iTop, iLeft + iWidth, iTop + iHeight),
Canvas.handle,
FillColor, FillColor2, GradientDir = gdVertical)
else
if FillColor <> clNone then
begin
Canvas.Brush.Color := FillColor;
Canvas.Brush.Style := bsSolid;
Canvas.FillRect(Rect(iLeft, iTop, iLeft + iWidth, iTop + iHeight));
end;
// BORDER
if ( BorderColor <> clNone ) and ( BorderWidth > 0 ) then
begin
Canvas.Brush.Color := BorderColor;
Canvas.Brush.Style := bsSolid;
FrameRgn(Canvas.Handle, rgnMain, Canvas.Brush.Handle, BorderWidth, BorderWidth);
end;
SelectClipRgn(Canvas.handle, 0);
finally
DeleteObject(rgnMain);
end;
end;
{$ifdef IEIncludeDeprecatedInV6}
procedure DrawCustomShape(Canvas: TCanvas; Shape: TXCustomShape; iLeft, iTop, iWidth, iHeight: Integer);
var
rgnMain: HRGN;
begin
rgnMain := CreateCustomShapeRegion( Shape, iLeft, iTop, iWidth, iHeight );
try
SelectClipRgn(Canvas.handle, rgnMain);
Canvas.FillRect(Rect(iLeft, iTop, iLeft + iWidth, iTop + iHeight));
SelectClipRgn(Canvas.handle, 0);
finally
DeleteObject(rgnMain);
end;
end;
{$endif}
{!!
<FS>CreateWallpaperBitmap
<FM>Declaration<FC>
function CreateWallpaperBitmap(Effect : <A TWallpaperEffect>; Color1 : TColor; Color2 : TColor; iSize : Integer = -1; iSpacing : integer = -1; iThickness: Integer = -1) : TBitmap;
<FM>Description<FN>
Create a bitmap suitable for use as HTML wallpaper (i.e. which can be tiled). Result is a TBitmap if the method succeeds. You MUST FREE the bitmap.
Note: Defined in iexCanvasUtils unit
<FM>Example<FC>
// Create a checkered wallpaper image
WPBmp := CreateWallpaperBitmap( wpDiagCheckers, clRed, clWhite );
TileBitmapOntoCanvas( DestBmp.Canvas, DestBmp.Width, DestBmp.Height, WPBmp );
WPBmp.Free;
<FM>See Also<FN>
- <A TileBitmapOntoCanvas>
!!}
//
// Returns a bitmap if succesful which must be freed after usage
function CreateWallpaperBitmap(Effect : TWallpaperEffect; Color1 : TColor; Color2 : TColor; iSize : Integer = -1; iSpacing : integer = -1; iThickness: Integer = -1) : TBitmap;
const
Full_Page_Wallpaper_Width = 4000;
Full_Page_Wallpaper_Height = 3000;
Small_Width = 5;
Small_Height = 5;
procedure _InitBitmap(iWidth, iHeight : Integer);
begin
Result := TBitmap.create;
Result.PixelFormat := pf24bit;
Result.Width := iWidth;
Result.Height := iHeight;
Result.Canvas.Brush.Color := Color2;
Result.Canvas.FillRect(Rect(0, 0, iWidth, iHeight));
end;
var
I: Integer;
AShape: TIEShape;
begin
Result := nil;
case Effect of
wpSolid :
// A color fill
begin
// iSize : Not used
// iSpacing : Not used
// iThickness : Not used
_InitBitmap(Small_Width, Small_Height);
end;
wpLeftLine :
// A single line on left
begin
// iSize : Not used
// iSpacing : Not used
// iThickness : Width of line (3)
if iThickness < 1 then
iThickness := 3;
_InitBitmap(Full_Page_Wallpaper_Width, 1);
for I := 0 to iThickness - 1 do
Result.Canvas.Pixels[I, 0] := Color1;
end;
wpTopLine :
// A single line along top
begin
// iSize : Not used
// iSpacing : Not used
// iThickness : Width of line (3)
if iThickness < 1 then
iThickness := 3;
_InitBitmap(1, Full_Page_Wallpaper_Height);
for I := 0 to iThickness - 1 do
Result.Canvas.Pixels[0, I] := Color1;
end;
wpDoubleLeftLines :
// Two lines on left
begin
// iSize : Not used
// iSpacing : Space between lines (3 x iThickness)
// iThickness : Width of line (2)
if iThickness < 1 then
iThickness := 2;
if iSpacing < 1 then
iSpacing := iThickness * 3;
_InitBitmap(Full_Page_Wallpaper_Width, 1);
for I := 0 to iThickness - 1 do
begin
Result.Canvas.Pixels[I, 0] := Color1;
Result.Canvas.Pixels[I + iSpacing, 0] := Color1;
end;
end;
wpDoubleTopLines :
// Two lines along top
begin
// iSize : Not used
// iSpacing : Space between lines (3 x iThickness)
// iThickness : Width of line (2)
if iThickness < 1 then
iThickness := 2;
if iSpacing < 1 then
iSpacing := iThickness * 3;
_InitBitmap(1, Full_Page_Wallpaper_Height);
for I := 0 to iThickness - 1 do
begin
Result.Canvas.Pixels[0, I] := Color1;
Result.Canvas.Pixels[0, I + iSpacing] := Color1;
end;
end;
wpDoubleVariedLeftLines :
// Two lines of decreasing widths on left
begin
// iSize : Not used
// iSpacing : Space between lines (3 x iThickness)
// iThickness : Width of thinnest line (2)
if iThickness < 1 then
iThickness := 2;
if iSpacing < 1 then
iSpacing := iThickness * 3;
_InitBitmap(Full_Page_Wallpaper_Width, 1);
for I := 0 to iThickness - 1 do
begin
Result.Canvas.Pixels[I, 0] := Color1;
Result.Canvas.Pixels[I + iThickness, 0] := Color1;
Result.Canvas.Pixels[I + iThickness + iSpacing, 0] := Color1;
end;
end;
wpDoubleVariedTopLines :
// Two lines of decreasing widths along top
begin
// iSize : Not used
// iSpacing : Space between lines (3 x iThickness)
// iThickness : Width of thinnest line (2)
if iThickness < 1 then
iThickness := 2;
if iSpacing < 1 then
iSpacing := iThickness * 3;
_InitBitmap(1, Full_Page_Wallpaper_Height);
for I := 0 to iThickness - 1 do
begin
Result.Canvas.Pixels[0, I] := Color1;
Result.Canvas.Pixels[0, I + iThickness] := Color1;
Result.Canvas.Pixels[0, I + iThickness + iSpacing] := Color1;
end;
end;
wpTripleLeftLines :
// Three lines on left
begin
// iSize : Not used
// iSpacing : Space between lines (3 x iThickness)
// iThickness : Width of line (2)
if iThickness < 1 then
iThickness := 2;
if iSpacing < 1 then
iSpacing := iThickness * 3;
_InitBitmap(Full_Page_Wallpaper_Width, 1);
for I := 0 to iThickness - 1 do
begin
Result.Canvas.Pixels[I, 0] := Color1;
Result.Canvas.Pixels[I + iSpacing, 0] := Color1;
Result.Canvas.Pixels[I + 2 * iSpacing, 0] := Color1;
end;
end;
wpTripleTopLines :
// Three lines along top
begin
// iSize : Not used
// iSpacing : Space between lines (3 x iThickness)
// iThickness : Width of line (2)
if iThickness < 1 then
iThickness := 2;
if iSpacing < 1 then
iSpacing := iThickness * 3;
_InitBitmap(1, Full_Page_Wallpaper_Height);
for I := 0 to iThickness - 1 do
begin
Result.Canvas.Pixels[0, I] := Color1;
Result.Canvas.Pixels[0, I + iSpacing] := Color1;
Result.Canvas.Pixels[0, I + 2 * iSpacing] := Color1;
end;
end;
wpTripleVariedLeftLines :
// Three lines of decreasing widths on left
begin
// iSize : Not used
// iSpacing : Space between lines (3 x iThickness)
// iThickness : Width of thinnest line (2)
if iThickness < 1 then
iThickness := 2;
if iSpacing < 1 then
iSpacing := iThickness * 3;
_InitBitmap(Full_Page_Wallpaper_Width, 1);
for I := 0 to iThickness - 1 do
begin
// Line 1
Result.Canvas.Pixels[I, 0] := Color1;
Result.Canvas.Pixels[I + iThickness, 0] := Color1;
Result.Canvas.Pixels[I + 2 * iThickness, 0] := Color1;
// Line 2
Result.Canvas.Pixels[I + 2 * iThickness + iSpacing, 0] := Color1;
Result.Canvas.Pixels[I + 3 * iThickness + iSpacing, 0] := Color1;
// Line 3
Result.Canvas.Pixels[I + 3 * iThickness + 2 * iSpacing, 0] := Color1;
end;
end;
wpTripleVariedTopLines :
// Three lines of decreasing widths along top
begin
// iSize : Not used
// iSpacing : Not used
// iThickness : Not used
if iThickness < 1 then
iThickness := 2;
if iSpacing < 1 then
iSpacing := iThickness * 3;
_InitBitmap(1, Full_Page_Wallpaper_Height);
for I := 0 to iThickness - 1 do
begin
// Line 1
Result.Canvas.Pixels[0, I] := Color1;
Result.Canvas.Pixels[0, I + iThickness] := Color1;
Result.Canvas.Pixels[0, I + 2 * iThickness] := Color1;
// Line 2
Result.Canvas.Pixels[0, I + 2 * iThickness + iSpacing] := Color1;
Result.Canvas.Pixels[0, I + 3 * iThickness + iSpacing] := Color1;
// Line 3
Result.Canvas.Pixels[0, I + 3 * iThickness + 2 * iSpacing] := Color1;
end;
end;
wpLeftDashes :
// Short lines of a uniform sizes on left
begin
// iSize : Length of dash (18)
// iSpacing : Space between dashes (3)
// iThickness : Thickness of dashes (1)
if iSize < 1 then
iSize := 18;
if iThickness < 1 then
iThickness := 1;
if iSpacing < 1 then
iSpacing := 3;
_InitBitmap(Full_Page_Wallpaper_Width, iSpacing + iThickness);
Result.Canvas.Pen.Color := Color1;
for I := 0 to iThickness - 1 do
begin
Result.Canvas.MoveTo(0, I);
Result.Canvas.LineTo(iSize, I);
end;
end;
wpTopDashes :
// Short lines of a uniform sizes along top
begin
// iSize : Length of dash (18)
// iSpacing : Space between dashes (3)
// iThickness : Thickness of dashes (1)
if iSize < 1 then
iSize := 18;
if iThickness < 1 then
iThickness := 1;
if iSpacing < 1 then
iSpacing := 3;
_InitBitmap(iSpacing + iThickness, Full_Page_Wallpaper_Height);
Result.Canvas.Pen.Color := Color1;
for I := 0 to iThickness - 1 do
begin
Result.Canvas.MoveTo(I, 0);
Result.Canvas.LineTo(I, iSize);
end;
end;
wpDoubleLeftDashes :
// Short lines of two sizes on left
begin
// iSize : Length of longest dash (15)
// iSpacing : Space between dashes (3)
// iThickness : Thickness of dashes (1)
if iSize < 1 then
iSize := 15;
if iThickness < 1 then
iThickness := 1;
if iSpacing < 1 then
iSpacing := 3;
_InitBitmap(Full_Page_Wallpaper_Width, 2 * (iSpacing + iThickness));
Result.Canvas.Pen.Color := Color1;
for I := 0 to iThickness - 1 do
begin
// Short Line
Result.Canvas.MoveTo(0, I);
Result.Canvas.LineTo(MulDiv(iSize, 2, 3), I);
// Long Line
Result.Canvas.MoveTo(0, I + iSpacing + iThickness);
Result.Canvas.LineTo(iSize, I + iSpacing + iThickness);
end;
end;
wpDoubleTopDashes :
// Short lines of two sizes along top
begin
// iSize : Length of longest dash (15)
// iSpacing : Space between dashes (3)
// iThickness : Thickness of dashes (1)
if iSize < 1 then
iSize := 15;
if iThickness < 1 then
iThickness := 1;
if iSpacing < 1 then
iSpacing := 3;
_InitBitmap(2 * (iSpacing + iThickness), Full_Page_Wallpaper_Height);
Result.Canvas.Pen.Color := Color1;
for I := 0 to iThickness - 1 do
begin
// Short Line
Result.Canvas.MoveTo(I, 0);
Result.Canvas.LineTo(I, MulDiv(iSize, 2, 3));
// Long Line
Result.Canvas.MoveTo(I + iSpacing + iThickness, 0);
Result.Canvas.LineTo(I + iSpacing + iThickness, iSize);
end;
end;
wpTripleLeftDashes :
// Short lines of three sizes on left
begin
// iSize : Length of longest dash (15)
// iSpacing : Space between dashes (4)
// iThickness : Thickness of dashes (1)
if iSize < 1 then
iSize := 15;
if iThickness < 1 then
iThickness := 1;
if iSpacing < 1 then
iSpacing := 4;
_InitBitmap(Full_Page_Wallpaper_Width, 4 * (iSpacing + iThickness));
Result.Canvas.Pen.Color := Color1;
for I := 0 to iThickness - 1 do
begin
// Short Line
Result.Canvas.MoveTo(0, I);
Result.Canvas.LineTo(MulDiv(iSize, 1, 3), I);
// Middle Line
Result.Canvas.MoveTo(0, I + iSpacing + iThickness);
Result.Canvas.LineTo(MulDiv(iSize, 2, 3), I + iSpacing + iThickness);
// Long Line
Result.Canvas.MoveTo(0, I + 2 * (iSpacing + iThickness));
Result.Canvas.LineTo(iSize, I + 2 * (iSpacing + iThickness));
// Second Middle Line
Result.Canvas.MoveTo(0, I + 3 * (iSpacing + iThickness));
Result.Canvas.LineTo(MulDiv(iSize, 2, 3), I + 3 * (iSpacing + iThickness));
end;
end;
wpTripleTopDashes :
// Short lines of three sizes along top
begin
// iSize : Length of longest dash (15)
// iSpacing : Space between dashes (4)
// iThickness : Thickness of dashes (1)
if iSize < 1 then
iSize := 15;
if iThickness < 1 then
iThickness := 1;
if iSpacing < 1 then
iSpacing := 4;
_InitBitmap(4 * (iSpacing + iThickness), Full_Page_Wallpaper_Height);
Result.Canvas.Pen.Color := Color1;
for I := 0 to iThickness - 1 do
begin
// Short Line
Result.Canvas.MoveTo(I, 0);
Result.Canvas.LineTo(I, MulDiv(iSize, 1, 3));
// Middle Line
Result.Canvas.MoveTo(I + iSpacing + iThickness, 0);
Result.Canvas.LineTo(I + iSpacing + iThickness, MulDiv(iSize, 2, 3));
// Long Line
Result.Canvas.MoveTo(I + 2 * (iSpacing + iThickness), 0);
Result.Canvas.LineTo(I + 2 * (iSpacing + iThickness), iSize);
// Second Middle Line
Result.Canvas.MoveTo(I + 3 * (iSpacing + iThickness), 0);
Result.Canvas.LineTo(I + 3 * (iSpacing + iThickness), MulDiv(iSize, 2, 3));
end;
end;
wpLeftZigZag :
// Shark tooth pattern on left
begin
// iSize : The solid area of the border (10)
// iSpacing : The height of the "peak" (15)
// iThickness : Not used
if iSize < 1 then
iSize := 10;
if iSpacing < 1 then
iSpacing := 15;
_InitBitmap(Full_Page_Wallpaper_Width, 2 * iSpacing);
Result.Canvas.Pen.Color := Color1;
for I := 0 to 2 * iSpacing - 1 do
begin
Result.Canvas.MoveTo(0, I);
if I <= iSpacing then
Result.Canvas.LineTo(iSize + I, I)
else
Result.Canvas.LineTo(iSize + 2 * iSpacing - I, I);
end;
end;
wpTopZigZag :
// Shark tooth pattern along top
begin
// iSize : The solid area of the border (10)
// iSpacing : The height of the "peak" (15)
// iThickness : Not used
if iSize < 1 then
iSize := 10;
if iSpacing < 1 then
iSpacing := 15;
// iSize : Not used
// iSpacing : Not used
// iThickness : Not used
_InitBitmap(2 * iSpacing, Full_Page_Wallpaper_Height);
Result.Canvas.Pen.Color := Color1;
for I := 0 to 2 * iSpacing - 1 do
begin
Result.Canvas.MoveTo(I, 0);
if I <= iSpacing then
Result.Canvas.LineTo(I, iSize + I)
else
Result.Canvas.LineTo(I, iSize + 2 * iSpacing - I);
end;
end;
wpLeftGradient :
// Color gradient on left
begin
// iSize : Width of gradient area (20)
// iSpacing : Not used
// iThickness : Not used
if iSize < 1 then
iSize := 30;
_InitBitmap(Full_Page_Wallpaper_Width, Small_Height);
IEDrawGradient(Rect(0, 0, iSize, Result.Height), Result.Canvas.handle, Color1, Color2, False);
end;
wpTopGradient :
// Color gradient along top
begin
// iSize : Width of gradient area (20)
// iSpacing : Not used
// iThickness : Not used
if iSize < 1 then
iSize := 30;
_InitBitmap(Small_Width, Full_Page_Wallpaper_Height);
IEDrawGradient(Rect(0, 0, Result.Width, iSize), Result.Canvas.handle, Color1, Color2, True);
end;
wpHorzPinStripe :
// Horizontal lines across image
begin
// iSize : Not used
// iSpacing : Space between lines (10)
// iThickness : Thickness of lines (1)
if iThickness < 1 then
iThickness := 1;
if iSpacing < 1 then
iSpacing := 10;
iSize := iSpacing + iThickness;
_InitBitmap(Small_Width, iSize);
Result.Canvas.Pen.Color := Color1;
for I := 1 to iThickness do
begin
Result.Canvas.MoveTo(0, iSize - I);
Result.Canvas.LineTo(Small_Width, iSize - I);
end;
end;
wpVertPinStripe :
// Vertical lines down image
begin
// iSize : Not used
// iSpacing : Space between lines (10)
// iThickness : Thickness of lines (1)
if iThickness < 1 then
iThickness := 1;
if iSpacing < 1 then
iSpacing := 10;
iSize := iSpacing + iThickness;
_InitBitmap(iSize, Small_Height);
Result.Canvas.Pen.Color := Color1;
for I := 1 to iThickness do
begin
Result.Canvas.MoveTo(iSize - I, 0);
Result.Canvas.LineTo(iSize - I, Small_Height);
end;
end;
wpDiagPinStripe, wpDiagPinStripe2 :
// Diagonal lines across image
begin
// iSize : Not used
// iSpacing : Space between lines (20)
// iThickness : Thickness of lines. Always 1
iThickness := 1;
if iSpacing < 1 then
iSpacing := 20;
iSize := iSpacing + iThickness;
_InitBitmap(iSize, iSize);
Result.Canvas.Pen.Color := Color1;
Result.Canvas.Pen.Width := iThickness;
if Effect = wpDiagPinStripe then
begin
Result.Canvas.MoveTo(0, 0);
Result.Canvas.LineTo(iSize, iSize);
end
else
begin
Result.Canvas.MoveTo(iSize - 1, 0);
Result.Canvas.LineTo(-1, iSize);
end;
end;
wpCrossHatch :
// Horizontal and vertical lines
begin
// iSize : Not used
// iSpacing : Space between lines (14)
// iThickness : Thickness of lines (1)
if iThickness < 1 then
iThickness := 1;
if iSpacing < 1 then
iSpacing := 14;
iSize := iSpacing + iThickness;
_InitBitmap(iSize, iSize);
Result.Canvas.Pen.Color := Color1;
for I := 1 to iThickness do
begin
// Horizontal
Result.Canvas.MoveTo(0, iSize - I);
Result.Canvas.LineTo(iSize, iSize - I);
// Vertical
Result.Canvas.MoveTo(iSize - I, 0);
Result.Canvas.LineTo(iSize - I, iSize);
end;
end;
wpDiagCrossHatch :
// Diagonal lines in two directions
begin
// iSize : Not used
// iSpacing : Space between lines (25). Always odd
// iThickness : Thickness of lines. Always 1
iThickness := 1;
if iSpacing < 1 then
iSpacing := 25;
iSpacing := iSpacing div 2 * 2 + 1; // must be odd
iSize := iSpacing + iThickness;
_InitBitmap(iSize, iSize);
Result.Canvas.Pen.Color := Color1;
Result.Canvas.Pen.Width := iThickness;
Result.Canvas.MoveTo(0, 0);
Result.Canvas.LineTo(iSize, iSize);
Result.Canvas.MoveTo(iSize, 0);
Result.Canvas.LineTo(0, iSize);
end;
wpHorzStripes :
// Horizontal stripes across image
begin
// iSize : Same as two * iThickness
// iSpacing : Not used
// iThickness : Width of stripes (60)
if iThickness < 1 then
iThickness := iSize div 2;
if iThickness < 1 then
iThickness := 60;
_InitBitmap(iThickness * 2, 1);
Result.Canvas.Brush.Style := bsSolid;
Result.Canvas.Brush.Color := Color1;
Result.Canvas.FillRect(Rect(iThickness, 0, 2 * iThickness, iThickness));
end;
wpVertStripes :
// Vertical stripes down image
begin
// iSize : Same as two * iThickness
// iSpacing : Not used
// iThickness : Width of stripes (60)
if iThickness < 1 then
iThickness := iSize div 2;
if iThickness < 1 then
iThickness := 60;
_InitBitmap(1, iThickness * 2);
Result.Canvas.Brush.Style := bsSolid;
Result.Canvas.Brush.Color := Color1;
Result.Canvas.FillRect(Rect(0, iThickness, iThickness, 2 * iThickness));
end;
wpDiagStripes, wpDiagStripes2 :
// Diagonal stripes down image
begin
// iSize : Same as two * iThickness
// iSpacing : Not used
// iThickness : Width of stripes (60)
if iThickness < 1 then
iThickness := iSize div 2;
if iThickness < 1 then
iThickness := 60;
_InitBitmap(2 * iThickness, 2 * iThickness);
Result.Canvas.Pen.Style := psClear;
Result.Canvas.Brush.Style := bsSolid;
Result.Canvas.Brush.Color := Color1;
if Effect = wpDiagStripes then
begin
Result.Canvas.Polygon([ Point(0, 0),
Point(2 * iThickness, 2 * iThickness),
Point(iThickness, 2 * iThickness),
Point(0, iThickness) ]);
Result.Canvas.Polygon([ Point(iThickness, 0),
Point(2 * iThickness, 0),
Point(2 * iThickness, iThickness) ]);
end
else
begin
Result.Canvas.Polygon([ Point(2 * iThickness, 0),
Point(0, 2 * iThickness),
Point(iThickness, 2 * iThickness),
Point(2 * iThickness, iThickness) ]);
Result.Canvas.Polygon([ Point(iThickness, 0),
Point(0, 0),
Point(0, iThickness) ]);
end
end;
wpCheckers :
// Alternativing blocks of color
begin
// iSize : Same as two * iThickness
// iSpacing : Not used
// iThickness : Width of stripes (60)
if iThickness < 1 then
iThickness := iSize div 2;
if iThickness < 1 then
iThickness := 60;
_InitBitmap(iThickness * 2, iThickness * 2);
Result.Canvas.Brush.Style := bsSolid;
Result.Canvas.Brush.Color := Color1;
Result.Canvas.FillRect(Rect(iThickness, 0, 2 * iThickness, iThickness));
Result.Canvas.FillRect(Rect(0, iThickness, iThickness, 2 * iThickness));
end;
wpDiagCheckers :
// Alternativing diagonal blocks of color
begin
// iSize : Same as two * iThickness
// iSpacing : Not used
// iThickness : Width of stripes (60)
if iThickness < 1 then
iThickness := iSize div 2;
if iThickness < 1 then
iThickness := 60;
_InitBitmap(iThickness * 2, iThickness * 2);
Result.Canvas.Pen.Style := psSolid;
Result.Canvas.Pen.Color := Color1;
Result.Canvas.Brush.Style := bsSolid;
Result.Canvas.Brush.Color := Color1;
Result.Canvas.Polygon([ Point(iThickness, 0),
Point(2 * iThickness, iThickness),
Point(iThickness, 2 * iThickness),
Point(0, iThickness) ]);
end;
wpRain, wpRain2 :
// Diagonal dashes
begin
// iSize : Not used
// iSpacing : Space between dashes (20)
// iThickness : Thickness of dashes (5)
if iThickness < 1 then
iThickness := 5;
if iSpacing < 1 then
iSpacing := 20;
iSize := iSpacing + iThickness;
_InitBitmap(iSize, iSize);
Result.Canvas.Pen.Color := Color1;
Result.Canvas.Pen.Width := iThickness;
if Effect = wpRain then
begin
Result.Canvas.MoveTo(MulDiv(iSize, 1, 5), MulDiv(iSize, 1, 5));
Result.Canvas.LineTo(MulDiv(iSize, 4, 5), MulDiv(iSize, 4, 5));
end
else
begin
Result.Canvas.MoveTo(MulDiv(iSize, 4, 5), MulDiv(iSize, 1, 5));
Result.Canvas.LineTo(MulDiv(iSize, 1, 5), MulDiv(iSize, 4, 5));
end
end;
wpRivets :
// Circles over page
begin
// iSize : Size of circle, Min: 4 (5)
// iSpacing : Spacing between shapes, Min: iSize Div 2 (3)
// iThickness : not used
if iSize < 1 then
iSize := 5;
if iSize < 4 then
iSize := 4;
if iSpacing < 1 then
iSpacing := 3;
if iSpacing < iSize div 2 + 1 then
iSpacing := iSize div 2 + 1;
_InitBitmap(2 * iSpacing + 2 * iSize , 2 * iSize);
Result.Canvas.Pen.Style := psClear;
Result.Canvas.Brush.Style := bsClear;
Result.Canvas.Brush.Color := Color1;
Result.Canvas.Ellipse(iSpacing, 0,
iSpacing + iSize, iSize);
Result.Canvas.Ellipse(2 * iSpacing + iSize, iSize,
2 * iSpacing + 2 * iSize, 2 * iSize);
end;
wpHearts :
// Hearts over page
begin
// iSize : Size of heart, Min: 5 (78)
// iSpacing : Spacing between shapes, Min: iSize Div 2 (5)
// iThickness : not used
if iSize < 1 then
iSize := 78;
if iSize < 4 then
iSize := 4;
if iSpacing < 1 then
iSpacing := 5;
if iSpacing < iSize div 2 + 1 then
iSpacing := iSize div 2 + 1;
_InitBitmap(2 * iSpacing + 2 * iSize , 2 * iSize);
Result.Canvas.Pen.Style := psClear;
Result.Canvas.Brush.Style := bsClear;
Result.Canvas.Brush.Color := Color1;
IEDrawShape(Result.Canvas, iesHeart, iSpacing, 0, iSize, iSize);
IEDrawShape(Result.Canvas, iesHeart, 2 * iSpacing + iSize, iSize, iSize, iSize);
end;
wpStars , // Stars over page
wpLightning : // Lightning over page
begin
// iSize : Size of star/lightning, Min: 5 (50)
// iSpacing : Spacing between shapes (10)
// iThickness : not used
if iSize < 1 then
iSize := 50;
if iSize < 5 then
iSize := 5;
if iSpacing < 1 then
iSpacing := 10;
_InitBitmap(iSize + iSpacing, iSize + iSpacing);
Result.Canvas.Pen.Style := psClear;
Result.Canvas.Brush.Style := bsClear;
Result.Canvas.Brush.Color := Color1;
if Effect = wpStars then
AShape := iesStar5
else
AShape := iesLightningLeft;
IEDrawShape(Result.Canvas, AShape, iSpacing div 2, iSpacing div 2, iSize, iSize);
end;
wpRuledPage:
// Similar to standard ruled page (with red line along side)
begin
// iSize : Not used
// iSpacing : Space between lines (24)
// iThickness : Thickness of lines (1)
if iThickness < 1 then
iThickness := 1;
if iSpacing < 1 then
iSpacing := 24;
iSize := iSpacing + iThickness;
_InitBitmap(Full_Page_Wallpaper_Width, iSize);
Result.Canvas.Pen.Color := Color1;
for I := 1 to iThickness do
begin
Result.Canvas.MoveTo(0, iSize - I);
Result.Canvas.LineTo(Full_Page_Wallpaper_Width, iSize - I);
end;
Result.Canvas.Pen.Color := clRed;
for I := 1 to iThickness do
begin
Result.Canvas.MoveTo(iSpacing * 3 + I, 0);
Result.Canvas.LineTo(iSpacing * 3 + I, iSize);
end;
end;
end;
end;
{!!
<FS>TileBitmapOntoCanvas
<FM>Declaration<FC>
Procedure TileBitmapOntoCanvas(Canvas : TCanvas; iWidth, iHeight : Integer; Bitmap : TBitmap); overload;
Procedure TileBitmapOntoCanvas(Canvas : TCanvas; iWidth, iHeight : Integer; Graphic : TGraphic); overload;
<FM>Description<FN>
Fill the canvas by tiling the specified bitmap (i.e. for wallpaper type effects)
Note: Defined in iexCanvasUtils unit
<FM>Example<FC>
// Create a checkered wallpaper image
WPBmp := CreateWallpaperBitmap( wpDiagCheckers, clRed, clWhite );
TileBitmapOntoCanvas( DestBmp.Canvas, DestBmp.Width, DestBmp.Height, WPBmp );
WPBmp.Free;
<FM>See Also<FN>
- <A CreateWallpaperBitmap>
!!}
//
Procedure TileBitmapOntoCanvas(Canvas : TCanvas; iWidth, iHeight : Integer; Bitmap : TBitmap);
var
X, Y: LongInt;
begin
if not assigned( Bitmap ) or ( Bitmap.Width = 0 ) or ( Bitmap.Height = 0 ) then
exit;
Y := 0;
while Y < iHeight do
begin
X := 0;
while X < iWidth do
begin
Canvas.Draw( X, Y, Bitmap );
Inc( X, Bitmap.Width );
end;
Inc( Y, Bitmap.Height );
end;
end;
//
Procedure TileBitmapOntoCanvas(Canvas : TCanvas; iWidth, iHeight : Integer; Graphic : TGraphic);
var
X, Y: LongInt;
begin
if not assigned( Graphic ) or ( Graphic.Width = 0 ) or ( Graphic.Height = 0 ) then
exit;
Y := 0;
while Y < iHeight do
begin
X := 0;
while X < iWidth do
begin
Canvas.Draw( X, Y, Graphic );
Inc( X, Graphic.Width );
end;
Inc( Y, Graphic.Height );
end;
end;
function ShapeToString(Shape: TIEShape): string;
begin
Result := '';
case Shape of
iesEllipse : Result := 'Ellipse';
iesHalfEllipse : Result := 'Half Ellipse';
iesQuarterEllipse : Result := 'Quarter Ellipse';
iesEllipseSegment : Result := 'Ellipse Segment';
iesRectangle : Result := 'Rectangle';
iesRoundRect : Result := 'Round Rectangle';
iesTriangle : Result := 'Triangle';
iesCorner : Result := 'Corner';
iesDiamond : Result := 'Diamond';
iesPentagon : Result := 'Pentagon';
iesHexagon : Result := 'Hexagon';
iesHeptagon : Result := 'Heptagon';
iesOctagon : Result := 'Octagon';
iesCustomShape : Result := 'Custom Shape';
iesStar5 : Result := '5-Point Star';
iesStar6 : Result := '6-Point Star';
iesCustomStar : Result := 'Custom Star';
iesArrowLeft : Result := 'Arrow Left';
iesArrowRight : Result := 'Arrow Right';
iesArrowUp : Result := 'Arrow Up';
iesArrowDown : Result := 'Arrow Down';
iesArrowLeftRight : Result := 'Arrow Left and Right';
iesArrowUpDown : Result := 'Arrow Up and Down';
iesArrowNW : Result := 'Arrow NW';
iesArrowNE : Result := 'Arrow NE';
iesArrowSW : Result := 'Arrow SW';
iesArrowSE : Result := 'Arrow SE';
iesFatArrowLeft : Result := 'Fat Arrow Left';
iesFatArrowRight : Result := 'Fat Arrow Right';
iesFatArrowUp : Result := 'Fat Arrow Up';
iesFatArrowDown : Result := 'Fat Arrow Down';
iesShootingArrowNW : Result := 'Shooting Arrow NW';
iesShootingArrowNE : Result := 'Shooting Arrow NE';
iesShootingArrowSW : Result := 'Shooting Arrow SW';
iesShootingArrowSE : Result := 'Shooting Arrow SE';
iesLightningLeft : Result := 'Lightning Left';
iesLightningRight : Result := 'Lightning Right';
iesExplosion : Result := 'Explosion';
iesCustomExplosion : Result := 'Custom Explosion';
iesCross : Result := 'Cross';
iesHeart : Result := 'Heart';
iesDoubleHeart : Result := 'Double Heart';
iesCloud : Result := 'Cloud';
iesMoon : Result := 'Moon';
iesSpeechBubbleLeftInShort : Result := 'Small Left Speech Bubble In';
iesSpeechBubbleLeftOutShort : Result := 'Small Left Speech Bubble Out';
iesSpeechBubbleRightInShort : Result := 'Small Right Speech Bubble In';
iesSpeechBubbleRightOutShort : Result := 'Small Right Speech Bubble Out';
iesSpeechBubbleLeftInLong : Result := 'Wide Left Speech Bubble In';
iesSpeechBubbleLeftOutLong : Result := 'Wide Left Speech Bubble Out';
iesSpeechBubbleRightInLong : Result := 'Wide Right Speech Bubble In';
iesSpeechBubbleRightOutLong : Result := 'Wide Right Speech Bubble Out';
iesThoughtBubbleLeft : Result := 'Left Thought Bubble';
iesThoughtBubbleRight : Result := 'Right Thought Bubble';
iesShield : Result := 'Shield';
iesBadge : Result := 'Badge';
iesNamePlate : Result := 'NamePlate';
iesFrame : Result := 'Frame';
iesNarrowFrame : Result := 'Narrow Frame';
iesFatFrame : Result := 'Fat Frame';
iesCircularFrame : Result := 'Circular Frame';
end;
end;
{
Example usage:
procedure Tfmain.cmbShapeDrawItem(Control: TWinControl; Index: Integer; Rect: TRect; State: TOwnerDrawState);
begin
IEDrawShapeToComboListBoxItem( TComboBox( Control ).Canvas, Rect, Control.Enabled, TIEShape( Index ), clRed );
end;
}
procedure IEDrawShapeToComboListBoxItem(ControlCanvas : TCanvas;
CanvasRect : TRect;
ControlEnabled : Boolean;
Shape: TIEShape;
Color: TColor;
ShowText : Boolean= True);
const
DRAW_SHAPE_MARGIN = 3;
DRAW_SHAPE_TEXT_MARGIN = 3;
var
textX : Integer;
textY : Integer;
shapeX : Integer;
shapeY : Integer;
shapeSize: Integer;
Text: string;
begin
Text := ShapeToString( Shape );
shapeSize := min( CanvasRect.Right - CanvasRect.Left - 2 * DRAW_SHAPE_MARGIN, CanvasRect.Bottom - CanvasRect.Top - 2 * DRAW_SHAPE_MARGIN );
textX := DRAW_SHAPE_MARGIN + shapeSize + DRAW_SHAPE_TEXT_MARGIN;
textY := ((CanvasRect.Bottom - CanvasRect.Top) - ControlCanvas.TextHeight(Text)) div 2;
shapeX := DRAW_SHAPE_MARGIN;
shapeY := ((CanvasRect.Bottom - CanvasRect.Top) - shapeSize) div 2;
ControlCanvas.FillRect( CanvasRect );
// is it enabled?
if ControlEnabled = False then
ControlCanvas.font.color := clGrayText;
ControlCanvas.TextOut( CanvasRect.left + textX, CanvasRect.top + textY, Text);
if ControlEnabled then
ControlCanvas.Brush.Color := Color
else
ControlCanvas.Brush.Color := clGrayText;
ControlCanvas.Brush.Style := bsSolid;
IEDrawShape( ControlCanvas, Shape, CanvasRect.left + shapeX, CanvasRect.Top + shapeY, shapeSize, shapeSize );
end;
end.