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

10595 lines
336 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
*)
(*
File: iexLayers.pas
Description: Handles the TIELayer and descendent classes for displaying layers in a TImageEnView
File version 1120
Doc revision 1001
*)
unit iexLayers;
{$R-}
{$Q-}
{$I ie.inc}
interface
uses
{$ifdef IEHASUITYPES} System.UITypes, {$endif}
Windows, Messages, Graphics, Controls, Forms, Classes, SysUtils, StdCtrls, ExtCtrls, Contnrs, hyiedefs, iexBitmaps, ieview,
imageenproc, hyieutils, iegdiplus;
type
{!!
<FS>TIELayerKind
<FM>Declaration<FC>
TIELayerKind = (ielkImage, ielkShape, ielkLine, ielkPolyline, ielkText);
<FM>Description<FN>
Returns the type of a <A TIELayer>.
<TABLE>
<R> <H>Kind</H> <H>Class</H> <H>Description</H> </R>
<R> <C><FC>ielkImage<FN></C> <C> <A TIEImageLayer> </C> <C>Layer that contains an image</C> </R>
<R> <C><FC>ielkShape<FN></C> <C> <A TIEShapeLayer> </C> <C>Layer that displays standard <L TIEShape>shapes</L> (rectangles, ellipses, stars, etc)</C> </R>
<R> <C><FC>ielkLine<FN></C> <C> <A TIELineLayer> </C> <C>Layer that displays a single line, optionally including a text label and start and ending arrows</C> </R>
<R> <C><FC>ielkPolyline<FN></C> <C> <A TIEPolylineLayer> </C> <C>Layer that displays a polyline or polgon comprising of multiple points</C> </R>
<R> <C><FC>ielkText<FN></C> <C> <A TIETextLayer> </C> <C>Layer that displays text</C> </R>
</TABLE>
<FM>Example 1<FC>
if ImageEnView1.CurrentLayer.Kind = ielkImage then
TIEImageLayer( ImageEnView1.CurrentLayer ).ResampleFilter := rfLanczos3;
// Which is the same as...
if ImageEnView1.CurrentLayer is TIEImageLayer then
TIEImageLayer( ImageEnView1.CurrentLayer ).ResampleFilter := rfLanczos3;
<FM>Example 2<FC>
// Hide labels of all line layers when user clicks a check box
procedure Tfmain.chkShowLabelsClick(Sender: TObject);
var
I: integer;
begin
for I := 0 to ImageEnView1.LayersCount - 1 do
if ImageEnView1.Layers[ I ].Kind = ielkLine then
begin
if chkShowLabels.Checked then
TIELineLayer( ImageEnView1.Layers[ I ]).LabelPosition := ielpAtEnd
else
TIELineLayer( ImageEnView1.Layers[ I ]).LabelPosition := ielpHide;
end;
ImageEnView1.Update();
end;
!!}
TIELayerKind = (ielkImage, ielkShape, ielkLine, ielkPolyline, ielkText);
{!!
<FS>TIEDrawingInfo
<FM>Declaration<FC>
}
TIEDrawingInfo = record
XDst: integer; // Destination x (output canvas)
YDst: integer; // Destination y (output canvas)
WidthDst: integer; // Destination width (output canvas)
HeightDst: integer; // Destination height (output canvas)
XSrc: integer; // Source x (input bitmap)
YSrc: integer; // Source y (input bitmap)
WidthSrc: integer; // Source width (input bitmap)
HeightSrc: integer; // Source height (input bitmap)
RotatedDest: array [0..3] of TPoint; // destination rotated points (output canvas)
end;
{!!}
{!!
<FS>TIEDrawLayerEvent
<FM>Declaration<FC>
}
TIEDrawLayerEvent = procedure(Sender: TObject; dest: TIEBitmap; LayerIndex: Integer) of object;
{!!}
{!!
<FS>TIEDrawLayerBoxEvent
<FM>Declaration<FC>
}
TIEDrawLayerBoxEvent = procedure (Sender: TObject; ABitmap: TBitmap; LayerIndex: integer) of object;
{!!}
{!!
<FS>TIEDrawLayerGrip
<FM>Declaration<FC>
}
TIEDrawLayerGrip = procedure (Sender: TObject; ABitmap: TBitmap; LayerIndex: integer; Grip: Integer; Rect: TRect) of object;
{!!}
{!!
<FS>TIELineEndShape
<FM>Declaration<FC>
type TIELineEndShape = (ieesNone, ieesArrow, ieesCircle);
<FM>Description<FN>
<TABLE>
<R> <H>Value</H> <H>Description</H> </R>
<R> <C>ieesNone</C> <C>No shape</C> </R>
<R> <C>ieesArrow</C> <C>Arrow</C> </R>
<R> <C>ieesCircle</C> <C>Circle</C> </R>
</TABLE>
<FM>Example<FC>
// Add yellow filled arrows and circle ends to our current line layer
TIELineLayer( ImageEnView1.CurrentLayer ).StartShape := ieesArrow;
TIELineLayer( ImageEnView1.CurrentLayer ).EndShape := ieesCircle;
TIELineLayer( ImageEnView1.CurrentLayer ).FillColor := clYellow;
TIELineLayer( ImageEnView1.CurrentLayer ).ShapeSize := 25;
ImageEnView1.Update();
<IMG help_images\Line_EndShapes.gif>
!!}
TIELineEndShape = (ieesNone, ieesArrow, ieesCircle);
{!!
<FS>TIELineLabelPos
<FM>Declaration<FC>
TIELineLabelPos = (ielpHide, ielpAtStart, ielpAtEnd);
<FM>Description<FN>
<TABLE>
<R> <H>Value</H> <H>Description</H> </R>
<R> <C>ielpHide</C> <C>Does not show the text label even if text has been specified</C> </R>
<R> <C>ielpAtStart</C> <C>Shows the text label at the start of the line</C> </R>
<R> <C>ielpAtEnd</C> <C>Shows the text label at the end of the line</C> </R>
</TABLE>
<FM>Examples<FC>
// Move the label to the start of the line
TIELineLayer( ImageEnView1.CurrentLayer ).LabelPosition := ielpAtStart;
// Hide labels of all line layers when user clicks a check box
procedure Tfmain.chkShowLabelsClick(Sender: TObject);
var
I: integer;
begin
for I := 0 to ImageEnView1.LayersCount - 1 do
if ImageEnView1.Layers[ I ].Kind = ielkLine then
begin
if chkShowLabels.Checked then
TIELineLayer( ImageEnView1.Layers[ I ]).LabelPosition := ielpAtEnd
else
TIELineLayer( ImageEnView1.Layers[ I ]).LabelPosition := ielpHide;
end;
ImageEnView1.Update();
end;
!!}
TIELineLabelPos = (ielpHide, ielpAtStart, ielpAtEnd);
{!!
<FS>TIELayerFeatures
<FM>Declaration<FC>
TIELayerFeatures = (ielfBorder, ielfFill, ielfGradient, ielfRotation, ielfMoveRotationCenter, ielfTextEditing);
<FM>Description<FN>
<TABLE>
<R> <H>Kind</H> <H>Description</H> <H>Supported By</H> </R>
<R> <C><FC>ielfBorder<FN></C> <C>Layer has a border or line that can be adjusted using <A TIELayer.BorderColor> and <A TIELayer.BorderWidth> </C> <C> All </C> </R>
<R> <C><FC>ielfFill<FN></C> <C>Layer has a solid fill that can be adjusted using <A TIELayer.FillColor> </C> <C> <A TIEShapeLayer>, <A TIELineLayer> (only if <A TIELineLayer.LabelText> is set), <A TIEPolylineLayer> (only if <A TIEPolylineLayer.PolylineClosed>=True), <A TIETextLayer> </C> </R>
<R> <C><FC>ielfGradient<FN></C> <C>If the solid fill can be gradiated using <A TIELayer.FillColor2> and <A TIELayer.FillGradient></C> <C> <A TIEShapeLayer>, <A TIELineLayer> (only if <A TIELineLayer.LabelText> is set), <A TIETextLayer> </C> </R>
<R> <C><FC>ielfRotation<FN></C> <C>Can be rotated by setting <A TIELayer.Rotate> or using <L TImageEnView.MouseInteract>miRotateLayers</L> </C> <C> All </C> </R>
<R> <C><FC>ielfMoveRotationCenter<FN></C> <C>The center of layer rotation can be moved by setting <A TIELayer.RotateCenterX> or moving the center grip with <L TImageEnView.MouseInteract>miRotateLayers</L> </C> <C> <A TIEImageLayer> </C> </R>
<R> <C><FC>ielfTextEditing<FN></C> <C>The layer has a text property and is not set to read-only</C> <C> <A TIETextLayer>, <A TIELineLayer> (only if <A TIELineLayer.LabelText> is set) </C> </R>
</TABLE>
<FM>Example<FC>
// Show border color selector if layer type supports it
btnSelBorder.Enabled := ImageEnView1.CurrentLayer.SupportsFeature( ielfBorder );
// Show fill color selector if layer type supports it
btnSelFill.Enabled := ImageEnView1.CurrentLayer.SupportsFeature( ielfFill );
// Show gradient selector if layer type supports it
btnGradient.Enabled := ImageEnView1.CurrentLayer.SupportsFeature( ielfGradient );
// Determine if the current layer type can be rotated
canRotate := ImageEnView1.CurrentLayer.SupportsFeature( ielfRotation );
// Determine if the current layer type can be rotated
canRotate := ImageEnView1.CurrentLayer.SupportsFeature( ielfRotation );
// Text can currently be edited for this layer
edtText.Enabled := ImageEnView1.CurrentLayer.SupportsFeature( ielfTextEditing );
!!}
TIELayerFeatures = (ielfBorder, ielfFill, ielfGradient, ielfRotation, ielfMoveRotationCenter, ielfTextEditing);
{!!
<FS>TIELayer Property Consts
Property consts used by <A TIELayer.GetProperties> and <A TIELayer.SetProperties>:
<TABLE>
<R> <H>Const</H> <H>Value</H> <H>Property</H> </R>
<R> <C><FC>IELP_Width<FN></C> <C> 'IELP_Width' </C> <C> <A TIELayer.Width></C> </R>
<R> <C><FC>IELP_Height<FN></C> <C> 'IELP_Height' </C> <C> <A TIELayer.Height></C> </R>
<R> <C><FC>IELP_Visible<FN></C> <C> 'IELP_Visible' </C> <C> <A TIELayer.Visible></C> </R>
<R> <C><FC>IELP_VisibleBox<FN></C> <C> 'IELP_VisibleBox' </C> <C> <A TIELayer.VisibleBox></C> </R>
<R> <C><FC>IELP_Selectable<FN></C> <C> 'IELP_Selectable' </C> <C> <A TIELayer.Selectable></C> </R>
<R> <C><FC>IELP_Transparency<FN></C> <C> 'IELP_Transparency' </C> <C> <A TIELayer.Transparency></C> </R>
<R> <C><FC>IELP_Opacity<FN></C> <C> 'IELP_Opacity' </C> <C> <A TIELayer.Opacity></C> </R>
<R> <C><FC>IELP_PosX<FN></C> <C> 'IELP_PosX' </C> <C> <A TIELayer.PosX></C> </R>
<R> <C><FC>IELP_PosY<FN></C> <C> 'IELP_PosY' </C> <C> <A TIELayer.PosY></C> </R>
<R> <C><FC>IELP_Cropped<FN></C> <C> 'IELP_Cropped' </C> <C> <A TIELayer.Cropped></C> </R>
<R> <C><FC>IELP_Locked<FN></C> <C> 'IELP_Locked' </C> <C> <A TIELayer.Locked></C> </R>
<R> <C><FC>IELP_Operation<FN></C> <C> 'IELP_Operation' </C> <C> <A TIELayer.Operation></C> </R>
<R> <C><FC>IELP_Name<FN></C> <C> 'IELP_Name' </C> <C> <A TIELayer.Name></C> </R>
<R> <C><FC>IELP_IsMask<FN></C> <C> 'IELP_IsMask' </C> <C> <A TIEImageLayer.IsMask></C> </R>
<R> <C><FC>IELP_DrawOuter<FN></C> <C> 'IELP_DrawOuter' </C> <C> <A TIELayer.DrawOuter></C> </R>
<R> <C><FC>IELP_AlphaEdgeFeathering<FN></C> <C> 'IELP_AlphaEdgeFeathering,' </C> <C> <A TIELayer.AlphaEdgeFeathering></C> </R>
<R> <C><FC>IELP_GroupIndex<FN></C> <C> 'IELP_GroupIndex' </C> <C> <A TIELayer.GroupIndex></C> </R>
<R> <C><FC>IELP_Selected<FN></C> <C> 'IELP_Selected' </C> <C> <A TIELayer.Selected></C> </R>
<R> <C><FC>IELP_AspectRatioLocked<FN></C> <C> 'IELP_AspectRatioLocked' </C> <C> <A TIELayer.AspectRatioLocked></C> </R>
<R> <C><FC>IELP_BorderColor<FN></C> <C> 'IELP_BorderColor' </C> <C> <A TIELayer.BorderColor></C> </R>
<R> <C><FC>IELP_BorderWidth<FN></C> <C> 'IELP_BorderWidth' </C> <C> <A TIELayer.BorderWidth></C> </R>
<R> <C><FC>IELP_FillColor<FN></C> <C> 'IELP_FillColor' </C> <C> <A TIELayer.FillColor></C> </R>
<R> <C><FC>IELP_FillColor2<FN></C> <C> 'IELP_FillColor2' </C> <C> <A TIELayer.FillColor2></C> </R>
<R> <C><FC>IELP_FillGradient<FN></C> <C> 'IELP_FillGradient' </C> <C> <A TIELayer.FillGradient></C> </R>
<R> <C><FC>IELP_Rotate<FN></C> <C> 'IELP_Rotate' </C> <C> <A TIELayer.Rotate></C> </R>
<R> <C><FC>IELP_RotateCenterX<FN></C> <C> 'IELP_RotateCenterX' </C> <C> <A TIELayer.RotateCenterX></C> </R>
<R> <C><FC>IELP_RotateCenterY<FN></C> <C> 'IELP_RotateCenterY' </C> <C> <A TIELayer.RotateCenterY></C> </R>
<R> <C><FC>IELP_SoftShadowEnabled<FN></C> <C> 'IELP_SoftShadowEnabled' </C> <C> <L TIELayer.SoftShadow>SoftShadow.Enabled</L></C> </R>
<R> <C><FC>IELP_SoftShadowRadius<FN></C> <C> 'IELP_SoftShadowRadius' </C> <C> <L TIELayer.SoftShadow>SoftShadow.Radius</L></C> </R>
<R> <C><FC>IELP_SoftShadowOffsetX<FN></C> <C> 'IELP_SoftShadowOffsetX' </C> <C> <L TIELayer.SoftShadow>SoftShadow.OffsetX</L></C> </R>
<R> <C><FC>IELP_SoftShadowOffsetY<FN></C> <C> 'IELP_SoftShadowOffsetY' </C> <C> <L TIELayer.SoftShadow>SoftShadow.OffsetY</L></C> </R>
<R> <C><FC>IELP_SoftShadowIntensity<FN></C> <C> 'IELP_SoftShadowIntensity' </C> <C> <L TIELayer.SoftShadow>SoftShadow.Intensity</L></C> </R>
<R> <C><FC>IELP_SoftShadowColor<FN></C> <C> 'IELP_SoftShadowColor' </C> <C> <L TIELayer.SoftShadow>SoftShadow.ShadowColor</L></C> </R>
<R> <C><FC>IELP_ImageResampleFilter<FN></C> <C> 'IELP_ImageResampleFilter' </C> <C> <A TIEImageLayer.ResampleFilter></C> </R>
<R> <C><FC>IELP_ImageUseResampleFilter<FN></C> <C> 'IELP_ImageUseResampleFilter' </C> <C> <A TIEImageLayer.UseResampleFilter></C> </R>
<R> <C><FC>IELP_Shape<FN></C> <C> 'IELP_Shape' </C> <C> <A TIEShapeLayer.Shape></C> </R>
<R> <C><FC>IELP_ShapeModifier<FN></C> <C> 'IELP_ShapeModifier' </C> <C> <A TIEShapeLayer.ShapeModifier></C> </R>
<R> <C><FC>IELP_LineColor<FN></C> <C> 'IELP_LineColor' </C> <C> <A TIELineLayer.LineColor></C> </R>
<R> <C><FC>IELP_LineWidth<FN></C> <C> 'IELP_LineWidth' </C> <C> <A TIELineLayer.LineWidth></C> </R>
<R> <C><FC>IELP_LineFillColor<FN></C> <C> 'IELP_LineFillColor' </C> <C> <A TIELineLayer.FillColor></C> </R>
<R> <C><FC>IELP_LabelText<FN></C> <C> 'IELP_LabelText' </C> <C> <A TIELineLayer.LabelText></C> </R>
<R> <C><FC>IELP_LabelAlignment<FN></C> <C> 'IELP_LabelAlignment' </C> <C> <A TIELineLayer.LabelAlignment></C> </R>
<R> <C><FC>IELP_LabelPosition<FN></C> <C> 'IELP_LabelPosition' </C> <C> <A TIELineLayer.LabelPosition></C> </R>
<R> <C><FC>IELP_LineEndShape<FN></C> <C> 'IELP_LineEndShape' </C> <C> <A TIELineLayer.EndShape></C> </R>
<R> <C><FC>IELP_LineShapeSize<FN></C> <C> 'IELP_LineShapeSize' </C> <C> <A TIELineLayer.ShapeSize></C> </R>
<R> <C><FC>IELP_LineStartShape<FN></C> <C> 'IELP_LineStartShape' </C> <C> <A TIELineLayer.StartShape></C> </R>
<R> <C><FC>IELP_LineLength<FN></C> <C> 'IELP_LineLength' </C> <C> <A TIELineLayer.LineLength></C> </R>
<R> <C><FC>IELP_PolylinePoints<FN></C> <C> 'IELP_PolylinePoints' </C> <C> <A TIEPolylineLayer.Points></C> </R>
<R> <C><FC>IELP_PolylineClosed<FN></C> <C> 'IELP_PolylineClosed' </C> <C> <A TIEPolylineLayer.PolylineClosed></C> </R>
<R> <C><FC>IELP_FontName<FN></C> <C> 'IELP_FontName' </C> <C> <L TIETextLayer.Font>Font.Name</L>, <L TIELineLayer.LabelFont>LabelFont.Name</L></C> </R>
<R> <C><FC>IELP_FontSize<FN></C> <C> 'IELP_FontSize' </C> <C> <L TIETextLayer.Font>Font.Size</L>, <L TIELineLayer.LabelFont>LabelFont.Size</L></C> </R>
<R> <C><FC>IELP_FontColor<FN></C> <C> 'IELP_FontColor' </C> <C> <L TIETextLayer.Font>Font.Color</L>, <L TIELineLayer.LabelFont>LabelFont.Color</L></C> </R>
<R> <C><FC>IELP_BorderShape<FN></C> <C> 'IELP_BorderShape' </C> <C> <A TIETextLayer.BorderShape>, <A TIELineLayer.LabelShape></C> </R>
<R> <C><FC>IELP_Text<FN></C> <C> 'IELP_Text' </C> <C> <A TIETextLayer.Text></C> </R>
<R> <C><FC>IELP_AutoSize<FN></C> <C> 'IELP_AutoSize' </C> <C> <A TIETextLayer.AutoSize></C> </R>
<R> <C><FC>IELP_ReadOnly<FN></C> <C> 'IELP_ReadOnly' </C> <C> <A TIETextLayer.ReadOnly>, <A TIELineLayer.ReadOnly></C> </R>
<R> <C><FC>IELP_TextAlignment<FN></C> <C> 'IELP_TextAlignment' </C> <C> <A TIETextLayer.Alignment></C> </R>
<R> <C><FC>IELP_TextLayout<FN></C> <C> 'IELP_TextLayout' </C> <C> <A TIETextLayer.Layout></C> </R>
<R> <C><FC>IELP_AntiAlias<FN></C> <C> 'IELP_AntiAlias' </C> <C> <A TIELayer.AntiAlias></C> </R>
<R> <C><FC>IELP_SizeToFit<FN></C> <C> 'IELP_SizeToFit' </C> <C> Calls either <A TIELineLayer.SizeToFit> or <A TIETextLayer.SizeToText> </C> </R>
<R> <C><FC>IELP_RestoreSize<FN></C> <C> 'IELP_RestoreSize' </C> <C> Calls <A TIEImageLayer.RestoreSize> </C> </R>
<R> <C><FC>IELP_RestoreAspectRatio<FN></C> <C> 'IELP_RestoreAspectRatio' </C> <C> Calls <A TIELayer.RestoreAspectRatio>(False) </C> </R>
<R> <C><FC>IELP_RestorePreferredAspectRatio<FN></C> <C> 'IELP_RestorePreferredAspectRatio' </C> <C> Calls <A TIELayer.RestoreAspectRatio>(True) </C> </R>
</TABLE>
!!}
const
IELP_Width = 'IELP_Width';
IELP_Height = 'IELP_Height';
IELP_Visible = 'IELP_Visible';
IELP_VisibleBox = 'IELP_VisibleBox';
IELP_Selectable = 'IELP_Selectable';
IELP_Transparency = 'IELP_Transparency';
IELP_Opacity = 'IELP_Opacity';
IELP_PosX = 'IELP_PosX';
IELP_PosY = 'IELP_PosY';
IELP_Cropped = 'IELP_Cropped';
IELP_Locked = 'IELP_Locked';
IELP_Operation = 'IELP_Operation';
IELP_Name = 'IELP_Name';
IELP_IsMask = 'IELP_IsMask';
IELP_DrawOuter = 'IELP_DrawOuter';
IELP_AlphaEdgeFeathering = 'IELP_AlphaEdgeFeathering';
IELP_GroupIndex = 'IELP_GroupIndex';
IELP_Selected = 'IELP_Selected';
IELP_AspectRatioLocked = 'IELP_AspectRatioLocked';
IELP_BorderColor = 'IELP_BorderColor';
IELP_BorderWidth = 'IELP_BorderWidth';
IELP_FillColor = 'IELP_FillColor';
IELP_FillColor2 = 'IELP_FillColor2';
IELP_FillGradient = 'IELP_FillGradient';
IELP_Rotate = 'IELP_Rotate';
IELP_RotateCenterX = 'IELP_RotateCenterX';
IELP_RotateCenterY = 'IELP_RotateCenterY';
IELP_SoftShadowEnabled = 'IELP_SoftShadowEnabled';
IELP_SoftShadowRadius = 'IELP_SoftShadowRadius';
IELP_SoftShadowOffsetX = 'IELP_SoftShadowOffsetX';
IELP_SoftShadowOffsetY = 'IELP_SoftShadowOffsetY';
IELP_SoftShadowIntensity = 'IELP_SoftShadowIntensity';
IELP_SoftShadowColor = 'IELP_SoftShadowColor';
IELP_ImageResampleFilter = 'IELP_ImageResampleFilter';
IELP_ImageUseResampleFilter = 'IELP_ImageUseResampleFilter';
IELP_Shape = 'IELP_Shape';
IELP_ShapeModifier = 'IELP_ShapeModifier';
IELP_LineColor = 'IELP_LineColor';
IELP_LineWidth = 'IELP_LineWidth';
IELP_LineFillColor = 'IELP_LineFillColor';
IELP_LabelText = 'IELP_LabelText';
IELP_LabelAlignment = 'IELP_LabelAlignment';
IELP_LabelPosition = 'IELP_LabelPosition';
IELP_LineEndShape = 'IELP_LineEndShape';
IELP_LineShapeSize = 'IELP_LineShapeSize';
IELP_LineStartShape = 'IELP_LineStartShape';
IELP_LineLength = 'IELP_LineLength';
IELP_PolylinePoints = 'IELP_PolylinePoints';
IELP_PolylineClosed = 'IELP_PolylineClosed';
IELP_FontName = 'IELP_FontName';
IELP_FontSize = 'IELP_FontSize';
IELP_FontColor = 'IELP_FontColor';
IELP_BorderShape = 'IELP_BorderShape';
IELP_Text = 'IELP_Text';
IELP_AutoSize = 'IELP_AutoSize';
IELP_ReadOnly = 'IELP_ReadOnly';
IELP_TextAlignment = 'IELP_TextAlignment';
IELP_TextLayout = 'IELP_TextLayout';
IELP_AntiAlias = 'IELP_AntiAlias';
IELP_SizeToFit = 'IELP_SizeToFit';
IELP_RestoreSize = 'IELP_RestoreSize';
IELP_RestoreAspectRatio = 'IELP_RestoreAspectRatio';
IELP_RestorePreferredAspectRatio = 'IELP_RestorePreferredAspectRatio';
// INTERNAL ONLY
IELP_LAYER_CACHE_CLEAR = 'IELP_LAYER_CACHE_CLEAR'; // Pass as true to free all fLayerCacheBitmap
{!!
<FS>TIELayer
<FM>Description<FN>
<A TImageEnView> supports layer editing, allowing your users to build complex images from text, shapes, lines, polygon and other images, and merge them. All layer types can be created, resized, rotated and moved, either programatically of by the end-user.
<AC><IMG help_images\Layers.jpg><AL>
<FM>Loading and Saving<FN>
Standard image types such as JPEG and BMP, do not support layers, so to preserve your layer information you will need to use one of the following formats:
- ImageEn Native Format (*.ien): Maintains all layer information. Supported only by ImageEn (<L TImageEnIO.LoadFromFileIEN>Loading</L> and <L TImageEnIO.SaveToFileIEN>Saving</L>)
- Photoshop (*.psd): Widely used layer format. Only image layers are supported; non-image layers will be converted when saving (<L TImageEnIO.LoadFromFilePSD>Loading</L> and <L TImageEnIO.SaveToFilePSD>Saving</L>)
- Scalable Vector Graphics (*.svg): Vector image format for web browsers (<L TImageEnIO.SaveToFileSVG>Saving</L> only)
<FM>Layer Types<FN>
<FC>TIELayer<FN> is the ancestor of all layer classes:
<TABLE>
<R> <H>Kind</H> <H>Class</H> <H>Description</H> </R>
<R> <C><FC>ielkImage<FN></C> <C> <A TIEImageLayer> </C> <C>Layer that contains an image</C> </R>
<R> <C><FC>ielkShape<FN></C> <C> <A TIEShapeLayer> </C> <C>Layer that displays standard <L TIEShape>shapes</L> (rectangles, ellipses, stars, etc)</C> </R>
<R> <C><FC>ielkLine<FN></C> <C> <A TIELineLayer> </C> <C>Layer that displays a single line, optionally including a text label and start and ending arrows</C> </R>
<R> <C><FC>ielkPolyline<FN></C> <C> <A TIEPolylineLayer> </C> <C>Layer that displays a polyline or polgon comprising of multiple points</C> </R>
<R> <C><FC>ielkText<FN></C> <C> <A TIETextLayer> </C> <C>Layer that displays text</C> </R>
</TABLE>
<FM>Demos<FN>
<TABLE>
<R> <H>Name</H> <H>Location</H> <H>Description</H> </R>
<R> <C>Layer Editing (Image Layers)</C> <C><FC>\Demo\ImageEditing\Layers\<FN></C> <C>Usage of image layers</C> </R>
<R> <C>Layer Editing (All Layer Types)</C> <C><FC>\Demo\ImageEditing\Layers_AllTypes\<FN></C> <C>Usage of image, shape, text and line layers</C> </R>
<R> <C>Layer Rotation</C> <C><FC>\Demo\ImageEditing\RotateLayers\<FN></C> <C>Free rotation and resizing of layers of a <A TImageEnView></C> </R>
<R> <C>ImageEn Layer Actions</C> <C><FC>\Demo\Other\Actions_Layers\<FN></C> <C>Image Layering application built using only <L TImageEnView Actions>ImageEnView actions</L> </C> </R>
<R> <C>Dragging to Create Layers</C> <C><FC>\Demo\DragDrop\Layers_DragDrop\<FN></C> <C>Dragging text, images and shapes onto a <A TImageEnView> to create layers </C> </R>
</TABLE>
<FM>Methods and Properties<FN>
<TABLE2>
<R> <C_IMG_PROPERTY> <C><A TIELayer.AntiAlias></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.AspectRatioLocked></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.Assign></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.AlphaEdgeFeathering></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Bitmap></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.BorderColor> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.BorderWidth> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.ClientAreaBox></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.ConvertToImageLayer></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.ConvXBmp2Scr></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.ConvXScr2Bmp></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.ConvYBmp2Scr></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.ConvYScr2Bmp></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.CopyToBitmap></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Cropped></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.DrawingInfo></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.DrawOuter></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.FillColor> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.FillColor2> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.FillGradient> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.GetIndex></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.GetLayerMask></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.GetProperties></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Guid></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.GroupIndex></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Height></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Kind></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Locked></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Modified></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Name></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Opacity></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Operation></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.PosX></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.PosY></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.PreferredAspectRatio></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.RestoreAspectRatio></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Rotate></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.RotateCenterX></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.RotateCenterY></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Selectable></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Selected></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.SetProperties></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.SoftShadow></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.Swap></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.SupportsFeature></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Tag></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Transparency></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.UserData></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.UserDataLen></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Visible></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.VisibleBox></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Width></C> </R>
</TABLE>
<IMG help_images\Star.gif> Provide generic access to properties in descendent classes
<FM>Examples<FC>
ImageEnView1.LayersAdd( ielkImage ); // Append an image layer
ImageEnView1.IO.LoadFromFile('C:\image.jpg'); // Load image into the new/active layer
// Add a yellow explosion shape layer at size 220 x 120
ImageEnView1.LayersAdd( iesExplosion, 50, 50, 220, 120 );
ImageEnView1.CurrentLayer.FillColor := clYellow;
ImageEnView1.CurrentLayer.BorderWidth := 0;
ImageEnView1.Update();
<IMG help_images\Polyline_NoBorder.gif>
// Append an image layer and assign a pink border
ImageEnView1.LayersAdd( ielkImage ); // Append an image layer
ImageEnView1.IO.LoadFromFile('C:\New Zealand.jpg'); // Load image into the new/active layer
ImageEnView1.CurrentLayer.BorderColor := $008000FF;
ImageEnView1.CurrentLayer.BorderWidth := 3;
<IMG help_images\Image_withBorder.gif>
<FM>See Also<FN>
- <A TImageEnView.LayersAdd>
- <A TImageEnView.LayersInsert>
- <A TIELayerKind>
!!}
type
TIELayer = class
private
fLayerCacheBitmap: TIEBitmap; // Cached view of the current layer
fLayerCacheValid : Boolean; // False when the cache image needs to redrawn
fLayerCachefastDrawn: Boolean; // True if the cache image was created with fast drawing enabled
fKind: TIELayerKind;
fIsMask: Boolean; // This is the "layer mask" of previous layer
fRotate: Double;
fRotateCenterX: Double; // in percentage. 0.5=center
fRotateCenterY: Double; // in percentage. 0.5=center
fAntiAlias: Boolean;
fOriginalAspectRatio: Double; // The aspect ratio the layer was designed at
fResizedWidth, fResizedHeight: Double; // 0=original sizes. Use doubles to avoid rounding areas
fAspectRatioLocked: Boolean;
fBorderColor: TColor;
fBorderWidth: Integer;
fFillColor: TColor;
fFillColor2: TColor;
fFillGradient: TIEGradientDir;
fLayerSize: Integer; // Size of the layer as stored in a stream
fModified : Boolean; // True if layer has changed since loading
fName: String;
fDrawingInfo: TIEDrawingInfo; // filled by PaintToEx
fDrawOuter: Boolean;
fGuid: TGuid;
fTag: Integer;
fVisible: boolean;
fVisibleBox: boolean;
fTransparency: integer; // 255=opaque, 0=transparent
fOpacity: double;
fAlphaEdgeFeathering: Integer;
fClientAreaBox: TRect;
fCropped: boolean;
fLocked: boolean;
fSelectable: boolean;
fOperation: TIERenderOperation;
fUserDataLen: Integer; // used when save. If >0 then saves UserData content. Also UserData will be freed on destroy
{$ifdef IEIncludeDeprecatedInV6}
// Moved to TIEImageLayer class in 7.0.0 (2016-10-26)
fResampleFilter: TResampleFilter;
fUseResampleFilter: Boolean;
{$ENDIF}
function GetBitmap : TIEBitmap; virtual; abstract;
procedure CopyToBitmapEx(var Dest: TIEBitmap;
CreateWidth : Integer; CreateHeight : Integer;
FastDrawing: Boolean;
EnableAlpha: Boolean; UseDisplayAR: Boolean;
UpdateSize: Boolean = False; EnlargeOnly: Boolean = False;
Zoom: Double = 1); virtual; abstract;
function GetAsSVG(): string; virtual; abstract;
function GetPosX: integer;
function GetPosY: integer;
procedure SetPosX(v: integer);
procedure SetPosY(v: integer);
function GetWidth: integer;
function GetHeight: integer;
procedure SetWidth(v: integer);
procedure SetHeight(v: integer);
procedure SetWidthD(v: Double);
procedure SetHeightD(v: Double);
function GetOriginalWidth: integer;
function GetOriginalHeight: integer;
procedure SetRotate(v: Double);
procedure SetRotateCenterX(v: Double);
procedure SetRotateCenterY(v: Double);
function GetSelected: boolean;
procedure SetSelected(const Value: boolean);
procedure SetGroupIndex(const Value: Integer);
procedure CalcClientAreaBox();
procedure CalcPaintPos(ImgWidth, ImgHeight: Integer;
out XDst, YDst, WidthDst, HeightDst: integer;
out XSrc, YSrc, WidthSrc, HeightSrc: integer);
function LoadMetaFromStream(Stream: TStream): Integer;
procedure SaveMetaToStream(Stream: TStream);
function GetIsMask: Boolean;
procedure SetIsMask(const Value: Boolean);
procedure SetAspectRatioLocked(const Value: Boolean);
procedure RenderLayerWithAdornments(DstBitmap: TIEBitmap; LyrIdx: Integer; SrcBitmap: TIEBitmap; CanModifySrc: Boolean;
XLUT, YLUT: pinteger; UpdRect: PRect; xDst, yDst, dxDst, dyDst: integer; xSrc, ySrc, dxSrc, dySrc: integer;
EnableAlpha: boolean; SolidBackground: boolean; Filter: TResampleFilter);
function Owner_EnableAlphaChannel(): Boolean;
function Owner_FastDrawingActive(): Boolean;
function Owner_FastOutputActive(): Boolean;
function GetBorderColor(): TColor;
procedure SetBorderColor(value: TColor);
function GetBorderWidth(): Integer;
procedure SetBorderWidth(value: Integer);
function GetFillColor(): TColor;
procedure SetFillColor(value: TColor);
procedure SetFillColor2(value: TColor);
procedure SetFillGradient(value: TIEGradientDir);
function GetModified(): Boolean;
procedure SetModified(value: Boolean);
procedure SetVisible(Value: Boolean);
procedure SetVisibleBox(Value: Boolean);
procedure SetTransparency(Value: integer);
procedure SetOpacity(Value: double);
procedure SetAlphaEdgeFeathering(Value: Integer);
procedure SetCropped(Value: boolean);
procedure SetLocked(Value: boolean);
procedure SetSelectable(Value: boolean);
procedure SetOperation(Value: TIERenderOperation);
procedure SetUserDataLen(Value: Integer);
procedure SetName(Value: String);
procedure SetDrawOuter(Value: Boolean);
procedure SetGuid(Value: TGuid);
procedure SetTag(Value: Integer);
public
fOwner: TObject; // must be TImageEnView
fSelected: Boolean;
fCachedLayerMask: TIEBitmap;
fPosX, fPosY: Double; // Use doubles to avoid rounding areas
fGroupIndex: Integer;
{!!
<FS>TIELayer.SoftShadow
<FM>Declaration<FC>
property SoftShadow: <A TIEVSoftShadow>;
<FM>Description<FN>
Enables and sets the properties of the layer shadow.
Note: Shadows cannot be enabled for the background layer (layer 0)
<FM>Example<FC>
// Display a soft shadow effect for the current layer
ImageEnView1.CurrentLayer.SoftShadow.Enabled := True;
ImageEnView1.Update();
<IMG help_images\SoftShadow.gif>
<FM>See Also<FN>
- <A TImageEnView.LayersFastDrawing>
!!}
SoftShadow: TIEVSoftShadow;
{!!
<FS>TIELayer.UserData
<FM>Declaration<FC>
property UserData: pointer;
<FM>Description<FN>
Contains a pointer to a user data buffer. This can be used for your own purposes to store information about the layer.
<FM>Example<FC>
type
TMyRecord = record
SourceText: array[0..255] of AnsiChar;
SourceWidth: integer;
SourceHeight: integer;
end;
PMyRecord = ^TMyRecord;
var
rc: PMyRecord;
begin
New( rc )
With rc^ do
begin
Width := ...;
Height := ...;
Text := ...;
end;
ImageEnView1.CurrentLayer.UserData := rc;
ImageEnView1.CurrentLayer.UserDataLen := SizeOf( PMyRecord );
end;
<FM>See Also<FN>
- <A TIELayer.UserDataLen>.
!!}
UserData: pointer;
{$ifdef IEIncludeDeprecatedInV6}
// Moved to TIEImageLayer class in 7.0.0 (2016-10-26)
Magnify: TIELayerMagnification;
property ResampleFilter: TResampleFilter read fResampleFilter write fResampleFilter;
property UseResampleFilter: Boolean read fUseResampleFilter write fUseResampleFilter;
{$ENDIF}
property AspectRatioLocked: Boolean read fAspectRatioLocked write SetAspectRatioLocked;
property Rotate: Double read fRotate write SetRotate;
property RotateCenterX: Double read fRotateCenterX write SetRotateCenterX;
property RotateCenterY: Double read fRotateCenterY write SetRotateCenterY;
property PosX: integer read GetPosX write SetPosX;
property PosY: integer read GetPosY write SetPosY;
property Width: integer read GetWidth write SetWidth; // displayed width of the layer
property Height: integer read GetHeight write SetHeight; // displayed height of the layer
property WidthD: Double read fResizedWidth write SetWidthD; // displayed width of the layer (as a double)
property HeightD: Double read fResizedHeight write SetHeightD; // displayed height of the layer (as a double)
property Selected: boolean read GetSelected write SetSelected;
property GroupIndex: Integer read fGroupIndex write SetGroupIndex;
property IsMask: Boolean read GetIsMask write SetIsMask;
property Owner: TObject read fOwner;
{!!
<FS>TIELayer.Bitmap
<FM>Declaration<FC>
property Bitmap: <A TIEBitmap>;
<FM>Description<FN>
If the layer is a <A TIEImageLayer> then <FC>Bitmap<FN> provides read/write access to the image and alpha channel of the layer.
For other TIELayer types, <FC>Bitmap<FN> provides read-only access to the layer content (e.g. to display an icon for the layer in a TImageEnMView).
<FM>Example 1<FC>
// Replace the image of the current layer with a bitmap
TIEImageLayer( ImageEnView1.CurrentLayer ).Bitmap.Assign( MyBitmap );
ImageEnView1.Update();
<FM>Example 2<FC>
// REFRESH LAYER VIEWER (Show thumbnails of all layers in a TImageEnMView - same as TImageEnMView.AssignLayers method)
procedure Tfmain.RefreshLayerViewer;
var
i, idx: integer;
begin
// Fill ImageEnMView1 with all layers of ImageEnView1
ImageEnMView1.Clear;
for i := 0 to ImageEnView1.LayersCount - 1 do
begin
idx := ImageEnMView1.AppendImage;
ImageEnMView1.SetImage( idx, ImageEnView1.Layers[i].Bitmap );
ImageEnMView1.ImageTopText[i] := 'Layer ' + inttostr(i);
end;
// Mark selected layers and highlight the current layer
ImageEnMView1.BeginSelectImages;
for i := 0 to ImageEnView1.LayersCount - 1 do
if ImageEnView1.Layers[ i ].Selected then
ImageEnMView1.SelectedImage := I;
ImageEnMView1.SelectedImage := ImageEnView1.LayersCurrent; // Make it the active image
ImageEnMView1.EndSelectImages;
end;
!!}
property Bitmap: TIEBitmap read GetBitmap;
{!!
<FS>TIELayer.CopyToBitmap
<FM>Declaration<FC>
procedure CopyToBitmap(var Dest: <A TIEBitmap>; CreateWidth : Integer = -1; CreateHeight : Integer = -1; EnableAlpha: Boolean = True; UseDisplayAR: Boolean = True); virtual; abstract;
<FM>Description<FN>
Creates a bitmap representation of the current layer.
You do not need to create <FC>Dest<FN>. It will be automatically created and sized as required.
If <FC>CreateWidth<FN> and <FC>CreateHeight<FN> are not specified, the bitmap will be created at the current size of the layer.
Set <FC>EnableAlpha<FN> to false if you do not want as alpha channel applied to <FC>Dest<FN>.
If <FC>UseDisplayAR<FN> is true, then the image will be returned with the same aspect ratio it is displayed, If false, it is stretched to the specified CreateWidth and CreateHeight dimensions.
Note: You must free <FC>Dest<FN>
<FM>Example<FC>
// Save the current layer as an image
var
bmp: TIEBitmap;
Begin
ImageEnView1.CurrentLayer.CopyToBitmap( bmp );
bmp.Write( 'D:\MyLayer.jpg' );
bmp.Free;
end;
// Assign Layer 1 to another ImageEnView
var
bmp: TIEBitmap;
begin
bmp := TIEBitmap.create;
ImageEnView1.Layers[1].CopyToBitmap( bmp, ImageEnView2.ClientWidth, ImageEnView2.ClientHeight );
ImageEnView2.IEBitmap.Assign( bmp );
ImageEnView2.Update;
bmp.Free();
end;
// Show a preview in ImageEnView2 of the layer selected in ImageEnView1
procedure Tfmain.ImageEnView1LayerSelectionChange(Sender: TObject);
var
bmp: TIEBitmap;
begin
bmp := ImageEnView2.IEBitmap;
ImageEnView1.CurrentLayer.CopyToBitmap( bmp, ImageEnView2.IdealImageWidth, ImageEnView2.IdealImageWidth );
ImageEnView2.Update();
end;
!!}
procedure CopyToBitmap(var Dest: TIEBitmap; CreateWidth : Integer = -1; CreateHeight : Integer = -1; EnableAlpha: Boolean = True; UseDisplayAR: Boolean = True); virtual; abstract;
{!!
<FS>TIELayer.Kind
<FM>Declaration<FC>
property Kind: <A TIELayerKind>;
<FM>Description<FN>
Returns the kind of layer.
Read-Only
<FM>Example 1<FC>
if ImageEnView1.CurrentLayer.Kind = ielkImage then
TIEImageLayer( ImageEnView1.CurrentLayer ).ResampleFilter := rfLanczos3;
ImageEnView1.Update();
// Which is the same as...
if ImageEnView1.CurrentLayer is TIEImageLayer then
TIEImageLayer( ImageEnView1.CurrentLayer ).ResampleFilter := rfLanczos3;
ImageEnView1.Update();
<FM>Example 2<FC>
// Hide labels of all line layers when user clicks a check box
procedure Tfmain.chkShowLabelsClick(Sender: TObject);
var
I: integer;
begin
ImageEnView1.LockUpdate();
for I := 0 to ImageEnView1.LayersCount - 1 do
if ImageEnView1.Layers[ I ].Kind = ielkLine then
begin
if chkShowLabels.Checked then
TIELineLayer( ImageEnView1.Layers[ I ]).LabelPosition := ielpAtEnd
else
TIELineLayer( ImageEnView1.Layers[ I ]).LabelPosition := ielpHide;
end;
ImageEnView1.UnlockUpdate();
end;
!!}
property Kind: TIELayerKind read fKind;
{!!
<FS>TIELayer.AntiAlias
<FM>Declaration<FC>
property AntiAlias: Boolean;
<FM>Description<FN>
Improves the quality of layer drawing by using anti-aliasing.
Notes:
- Does not apply to <A TIEImageLayer>. For display quality of <A TIEImageLayer>, see <A TIEImageLayer.UseResampleFilter>
- Anti-Alias is not applied if <A TImageEnView.LayersFastDrawing> is active
Default: True
<FM>Example<FC>
// Disable anti-aliasing
ImageEnView1.CurrentLayer.AntiAlias := False;
ImageEnView1.Update();
!!}
property AntiAlias: Boolean read fAntiAlias write fAntiAlias;
// Returns the size of the bitmap if an image layer, otherwise the user's specified size for the object
property OriginalWidth: integer read GetOriginalWidth;
property OriginalHeight: integer read GetOriginalHeight;
constructor Create(Owner: TObject); virtual;
destructor Destroy; override;
function ConvXScr2Bmp(x: Integer): Integer;
function ConvYScr2Bmp(y: Integer): Integer;
function ConvXBmp2Scr(x: Integer): Integer;
function ConvYBmp2Scr(y: Integer): Integer;
procedure Assign(Source: TIELayer);
procedure Swap(OtherLayer: TIELayer);
function SupportsFeature(Feature: TIELayerFeatures): Boolean;
procedure GetProperties(Props: TStrings);
procedure SetProperties(Props: TStrings); overload;
procedure SetProperties(PropName, Value: String); overload;
procedure SetDefaults;
function GetLayerMask(): TIELayer;
function GetIndex(): integer;
procedure ConvertToImageLayer(QualityFactor: Double = 2; CropAlpha: Boolean = True);
function PreferredAspectRatio(): Double;
procedure RestoreAspectRatio(PreferredOnly: Boolean = True);
{!!
<FS>TIELayer.DrawingInfo
<FM>Declaration<FC>
property DrawingInfo: <A TIEDrawingInfo>; (read-only)
<FM>Description<FN>
Specifies the source and destination rectangle recorded on last drawing.
!!}
property DrawingInfo: TIEDrawingInfo read fDrawingInfo;
{!!
<FS>TIELayer.ClientAreaBox
<FM>Declaration<FC>
property ClientAreaBox: TRect; (Read-Only)
<FM>Description<FN>
Returns the drawing area of the layer. The coordinates are relative to the component client area.
!!}
property ClientAreaBox: TRect read fClientAreaBox;
property Visible: boolean read fVisible write SetVisible;
property VisibleBox: Boolean read fVisibleBox write SetVisibleBox;
property Transparency: integer read fTransparency write SetTransparency;
property Opacity: double read fOpacity write SetOpacity;
property AlphaEdgeFeathering: Integer read fAlphaEdgeFeathering write SetAlphaEdgeFeathering;
property Cropped: boolean read fCropped write SetCropped;
property Locked: boolean read fLocked write SetLocked;
property Selectable: boolean read fSelectable write SetSelectable;
property Operation: TIERenderOperation read fOperation write SetOperation;
property UserDataLen: Integer read fUserDataLen write SetUserDataLen;
property Name: String read fName write SetName;
property DrawOuter: Boolean read fDrawOuter write SetDrawOuter;
property Guid: TGuid read fGuid write SetGuid;
property Tag: Integer read fTag write SetTag;
// Style
property BorderColor: TColor read GetBorderColor write SetBorderColor;
property BorderWidth: Integer read GetBorderWidth write SetBorderWidth;
property FillColor: TColor read GetFillColor write SetFillColor;
property FillColor2: TColor read fFillColor2 write SetFillColor2;
property FillGradient: TIEGradientDir read fFillGradient write SetFillGradient;
property Modified: Boolean read GetModified write SetModified;
// Internal
procedure PaintTo(DstBitmap: TIEBitmap; LyrIdx: Integer;
XLUT, YLUT: pinteger; UpdRect: PRect; xDst, yDst, dxDst, dyDst: integer; xSrc, ySrc, dxSrc, dySrc: integer;
EnableAlpha: boolean; SolidBackground: boolean; Filter: TResampleFilter; RotationFilter: TIEAntialiasMode; ResizingLayer: Boolean); Virtual;
procedure LoadFromStream(Stream: TStream); Virtual; Abstract;
procedure LoadFromLegacyStream(Stream: TStream; HdrVersion: Integer; FileFormat: TIOFileType);
procedure SaveToStream(Stream: TStream; MetaOnly: Boolean = False; CompressionFormat: TIOFileType = -2); Virtual; Abstract;
procedure LayerChange(ResetLayerCache: Boolean = True);
property AsSVG: string read GetAsSVG;
end;
{!!
<FS>TIEImageLayer
<FM>Description<FN>
TImageEnView supports multiple layers, allowing the creation of a single image from multiple source images (which can be resized, rotated, moved, etc).
TIEImageLayer is a descendent of <A TIELayer> which contains an image.
<IMG help_images\Image_withBorder.gif>
Review the <L TIELayer>Layer Documentation</L> for a full description of layer support.
<FM>Methods and Properties<FN>
<TABLE2>
<R> <C_IMG_PROPERTY> <C><A TIELayer.AspectRatioLocked></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.Assign></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.AlphaEdgeFeathering></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Bitmap> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.BorderColor> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.BorderWidth> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_METHOD> <C><A TIEImageLayer.Clear> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.ClientAreaBox></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.ConvXBmp2Scr></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.ConvXScr2Bmp></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.ConvYBmp2Scr></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.ConvYScr2Bmp></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.CopyToBitmap></C> </R>
<R> <C_IMG_METHOD> <C><A TIEImageLayer.CropAlpha> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Cropped></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.DrawingInfo></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.DrawOuter></C> </R>
<R> <C_IMG_METHOD> <C><A TIEImageLayer.ExecuteOpenDialog> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.GetIndex></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.GetLayerMask></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.GetProperties></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Guid></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.GroupIndex></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Height></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIEImageLayer.IsMask> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Kind></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Locked></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Modified></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIEImageLayer.Magnify> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Name></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Opacity></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Operation></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.PosX></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.PosY></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.PreferredAspectRatio></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIEImageLayer.ResampleFilter> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.RestoreAspectRatio></C> </R>
<R> <C_IMG_METHOD> <C><A TIEImageLayer.RestoreSize> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Rotate></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.RotateCenterX></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.RotateCenterY></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Selectable></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Selected></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.SetProperties></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.Swap></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.SupportsFeature></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Tag></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Transparency></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.UserData></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.UserDataLen></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIEImageLayer.UseResampleFilter> <IMG help_images\Star.gif>/C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Visible></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.VisibleBox></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Width></C> </R>
</TABLE>
<IMG help_images\Star.gif> Unique to TIEImageLayer
<FM>Example<FC>
// Load an image layer and assign a pink border
ImageEnView1.LayersAdd( ielkImage ); // Append an image layer
ImageEnView1.IO.LoadFromFile('C:\New Zealand.jpg'); // Load image into the new/active layer
ImageEnView1.CurrentLayer.BorderColor := $008000FF;
ImageEnView1.CurrentLayer.BorderWidth := 3;
ImageEnView1.Update();
<IMG help_images\Image_withBorder.gif>
// Fix the aspect ratio of an image (that has been resized)
if ImageEnView1.CurrentLayer is TIEImageLayer then
ImageEnView1.CurrentLayer.RestoreAspectRatio();
ImageEnView1.Update();
<FM>See Also<FN>
- <A TImageEnView.LayersAdd>
- <A TImageEnView.LayersInsert>
- <A TIELayerKind>
!!}
TIEImageLayer = class( TIELayer )
private
{$ifndef IEIncludeDeprecatedInV6}
// Moved from TIELayer class in 7.0.0 (2016-10-26)
fResampleFilter: TResampleFilter;
fUseResampleFilter: Boolean; // if true uses this ResampleFilter instead of TImageEnView.ZoomFilter/LayersMergeFilter
{$ENDIF}
function GetBitmap : TIEBitmap; override;
procedure CopyToBitmapEx(var Dest: TIEBitmap;
CreateWidth : Integer; CreateHeight : Integer;
FastDrawing: Boolean;
EnableAlpha: Boolean; UseDisplayAR: Boolean;
UpdateSize: Boolean = False; EnlargeOnly: Boolean = False;
Zoom: Double = 1); override;
function GetAsSVG(): string; override;
function GetBorderColor(): TColor;
procedure SetBorderColor(value: TColor);
function GetBorderWidth: Integer;
procedure SetBorderWidth(value: Integer);
// Moved from TIELayer class in 7.0.0 (2016-10-26)
{$ifndef IEIncludeDeprecatedInV6}
procedure SetResampleFilter(Value: TResampleFilter);
procedure SetUseResampleFilter(Value : Boolean);
{$ENDIF}
public
fBitmap: TIEBitmap;
fFreeBitmapOnDestroy: boolean;
{!!
<FS>TIEImageLayer.Magnify
<FM>Declaration<FC>
property Magnify: <A TIELayerMagnification>
<FM>Description<FN>
Set properties if the layer is a magnification layer.
Note: Only available to <A TIEImageLayer>
<FM>Demo<FN>
<TABLE2>
<R> <C_IMG_DEMO> <C>Demos\Display\Magnify2\Magnify2.dpr </C> </R>
</TABLE>
!!}
{$ifndef IEIncludeDeprecatedInV6}
// Moved from TIELayer class in 7.0.0 (2016-10-26)
Magnify: TIELayerMagnification;
property ResampleFilter: TResampleFilter read fResampleFilter write SetResampleFilter;
property UseResampleFilter: Boolean read fUseResampleFilter write SetUseResampleFilter;
{$ENDIF}
// Style
property BorderColor: TColor read GetBorderColor write SetBorderColor;
property BorderWidth: Integer read GetBorderWidth write SetBorderWidth;
constructor Create(Owner: TObject; TemplateBitmap: TIEBitmap; JustAssign: boolean); reintroduce; overload;
constructor Create(Owner: TObject; Width, Height : Integer); reintroduce; overload;
constructor Create(Owner: TObject; TemplateLayer: TIELayer; QualityFactor: Double = 2; CropAlpha: Boolean = True); reintroduce; overload;
destructor Destroy; override;
procedure CopyToBitmap(var Dest: TIEBitmap; CreateWidth : Integer = -1; CreateHeight : Integer = -1; EnableAlpha: Boolean = True; UseDisplayAR: Boolean = True); override;
procedure PaintTo(DstBitmap: TIEBitmap; LyrIdx: Integer;
XLUT, YLUT: pinteger; UpdRect: PRect; xDst, yDst, dxDst, dyDst: integer; xSrc, ySrc, dxSrc, dySrc: integer;
EnableAlpha: boolean; SolidBackground: boolean; Filter: TResampleFilter; RotationFilter: TIEAntialiasMode; ResizingLayer: Boolean); override;
function CropAlpha(): Boolean;
procedure Clear(FillColor: TColor = clWhite; Width: Integer = 1; Height: Integer = 1);
procedure RestoreSize();
function ExecuteOpenDialog(): Boolean;
procedure LoadFromStream(Stream: TStream); override;
procedure SaveToStream(Stream: TStream; MetaOnly: Boolean = False; CompressionFormat: TIOFileType = -2); override;
end;
{!!
<FS>TIEShapeLayer
<FM>Description<FN>
TImageEnView supports multiple layers, allowing the creation of a single image from multiple source images (which can be resized, rotated, moved, etc).
TIEShapeLayer is a descendent of <A TIELayer> that displays one of ImageEn's <L TIEShape>pre-built shapes</L>.
<IMG help_images\Shape_Ellipse.gif> <IMG help_images\Shape_Lightning.gif>
Review the <L TIELayer>Layer Documentation</L> for a full description of layer support.
<FM>Methods and Properties<FN>
<TABLE2>
<R> <C_IMG_PROPERTY> <C><A TIELayer.AntiAlias></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.AspectRatioLocked></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.Assign></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.AlphaEdgeFeathering></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIEShapeLayer.BorderColor> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIEShapeLayer.BorderWidth> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.ClientAreaBox></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.ConvertToImageLayer></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.ConvXBmp2Scr></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.ConvXScr2Bmp></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.ConvYBmp2Scr></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.ConvYScr2Bmp></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.CopyToBitmap></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Cropped></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.DrawingInfo></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.DrawOuter></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIEShapeLayer.FillColor> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIEShapeLayer.FillColor2> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIEShapeLayer.FillGradient> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.GetIndex></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.GetLayerMask></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.GetProperties></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Guid></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.GroupIndex></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Height></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Kind></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Locked></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Modified></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Name></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Opacity></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Operation></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.PosX></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.PosY></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.PreferredAspectRatio></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.RestoreAspectRatio></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Rotate></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Selectable></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Selected></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.SetProperties></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIEShapeLayer.Shape> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIEShapeLayer.ShapeModifier> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.Swap></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.SupportsFeature></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Tag></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Transparency></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.UserData></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.UserDataLen></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Visible></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.VisibleBox></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Width></C> </R>
</TABLE>
<IMG help_images\Star.gif> Unique to TIEShapeLayer
<FM>Example<FC>
// Add a yellow explosion layer
ImageEnView1.LayersAdd( ielkShape );
ImageEnView1.CurrentLayer.Shape := iesExplosion;
ImageEnView1.CurrentLayer.FillColor := clYellow;
ImageEnView1.CurrentLayer.BorderColor := $004080FF;
ImageEnView1.CurrentLayer.BorderWidth := 2;
ImageEnView1.Update();
<IMG help_images\Polyline_WithBorder.gif>
// Remove the border...
ImageEnView1.CurrentLayer.BorderWidth := 0;
ImageEnView1.Update();
<IMG help_images\Polyline_NoBorder.gif>
<FM>See Also<FN>
- <A TImageEnView.LayersAdd>
- <A TImageEnView.LayersInsert>
- <A TIEShape>
- <A TIELayerKind>
!!}
TIEShapeLayer = class( TIELayer )
private
fShape: TIEShape;
fShapeModifier: Integer;
function GetBitmap : TIEBitmap; override;
procedure CopyToBitmapEx(var Dest: TIEBitmap;
CreateWidth : Integer; CreateHeight : Integer;
FastDrawing: Boolean;
EnableAlpha: Boolean; UseDisplayAR: Boolean;
UpdateSize: Boolean = False; EnlargeOnly: Boolean = False;
Zoom: Double = 1); override;
function GetAsSVG(): string; override;
function GetBorderColor(): TColor;
procedure SetBorderColor(value: TColor);
function GetBorderWidth(): Integer;
procedure SetBorderWidth(value: Integer);
function GetFillColor(): TColor;
procedure SetFillColor(value: TColor);
function GetFillColor2(): TColor;
procedure SetFillColor2(value: TColor);
function GetFillGradient(): TIEGradientDir;
procedure SetFillGradient(value: TIEGradientDir);
procedure SetShape(value: TIEShape);
procedure SetShapeModifier(value: Integer);
public
property Shape: TIEShape read fShape write SetShape;
property ShapeModifier: Integer read fShapeModifier write SetShapeModifier;
// Style
property BorderColor: TColor read GetBorderColor write SetBorderColor;
property BorderWidth: Integer read GetBorderWidth write SetBorderWidth;
property FillColor: TColor read GetFillColor write SetFillColor;
property FillColor2: TColor read GetFillColor2 write SetFillColor2;
property FillGradient: TIEGradientDir read GetFillGradient write SetFillGradient;
constructor Create(Owner: TObject); override;
destructor Destroy; override;
procedure CopyToBitmap(var Dest: TIEBitmap; CreateWidth : Integer = -1; CreateHeight : Integer = -1; EnableAlpha: Boolean = True; UseDisplayAR: Boolean = True); override;
procedure LoadFromStream(Stream: TStream); override;
procedure SaveToStream(Stream: TStream; MetaOnly: Boolean = False; CompressionFormat: TIOFileType = -2); override;
end;
type
TIEEndShapeDrawInfo = record
Shape: TIELineEndShape;
Pt1 : TPoint;
Pt2 : TPoint;
Pt3 : TPoint;
end;
{!!
<FS>TIELineLayer
<FM>Description<FN>
TImageEnView supports multiple layers, allowing the creation of a single image from multiple source images (which can be resized, rotated, moved, etc).
TIELineLayer is a descendent of <A TIELayer> that displays a single line. It can optionally display a text label and starting and ending arrows.
<IMG help_images\Line_withLabel.gif>
Review the <L TIELayer>Layer Documentation</L> for a full description of layer support.
<FM>Methods and Properties<FN>
<TABLE2>
<R> <C_IMG_METHOD> <C><A TIELineLayer.ActivateEditor> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.AntiAlias></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.AspectRatioLocked></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.Assign></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.AlphaEdgeFeathering></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.ClientAreaBox></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.ConvertToImageLayer></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.ConvXBmp2Scr></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.ConvXScr2Bmp></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.ConvYBmp2Scr></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.ConvYScr2Bmp></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.CopyToBitmap></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Cropped></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.DrawingInfo></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.DrawOuter></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELineLayer.EndShape> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELineLayer.FillColor> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.GetIndex></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.GetLayerMask></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.GetProperties></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Guid></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.GroupIndex></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Height></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Kind></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELineLayer.LabelAlignment> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELineLayer.LabelBorderColor> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELineLayer.LabelBorderWidth> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELineLayer.LabelFillColor> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELineLayer.LabelFillColor2> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELineLayer.LabelFillGradient> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELineLayer.LabelFont> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELineLayer.LabelPosition> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELineLayer.LabelShape> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELineLayer.LabelText> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELineLayer.LineColor> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELineLayer.LineLength> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELineLayer.LinePoints> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELineLayer.LineWidth> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Locked></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Modified></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Name></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Opacity></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Operation></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.PosX></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.PosY></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.PreferredAspectRatio></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.RestoreAspectRatio></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELineLayer.ReadOnly> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Rotate></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Selectable></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Selected></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.SetProperties></C> </R>
<R> <C_IMG_METHOD> <C><A TIELineLayer.SizeToFit> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELineLayer.ShapeSize> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELineLayer.StartShape> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.Swap></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.SupportsFeature></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Tag></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Transparency></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.UserData></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.UserDataLen></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Visible></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.VisibleBox></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Width></C> </R>
</TABLE>
<IMG help_images\Star.gif> Unique to TIELineLayer
<FM>Examples<FC>
// Add a layer with yellow filled arrows and circle ends
ImageEnView1.LayersAdd( ielkLine );
TIELineLayer( ImageEnView1.CurrentLayer ).StartShape := ieesArrow;
TIELineLayer( ImageEnView1.CurrentLayer ).EndShape := ieesCircle;
TIELineLayer( ImageEnView1.CurrentLayer ).FillColor := clYellow;
TIELineLayer( ImageEnView1.CurrentLayer ).ShapeSize := 25;
ImageEnView1.Update();
<IMG help_images\Line_EndShapes.gif>
// Hide labels of all line layers when user clicks a check box
procedure Tfmain.chkShowLabelsClick(Sender: TObject);
var
I: integer;
begin
ImageEnView1.LockUpdate();
for I := 0 to ImageEnView1.LayersCount - 1 do
if ImageEnView1.Layers[ I ].Kind = ielkLine then
begin
if chkShowLabels.Checked then
TIELineLayer( ImageEnView1.Layers[ I ]).LabelPosition := ielpAtEnd
else
TIELineLayer( ImageEnView1.Layers[ I ]).LabelPosition := ielpHide;
end;
ImageEnView1.UnlockUpdate();
end;
<FM>See Also<FN>
- <A TImageEnView.LayersAdd>
- <A TImageEnView.LayersInsert>
- <A TIELayerKind>
!!}
TIELineLayer = class( TIELayer )
private
fLabelFont: TFont;
fLabelText: string;
fLineLength: Double;
fLastLineLength: Double;
fStartShape: TIELineEndShape;
fEndShape: TIELineEndShape;
fShapeSize: integer;
fLabelPosition: TIELineLabelPos;
fAutoSize: boolean;
fLabelShape: TIEShape;
fLabelAlignment: TIEAlignment;
fReadOnly: Boolean;
fLineColor: TColor; // Also used for Line End shapes
fLineWidth: Integer; // Also used for Line End shapes
fLineFillColor: TColor; // Only used for Line End shapes
fLineRect: TRect; // Rect where line is drawn (Pt1 is Left,Top. Pt2 is Right,Bottom)
fLabelRect: TRect; // Rect where text label is drawn
fStartShapePoints: TIEEndShapeDrawInfo; // Where the starting shape is drawn
fEndShapePoints: TIEEndShapeDrawInfo; // Where the ending shape is drawn
function GetBitmap : TIEBitmap; override;
procedure CopyToBitmapEx(var Dest: TIEBitmap;
CreateWidth : Integer; CreateHeight : Integer;
FastDrawing: Boolean;
EnableAlpha: Boolean; UseDisplayAR: Boolean;
UpdateSize: Boolean = False; EnlargeOnly: Boolean = False;
Zoom: Double = 1); override;
function GetAsSVG(): string; override;
procedure SetLabelFont(const Value: TFont);
procedure SetLabelText(const Value: string);
procedure SetLabelPosition(const Value: TIELineLabelPos);
procedure SetAutoSize(const Value: boolean);
procedure SetReadOnly(const Value: boolean);
procedure SetStartShape(const Value: TIELineEndShape);
procedure SetEndShape(const Value: TIELineEndShape);
procedure SetShapeSize(const Value: Integer);
function GetLabelBorderColor(): TColor;
procedure SetLabelBorderColor(value: TColor);
function GetLabelBorderWidth(): Integer;
procedure SetLabelBorderWidth(value: Integer);
function GetLabelFillColor(): TColor;
procedure SetLabelFillColor(value: TColor);
function GetLabelFillColor2(): TColor;
procedure SetLabelFillColor2(value: TColor);
function GetLabelFillGradient(): TIEGradientDir;
procedure SetLabelFillGradient(value: TIEGradientDir);
procedure SetLineColor(const Value: TColor);
procedure SetLineWidth(const Value: Integer);
procedure SetLineFillColor(const Value: TColor);
function GetLineLength: Integer;
procedure SetLineLength(const Value: Integer);
function GetLinePoints: TRect;
procedure SetLinePoints(Value: TRect);
procedure SetLabelShape(Value: TIEShape);
procedure SetLabelAlignment(Value: TIEAlignment);
public
property ReadOnly: Boolean read fReadOnly write SetReadOnly;
property LabelShape: TIEShape read fLabelShape write SetLabelShape;
property LabelAlignment: TIEAlignment read fLabelAlignment write SetLabelAlignment;
// Not exposed in doc
property AutoSize: boolean read fAutoSize write SetAutoSize;
property LabelPosition: TIELineLabelPos read fLabelPosition write SetLabelPosition;
property LabelText: String read fLabelText write SetLabelText;
property LabelFont: TFont read fLabelFont write SetLabelFont;
// Rect where line is drawn (Pt1 is Left,Top. Pt2 is Right,Bottom)
property LinePoints: TRect read GetLinePoints write SetLinePoints;
// The position where the text label is drawn
property LabelRect: TRect read fLabelRect;
property StartShape: TIELineEndShape read fStartShape write SetStartShape;
property EndShape: TIELineEndShape read fEndShape write SetEndShape;
property ShapeSize: Integer read fShapeSize write SetShapeSize;
procedure SizeToFit();
procedure ActivateEditor();
property LineColor: TColor read fLineColor write SetLineColor;
property LineWidth: Integer read fLineWidth write SetLineWidth;
property FillColor: TColor read fLineFillColor write SetLineFillColor;
// Style
property LabelBorderColor: TColor read GetLabelBorderColor write SetLabelBorderColor;
property LabelBorderWidth: Integer read GetLabelBorderWidth write SetLabelBorderWidth;
property LabelFillColor: TColor read GetLabelFillColor write SetLabelFillColor;
property LabelFillColor2: TColor read GetLabelFillColor2 write SetLabelFillColor2;
property LabelFillGradient: TIEGradientDir read GetLabelFillGradient write SetLabelFillGradient;
property LineLength: Integer read GetLineLength write SetLineLength;
constructor Create(Owner: TObject); override;
destructor Destroy; override;
procedure CopyToBitmap(var Dest: TIEBitmap; CreateWidth : Integer = -1; CreateHeight : Integer = -1; EnableAlpha: Boolean = True; UseDisplayAR: Boolean = True); override;
procedure LoadFromStream(Stream: TStream); override;
procedure SaveToStream(Stream: TStream; MetaOnly: Boolean = False; CompressionFormat: TIOFileType = -2); override;
end;
{!!
<FS>TIEPolylineLayer
<FM>Description<FN>
TImageEnView supports multiple layers, allowing the creation of a single image from multiple source images (which can be resized, rotated, moved, etc).
TIEPolylineLayer is a descendent of <A TIELayer> that displays a line formed from multiple points. It can also be closed to display a polygon.
<IMG help_images\Polyline_Arrow.gif>
Review the <L TIELayer>Layer Documentation</L> for a full description of layer support.
<FM>Methods and Properties<FN>
<TABLE2>
<R> <C_IMG_PROPERTY> <C><A TIELayer.AntiAlias></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.AspectRatioLocked></C> </R>
<R> <C_IMG_METHOD> <C><A TIEPolylineLayer.AddPoint> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.Assign></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.AlphaEdgeFeathering></C> </R>
<R> <C_IMG_METHOD> <C><A TIEPolylineLayer.ClearAllPoints> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.ClientAreaBox></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.ConvertToImageLayer></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.ConvXBmp2Scr></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.ConvXScr2Bmp></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.ConvYBmp2Scr></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.ConvYScr2Bmp></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.CopyToBitmap></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Cropped></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.DrawingInfo></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.DrawOuter></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIEPolylineLayer.FillColor> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.GetIndex></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.GetLayerMask></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.GetProperties></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Guid></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.GroupIndex></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Height></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Kind></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIEPolylineLayer.LineColor> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIEPolylineLayer.LineWidth> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Locked></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Modified></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Name></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Opacity></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Operation></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIEPolylineLayer.PolylineClosed> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIEPolylineLayer.Points> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIEPolylineLayer.PointCount> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.PosX></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.PosY></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.PreferredAspectRatio></C> </R>
<R> <C_IMG_METHOD> <C><A TIEPolylineLayer.RemovePoint> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.RestoreAspectRatio></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Rotate></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Selectable></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Selected></C> </R>
<R> <C_IMG_METHOD> <C><A TIEPolylineLayer.SetPoints> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.SetProperties></C> </R>
<R> <C_IMG_METHOD> <C><A TIEPolylineLayer.SimplifyPolygon> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.Swap></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.SupportsFeature></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Tag></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Transparency></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.UserData></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.UserDataLen></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Visible></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.VisibleBox></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Width></C> </R>
</TABLE>
<IMG help_images\Star.gif> Unique to TIEPolylineLayer
<FM>Example<FC>
// Draw a triangle polygon
With TIEPolylineLayer( ImageEnView1.CurrentLayer ) do
begin
ClearAllPoints();
AddPoint( 500, 0 );
AddPoint( 1000, 1000 );
AddPoint( 0, 1000 );
PolylineClosed := True;
end;
ImageEnView1.Update();
// Which is the same as...
TIEPolylineLayer( ImageEnView1.CurrentLayer ).SetPoints( [ Point(500, 0), Point(1000, 1000), Point(0, 1000) ], True );
ImageEnView1.Update();
// Which is the same as...
TIEPolylineLayer( ImageEnView1.CurrentLayer ).SetPoints( iesTriangle, True );
ImageEnView1.Update();
<IMG help_images\Polyline_Closed.gif>
// If PolylineClosed is not enabled, we get a polyline, instead of a polygon
TIEPolylineLayer( ImageEnView1.CurrentLayer ).PolylineClosed := False;
ImageEnView1.Update();
<IMG help_images\Polyline_Open.gif>
<FM>See Also<FN>
- <A TImageEnView.LayersAdd>
- <A TImageEnView.LayersInsert>
- <A TIELayerKind>
!!}
TIEPolylineLayer = class( TIELayer )
private
fPolyPoints: pointer; // array of TPoint. Coordinates are in bitmap pixels, they are never translated or resized.
// C++Builder doesn't work with fPolyPoints as PPointArray
fPolyPointCount: integer;
fPolyPointsAllocated: integer; // allocated Polyline points
fDrawnPoints: pointer;
fDrawnPointCount: integer;
fDrawnPointsAllocated: integer;
fPolylineClosed: boolean;
function GetBitmap : TIEBitmap; override;
procedure CopyToBitmapEx(var Dest: TIEBitmap;
CreateWidth : Integer; CreateHeight : Integer;
FastDrawing: Boolean;
EnableAlpha: Boolean; UseDisplayAR: Boolean;
UpdateSize: Boolean = False; EnlargeOnly: Boolean = False;
Zoom: Double = 1); override;
function GetAsSVG(): string; override;
function GetPoints(index: integer): TPoint;
function GetPointCount(): integer;
function GetLineColor(): TColor;
procedure SetLineColor(value: TColor);
function GetLineWidth(): Integer;
procedure SetLineWidth(value: Integer);
function GetFillColor(): TColor;
procedure SetFillColor(value: TColor);
procedure SetPolylineClosed(value: Boolean);
public
property PolylineClosed: Boolean read fPolylineClosed write SetPolylineClosed;
property Points[index: integer]: TPoint read GetPoints;
property PointCount: integer read GetPointCount;
// Style
property LineColor: TColor read GetLineColor write SetLineColor;
property LineWidth: Integer read GetLineWidth write SetLineWidth;
property FillColor: TColor read GetFillColor write SetFillColor;
constructor Create(Owner: TObject); override;
destructor Destroy; override;
procedure CopyToBitmap(var Dest: TIEBitmap; CreateWidth : Integer = -1; CreateHeight : Integer = -1; EnableAlpha: Boolean = True; UseDisplayAR: Boolean = True); override;
procedure LoadFromStream(Stream: TStream); override;
procedure SaveToStream(Stream: TStream; MetaOnly: Boolean = False; CompressionFormat: TIOFileType = -2); override;
procedure ClearAllPoints();
procedure SetPoints(Points: array of TPoint; ClosePolyline: Boolean); overload;
procedure SetPoints(Points: array of TPoint); overload;
procedure SetPoints(Shape: TIEShape; ClosePolyline: Boolean = True); overload;
procedure AddPoint(X, Y: integer);
procedure RemovePoint(Index: integer);
procedure SimplifyPolygon(MaxPoints: integer);
end;
{!!
<FS>TIETextLayer
<FM>Description<FN>
TImageEnView supports multiple layers, allowing the creation of a single image from multiple source images (which can be resized, rotated, moved, etc).
TIETextLayer is a descendent of <A TIELayer> that displays text.
<IMG help_images\TextLayers.gif>
Review the <L TIELayer>Layer Documentation</L> for a full description of layer support.
<FM>Methods and Properties<FN>
<TABLE2>
<R> <C_IMG_PROPERTY> <C><A TIELayer.AntiAlias></C> </R>
<R> <C_IMG_METHOD> <C><A TIETextLayer.ActivateEditor> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.AspectRatioLocked></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIETextLayer.Alignment> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.Assign></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIETextLayer.AutoSize> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.AlphaEdgeFeathering></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIETextLayer.BorderColor> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIETextLayer.BorderWidth> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIETextLayer.BorderShape> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.ClientAreaBox></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.ConvertToImageLayer></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.ConvXBmp2Scr></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.ConvXScr2Bmp></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.ConvYBmp2Scr></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.ConvYScr2Bmp></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.CopyToBitmap></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Cropped></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.DrawingInfo></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.DrawOuter></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIETextLayer.FillColor> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIETextLayer.FillColor2> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIETextLayer.FillGradient> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIETextLayer.Font> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.GetIndex></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.GetLayerMask></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.GetProperties></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Guid></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.GroupIndex></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Height></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Kind></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIETextLayer.Layout> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Locked></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Modified></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Name></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Opacity></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Operation></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.PreferredAspectRatio></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.RestoreAspectRatio></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.PosX></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.PosY></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIETextLayer.ReadOnly> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Rotate></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Selectable></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Selected></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.SetProperties></C> </R>
<R> <C_IMG_METHOD> <C><A TIETextLayer.SizeToText> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.Swap></C> </R>
<R> <C_IMG_METHOD> <C><A TIELayer.SupportsFeature></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Tag></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIETextLayer.Text> <IMG help_images\Star.gif></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Transparency></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.UserData></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.UserDataLen></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Visible></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.VisibleBox></C> </R>
<R> <C_IMG_PROPERTY> <C><A TIELayer.Width></C> </R>
</TABLE>
<IMG help_images\Star.gif> Unique to TIETextLayer
<FM>Examples<FC>
// Append a text layer
ImageEnView1.LayersAdd( ielkText );
TIETextLayer( ImageEnView1.CurrentLayer ).Text := 'This is a Text Layer';
TIETextLayer( ImageEnView1.CurrentLayer ).BorderColor := clBlack;
TIETextLayer( ImageEnView1.CurrentLayer ).BorderWidth := 1;
TIETextLayer( ImageEnView1.CurrentLayer ).FillColor := clWhite;
ImageEnView1.Update();
<IMG help_images\TextLayer.gif>
// Apply a "Paid" stamp to image
with ImageEnView1 do
begin
LayersAdd( 'PAID', 'Arial Black', 42, clRed, [fsBold] );
CurrentLayer.Rotate := 30;
TIETextLayer( CurrentLayer ).SizeToText();
CurrentLayer.PosX := IELayer_Pos_HCenter;
CurrentLayer.PosY := IELayer_Pos_VCenter;
LayersMergeAll();
end;
<FM>See Also<FN>
- <A TImageEnView.LayersAdd>
- <A TImageEnView.LayersInsert>
- <A TIELayerKind>
!!}
TIETextLayer = class( TIELayer )
private
fFont: TFont;
fText: string;
fAutoSize: boolean;
fBorderShape: TIEShape;
fAlignment: TIEAlignment;
fLayout: TIELayout;
fReadOnly: Boolean;
function GetBitmap : TIEBitmap; override;
procedure CopyToBitmapEx(var Dest: TIEBitmap;
CreateWidth : Integer; CreateHeight : Integer;
FastDrawing: Boolean;
EnableAlpha: Boolean; UseDisplayAR: Boolean;
UpdateSize: Boolean = False; EnlargeOnly: Boolean = False;
Zoom: Double = 1); override;
function GetAsSVG(): string; override;
procedure SetFont(const Value: TFont);
procedure SetText(const Value: string);
procedure SetAutoSize(const Value: boolean);
procedure SetReadOnly(const Value: boolean);
procedure SetBorderShape(const Value: TIEShape);
function GetBorderColor(): TColor;
procedure SetBorderColor(value: TColor);
function GetBorderWidth(): Integer;
procedure SetBorderWidth(value: Integer);
function GetFillColor(): TColor;
procedure SetFillColor(value: TColor);
function GetFillColor2(): TColor;
procedure SetFillColor2(value: TColor);
function GetFillGradient(): TIEGradientDir;
procedure SetFillGradient(value: TIEGradientDir);
procedure SetAlignment(value: TIEAlignment);
procedure SetLayout(value: TIELayout);
public
property Alignment: TIEAlignment read fAlignment write SetAlignment;
property Layout: TIELayout read fLayout write SetLayout;
// Style
property BorderColor: TColor read GetBorderColor write SetBorderColor;
property BorderWidth: Integer read GetBorderWidth write SetBorderWidth;
property FillColor: TColor read GetFillColor write SetFillColor;
property FillColor2: TColor read GetFillColor2 write SetFillColor2;
property FillGradient: TIEGradientDir read GetFillGradient write SetFillGradient;
property AutoSize: boolean read fAutoSize write SetAutoSize;
property Text: String read fText write SetText;
property Font: TFont read fFont write SetFont;
property BorderShape: TIEShape read fBorderShape write SetBorderShape;
property ReadOnly: Boolean read fReadOnly write SetReadOnly;
procedure ActivateEditor();
procedure SizeToText(EnlargeOnly: Boolean = False);
constructor Create(Owner: TObject); override;
destructor Destroy; override;
procedure CopyToBitmap(var Dest: TIEBitmap; CreateWidth : Integer = -1; CreateHeight : Integer = -1; EnableAlpha: Boolean = True; UseDisplayAR: Boolean = True); override;
procedure LoadFromStream(Stream: TStream); override;
procedure SaveToStream(Stream: TStream; MetaOnly: Boolean = False; CompressionFormat: TIOFileType = -2); override;
end;
function IESimplifyPolygon(tol: double; V: array of TPoint): TIEArrayOfTPoint;
procedure IECleanupLayers();
function IETryIEN(Stream: TStream): Boolean;
procedure IELayersMerge(Layer1, Layer2, LayerMask: TIELayer; Destination: TIEBitmap; ZoomFilter: TResampleFilter; Background: TColor; RelativePositions: Boolean; ForceCropLayer2: Boolean = False);
procedure ReadLayerPropsFromStream(Stream: TStream;
ResetPos: Boolean; // Position Stream after read to inital pos
out RecSize: Integer; // Total size of layer data block
out LayerKind: TIELayerKind; // Type of layer
out GUID: TGuid); // Layer identifier
type
TLayerHeader=packed record
Magic: array [0..12] of AnsiChar; // must be IELayers_File_Magic
Version: Integer; // must be IELayers_File_Version
FileFormat: TIOFileType;
LayersCount: Integer;
end;
const
IELayers_File_Version = 7003;
Layers_Thumbnail_Format = ioPNG;
{
10 (~ ImageEn 6.3.2)
- Legacy load format
- Last version that supported only layer types
7000 (unreleased):
- First version that is handled by TImageEnIO
- Contains thumbnail
- Supports layer kinds
7001 (unreleased):
- Add Tag property
7002 (unreleased):
- Changed linelayer storage to store line length
7003 (ImageEn 7.0.0):
- Store size of thumbnail
}
IELayers_File_Magic : AnsiString = 'IMAGEENLAYERS';
IELayer_Pos_Left = MaxInt - 11;
IELayer_Pos_HCenter = MaxInt - 10;
IELayer_Pos_Right = MaxInt - 9;
IELayer_Pos_Top = IELayer_Pos_Left;
IELayer_Pos_VCenter = IELayer_Pos_HCenter;
IELayer_Pos_Bottom = IELayer_Pos_Right;
implementation
uses
imageenview, math, imageenio, iexCanvasUtils, ietextc, iesettings, iexSVG
{$IfDef UNICODE}, AnsiStrings {$EndIf}
{$ifdef DelphiXE5orNewer},System.Types{$endif}
{$ifdef IEUSEVCLZLIB}, zlib{$else}, iezlib{$endif};
var
fGlobalCacheBitmap: TIEBitmap; // Image that is shared by all non-image layers
const
Zero_Alpha_Color = $0;
Full_Alpha_Color = $02FFFFFF;
function CoCreateGuid(out guid: TGUID): HResult; stdcall; external 'ole32.dll' name 'CoCreateGuid';
// Delete cache bitmap
procedure IECleanupLayers();
begin
if assigned( fGlobalCacheBitmap ) then
FreeAndNil( fGlobalCacheBitmap );
end;
{!!
<FS>IELayersMerge
<FM>Declaration<FC>
procedure IELayersMerge(Layer1, Layer2, LayerMask: <A TIELayer>; Destination: <A TIEBitmap>; ZoomFilter: <A TResampleFilter>; Background: TColor; RelativePositions: Boolean);
<FM>Description<FN>
Merges two layers to the destination bitmap.
ZoomFilter specifies the filter to use when layers needs to be stretched.
Background is the color used to fill empty regions.
LayerMask is the upper layer's mask. This can be 'nil' if no layer mask exists.
If RelativePositions = false the output layer should have posx = 0 and posy = 0 because the required space is added to the destination bitmap.
If ForceCropLayer2 = true, then any parts of Layer 2 lying outside of layer 1 will be cropped. If False, cropping will only occur if <A TIELayer.Cropped> is enabled.
<FM>Example<FC>
// this merges all layers of ImageEnView1 to tempIE (invisible), then saves to jpeg file
var
tempIE: TImageEnView;
tempBMP: TIEBitmap;
i: Integer;
begin
tempIE := TImageEnView.Create(nil);
tempIE.Layers[0].Bitmap.Assign( ImageEnView1.Layers[0].Bitmap );
tempBMP := TIEBitmap.Create;
for i := 1 to ImageEnView1.LayersCount-1 do
begin
IELayersMerge( tempIE.Layers[0], ImageEnView1.Layers[i], nil, tempBMP, rfNone, clBlack );
tempIE.Layers[0].Bitmap.Assign( tempBMP );
end;
tempBMP.free;
tempIE.Background := clBlack;
tempIE.RemoveAlphaChannel(true);
tempIE.IO.SaveToFile('output.jpg');
tempIE.free;
end;
!!}
procedure IELayersMerge(Layer1, Layer2, LayerMask: TIELayer; Destination: TIEBitmap; ZoomFilter: TResampleFilter; Background: TColor; RelativePositions: Boolean; ForceCropLayer2: Boolean = False);
var
// l0...is layer 0 (down layer)
// l1...is layer 1 (up layer)
// l2...is layer mask of layer 1
l0bitmap, l1bitmap, l2bitmap: TIEBitmap;
l0alpha, l1alpha: TIEBitmap;
l0transp, l1transp: integer;
l0palpha, l1palpha: pbyte;
l1transp255, l0transp255: double;
l1opacity, l0opacity: double;
l0prgb, l1prgb: PRGB;
l2pbyte: pbyte;
l0posx, l1posx, l2posx: integer;
l0posy, l1posy, l2posy: integer;
l0row, l1row, l2row: integer;
l0col, l1col, l2col: integer;
l1cropped: Boolean;
proc0, proc1: TImageEnProc;
l0width, l1width, l2width: integer;
l0height, l1height, l2height: integer;
outbitmap: TIEBitmap;
outalpha: TIEBitmap;
outwidth, outheight: Integer;
row, col: integer;
SimAlphaRow0, SimAlphaRow1: array of byte;
ConvRGBRow0, ConvRGBRow1: array of TRGB;
pdestalpha: pbyte;
pdest: PRGB;
aa, bb, cc, opt1: double;
maxwidth, maxheight: integer;
minposx, minposy, maxposx: Integer;
all0: array of byte;
allBak: array of TRGB;
vv: TRGB;
op: TIERenderOperation;
i, a, r, g, b: integer;
doFreeLayer1, doFreeLayer2: Boolean;
zf: TResampleFilter;
begin
doFreeLayer1 := False;
doFreeLayer2 := False;
// If Layer1 or Layer2 are not TIEImageLayer then they must be converted to a TIEImageLayer
if not ( Layer1 is TIEImageLayer ) then
begin
Layer1 := TIEImageLayer.create( Layer1.fOwner, Layer1 );
doFreeLayer1 := True;
end;
if not ( Layer2 is TIEImageLayer ) then
begin
Layer2 := TIEImageLayer.create( Layer2.fOwner, Layer2 );
doFreeLayer2 := True;
end;
l2Width := 0;
l2Height := 0;
op := Layer2.Operation;
proc0 := TImageEnProc.Create(nil);
proc1 := TImageEnProc.Create(nil);
proc0.AutoUndo := True;
proc1.AutoUndo := True;
l0bitmap := nil;
l1bitmap := nil;
l2bitmap := nil;
try
// layer 0 vars
l0bitmap := Layer1.Bitmap;
l0width := Layer1.Width;
l0height := Layer1.Height;
if (l0width <> l0bitmap.Width) or (l0height <> l0bitmap.Height) then
begin
// resize the layer
l0bitmap := TIEBitmap.Create;
proc0.AttachedIEBitmap := Layer1.Bitmap;
zf := ZoomFilter;
if TIEImageLayer( Layer1 ).UseResampleFilter then
zf := TIEImageLayer( Layer1 ).ResampleFilter;
proc0.ResampleTo(l0bitmap, l0width, l0height, zf);
end;
l0posx := Layer1.PosX;
l0posy := Layer1.PosY;
if l0bitmap.HasAlphaChannel then
l0alpha := l0bitmap.AlphaChannel
else
l0alpha := nil;
l0transp := Layer1.Transparency;
l0transp255 := l0transp / 255.0;
l0opacity := Layer1.Opacity;
SetLength(SimAlphaRow0, l0bitmap.Width);
FillChar(SimAlphaRow0[0], l0bitmap.Width, 255);
SetLength(ConvRGBRow0, l0bitmap.Width);
// layer 1 vars
l1bitmap := Layer2.Bitmap;
l1width := Layer2.Width;
l1height := Layer2.Height;
if ForceCropLayer2 then
l1cropped := true
else
l1cropped := Layer2.Cropped and not RelativePositions;
if (l1width <> l1bitmap.Width) or (l1height <> l1bitmap.Height) then
begin
// resize the layer
l1bitmap := TIEBitmap.Create;
proc1.AttachedIEBitmap := Layer2.Bitmap;
zf := ZoomFilter;
if TIEImageLayer( Layer2 ).UseResampleFilter then
zf := TIEImageLayer( Layer2 ).ResampleFilter;
proc1.ResampleTo(l1bitmap, l1width, l1height, zf);
end;
l1posx := Layer2.PosX;
l1posy := Layer2.PosY;
if l1bitmap.HasAlphaChannel then
l1alpha := l1bitmap.AlphaChannel
else
l1alpha := nil;
l1transp := Layer2.Transparency;
l1transp255 := l1transp / 255.0;
l1opacity := Layer2.Opacity;
SetLength(SimAlphaRow1, l1bitmap.Width);
FillChar(SimAlphaRow1[0], l1bitmap.Width, 255);
SetLength(ConvRGBRow1, l1bitmap.Width);
// layer mask vars (of layer 1)
if LayerMask <> nil then
begin
LayerMask.Bitmap.PixelFormat := ie8g; // in case it is not!
l2width := LayerMask.Width;
l2height := LayerMask.Height;
if (l2width <> LayerMask.Bitmap.Width) or (l2height <> LayerMask.Bitmap.Height) then
begin
// resize the layer
l2bitmap := TIEBitmap.Create;
l2bitmap.Allocate(l2width, l2height, ie8g);
_IEBmpStretchEx(LayerMask.Bitmap, l2bitmap, nil, nil);
end
else
l2bitmap := LayerMask.Bitmap;
l2posx := LayerMask.PosX;
l2posy := LayerMask.PosY;
end
else
begin
l2posx := 0;
l2posy := 0;
end;
// output vars
if l0posx < 0 then
begin
inc(l1posx, -l0posx);
inc(l2posx, -l0posx);
l0posx := 0;
end;
if l0posy < 0 then
begin
inc(l1posy, -l0posy);
inc(l2posy, -l0posy);
l0posy := 0;
end;
if (l1posx < 0) and not l1cropped then
begin
inc(l0posx, -l1posx);
inc(l2posx, -l1posx);
l1posx := 0;
end;
if (l1posy < 0) and not l1cropped then
begin
inc(l0posy, -l1posy);
inc(l2posy, -l1posy);
l1posy := 0;
end;
if l1cropped then
begin
maxwidth := l0width + l0posx;
maxheight := l0height + l0posy;
end
else
begin
maxwidth := imax(l0width + l0posx, l1width + l1posx);
maxheight := imax(l0height + l0posy, l1height + l1posy);
end;
if not l1cropped then // todo: @FAB: Please check this
begin
minposx := imin(l0posx, l1posx);
minposy := imin(l0posy, l1posy);
end
else
begin
// todo: @FAB: Changed this from 0,0 to handle layer 0 not being positioned at 0,0
// Not sure what the full effect of this will be
minposx := l0posx;
minposy := l0posy;
end;
outwidth := maxwidth - minposx;
outheight := maxheight - minposy;
outbitmap := Destination;
if (outwidth <> outbitmap.Width) or (outheight <> outbitmap.Height) or (outbitmap.PixelFormat <> ie24RGB) then
outbitmap.Allocate(outwidth, outheight, ie24RGB);
outalpha := outbitmap.AlphaChannel; // this creates alpha channel
outalpha.Full := false;
SetLength(all0, outwidth * 4);
FillChar(all0[0], outwidth * 4, 0);
// set background row
vv := TColor2TRGB(Background);
SetLength(allBak, outwidth * 2);
pdest := @allBak[0];
for i := 1 to outwidth do
begin
pdest^ := vv;
inc(pdest);
end;
// combine images
for row := minposy to minposy + outheight - 1 do
begin
// set layer 0 pointers
l0row := row - l0posy;
if (l0row >= 0) and (l0row < l0bitmap.Height) then
begin
if assigned(l0alpha) then
l0palpha := l0alpha.Scanline[l0row]
else
l0palpha := @SimAlphaRow0[0];
if l0bitmap.PixelFormat = ie24RGB then
l0prgb := l0bitmap.Scanline[l0row]
else
begin
// convert one row of l0bitmap to 24bit
_ConvRow1To24(l0bitmap.Scanline[l0row], pbyte(@ConvRGBRow0[0]), l0Width);
l0prgb := @ConvRGBRow0[0];
end;
end
else
begin
l0palpha := @all0[0];
l0prgb := @allBak[0];
end;
// set layer 1 pointers
l1row := row - l1posy;
if (l1row >= 0) and (l1row < l1Height) then
begin
if assigned(l1alpha) then
l1palpha := l1alpha.ScanLine[l1row]
else
l1palpha := @SimAlphaRow1[0];
if l1bitmap.PixelFormat = ie24RGB then
l1prgb := l1bitmap.Scanline[l1row]
else
begin
// convert one row of l1bitmap to 24bit
_ConvRow1To24(l1bitmap.Scanline[l1row], pbyte(@ConvRGBRow1[0]), l1Width);
l1prgb := @ConvRGBRow1[0];
end;
end
else
begin
l1palpha := @all0[0];
l1prgb := @allBak[0];
end;
// set layer mask pointers
if LayerMask <> nil then
begin
l2row := row - l2posy;
if (l2row >= 0) and (l2row < l2Height) then
l2pbyte := l2bitmap.Scanline[l2row]
else
l2pbyte := @all0[0];
end
else
begin
l2pbyte := @all0[0];
end;
// set output pointers
pdest := outbitmap.Scanline[row - minposy];
pdestalpha := outalpha.Scanline[row - minposy];
// main loop
l0col := minposx - l0posx;
l1col := minposx - l1posx;
l2col := minposx - l2posx;
maxposx := minposx + outwidth - 1;
if l1col > 0 then
begin
inc(l1prgb, l1col);
inc(l1palpha, l1col);
end;
if l2col > 0 then
inc(l2pbyte, l2col);
for col := minposx to maxposx do
begin
// combine pixels
if (l0col >= 0) and (l1col >= 0) and (l0col < l0Width) and (l1col < l1Width) then
begin
if l0palpha^ < l0transp then
aa := l0palpha^ / 255.0 * l0opacity
else
aa := l0transp255 * l0opacity;
if LayerMask <> nil then
begin
if (l2col >= 0) and (l2col < l2Width) then
begin
bb := imin(imin(l1palpha^, l2pbyte^), l1transp) / 255 * l1opacity;
inc(l2pbyte);
end
else
bb := 0.0;
end
else
begin
if l1palpha^ < l1transp then
bb := l1palpha^ / 255.0 * l1opacity
else
bb := l1transp255 * l1opacity;
end;
opt1 := (1.0 - bb) * aa;
cc := bb + opt1;
vv := l0prgb^;
if op = ielNormal then
vv := l1prgb^
else
IEBlend(l1prgb^, vv, op, row);
if cc <> 0.0 then
begin
r := round((bb * vv.r + opt1 * l0prgb^.r) / cc);
g := round((bb * vv.g + opt1 * l0prgb^.g) / cc);
b := round((bb * vv.b + opt1 * l0prgb^.b) / cc);
pdest^.r := blimit(r);
pdest^.g := blimit(g);
pdest^.b := blimit(b);
end
else
pdest^ := vv;
a := round(cc * 255.0);
pdestalpha^ := ilimit(a, 0, 255);
inc(l0palpha);
inc(l0prgb);
inc(l1palpha);
inc(l1prgb);
end
else
if (l0col >= 0) and (l0col < l0Width) then
begin
// copy only l0bitmap
pdest^ := l0prgb^;
pdestalpha^ := trunc(imin(l0palpha^, l0transp) * l0opacity);
inc(l0palpha);
inc(l0prgb);
end
else
if (l1col >= 0) and (l1col < l1Width) then
begin
// copy only l1bitmap
pdest^ := l1prgb^;
if LayerMask <> nil then
begin
if (l2col >= 0) and (l2col < l2Width) then
begin
pdestalpha^ := trunc(imin(imin(l1palpha^, l2pbyte^), l1transp) * l1opacity);
inc(l2pbyte);
end
else
pdestalpha^ := 0;
end
else
begin
if l1palpha^ < l1transp then
pdestalpha^ := trunc(l1palpha^ * l1opacity)
else
pdestalpha^ := trunc(l1transp * l1opacity);
end;
inc(l1palpha);
inc(l1prgb);
end
else
begin
// transparent area
pdestalpha^ := 0;
pdest^ := TColor2TRGB(Background);
end;
inc(pdest);
inc(pdestalpha);
inc(l0col);
inc(l1col);
inc(l2col);
end;
end;
// IELayersMerge should not change source bitmaps, but when proc0.ResampleTo or proc1.ResampleTo is called we need
// to restore original bitmaps
if proc0.CanUndo then
proc0.Undo;
if proc1.CanUndo then
proc1.Undo;
finally
FreeAndNil(proc0);
FreeAndNil(proc1);
if (LayerMask <> nil) and (LayerMask.Bitmap <> l2bitmap) then
FreeAndNil(l2Bitmap);
if l0bitmap <> Layer1.Bitmap then
l0bitmap.Free;
if l1bitmap <> Layer2.Bitmap then
l1bitmap.Free;
if doFreeLayer1 then
Layer1.Free;
if doFreeLayer2 then
Layer2.Free;
end;
// verify if outalpha is full and remove it if not needed
outalpha.SyncFull;
if outalpha.Full then
begin
// remove alpha
outbitmap.RemoveAlphaChannel;
end;
end;
// Returns true is Stream is a ImageEn Layers file
function IETryIEN(Stream: TStream): Boolean;
var
l: int64;
recHead: TLayerHeader;
begin
l := Stream.Position;
result := true;
Stream.Read(recHead, sizeof(TLayerHeader));
if ( {$IfDef DelphiXE4orNewer}AnsiStrings.{$EndIf} StrLComp(recHead.Magic, PAnsiChar(IELayers_File_Magic), length(IELayers_File_Magic)) <> 0) or (recHead.Version <= 0) then
result := false;
Stream.Position := l;
end;
procedure InitBitmap(var Bitmap: TIEBitmap; w, h: Integer; FillColor: TColor = clWhite);
begin
if assigned( Bitmap ) and (( Bitmap.Width <> w ) or ( Bitmap.Height <> h ) or (Bitmap.PixelFormat = ie32RGB)) then
FreeAndNil( Bitmap );
if not assigned( Bitmap ) then
Bitmap := TIEBitmap.Create( w, h, ie24RGB );
Bitmap.Fill( FillColor );
end;
procedure InitBitmapRGBA(var Bitmap: TIEBitmap; w, h: Integer);
begin
if assigned( Bitmap ) and (( Bitmap.Width <> w ) or ( Bitmap.Height <> h ) or (Bitmap.PixelFormat <> ie32RGB)) then
FreeAndNil( Bitmap );
if not assigned( Bitmap ) then
Bitmap := TIEBitmap.Create( w, h, ie32RGB );
Bitmap.Fill( clWhite ); // Note: Used as the blend color for the anti-aliasing of GDI+ objects
Bitmap.AlphaChannel.Fill(0);
end;
// Gradients only supported when Shape = iesRectangle
procedure IEDrawSimpleShape(Canvas: TIECanvas;
Left, Top, Width, Height: Integer;
BorderColor: TColor; BorderWidth: Integer;
FillColor: TColor; FillColor2: TColor = clNone_; FillGradient: TIEGradientDir = gdVertical;
Zoom: Double = 1;
Shape : TIEShape = iesRectangle;
AntiAlias: Boolean = True);
const
Rect_Rounding = 20;
var
drawGradient: Boolean;
prevSmoothingMode : TIECanvasSmoothingMode;
begin
if Shape <> iesRectangle then
FillColor2 := clNone_;
drawGradient := ( FillColor2 <> FillColor ) and ( FillColor <> clNone_ ) and ( FillColor2 <> clNone_ );
prevSmoothingMode := Canvas.SmoothingMode;
try
if AntiAlias then
Canvas.SmoothingMode := iesmAntialias
else
Canvas.SmoothingMode := iesmBestPerformance;
// Image has been scaled to zoom level, so ensure we scale the border too
if BorderColor = clNone_ then
BorderWidth := 0;
if BorderWidth > 0 then
BorderWidth := max( 1, Round( BorderWidth * Zoom ));
// Border
if ( BorderColor = clNone_ ) or ( BorderWidth < 1 ) then
Canvas.Pen.Style := psClear
else
Canvas.Pen.Style := psSolid;
Canvas.Pen.Color := BorderColor;
Canvas.Pen.Width := BorderWidth;
// Fill
if drawGradient or ( FillColor = clNone_ ) then
Canvas.Brush.Style := bsClear
else
Canvas.Brush.Style := bsSolid;
Canvas.Brush.Color := FillColor;
inc( Left , BorderWidth div 2 );
inc( Top , BorderWidth div 2 );
dec( Width , BorderWidth );
dec( Height, BorderWidth );
if drawGradient then
begin
Canvas.GradientFillRect( Rect( Left, Top, Left + Width - 1, Top + Height - 1), FillColor, FillColor2, FillGradient = gdVertical );
Canvas.Brush.Style := bsClear;
end;
case Shape of
iesEllipse : Canvas.Ellipse ( Left, Top, Left + Width, Top + Height );
iesRectangle : Canvas.Rectangle( Left, Top, Left + Width, Top + Height );
iesRoundRect : Canvas.RoundRect( Left, Top, Left + Width, Top + Height, Round( Rect_Rounding * Zoom ), Round( Rect_Rounding * Zoom ));
end;
finally
Canvas.SmoothingMode := prevSmoothingMode;
end;
end;
// draw text to the coordinates x1, y1, x2, y2 on Bitmap.IECanvas
function IEDrawText(Canvas: TIECanvas;
x1, y1, x2, y2: integer;
Zoom: double;
Text: WideString;
Font: TFont;
TextAlign: TIEAlignment;
TextLayout: TIELayout;
TextAngle: Integer;
BorderColor: TColor; BorderWidth: Integer;
FillColor: TColor; FillColor2: TColor; FillGradient: TIEGradientDir;
TextAutoSize: boolean;
AntiAlias: Boolean;
Shape : TIEShape;
EstimateSizeOnly: boolean = False
): TSize;
const
Maintain_Alignment_On_Rotate = True;
Shape_Border = 1; // Drawing too close to the boundary can affect transparency (No alpha). This will prevent it
var
borderPadding: Integer;
ox, oy: integer;
dx, dy: integer;
fa: double;
nx2, ny2: integer;
haveBorder: Boolean;
OutSize: TSize;
ellipseHPadding, ellipseVPadding : Integer;
wasTextRendering: TIETextRenderingHintMode;
begin
if Shape = iesEllipse then
begin
TextAlign := iejCenter;
TextLayout := ielCenter;
end;
wasTextRendering := Canvas.TextRendering;
try
if AntiAlias then
Canvas.TextRendering := ietrTextRenderingHintAntiAlias
else
Canvas.TextRendering := ietrTextRenderingHintSingleBitPerPixel;
haveBorder := ( BorderColor <> clNone_ ) and ( BorderWidth > 0 );
borderPadding := 0;
if haveBorder then
borderPadding := round((BorderWidth + 3) * Zoom );
while TextAngle < 0 do
TextAngle := TextAngle + 360;
Canvas.Font.Assign( Font );
Canvas.Font.Height := Round( Font.Height * Zoom );
if TextAutoSize or EstimateSizeOnly then
OutSize := Canvas.MeasureText( Text, True )
else
OutSize := Canvas.MeasureText( Text, rect( x1, y1, x2, y2 ), -TextAngle, True );
dx := OutSize.cX;
dy := OutSize.cY;
// Text can't be wider than object
if ( EstimateSizeOnly = False ) and ( TextAngle mod 180 = 0 ) and ( dx > x2 - x1 ) then
begin
while dx > x2 - x1 do
begin
SetLength( Text, Length( Text ) - 1 );
dx := Canvas.TextWidth( Text + '...' ) + 2 * borderPadding;
if Text = '' then
Break;
end;
Text := Text + '...';
end;
fa := IEDegreesToRadians( -TextAngle ); // angle in radians
nx2 := x2;
ny2 := y2;
if EstimateSizeOnly then
begin
nx2 := trunc(x1 + abs(dx * cos(fa)) + abs(dy * sin(fa))) + 3 * borderPadding; // 3 for overflow
ny2 := trunc(y1 + abs(dx * sin(fa)) + abs(dy * cos(fa))) + 2 * borderPadding;
end;
ox := 0;
case TextAlign of
iejLeft:
begin
if fa < PI / 2 then
ox := 0
else
if fa < PI then
ox := trunc(- dx * cos(fa))
else
if fa < PI * 3 / 2 then
ox := trunc(- dx * cos(fa) - dy * sin(fa))
else
if fa < PI * 2 then
ox := trunc(- dy * sin(fa));
inc( ox, x1 + borderPadding );
end;
iejRight:
begin
if fa < PI / 2 then
ox := trunc(nx2 - x1 - dx * cos(fa) - dy * sin(fa))
else
if fa < PI then
ox := trunc(nx2 - x1 - dy * sin(fa))
else
if fa < PI * 3 / 2 then
ox := trunc(nx2 - x1)
else
if fa < PI * 2 then
ox := trunc(nx2 - x1 - dx * cos(fa));
inc( ox, x1 - borderPadding );
end;
iejCenter, iejJustify:
begin
ox := x1 + trunc(nx2 - x1 - dx * cos(fa) - dy * sin(fa)) div 2;
end;
end;
case TextLayout of
ielBottom: oy := y1 + trunc(ny2 - abs(dx * sin(fa)) - abs(dy * cos(fa))) - borderPadding;
ielCenter: oy := y1 + trunc(ny2 - y1 - abs(dx * sin(fa)) - abs(dy * cos(fa))) div 2;
else { ielTop } oy := y1 + borderPadding;
end;
ellipseHPadding := 0;
ellipseVPadding := 0;
if EstimateSizeOnly and ( Shape = iesEllipse ) then
begin
// PAD SHAPE TO ALLOW SPACE FOR ELLIPSE
OutSize := Canvas.MeasureText( 'W', True );
ellipseHPadding := OutSize.cX;
ellipseVPadding := OutSize.cY;
end;
Result.cX := nx2 + 1 + ellipseHPadding;
Result.cY := ny2 + 1 + ellipseVPadding;
if not EstimateSizeOnly then
begin
// Draw border
if haveBorder or ( FillColor <> clNone_ ) then
IEDrawSimpleShape( Canvas,
x1, y1, x2 - x1 + 1, y2 - y1 + 1 - Shape_Border, // Just put at boundary
BorderColor, BorderWidth,
FillColor, FillColor2, FillGradient,
Zoom, Shape, AntiAlias );
// draw text
if Text <> '' then
begin
Canvas.Brush.Style := bsSolid;
Canvas.Brush.Color := Font.Color;
Canvas.DrawText( Text, rect( ox, oy, nx2, ny2 ), -TextAngle, True )
end;
end;
finally
Canvas.TextRendering := wasTextRendering;
end;
end;
// *************************************************************************************** //
// ** ** //
// ** TIELayer ** //
// ** ** //
// *************************************************************************************** //
constructor TIELayer.Create(Owner: TObject);
begin
inherited Create;
CoCreateGuid(fGUID);
fOwner := Owner;
fCachedLayerMask := nil;
fLayerCacheBitmap := nil;
fLayerCacheValid := False;
fOriginalAspectRatio := 0;
softShadow := TIEVSoftShadow.Create;
fModified := False;
end;
destructor TIELayer.Destroy;
begin
if fUserDataLen > 0 then
freemem(UserData);
if assigned(fCachedLayerMask) then
FreeAndNil(fCachedLayerMask);
FreeAndNil( fLayerCacheBitmap );
FreeAndNil( SoftShadow );
inherited Destroy;
end;
procedure TIELayer.LayerChange(ResetLayerCache: Boolean = True);
begin
fModified := True;
if ResetLayerCache then
fLayerCacheValid := False;
if assigned( fOwner ) then
TImageEnView( fOwner ).ImageChange();
end;
{!!
<FS>TIELayer.Modified
<FM>Declaration<FC>
property Modified: Boolean;
<FM>Description<FN>
Returns true if the layer has been changed since it was created or loaded.
<FM>Example<FC>
// Get list of changed layers
changedLayers := '';
for I := 0 to ImageEnView1.LayersCount -1 do
if ImageEnView1.Layers[I].Modified then
changedLayers := changedLayers + IntToStr( I ) + ', ';
// Mark all layers as unmodified
for I := 0 to ImageEnView1.LayersCount -1 do
ImageEnView1.Layers[I].Modified := False;
!!}
function TIELayer.GetModified(): Boolean;
begin
Result := fModified;
if ( Self is TIEImageLayer ) and TIEImageLayer(Self).fBitmap.Modified then
Result := True;
end;
procedure TIELayer.SetModified(value: Boolean);
begin
fModified := value;
if ( Value = False ) and ( Self is TIEImageLayer ) and
assigned( TIEImageLayer(Self).fBitmap ) then
TIEImageLayer(Self).fBitmap.Modified := False;
if value then
fLayerCacheValid := False;
end;
procedure TIELayer.SetDefaults;
procedure _InitFont(var Font: TFont; FontSize: Integer);
begin
Font.Charset := DEFAULT_CHARSET;
Font.Color := clBlack;
Font.Size := FontSize;
Font.Name := 'Arial';
Font.Style := [];
end;
begin
fVisible := true;
fTransparency := 255; // full opaque
fOpacity := 1.0; // full opaque
fPosX := 0;
fPosY := 0;
fClientAreaBox := Rect(0, 0, 0, 0);
fResizedWidth := 0;
fResizedHeight := 0;
fCropped := false;
fVisibleBox := true;
fSelectable := true;
fLocked := false;
fOperation := ielNormal;
UserData := nil;
fUserDataLen := 0;
IsMask := false;
fDrawOuter := false;
FillChar(fDrawingInfo, sizeof(fDrawingInfo), 0);
fRotate := 0;
fRotateCenterX := 0.5;
fRotateCenterY := 0.5;
fSelected := False;
fAlphaEdgeFeathering := 0;
fGroupIndex := 0;
fAspectRatioLocked := False;
fAntiAlias := True;
fLayerCacheValid := False;
with SoftShadow do
begin
Enabled := false;
Radius := 3;
OffsetX := 0;
OffsetY := 0;
Intensity := 100;
ShadowColor := CreateRGB(0, 0, 0);
end;
if Self is TIEImageLayer then
with TIEImageLayer( Self ) do
begin
fBorderColor := clNone_;
fBorderWidth := 1;
Magnify.Enabled := false;
Magnify.Rate := 2;
Magnify.Style := iemRectangle;
Magnify.Source := iemCanvas;
fResampleFilter := rfFastLinear;
fUseResampleFilter := False;
end
else
if Self is TIEShapeLayer then
with TIEShapeLayer( Self ) do
begin
fShape := iesEllipse;
fBorderColor := clBlack;
fBorderWidth := 1;
fFillColor := clRed;
fFillColor2 := clNone_;
fFillGradient := gdVertical;
fShapeModifier := 0;
end
else
if Self is TIELineLayer then
with TIELineLayer( Self ) do
begin
fAutoSize := True;
fLineColor := clBlack;
fLineWidth := 1;
fLineFillColor := clWhite;
fBorderColor := clBlack;
fBorderWidth := 1;
fFillColor := clWhite;
fFillColor2 := clNone_;
fFillGradient := gdVertical;
_InitFont( fLabelFont, 12 );
fLabelText := '';
fLabelAlignment := iejLeft;
fLabelPosition := ielpAtEnd;
fLabelShape := iesRectangle;
fReadOnly := False;
fEndShape := ieesNone;
fStartShape := ieesNone;
fShapeSize := 20;
end
else
if Self is TIEPolylineLayer then
with TIEPolylineLayer( Self ) do
begin
fBorderColor := clBlack;
fBorderWidth := 1;
fFillColor := clWhite;
fFillColor2 := clNone_;
fFillGradient := gdVertical;
fPolylineClosed := False;
ClearAllPoints();
end
else
if Self is TIETextLayer then
with TIETextLayer( Self ) do
begin
_InitFont( fFont, 14 );
fBorderColor := clNone_;
fBorderWidth := 1;
fFillColor := clNone_;
fFillColor2 := clNone_;
fFillGradient := gdVertical;
fBorderShape := iesRectangle;
fText := IEGlobalSettings().DefaultLayerText;
fAutoSize := False;
fReadOnly := False;
fAlignment := iejLeft;
fLayout := ielTop;
end;
end;
{!!
<FS>TIELayer.BorderColor
<FM>Declaration<FC>
property BorderColor: TColor;
<FM>Description<FN>
Provides generic access to the color of the border/line of the layer.
<FC>BorderColor<FN> accesses the following properties:
<TABLE>
<R> <H>Class</H> <H>Property</H> </R>
<R> <C> <A TIEImageLayer> </C> <C><A TIEImageLayer.BorderColor></C> </R>
<R> <C> <A TIEShapeLayer> </C> <C><A TIEShapeLayer.BorderColor></C> </R>
<R> <C> <A TIELineLayer> </C> <C><A TIELineLayer.LineColor> (also sets <A TIELineLayer.LabelBorderColor>)</C> </R>
<R> <C> <A TIEPolylineLayer> </C> <C><A TIEPolylineLayer.LineColor></C> </R>
<R> <C> <A TIETextLayer> </C> <C><A TIETextLayer.BorderColor></C> </R>
</TABLE>
<FM>Examples<FC>
// Load an image layer and assign a pink border
ImageEnView1.LayersAdd( ielkImage ); // Append an image layer
ImageEnView1.IO.LoadFromFile('C:\New Zealand.jpg'); // Load image into the new/active layer
ImageEnView1.CurrentLayer.BorderColor := $008000FF;
ImageEnView1.CurrentLayer.BorderWidth := 3;
ImageEnView1.Update();
<IMG help_images\Image_withBorder.gif>
// Set style properties to an orange border with yellow fill
ImageEnView1.CurrentLayer.BorderColor := $004080FF;
ImageEnView1.CurrentLayer.BorderWidth := 2;
ImageEnView1.CurrentLayer.FillColor := clYellow;
ImageEnView1.Update();
<IMG help_images\Polyline_WithBorder.gif>
// Remove the border...
ImageEnView1.CurrentLayer.BorderWidth := 0;
ImageEnView1.Update();
<IMG help_images\Polyline_NoBorder.gif>
<FM>See Also<FN>
- <L TIELayer.BorderColor>TIELayer.BorderWidth</L>
!!}
function TIELayer.GetBorderColor: TColor;
begin
if Kind = ielkLine then
Result := TIELineLayer( Self ).fLineColor
else
Result := fBorderColor;
end;
procedure TIELayer.SetBorderColor(value: TColor);
begin
fBorderColor := Value;
if Kind = ielkLine then
TIELineLayer( Self ).fLineColor := Value;
LayerChange();
end;
{!!
<FS>TIELayer.BorderWidth
<FM>Declaration<FC>
property BorderWidth: Integer;
<FM>Description<FN>
Provides generic access to the width of the border/line of the layer.
<FC>BorderWidth<FN> accesses the following properties:
<TABLE>
<R> <H>Class</H> <H>Property</H> </R>
<R> <C> <A TIEImageLayer> </C> <C><A TIEImageLayer.BorderWidth></C> </R>
<R> <C> <A TIEShapeLayer> </C> <C><A TIEShapeLayer.BorderWidth></C> </R>
<R> <C> <A TIELineLayer> </C> <C><A TIELineLayer.LineWidth> (also sets <A TIELineLayer.LabelBorderWidth>)</C> </R>
<R> <C> <A TIEPolylineLayer> </C> <C><A TIEPolylineLayer.LineWidth></C> </R>
<R> <C> <A TIETextLayer> </C> <C><A TIETextLayer.BorderWidth></C> </R>
</TABLE>
<FM>Example<FC>
// Load an image layer and assign a pink border
ImageEnView1.LayersAdd( ielkImage ); // Append an image layer
ImageEnView1.IO.LoadFromFile('C:\New Zealand.jpg'); // Load image into the new/active layer
ImageEnView1.CurrentLayer.BorderColor := $008000FF;
ImageEnView1.CurrentLayer.BorderWidth := 3;
ImageEnView1.Update();
<IMG help_images\Image_withBorder.gif>
// Set style properties to an orange border with yellow fill
ImageEnView1.CurrentLayer.BorderColor := $004080FF;
ImageEnView1.CurrentLayer.BorderWidth := 2;
ImageEnView1.CurrentLayer.FillColor := clYellow;
ImageEnView1.Update();
<IMG help_images\Polyline_WithBorder.gif>
// Remove the border...
ImageEnView1.CurrentLayer.BorderWidth := 0;
ImageEnView1.Update();
<IMG help_images\Polyline_NoBorder.gif>
<FM>See Also<FN>
- <L TIELayer.BorderColor>TIELayer.BorderColor</L>
!!}
function TIELayer.GetBorderWidth(): Integer;
begin
if Kind = ielkLine then
Result := TIELineLayer( Self ).fLineWidth
else
Result := fBorderWidth;
end;
procedure TIELayer.SetBorderWidth(value: Integer);
begin
fBorderWidth := Value;
if Kind = ielkLine then
TIELineLayer( Self ).fLineWidth := Value;
LayerChange();
end;
{!!
<FS>TIELayer.FillColor
<FM>Declaration<FC>
property FillColor: TColor;
<FM>Description<FN>
Provides generic access to the fill color of the layer. Set to clNone for no fill (i.e. transparent background)
<FC>FillColor<FN> accesses the following properties:
<TABLE>
<R> <H>Class</H> <H>Property</H> </R>
<R> <C> <A TIEImageLayer> </C> <C> N/A </C> </R>
<R> <C> <A TIEShapeLayer> </C> <C><A TIEShapeLayer.FillColor></C> </R>
<R> <C> <A TIELineLayer> </C> <C><A TIELineLayer.FillColor> (also sets <A TIELineLayer.LabelFillColor>)</C> </R>
<R> <C> <A TIEPolylineLayer> </C> <C><A TIEPolylineLayer.FillColor></C> </R>
<R> <C> <A TIETextLayer> </C> <C><A TIETextLayer.FillColor></C> </R>
</TABLE>
<FM>Example<FC>
// Set fill color for a shape to yellow
ImageEnView1.CurrentLayer.FillColor := clYellow;
ImageEnView1.Update();
<IMG help_images\Shape_WithFill.jpg>
// Remove fill color from shape
ImageEnView1.CurrentLayer.FillColor := clNone;
ImageEnView1.Update();
<IMG help_images\Shape_NoFill.jpg>
<FM>See Also<FN>
- <L TIELayer.BorderColor>TIELayer.FillColor2</L>
- <L TIELayer.BorderColor>TIELayer.FillGradient</L>
!!}
function TIELayer.GetFillColor(): TColor;
begin
if Kind = ielkLine then
Result := TIELineLayer( Self ).fLineFillColor
else
Result := fFillColor;
end;
procedure TIELayer.SetFillColor(value: TColor);
begin
fFillColor := Value;
if Kind = ielkLine then
TIELineLayer( Self ).fLineFillColor := Value;
LayerChange();
end;
{!!
<FS>TIELayer.FillColor2
<FM>Declaration<FC>
property FillColor2: TColor;
<FM>Description<FN>
Provides generic access to the secondary gradient fill color of the layer.
If <FC>FillColor2<FN> is clNone, the layer is filled by a solid color specified by <A TIELayer.FillColor>. If <FC>FillColor2<FN> is different from <A TIELayer.FillColor> it is drawn as a gradient.
The direction of the gradient is specified by <A TIELayer.FillGradient>.
<FC>FillColor2<FN> accesses the following properties:
<TABLE>
<R> <H>Class</H> <H>Property</H> </R>
<R> <C> <A TIEImageLayer> </C> <C> N/A </C> </R>
<R> <C> <A TIEShapeLayer> </C> <C><A TIEShapeLayer.FillColor2></C> </R>
<R> <C> <A TIELineLayer> </C> <C><A TIELineLayer.LabelFillColor2></C> </R>
<R> <C> <A TIEPolylineLayer> </C> <C> N/A </C> </R>
<R> <C> <A TIETextLayer> </C> <C><A TIETextLayer.FillColor2></C> </R>
</TABLE>
<FM>Example<FC>
// Set a vertical gradient fill for an ellipse
ImageEnView1.CurrentLayer.FillColor2 := clRed;
ImageEnView1.CurrentLayer.FillColor := clYellow;
ImageEnView1.CurrentLayer.FillGradient := clVertical;
ImageEnView1.CurrentLayer.BorderWidth := 0;
ImageEnView1.Update();
<IMG help_images\Shape_Ellipse.gif>
// Set a horizontal gradient fill for the label of a line layer
ImageEnView1.CurrentLayer.FillColor := clRed;
ImageEnView1.CurrentLayer.FillColor2 := clYellow;
ImageEnView1.CurrentLayer.FillGradient := clHorizontal;
ImageEnView1.CurrentLayer.BorderColor := clBlack;
ImageEnView1.CurrentLayer.BorderWidth := 3;
ImageEnView1.Update();
<IMG help_images\Line_withLabel.gif>
<FM>See Also<FN>
- <L TIELayer.BorderColor>TIELayer.FillColor</L>
- <L TIELayer.BorderColor>TIELayer.FillGradient</L>
!!}
procedure TIELayer.SetFillColor2(value: TColor);
begin
fFillColor2 := Value;
LayerChange();
end;
{!!
<FS>TIELayer.FillGradient
<FM>Declaration<FC>
property FillGradient: <A TIEGradientDir>;
<FM>Description<FN>
Provides generic access to the gradient fill direction for the layer.
<FC>FillGradient<FN> accesses the following properties:
<TABLE>
<R> <H>Class</H> <H>Property</H> </R>
<R> <C> <A TIEImageLayer> </C> <C> N/A </C> </R>
<R> <C> <A TIEShapeLayer> </C> <C><A TIEShapeLayer.FillGradient></C> </R>
<R> <C> <A TIELineLayer> </C> <C><A TIELineLayer.LabelFillGradient></C> </R>
<R> <C> <A TIEPolylineLayer> </C> <C> N/A </C> </R>
<R> <C> <A TIETextLayer> </C> <C><A TIETextLayer.FillGradient></C> </R>
</TABLE>
<FM>Example<FC>
// Set a vertical gradient fill for an ellipse
ImageEnView1.CurrentLayer.FillColor2 := clRed;
ImageEnView1.CurrentLayer.FillColor := clYellow;
ImageEnView1.CurrentLayer.FillGradient := clVertical;
ImageEnView1.CurrentLayer.BorderWidth := 0;
ImageEnView1.Update();
<IMG help_images\Shape_Ellipse.gif>
// Set a horizontal gradient fill for the label of a line layer
ImageEnView1.CurrentLayer.FillColor := clRed;
ImageEnView1.CurrentLayer.FillColor2 := clYellow;
ImageEnView1.CurrentLayer.FillGradient := clHorizontal;
ImageEnView1.CurrentLayer.BorderColor := clBlack;
ImageEnView1.CurrentLayer.BorderWidth := 3;
ImageEnView1.Update();
<IMG help_images\Line_withLabel.gif>
<FM>See Also<FN>
- <L TIELayer.BorderColor>TIELayer.FillColor</L>
- <L TIELayer.BorderColor>TIELayer.FillColor2</L>
!!}
procedure TIELayer.SetFillGradient(value: TIEGradientDir);
begin
fFillGradient := value;
LayerChange();
end;
{!!
<FS>TIELayer.GroupIndex
<FM>Declaration<FC>
property GroupIndex: Integer;
<FM>Description<FN>
Specifies the Group ID of the layer. When a layer is selected all other layers with the same group ID are automatically selected too.
<FC>GroupIndex<FN> can be any value. A <FC>GroupIndex<FN> of 0 means the layer is not grouped.
Note: <FC>GroupIndex<FN> is only valid if <L TImageEnView.LayerOptions>multiple layer selection</L> is enabled.
<FM>Example<FC>
// Group all layers (except background)
ImageEnView1.LockUpdate();
for i := 1 to ImageEnView1.LayersCount - 1 do
ImageEnView1.Layers[ I ].GroupIndex := Random( Max_Int );
ImageEnView1.UnlockUpdate();
// Ungroup all layers
ImageEnView1.LockUpdate();
for i := 0 to ImageEnView1.LayersCount - 1 do
ImageEnView1.Layers[ I ].GroupIndex := 0;
ImageEnView1.UnlockUpdate();
<FM>See Also<FN>
- <A TImageEnView.LayersGroup>
- <A TImageEnView.LayersUngroup>
!!}
// Note: calls update
procedure TIELayer.SetGroupIndex(const Value: Integer);
var
ieview: TImageEnView;
i: Integer;
begin
fGroupIndex := Value;
ieview := (fOwner as TImageEnView);
if assigned(ieview) then
begin
if value <> 0 then
begin
// if selected then select all other members of this group
if fSelected then
ieview.SelectByGroupIndex( Value, True, False )
else
// If others of group are already selected then select this layer
for i := 0 to ieview.LayersCount - 1 do
if ieview.Layers[ i ].GroupIndex = Value then
begin
if ieview.Layers[ i ].Selected then
fSelected := True;
Break;
end;
end;
ieview.Update;
end;
LayerChange( False );
end;
{!!
<FS>TIELayer.Assign
<FM>Declaration<FC>
procedure Assign(Source: <A TIELayer>);
<FM>Description<FN>
Copy the content of a layer to the current one.
<FM>Example<FC>
// Assign layers from one ImageEnView to another
// Note: ImageEnView2.assign( ImageEnView1 ) will assign all content including layers
for I := 0 to ImageEnView1.LayersCount - 1 do
begin
iLayer := ImageEnView2.LayersAdd; // append a new layer
ImageEnView2.Layers[ iLayer ].Assign( ImageEnView1.Layers[ i ] );
end;
ImageEnView2.Update();
!!}
procedure TIELayer.Assign(Source: TIELayer);
begin
fResizedWidth := Source.fResizedWidth;
fResizedHeight := Source.fResizedHeight;
fVisible := Source.fVisible;
fVisibleBox := Source.fVisibleBox;
fSelectable := Source.fSelectable;
fTransparency := Source.fTransparency;
fOpacity := Source.fOpacity;
PosX := Source.PosX;
PosY := Source.PosY;
fClientAreaBox := Source.fClientAreaBox;
fCropped := Source.fCropped;
fLocked := Source.fLocked;
fOperation := Source.fOperation;
// Do not copy user data (UserData may contain objects or memory buffer that will never get freed)
// UserData := Source.UserData;
// UserDataLen := Source.UserDataLen;
fUserDataLen := 0;
fName := Source.fName;
fIsMask := Source.fIsMask;
fDrawOuter := Source.fDrawOuter;
fAlphaEdgeFeathering := Source.fAlphaEdgeFeathering;
fGroupIndex := Source.fGroupIndex;
fSelected := Source.fSelected;
fAspectRatioLocked := Source.fAspectRatioLocked;
fBorderColor := Source.fBorderColor;
fBorderWidth := Source.fBorderWidth;
fFillColor := Source.fFillColor;
fFillColor2 := Source.fFillColor2;
fFillGradient := Source.fFillGradient;
fRotate := Source.fRotate;
fAntiAlias := Source.fAntiAlias;
fOriginalAspectRatio := Source.fOriginalAspectRatio;
fRotateCenterX := Source.fRotateCenterX;
fRotateCenterY := Source.fRotateCenterY;
// Soft shadow
SoftShadow.Assign( Source.SoftShadow );
if ( Self is TIEImageLayer ) and ( Source is TIEImageLayer ) then
with TIEImageLayer( Self ) do
begin
fBitmap.Assign( TIEImageLayer( Source ).fBitmap);
Magnify := TIEImageLayer( Source ).Magnify;
fResampleFilter := TIEImageLayer( Source ).fResampleFilter;
fUseResampleFilter := TIEImageLayer( Source ).fUseResampleFilter;
end
else
if ( Self is TIEShapeLayer ) and ( Source is TIEShapeLayer ) then
with TIEShapeLayer( Self ) do
begin
fShape := TIEShapeLayer( Source ).fShape;
fShapeModifier := TIEShapeLayer( Source ).fShapeModifier;
end
else
if ( Self is TIELineLayer ) and ( Source is TIELineLayer ) then
with TIELineLayer( Self ) do
begin
fAutoSize := TIELineLayer( Source ).fAutoSize;
fLineColor := TIELineLayer( Source ).fLineColor;
fLineWidth := TIELineLayer( Source ).fLineWidth;
fLineFillColor := TIELineLayer( Source ).fLineFillColor;
fLabelFont.Assign( TIELineLayer( Source ).fLabelFont );
fLabelText := TIELineLayer( Source ).fLabelText;
fLabelAlignment := TIELineLayer( Source ).fLabelAlignment;
fLabelPosition := TIELineLayer( Source ).fLabelPosition;
fLabelShape := TIELineLayer( Source ).fLabelShape;
fReadOnly := TIELineLayer( Source ).fReadOnly;
fEndShape := TIELineLayer( Source ).fEndShape;
fShapeSize := TIELineLayer( Source ).fShapeSize;
fStartShape := TIELineLayer( Source ).fStartShape;
fLastLineLength := TIELineLayer( Source ).fLastLineLength;
end
else
if ( Self is TIEPolylineLayer ) and ( Source is TIEPolylineLayer ) then
with TIEPolylineLayer( Self ) do
begin
fPolyPointCount := TIEPolylineLayer( Source ).fPolyPointCount;
fPolyPointsAllocated := fPolyPointCount; // allocates only actually necessary items
getmem( fPolyPoints, fPolyPointCount * sizeof(TPoint));
copymemory( fPolyPoints, TIEPolylineLayer( Source ).fPolyPoints, fPolyPointCount * sizeof(TPoint));
fPolylineClosed := TIEPolylineLayer( Source ).fPolylineClosed;
end
else
if ( Self is TIETextLayer ) and ( Source is TIETextLayer ) then
with TIETextLayer( Self ) do
begin
Font.Assign( TIETextLayer( Source ).Font );
fBorderShape := TIETextLayer( Source ).fBorderShape;
fText := TIETextLayer( Source ).fText;
fAutoSize := TIETextLayer( Source ).fAutoSize;
fReadOnly := TIETextLayer( Source ).fReadOnly;
fAlignment := TIETextLayer( Source ).fAlignment;
fLayout := TIETextLayer( Source ).fLayout;
end;
LayerChange();
end;
{!!
<FS>TIELayer.GetProperties
<FM>Declaration<FC>
procedure GetProperties(Props: TStrings);
<FM>Description<FN>
Returns all properties of the layer as a list of Name=Value pairs.
Names will be drawn from the <A TIELayer Property Consts>. Changes made to the list can be applied using <A TIELayer.SetProperties>.
<FM>Sample Output<FC>
IELP_BorderColor=clNone
IELP_BorderWidth=0
IELP_FillColor=clYellow
IELP_FillColor2=clRed
IELP_FillGradient=1
IELP_Rotate=0
<FM>Example<FC>
// Save properties of the current layer to a file
ss := TStringList.create();
ImageEnView1.CurrentLayer.GetProperties( ss );
ss.SaveToFile( 'D:\CurrentLayer.txt' );
ss.Free();
<FM>See Also<FN>
- <A TIELayer.SetProperties>
- <A TImageEnView.LayerDefaults>
!!}
procedure TIELayer.GetProperties(Props: TStrings);
procedure _WriteProp(const Prop, Value: string);
begin
Props.Add( Prop + '=' + Value );
end;
procedure _WritePropI(const Prop: string; Value: Integer);
begin
Props.Add( Prop + '=' + IntToStr( Value ));
end;
procedure _WritePropB(const Prop: string; Value: Boolean);
begin
if Value then
Props.Add( Prop + '=True' )
else
Props.Add( Prop + '=False' );
end;
procedure _WritePropD(const Prop: string; Value: Double);
begin
Props.Add( Prop + '=' + FloatToStr( Value ));
end;
procedure _WritePropC(const Prop: string; Value: TColor);
begin
Props.Add( Prop + '=' + ColorToString( Value ));
end;
var
I: Integer;
pointStr: string;
begin
Props.Clear();
_WritePropI( IELP_Width , Width );
_WritePropI( IELP_Height , Height );
_WritePropB( IELP_Visible , fVisible );
_WritePropB( IELP_VisibleBox , fVisibleBox );
_WritePropB( IELP_Selectable , fSelectable );
_WritePropI( IELP_Transparency , fTransparency );
_WritePropD( IELP_Opacity , fOpacity );
_WritePropI( IELP_PosX , PosX );
_WritePropI( IELP_PosY , PosY );
_WritePropB( IELP_Cropped , fCropped );
_WritePropB( IELP_Locked , fLocked );
_WritePropI( IELP_Operation , ord( fOperation ));
_WriteProp( IELP_Name , fName );
_WritePropB( IELP_IsMask , fIsMask );
_WritePropB( IELP_DrawOuter , fDrawOuter );
_WritePropI( IELP_AlphaEdgeFeathering, fAlphaEdgeFeathering );
_WritePropI( IELP_GroupIndex , fGroupIndex );
_WritePropB( IELP_Selected , fSelected );
_WritePropB( IELP_AspectRatioLocked, fAspectRatioLocked );
_WritePropC( IELP_BorderColor , fBorderColor );
_WritePropI( IELP_BorderWidth , fBorderWidth );
_WritePropC( IELP_FillColor , fFillColor );
_WritePropC( IELP_FillColor2 , fFillColor2 );
_WritePropI( IELP_FillGradient , ord( fFillGradient ));
_WritePropB( IELP_AntiAlias , fAntiAlias );
_WritePropD( IELP_Rotate , fRotate );
_WritePropD( IELP_RotateCenterX , fRotateCenterX );
_WritePropD( IELP_RotateCenterY , fRotateCenterY );
// Soft shadow
with SoftShadow do
begin
_WritePropB( IELP_SoftShadowEnabled , Enabled );
_WritePropD( IELP_SoftShadowRadius , Radius );
_WritePropI( IELP_SoftShadowOffsetX , OffsetX );
_WritePropI( IELP_SoftShadowOffsetY , OffsetY );
_WritePropI( IELP_SoftShadowIntensity , Intensity );
_WritePropC( IELP_SoftShadowColor , TRGB2TColor( ShadowColor ));
end;
if Self is TIEImageLayer then
with TIEImageLayer( Self ) do
begin
_WritePropI( IELP_ImageResampleFilter , ord( fResampleFilter ));
_WritePropB( IELP_ImageUseResampleFilter , fUseResampleFilter );
end
else
if Self is TIEShapeLayer then
with TIEShapeLayer( Self ) do
begin
_WritePropI( IELP_Shape , ord( fShape ));
_WritePropI( IELP_ShapeModifier , fShapeModifier );
end
else
if Self is TIELineLayer then
with TIELineLayer( Self ) do
begin
_WritePropC( IELP_LineColor , fLineColor );
_WritePropI( IELP_LineWidth , fLineWidth );
_WritePropC( IELP_LineFillColor , fLineFillColor );
_WriteProp( IELP_FontName , fLabelFont.Name );
_WritePropI( IELP_FontSize , fLabelFont.Size );
_WritePropC( IELP_FontColor , fLabelFont.Color );
_WriteProp( IELP_LabelText , fLabelText );
_WritePropI( IELP_LabelAlignment , ord( fLabelAlignment ));
_WritePropI( IELP_LabelPosition , ord( fLabelPosition ));
_WritePropI( IELP_BorderShape , ord( fLabelShape ));
_WritePropB( IELP_ReadOnly , fReadOnly );
_WritePropI( IELP_LineEndShape , ord( fEndShape ));
_WritePropI( IELP_LineShapeSize , fShapeSize );
_WritePropI( IELP_LineStartShape , ord( fStartShape ));
_WritePropI( IELP_LineLength , Round( fLineLength ));
end
else
if Self is TIEPolylineLayer then
with TIEPolylineLayer( Self ) do
begin
pointStr := '';
for I := 0 to PointCount - 1 do
pointStr := pointStr + IntToStr( Points[ i ].X ) + ',' + IntToStr( Points[ i ].Y ) + ',';
if pointStr <> '' then
SetLength( pointStr, Length( pointStr ) - 1 );
_WriteProp( IELP_PolylinePoints , pointStr );
_WritePropB( IELP_PolylineClosed , fPolylineClosed );
end
else
if Self is TIETextLayer then
with TIETextLayer( Self ) do
begin
_WriteProp( IELP_FontName , Font.Name );
_WritePropI( IELP_FontSize , Font.Size );
_WritePropC( IELP_FontColor , Font.Color );
_WritePropI( IELP_BorderShape , ord( fBorderShape ));
_WriteProp( IELP_Text , fText );
_WritePropB( IELP_AutoSize , fAutoSize );
_WritePropB( IELP_ReadOnly , fReadOnly );
_WritePropI( IELP_TextAlignment , ord( fAlignment ));
_WritePropI( IELP_TextLayout , ord( fLayout ));
end;
end;
{!!
<FS>TIELayer.SetProperties
<FM>Declaration<FC>
procedure GetProperties(Props: TStrings);
<FM>Description<FN>
Sets properties of the layer using a list of Name=Value pairs.
Names will be drawn from the <A TIELayer Property Consts>. Properties can be retrieved using <A TIELayer.GetProperties>.
<FM>Sample Input<FC>
IELP_BorderColor=clNone
IELP_BorderWidth=0
IELP_FillColor=clYellow
IELP_FillColor2=clRed
IELP_FillGradient=1
IELP_Rotate=0
<FM>Examples<FC>
// Set properties of the current using a file
ss := TStringList.create();
ss.LoadFromFile( 'D:\CurrentLayer.txt' );
ImageEnView1.CurrentLayer.SetProperties( ss );
ImageEnView1.Update();
ss.Free();
// Apply a thick green border to all selected layers
ss := TStringList.create();
ss.Add( IELP_BorderColor + '=clGreen' );
ss.Add( IELP_BorderWidth + '=10' );
for i := 0 to ImageEnView1.LayersCount - 1 do
if ImageEnView1.Layers[ I ].Selected then
ImageEnView1.Layers[ I ].SetProperties( ss );
ImageEnView1.Update();
ss.Free();
<FM>See Also<FN>
- <A TIELayer.GetProperties>
- <A TImageEnView.LayerDefaults>
- <A TImageEnView.LayersSetProperties>
!!}
procedure TIELayer.SetProperties(Props: TStrings);
var
i, P: Integer;
propName, propValue: string;
begin
for i := 0 to Props.Count - 1 do
begin
propName := Props[ i ];
P := AnsiPos( {$ifdef Delphi7orNewer}Props.NameValueSeparator{$else}'='{$endif}, propName );
if P <> 0 then
SetLength( propName, P - 1 )
else
propName := '';
propValue := Copy( Props[ i ], Length( propName ) + 2, MaxInt );
SetProperties( propName, propValue );
end;
end;
procedure TIELayer.SetProperties(PropName, Value: String);
function _IsProp(const Prop: string): Boolean;
begin
Result := CompareText( Prop, PropName ) = 0;
end;
function _GetNextPoint(var Points: string) : integer;
var
idx: Integer;
begin
idx := pos( ',', Points );
Result := StrToInt( Copy( Points, 1, idx - 1 ));
Delete( Points, 1, idx );
end;
var
pointStr: string;
begin
PropName := Trim( propName );
Value := Trim( Value );
if PropName <> '' then
try
if _IsProp( IELP_LAYER_CACHE_CLEAR ) then
FreeAndNil( fLayerCacheBitmap )
else
if _IsProp( IELP_Width ) then
Width := StrToInt( Value )
else
if _IsProp( IELP_Height ) then
Height := StrToInt( Value )
else
if _IsProp( IELP_Visible ) then
fVisible := IEStr2BoolS( Value )
else
if _IsProp( IELP_VisibleBox ) then
fVisibleBox := IEStr2BoolS( Value )
else
if _IsProp( IELP_Selectable ) then
fSelectable := IEStr2BoolS( Value )
else
if _IsProp( IELP_Transparency ) then
fTransparency := StrToInt( Value )
else
if _IsProp( IELP_Opacity ) then
fOpacity := StrToFloat( Value )
else
if _IsProp( IELP_PosX ) then
PosX := StrToInt( Value )
else
if _IsProp( IELP_PosY ) then
PosY := StrToInt( Value )
else
if _IsProp( IELP_Cropped ) then
fCropped := IEStr2BoolS( Value )
else
if _IsProp( IELP_Locked ) then
fLocked := IEStr2BoolS( Value )
else
if _IsProp( IELP_Operation ) then
fOperation := TIERenderOperation( StrToInt( Value ))
else
if _IsProp( IELP_Name ) then
fName := Value
else
if _IsProp( IELP_IsMask ) then
fIsMask := IEStr2BoolS( Value )
else
if _IsProp( IELP_DrawOuter ) then
fDrawOuter := IEStr2BoolS( Value )
else
if _IsProp( IELP_AlphaEdgeFeathering ) then
fAlphaEdgeFeathering := StrToInt( Value )
else
if _IsProp( IELP_GroupIndex ) then
fGroupIndex := StrToInt( Value )
else
if _IsProp( IELP_Selected ) then
fSelected := IEStr2BoolS( Value )
else
if _IsProp( IELP_AspectRatioLocked ) then
fAspectRatioLocked := IEStr2BoolS( Value )
else
if _IsProp( IELP_BorderColor ) then
fBorderColor := StringToColor( Value )
else
if _IsProp( IELP_BorderWidth ) then
fBorderWidth := StrToInt( Value )
else
if _IsProp( IELP_FillColor ) then
fFillColor := StringToColor( Value )
else
if _IsProp( IELP_FillColor2 ) then
fFillColor2 := StringToColor( Value )
else
if _IsProp( IELP_FillGradient ) then
fFillGradient := TIEGradientDir( StrToInt( Value ))
else
if _IsProp( IELP_AntiAlias ) then
fAntiAlias := IEStr2BoolS( Value )
else
if _IsProp( IELP_Rotate ) then
fRotate := StrToFloat( Value )
else
if _IsProp( IELP_RotateCenterX ) then
fRotateCenterX := StrToFloat( Value )
else
if _IsProp( IELP_RotateCenterY ) then
fRotateCenterY := StrToFloat( Value )
else
if _IsProp( IELP_RestorePreferredAspectRatio ) then
RestoreAspectRatio( True )
else
if _IsProp( IELP_RestoreAspectRatio ) then
RestoreAspectRatio( False )
else
// Soft Shadow
if _IsProp( IELP_SoftShadowEnabled ) then
SoftShadow.Enabled := IEStr2BoolS( Value )
else
if _IsProp( IELP_SoftShadowRadius ) then
SoftShadow.Radius := StrToFloat( Value )
else
if _IsProp( IELP_SoftShadowOffsetX ) then
SoftShadow.OffsetX := StrToInt( Value )
else
if _IsProp( IELP_SoftShadowOffsetY ) then
SoftShadow.OffsetY := StrToInt( Value )
else
if _IsProp( IELP_SoftShadowIntensity ) then
SoftShadow.Intensity := StrToInt( Value )
else
if _IsProp( IELP_SoftShadowColor ) then
SoftShadow.ShadowColor := TColor2TRGB( StringToColor( Value ))
else
// TIEImageLayer
if _IsProp( IELP_ImageResampleFilter ) and ( Self is TIEImageLayer ) then
TIEImageLayer( Self ).fResampleFilter := TResampleFilter( StrToInt( Value ))
else
if _IsProp( IELP_ImageUseResampleFilter ) and ( Self is TIEImageLayer ) then
TIEImageLayer( Self ).fUseResampleFilter := IEStr2BoolS( Value )
else
if _IsProp( IELP_RestoreSize ) and ( Self is TIEImageLayer ) then
TIEImageLayer( Self ).RestoreSize()
else
// TIEShapeLayer
if _IsProp( IELP_Shape ) and ( Self is TIEShapeLayer ) then
TIEShapeLayer( Self ).fShape := TIEShape( StrToInt( Value ))
else
if _IsProp( IELP_ShapeModifier ) and ( Self is TIEShapeLayer ) then
TIEShapeLayer( Self ).fShapeModifier := StrToInt( Value )
else
// TIELineLayer
if _IsProp( IELP_LineColor ) and ( Self is TIELineLayer ) then
TIELineLayer( Self ).fLineColor := StringToColor( Value )
else
if _IsProp( IELP_LineWidth ) and ( Self is TIELineLayer ) then
TIELineLayer( Self ).fLineWidth := StrToInt( Value )
else
if _IsProp( IELP_LineFillColor ) and ( Self is TIELineLayer ) then
TIELineLayer( Self ).fLineFillColor := StringToColor( Value )
else
if _IsProp( IELP_FontName ) and ( Self is TIELineLayer ) then
TIELineLayer( Self ).fLabelFont.Name := Value
else
if _IsProp( IELP_FontSize ) and ( Self is TIELineLayer ) then
TIELineLayer( Self ).fLabelFont.Size := StrToInt( Value )
else
if _IsProp( IELP_FontColor ) and ( Self is TIELineLayer ) then
TIELineLayer( Self ).fLabelFont.Color := StringToColor( Value )
else
if _IsProp( IELP_LabelText ) and ( Self is TIELineLayer ) then
TIELineLayer( Self ).fLabelText := Value
else
if _IsProp( IELP_LabelAlignment ) and ( Self is TIELineLayer ) then
TIELineLayer( Self ).fLabelAlignment := TIEAlignment( StrToInt( Value ))
else
if _IsProp( IELP_LabelPosition ) and ( Self is TIELineLayer ) then
TIELineLayer( Self ).fLabelPosition := TIELineLabelPos( StrToInt( Value ))
else
if _IsProp( IELP_BorderShape ) and ( Self is TIELineLayer ) then
TIELineLayer( Self ).fLabelShape := TIEShape( StrToInt( Value ))
else
if _IsProp( IELP_ReadOnly ) and ( Self is TIELineLayer ) then
TIELineLayer( Self ).fReadOnly := IEStr2BoolS( Value )
else
if _IsProp( IELP_LineEndShape ) and ( Self is TIELineLayer ) then
TIELineLayer( Self ).fEndShape := TIELineEndShape( StrToInt( Value ))
else
if _IsProp( IELP_LineShapeSize ) and ( Self is TIELineLayer ) then
TIELineLayer( Self ).fShapeSize := StrToInt( Value )
else
if _IsProp( IELP_LineStartShape ) and ( Self is TIELineLayer ) then
TIELineLayer( Self ).fStartShape := TIELineEndShape( StrToInt( Value ))
else
if _IsProp( IELP_LineLength ) and ( Self is TIELineLayer ) then
TIELineLayer( Self ).fLastLineLength := StrToInt( Value ) // NB: not fLineLength
else
if _IsProp( IELP_SizeToFit ) and ( Self is TIELineLayer ) then
TIELineLayer( Self ).SizeToFit()
else
// TIEPolylineLayer
if _IsProp( IELP_PolylinePoints ) and ( Self is TIEPolylineLayer ) then
begin
TIEPolylineLayer( Self ).ClearAllPoints();
pointStr := Value + ',';
while pointStr <> '' do
TIEPolylineLayer( Self ).AddPoint( _GetNextPoint( pointStr ), _GetNextPoint( pointStr ));
end
else
if _IsProp( IELP_PolylineClosed ) and ( Self is TIEPolylineLayer ) then
TIEPolylineLayer( Self ).fPolylineClosed := IEStr2BoolS( Value )
else
// TIETextLayer
if _IsProp( IELP_FontName ) and ( Self is TIETextLayer ) then
TIETextLayer( Self ).Font.Name := Value
else
if _IsProp( IELP_FontSize ) and ( Self is TIETextLayer ) then
TIETextLayer( Self ).Font.Size := StrToInt( Value )
else
if _IsProp( IELP_FontColor ) and ( Self is TIETextLayer ) then
TIETextLayer( Self ).Font.Color := StringToColor( Value )
else
if _IsProp( IELP_BorderShape ) and ( Self is TIETextLayer ) then
TIETextLayer( Self ).fBorderShape := TIEShape( StrToInt( Value ))
else
if _IsProp( IELP_Text ) and ( Self is TIETextLayer ) then
TIETextLayer( Self ).fText := Value
else
if _IsProp( IELP_AutoSize ) and ( Self is TIETextLayer ) then
TIETextLayer( Self ).fAutoSize := IEStr2BoolS( Value )
else
if _IsProp( IELP_ReadOnly ) and ( Self is TIETextLayer ) then
TIETextLayer( Self ).fReadOnly := IEStr2BoolS( Value )
else
if _IsProp( IELP_TextAlignment ) and ( Self is TIETextLayer ) then
TIETextLayer( Self ).fAlignment := TIEAlignment( StrToInt( Value ))
else
if _IsProp( IELP_TextLayout ) and ( Self is TIETextLayer ) then
TIETextLayer( Self ).fLayout := TIELayout( StrToInt( Value ))
else
if _IsProp( IELP_SizeToFit ) and ( Self is TIETextLayer ) then
TIETextLayer( Self ).SizeToText();
LayerChange();
except
// conversion error
end;
end;
{!!
<FS>TIELayer.PreferredAspectRatio
<FM>Declaration<FC>
function PreferredAspectRatio(): Double;
<FM>Description<FN>
Returns the best ratio of Width/Height to display this layer.
Some layer types look best at their original aspect ratio (i.e. the ratio of Height:Width).
This is particularly true of images and some <L TIEShape>shapes</L>.
Result is 0 if this layer type does not have a preferred aspect ratio.
Typical results:
Portrait image: 0.67
Landscape image: 1.33
Star <L TIEShape>shape</L>: 1
<L TIETextLayer>Text box</L>: 0 (i.e. no preferred ratio)
<FM>Example<FC>
// Force aspect ratio locking if the object prefers it
ImageEnView1.CurrentLayer.AspectRatioLocked := ImageEnView1.CurrentLayer.PreferredAspectRatio <> 0;
<FM>See Also<FN>
- <A TIELayer.AspectRatioLocked>
- <A TIELayer.RestoreAspectRatio>
- <A TImageEnView.LayersResizeAspectRatio>
!!}
function TIELayer.PreferredAspectRatio(): Double;
begin
Result := 0;
if Self is TIEImageLayer and not TIEImageLayer( Self ).Magnify.Enabled then
Result := TIEImageLayer( Self ).Width / TIEImageLayer( Self ).Height
else
if Self is TIEShapeLayer then
Result := IEShapePreferredAspectRatio( TIEShapeLayer( Self ).Shape );
end;
{!!
<FS>TIELayer.RestoreAspectRatio
<FM>Declaration<FC>
procedure RestoreAspectRatio(PreferredOnly: Boolean = True);
<FM>Description<FN>
Sizes the layer to restore its preferred or original aspect ratio (i.e. the ratio of Height:Width).
Some layer types look best at their original aspect ratio. This is particularly true of images and some <L TIEShape>shapes</L>.
Calling <FC>RestoreAspectRatio<FN> will resize it (reducing its display size) to display it correctly.
If <FC>PreferredOnly<FN> = True then it is only sized if it has a <A TIELayer.PreferredAspectRatio>.
If <FC>PreferredOnly<FN> = False and it does not have a <A TIELayer.PreferredAspectRatio> then it is restored to its design size.
<FM>Example<FC>
// Fix the aspect ratio for the selected layer if it is an image
if ImageEnView1.CurrentLayer is TIEImageLayer then
ImageEnView1.CurrentLayer.RestoreAspectRatio();
ImageEnView1.Update();
// Create a layer at 50,50 and display an image (maintaining its aspect ratio)
ImageEnView1.LockUpdate();
ImageEnView1.LayersAdd( 100, 100, ie24RGB, 50, 50 );
ImageEnView1.IO.LoadFromFile( 'D:\image.jpeg' );
ImageEnView1.CurrentLayer.RestoreAspectRatio();
ImageEnView1.UnlockUpdate();
<FM>See Also<FN>
- <A TIEImageLayer.RestoreSize>
- <A TIELayer.AspectRatioLocked>
- <A TIELayer.PreferredAspectRatio>
- <A TImageEnView.LayersResizeAspectRatio>
!!}
procedure TIELayer.RestoreAspectRatio(PreferredOnly: Boolean = True);
var
aRect: TRect;
aspectRatio: Double;
imgWidth, imgHeight: Integer;
begin
if Self is TIEImageLayer then
begin
imgWidth := OriginalWidth;
imgHeight := OriginalHeight;
end
else
begin
aspectRatio := PreferredAspectRatio;
if ( aspectRatio = 0 ) and ( PreferredOnly = False ) then
aspectRatio := fOriginalAspectRatio;
imgWidth := Round( 1000 * aspectRatio );
imgHeight := 1000;
end;
if ( imgWidth < 1 ) or ( imgHeight < 1 ) then
exit;
aRect := GetImageRectWithinArea( imgWidth, imgHeight, Width, Height );
PosX := PosX + aRect.Left;
PosY := PosY + aRect.Top;
Width := aRect.Right - aRect.Left;
Height := aRect.Bottom - aRect.Top;
LayerChange();
end;
{!!
<FS>TIELayer.SupportsFeature
<FM>Declaration<FC>
function SupportsFeature(Feature: <A TIELayerFeatures>): Boolean;
<FM>Description<FN>
Returns true if the specified feature is supported by this <A TIELayer.Kind>layer type</L>
<TABLE>
<R> <H>Kind</H> <H>Description</H> <H>Supported By</H> </R>
<R> <C><FC>ielfBorder<FN></C> <C>Layer has a border or line that can be adjusted using <A TIELayer.BorderColor> and <A TIELayer.BorderWidth> </C> <C> All </C> </R>
<R> <C><FC>ielfFill<FN></C> <C>Layer has a solid fill that can be adjusted using <A TIELayer.FillColor> </C> <C> <A TIEShapeLayer>, <A TIELineLayer> (only if <L TIELineLayer.LabelText>label</L> or <L TIELineLayer.StartShape>end shapes</L> are visible), <A TIEPolylineLayer> (only if <A TIEPolylineLayer.PolylineClosed>=True), <A TIETextLayer> </C> </R>
<R> <C><FC>ielfGradient<FN></C> <C>If the solid fill can be gradiated using <A TIELayer.FillColor2> and <A TIELayer.FillGradient></C> <C> <A TIEShapeLayer>, <A TIELineLayer> (only if <A TIELineLayer.LabelText> is set), <A TIETextLayer> </C> </R>
<R> <C><FC>ielfRotation<FN></C> <C>Can be rotated by setting <A TIELayer.Rotate> or using <L TImageEnView.MouseInteract>miRotateLayers</L> </C> <C> All </C> </R>
<R> <C><FC>ielfMoveRotationCenter<FN></C> <C>The center of layer rotation can be moved by setting <A TIELayer.RotateCenterX> or moving the center grip with <L TImageEnView.MouseInteract>miRotateLayers</L> </C> <C> <A TIEImageLayer> </C> </R>
<R> <C><FC>ielfTextEditing<FN></C> <C>The layer has a text property and is not set to read-only</C> <C> <A TIETextLayer>, <A TIELineLayer> (only if <A TIELineLayer.LabelText> is set) </C> </R>
</TABLE>
<FM>Example<FC>
// Show border color selector if layer type supports it
btnSelBorder.Enabled := ImageEnView1.CurrentLayer.SupportsFeature( ielfBorder );
// Show fill color selector if layer type supports it
btnSelFill.Enabled := ImageEnView1.CurrentLayer.SupportsFeature( ielfFill );
// Show gradient selector if layer type supports it
btnGradient.Enabled := ImageEnView1.CurrentLayer.SupportsFeature( ielfGradient );
// Determine if the current layer type can be rotated
canRotate := ImageEnView1.CurrentLayer.SupportsFeature( ielfRotation );
// Determine if the current layer type can be rotated
canRotate := ImageEnView1.CurrentLayer.SupportsFeature( ielfRotation );
// Text can currently be edited for this layer
edtText.Enabled := ImageEnView1.CurrentLayer.SupportsFeature( ielfTextEditing );
!!}
function TIELayer.SupportsFeature(Feature: TIELayerFeatures): Boolean;
begin
Result := False;
case Feature of
ielfBorder : Result := fKind in [ ielkImage, ielkShape, ielkLine, ielkPolyline, ielkText ];
ielfFill : if fKind = ielkLine then
Result := (( TIELineLayer( Self ).LabelText <> '' ) and ( TIELineLayer( Self ).LabelPosition <> ielpHide )) or
( TIELineLayer( Self ).StartShape <> ieesNone ) or ( TIELineLayer( Self ).EndShape <> ieesNone )
else
if fKind = ielkPolyline then
Result := TIEPolylineLayer( Self ).PolylineClosed
else
Result := fKind in [ ielkShape, ielkText ];
ielfGradient : if fKind = ielkLine then
Result := ( TIELineLayer( Self ).LabelText <> '' ) and ( TIELineLayer( Self ).LabelPosition <> ielpHide )
else
Result := fKind in [ ielkShape, ielkText ];
ielfRotation : Result := fKind in [ ielkImage, ielkShape, ielkLine, ielkPolyline, ielkText ];
ielfMoveRotationCenter : Result := fKind in [ ielkImage ];
ielfTextEditing : begin
Result := Result;
if fKind = ielkText then
Result := not TIETextLayer( Self ).fReadOnly
else
if fKind = ielkLine then
Result := ( TIELineLayer( Self ).fReadOnly = False ) and
(( TIELineLayer( Self ).LabelRect.Left <> 0 ) or
( TIELineLayer( Self ).LabelRect.Right <> 0 )); // can only edit text if label is visible
end;
end;
end;
{!!
<FS>TIELayer.Swap
<FM>Declaration<FC>
procedure Swap(OtherLayer: <A TIELayer>);
<FM>Description<FN>
Swaps the content of two layers.
Note: Both layers must be of the same <A TIELayer.Kind>layer type</L>
<FM>Example<FC>
// Swap the current layer with the second one
ImageEnView1.CurrentLayer.Swap( ImageEnView1.Layers[ 1 ]);
ImageEnView1.Update();
!!}
procedure TIELayer.Swap(OtherLayer: TIELayer);
procedure IESwapLP(var a: TIELineLabelPos; var b: TIELineLabelPos);
var
t: TIELineLabelPos;
begin
t := a; a := b; b := t;
end;
procedure IESwapAS(var a: TIELineEndShape; var b: TIELineEndShape);
var
t: TIELineEndShape;
begin
t := a; a := b; b := t;
end;
procedure IESwapGD(var a: TIEGradientDir; var b: TIEGradientDir);
var
t: TIEGradientDir;
begin
t := a; a := b; b := t;
end;
procedure IESwapFQ(var a: TIEFontQuality; var b: TIEFontQuality);
var
t: TIEFontQuality;
begin
t := a; a := b; b := t;
end;
procedure IESwapAL(var a: TIEAlignment; var b: TIEAlignment);
var
t: TIEAlignment;
begin
t := a; a := b; b := t;
end;
procedure IESwapLY(var a: TIELayout; var b: TIELayout);
var
t: TIELayout;
begin
t := a; a := b; b := t;
end;
begin
if Kind <> OtherLayer.Kind then
raise EIEException.create( 'Layers must be of same type' );
IESwap( fResizedWidth, OtherLayer.fResizedWidth);
IESwap( fResizedHeight, OtherLayer.fResizedHeight);
IESwap( fVisible, OtherLayer.fVisible);
IESwap( fVisibleBox, OtherLayer.fVisibleBox);
IESwap( fSelectable, OtherLayer.fSelectable);
IESwap( fTransparency, OtherLayer.fTransparency);
IESwap( fOpacity, OtherLayer.fOpacity);
IESwap( fPosX, OtherLayer.fPosX);
IESwap( fPosY, OtherLayer.fPosY);
IESwap( fCropped, OtherLayer.fCropped);
IESwap( fLocked, OtherLayer.fLocked);
IESwap( fOperation, OtherLayer.fOperation);
IESwap( UserData, OtherLayer.UserData);
IESwap( fUserDataLen, OtherLayer.fUserDataLen);
IESwap( fName, OtherLayer.fName);
IESwap( fIsMask, OtherLayer.fIsMask);
IESwap( fDrawOuter, OtherLayer.fDrawOuter);
IESwap( fGUID, OtherLayer.fGUID);
IESwap( fAlphaEdgeFeathering, OtherLayer.fAlphaEdgeFeathering);
IESwap( fGroupIndex, OtherLayer.fGroupIndex);
IESwap( fSelected, OtherLayer.fSelected);
IESwap( fAspectRatioLocked, OtherLayer.fAspectRatioLocked );
IESwap( fTag, OtherLayer.fTag);
IESwap( fBorderColor, OtherLayer.fBorderColor );
IESwap( fBorderWidth, OtherLayer.fBorderWidth );
IESwap( fFillColor, OtherLayer.fFillColor );
IESwap( fFillColor2, OtherLayer.fFillColor2 );
IESwapGD( fFillGradient, OtherLayer.fFillGradient );
IESwap( fRotate, OtherLayer.fRotate );
IESwap( fRotateCenterX, OtherLayer.fRotateCenterX );
IESwap( fRotateCenterY, OtherLayer.fRotateCenterY );
IESwap( fAntiAlias, OtherLayer.fAntiAlias );
IESwap( fOriginalAspectRatio, OtherLayer.fOriginalAspectRatio ) ;
// Soft shadow
IESwap( softShadow.Enabled , OtherLayer.softShadow.Enabled);
IESwap( softShadow.Radius , OtherLayer.softShadow.Radius);
IESwap( softShadow.OffsetX , OtherLayer.softShadow.OffsetX);
IESwap( softShadow.OffsetY , OtherLayer.softShadow.OffsetY);
IESwap( softShadow.Intensity , OtherLayer.softShadow.Intensity);
IESwap( softShadow.ShadowColor , OtherLayer.softShadow.ShadowColor);
if ( OtherLayer is TIEImageLayer ) and ( Self is TIEImageLayer ) then
with TIEImageLayer( Self ) do
begin
TIEImageLayer( OtherLayer ).fBitmap.SwitchTo(fBitmap);
IESwap(fFreeBitmapOnDestroy, TIEImageLayer( OtherLayer ).fFreeBitmapOnDestroy);
IESwap(Magnify, TIEImageLayer( OtherLayer ).Magnify);
IESwap(fResampleFilter, TIEImageLayer( OtherLayer ).fResampleFilter);
IESwap(fUseResampleFilter, TIEImageLayer( OtherLayer ).fUseResampleFilter);
if assigned(fOwner) and assigned((fOwner as TImageEnView).fIEBitmap) and
((fOwner as TImageEnView).fIEBitmap = TIEImageLayer( OtherLayer ).fBitmap) then
begin
(fOwner as TImageEnView).fIEBitmap := fBitmap;
if fBitmap.EncapsulatedFromTBitmap then
(fOwner as TImageEnView).fBitmap := fBitmap.VclBitmap
else
(fOwner as TImageEnView).fBitmap := nil;
end;
end
else
if ( OtherLayer is TIEShapeLayer ) and ( Self is TIEShapeLayer ) then
with TIEShapeLayer( Self ) do
begin
IESwap( fShape, TIEShapeLayer( OtherLayer ).fShape );
IESwap( fShapeModifier, TIEShapeLayer( OtherLayer ).fShapeModifier );
end
else
if ( OtherLayer is TIELineLayer ) and ( Self is TIELineLayer ) then
with TIELineLayer( Self ) do
begin
IESwap( fAutoSize , TIELineLayer( OtherLayer ).fAutoSize );
IESwap( fLineColor , TIELineLayer( OtherLayer ).fLineColor );
IESwap( fLineWidth , TIELineLayer( OtherLayer ).fLineWidth );
IESwap( fLineFillColor , TIELineLayer( OtherLayer ).fLineFillColor );
IESwap( fLabelFont , TIELineLayer( OtherLayer ).fLabelFont );
IESwap( fLabelText , TIELineLayer( OtherLayer ).fLabelText );
IESwapAL( fLabelAlignment, TIELineLayer( OtherLayer ).fLabelAlignment );
IESwapLP( fLabelPosition , TIELineLayer( OtherLayer ).fLabelPosition );
IESwap( fLabelShape , TIELineLayer( OtherLayer ).fLabelShape );
IESwap( fReadOnly , TIELineLayer( OtherLayer ).fReadOnly );
IESwapAS( fStartShape , TIELineLayer( OtherLayer ).fStartShape );
IESwapAS( fEndShape , TIELineLayer( OtherLayer ).fEndShape );
IESwap( fShapeSize , TIELineLayer( OtherLayer ).fShapeSize );
IESwap( fLastLineLength , TIELineLayer( OtherLayer ).fLastLineLength );
end
else
if ( OtherLayer is TIEPolylineLayer ) and ( Self is TIEPolylineLayer ) then
with TIEPolylineLayer( Self ) do
begin
// todo: @FAB: This code OK?
IESwap( fPolyPoints , TIEPolylineLayer( OtherLayer ).fPolyPoints );
IESwap( fPolyPointCount , TIEPolylineLayer( OtherLayer ).fPolyPointCount );
IESwap( fPolyPointsAllocated , TIEPolylineLayer( OtherLayer ).fPolyPointsAllocated );
IESwap( fDrawnPoints , TIEPolylineLayer( OtherLayer ).fDrawnPoints );
IESwap( fDrawnPointCount , TIEPolylineLayer( OtherLayer ).fDrawnPointCount );
IESwap( fDrawnPointsAllocated , TIEPolylineLayer( OtherLayer ).fDrawnPointsAllocated );
IESwap( fPolylineClosed , TIEPolylineLayer( OtherLayer ).fPolylineClosed );
end
else
if ( OtherLayer is TIETextLayer ) and ( Self is TIETextLayer ) then
with TIETextLayer( Self ) do
begin
IESwap( fFont, TIETextLayer( OtherLayer ).fFont );
IESwap( fBorderShape, TIETextLayer( OtherLayer ).fBorderShape );
IESwap( fText, TIETextLayer( OtherLayer ).fText );
IESwap( fAutoSize, TIETextLayer( OtherLayer ).fAutoSize );
IESwap( fReadOnly, TIETextLayer( OtherLayer ).fReadOnly );
IESwapAL( fAlignment, TIETextLayer( OtherLayer ).fAlignment );
IESwapLY( fLayout, TIETextLayer( OtherLayer ).fLayout );
end;
LayerChange();
OtherLayer.LayerChange();
end;
// Does not reset position!
// Incompatible with old TIELayer.SaveInfo
procedure TIELayer.SaveMetaToStream(Stream: TStream);
var
val, l: integer;
begin
l := Stream.Position;
Stream.Write(l, sizeof(integer)); // Place holder. Descendent classes will fill with size
val := IELayers_File_Version;
Stream.Write( val, sizeof( integer )); // Save Version
val := ord( Kind );
Stream.Write( val, sizeof( integer )); // Layer kind
Stream.Write( fGUID, sizeof(TGuid));
val := Round( fResizedWidth );
Stream.Write( val, sizeof( integer ));
val := Round( fResizedHeight );
Stream.Write( val, sizeof( integer ));
Stream.Write( fVisible, sizeof(fVisible));
Stream.Write( fVisibleBox, sizeof(fVisibleBox));
Stream.Write( fSelectable, sizeof(fSelectable));
Stream.Write( fTransparency, sizeof(fTransparency));
Stream.Write( fOpacity, sizeof(fOpacity));
val := Trunc( fPosX );
Stream.Write( val, sizeof( Integer ));
val := Trunc( fPosY );
Stream.Write( val, sizeof( Integer ));
Stream.Write( fClientAreaBox, sizeof(fClientAreaBox));
Stream.Write( fCropped, sizeof(fCropped));
Stream.Write( fLocked, sizeof(fLocked));
Stream.Write( fOperation, sizeof(fOperation));
Stream.Write( fUserDataLen, sizeof(fUserDataLen));
if (UserData <> nil) and (fUserDataLen > 0) then
Stream.Write(pbyte(UserData)^, fUserDataLen);
IESaveStringToStreamW(Stream, fName);
Stream.Write( fIsMask, sizeof(fIsMask));
Stream.Write( fDrawOuter, sizeof(fDrawOuter));
Stream.Write( fRotate, sizeof(double));
Stream.Write( fRotateCenterX, sizeof(double));
Stream.Write( fRotateCenterY, sizeof(double));
Stream.Write( fAlphaEdgeFeathering, sizeof(fAlphaEdgeFeathering));
Stream.Write( fSelected, sizeof(boolean));
Stream.Write( fGroupIndex, sizeof(integer));
Stream.Write( fAspectRatioLocked, SizeOf( Boolean ));
Stream.Write( fAntiAlias, SizeOf( Boolean ));
Stream.Write( fOriginalAspectRatio, SizeOf( Double ));
Stream.Write( fTag, SizeOf( Integer ));
Stream.Write( fBorderColor, SizeOf( TColor ));
Stream.Write( fBorderWidth, SizeOf( Integer ));
Stream.Write( fFillColor, SizeOf( TColor ));
Stream.Write( fFillColor2, SizeOf( TColor ));
Stream.Write( fFillGradient, SizeOf( TIEGradientDir ));
// Soft shadow
Stream.Write( softShadow.Enabled, sizeof(boolean));
Stream.Write( softShadow.Radius, sizeof(double));
Stream.Write( softShadow.OffsetX, sizeof(integer));
Stream.Write( softShadow.OffsetY, sizeof(integer));
Stream.Write( softShadow.Intensity, sizeof(integer));
Stream.Write( softShadow.ShadowColor, sizeof(TRGB));
end;
// Ensure code match with TIELayer.LoadMetaFromStream
procedure ReadLayerPropsFromStream(Stream: TStream;
ResetPos: Boolean; // Position Stream after read to inital pos
out RecSize: Integer; // Total size of layer data block
out LayerKind: TIELayerKind; // Type of layer
out GUID: TGuid); // Layer identifier
var
l, val, ver: integer;
begin
l := Stream.Position;
Stream.Read( RecSize, sizeof( Integer )); // Size
Stream.Read( ver, sizeof( Integer )); // Version
Stream.Read( val, sizeof( Integer )); // Layer Kind
LayerKind := TIELayerKind( val );
Stream.Read(GUID, sizeof(TGuid)); // Identifier
if ResetPos then
Stream.Position := l;
end;
// Incompatible with old TIELayer.LoadInfo
// Returns layer save version
function TIELayer.LoadMetaFromStream(Stream: TStream): Integer;
var
val: integer;
begin
Stream.Read( fLayerSize, sizeof(fLayerSize)); // Size
Stream.Read( Result, sizeof( Integer )); // Version
Stream.Read( val, sizeof( Integer )); // Layer Kind - don't store
Stream.Read( fGUID, sizeof(TGuid));
Stream.Read( val, sizeof( Integer ));
fResizedWidth := val;
Stream.Read( val, sizeof( Integer ));
fResizedHeight := val;
Stream.Read( fVisible, sizeof(fVisible));
Stream.Read( fVisibleBox, sizeof(fVisibleBox));
Stream.Read( fSelectable, sizeof(fSelectable));
Stream.Read( fTransparency, sizeof(fTransparency));
Stream.Read( fOpacity, sizeof(fOpacity));
Stream.Read( val, sizeof( Integer ));
fPosX := val;
Stream.Read( val, sizeof( Integer ));
fPosY := val;
Stream.Read( fClientAreaBox, sizeof(fClientAreaBox));
Stream.Read( fCropped, sizeof(fCropped));
Stream.Read( fLocked, sizeof(fLocked));
Stream.Read( fOperation, sizeof(fOperation));
if ( fUserDataLen > 0 ) and ( UserData <> nil ) then
begin
freemem( UserData );
fUserDataLen := 0;
UserData := nil;
end;
Stream.Read( fUserDataLen, sizeof( fUserDataLen ));
if fUserDataLen > 0 then
begin
getmem( UserData, fUserDataLen);
Stream.Read(pbyte(UserData)^, fUserDataLen);
end;
IELoadStringFromStreamW(Stream, fName);
Stream.Read( fIsMask, sizeof(fIsMask));
Stream.Read( fDrawOuter, sizeof(fDrawOuter));
Stream.Read( fRotate, sizeof(double));
Stream.Read( fRotateCenterX, sizeof(double));
Stream.Read( fRotateCenterY, sizeof(double));
Stream.Read( fAlphaEdgeFeathering, sizeof(fAlphaEdgeFeathering));
Stream.Read( fSelected, SizeOf( Boolean ));
Stream.Read( fGroupIndex, sizeof(Integer));
Stream.Read( fAspectRatioLocked, SizeOf( Boolean ));
Stream.Read( fAntiAlias, SizeOf( Boolean ));
Stream.Read( fOriginalAspectRatio, SizeOf( Double ));
if Result >= 7001 then
Stream.Read( fTag, SizeOf( Integer ));
Stream.Read( fBorderColor, SizeOf( TColor ));
Stream.Read( fBorderWidth, SizeOf( Integer ));
Stream.Read( fFillColor, SizeOf( TColor ));
Stream.Read( fFillColor2, SizeOf( TColor ));
Stream.Read( fFillGradient, SizeOf( TIEGradientDir ));
// Soft shadow
Stream.Read( softShadow.Enabled, sizeof(boolean));
Stream.Read( softShadow.Radius, sizeof(double));
Stream.Read( softShadow.OffsetX, SizeOf( integer ));
Stream.Read( softShadow.OffsetY, SizeOf( integer ));
Stream.Read( softShadow.Intensity, sizeof(integer));
Stream.Read( softShadow.ShadowColor, sizeof(TRGB));
LayerChange();
end;
procedure TIELayer.LoadFromLegacyStream(Stream: TStream; HdrVersion: Integer; FileFormat: TIOFileType);
var
val: Integer;
poslo, poshi: Dword;
p1: int64;
ms: TMemoryStream;
dw: Dword;
LZStream: TZDecompressionStream;
lnative: Boolean;
{$ifndef IEIncludeDeprecatedInV6}
dummy: TIEMagnifyStyle;
dummy2: TIEMagnifySource;
dummy3: TResampleFilter;
{$ENDIF}
ansiName: AnsiString;
iev: TImageEnView;
begin
if not assigned( fOwner ) then
raise EIEException.create( 'Onwer not assigned' );
iev := TImageEnView( fOwner );
Stream.Read( fVisible, sizeof(boolean));
Stream.Read( fVisibleBox, sizeof(boolean));
Stream.Read( fTransparency, sizeof(integer));
if HdrVersion >= 7 then
Stream.Read( fOpacity, sizeof(double));
Stream.Read( val, sizeof( integer ));
fPosX := val;
Stream.Read( val, sizeof( integer ));
fPosY := val;
Stream.Read( fCropped, sizeof(boolean));
Stream.Read( fLocked, sizeof(boolean));
{$ifdef IEIncludeDeprecatedInV6}
// Magnify moved to TIEImageLayer class in 7.0.0 (2016-10-26)
Stream.Read( Magnify.Enabled, sizeof(boolean));
Stream.Read( Magnify.Rate, sizeof(double));
Stream.Read( Magnify.Style, sizeof(TIEMagnifyStyle));
if HdrVersion >= 3 then
Stream.Read( Magnify.Source, sizeof(TIEMagnifySource));
{$ELSE}
Stream.Read( bval, sizeof(boolean));
Stream.Read( dval, sizeof(double));
Stream.Read( dummy, sizeof(TIEMagnifyStyle));
if HdrVersion >= 3 then
Stream.Read( dummy2, sizeof(TIEMagnifySource));
{$ENDIF}
Stream.Read( fOperation, sizeof(TIERenderOperation));
Stream.Read( val, sizeof( integer ));
WidthD := val;
Stream.Read( val, sizeof( integer ));
HeightD := val;
if HdrVersion >= 3 then
begin
{$ifdef IEIncludeDeprecatedInV6}
// ResampleFilter moved to TIEImageLayer class in 7.0.0 (2016-10-26)
Stream.Read( fResampleFilter, sizeof(TResampleFilter));
Stream.Read( fUseResampleFilter, sizeof(boolean));
{$ELSE}
Stream.Read( dummy3, sizeof(TResampleFilter));
Stream.Read( bval, sizeof(boolean));
{$ENDIF}
IELoadStringFromStream(Stream, ansiName);
fName := string( ansiName );
if ( fUserDataLen > 0) and ( UserData <> nil ) then
begin
freemem( UserData );
fUserDataLen := 0;
UserData := nil;
end;
Stream.Read( fUserDataLen, sizeof(integer));
if fUserDataLen > 0 then
begin
getmem( UserData, fUserDataLen);
Stream.Read(pbyte( UserData )^, fUserDataLen);
end;
Stream.Read(fIsMask, sizeof(boolean));
end;
if HdrVersion >= 4 then
Stream.Read( fSelectable, sizeof(boolean));
if HdrVersion >= 6 then
Stream.Read( fDrawOuter, sizeof(Boolean));
if HdrVersion >= 8 then
Stream.Read( fAlphaEdgeFeathering, SizeOf(Integer));
if HdrVersion >= 9 then
begin
Stream.Read( fRotateCenterX, sizeof(Double));
Stream.Read( fRotateCenterY, sizeof(Double));
Stream.Read( fRotate, sizeof(Double));
end;
if HdrVersion >= 9 then
begin
Stream.Read( fGroupIndex, sizeof(Integer));
Stream.Read( fSelected, sizeof(Boolean));
end;
fClientAreaBox := Rect(0, 0, 0, 0);
Stream.Read(poslo, sizeof(dword));
Stream.Read(poshi, sizeof(dword));
p1 := Stream.Position;
Stream.Position := poslo+(poshi shl 32);
iev.LayersCurrent := iev.LayersCount;
if (FileFormat = -1) or (FileFormat = -2) then
begin
// use internal file format
Stream.Read(dw, sizeof(dword)); // compressed stream size
ms := TMemoryStream.Create;
try
ms.SetSize(dw); // to speed up loading
if dw > 0 then
IECopyFrom(ms, Stream, dw);
ms.Position := 0;
if FileFormat = -1 then
begin
LZStream := TZDecompressionStream.Create(ms);
try
iev.fIEBitmap.LoadRAWFromBufferOrStream(nil, LZStream);
finally
FreeAndNil(LZStream);
end;
end
else
iev.fIEBitmap.LoadRAWFromBufferOrStream(nil, ms);
finally
FreeAndNil(ms);
end;
end
else
begin
// use standard file formats
lnative := iev.IO.NativePixelFormat;
if fIsMask then
iev.IO.NativePixelFormat := true;
iev.IO.LoadFromStream(Stream, FileFormat);
iev.IO.NativePixelFormat := lnative;
end;
fModified := False;
Stream.Position := p1;
end;
{!!
<FS>TIELayer.PosX
<FM>Declaration<FC>
property PosX: Integer;
<FM>Description<FN>
Specifies the horizontal position of the layer relative to the background image (layer 0).
These consts are also supported:
<TABLE>
<R> <H>Const</H> <H>Description</H> </R>
<R> <C><FC>IELayer_Pos_Left<FN></C> <C>Adjust PosX so layer is aligned to the left of the background layer</C> </R>
<R> <C><FC>IELayer_Pos_HCenter<FN></C> <C>Adjust PosX so layer is aligned to the horizontal center of the background layer</C> </R>
<R> <C><FC>IELayer_Pos_Right<FN></C> <C>Adjust PosX so layer is aligned to the right of the background layer</C> </R>
</TABLE>
<FM>Example<FN>
// Apply a "Paid" stamp to image
with ImageEnView1 do
begin
LayersAdd( 'PAID', 'Arial Black', 42, clRed, [fsBold] );
CurrentLayer.Rotate := 30;
TIETextLayer( CurrentLayer ).SizeToText();
CurrentLayer.PosX := IELayer_Pos_HCenter;
CurrentLayer.PosY := IELayer_Pos_VCenter;
LayersMergeAll();
end;
<FM>See Also<FN>
- <A TImageEnView.LayersRepositionAll>
!!}
function TIELayer.GetPosX: integer;
begin
Result := Trunc( fPosX );
end;
procedure TIELayer.SetPosX(v: integer);
begin
if v < IELayer_Pos_Left then
fPosX := v
else
if ( fOwner = nil ) or ( TImageEnView( fOwner ).Layers[ 0 ].Width < 2 ) then
fPosX := 0
else
if v = IELayer_Pos_Left then
fPosX := TImageEnView( fOwner ).Layers[ 0 ].PosX
else
if v = IELayer_Pos_HCenter then
fPosX := TImageEnView( fOwner ).Layers[ 0 ].PosX + ( TImageEnView( fOwner ).Layers[ 0 ].Width - Width ) div 2
else
if v = IELayer_Pos_Right then
fPosX := TImageEnView( fOwner ).Layers[ 0 ].PosX + TImageEnView( fOwner ).Layers[ 0 ].Width - Width;
// Call LayerChange without resetting the layer cache
LayerChange( False );
end;
{!!
<FS>TIELayer.PosY
<FM>Declaration<FC>
property PosY: Integer;
<FM>Description<FN>
Specifies the vertical position of the layer relative to the background image (layer 0).
These consts are also supported:
<TABLE>
<R> <H>Const</H> <H>Description</H> </R>
<R> <C><FC>IELayer_Pos_Top<FN></C> <C>Adjust PosY so layer is aligned to the top of the background layer</C> </R>
<R> <C><FC>IELayer_Pos_VCenter<FN></C> <C>Adjust PosY so layer is aligned to the vertical center of the background layer</C> </R>
<R> <C><FC>IELayer_Pos_Bottom<FN></C> <C>Adjust PosY so layer is aligned to the bottom of the background layer</C> </R>
</TABLE>
<FM>Example<FN>
// Apply a "Paid" stamp to image
with ImageEnView1 do
begin
LayersAdd( 'PAID', 'Arial Black', 42, clRed, [fsBold] );
CurrentLayer.Rotate := 30;
TIETextLayer( CurrentLayer ).SizeToText();
CurrentLayer.PosX := IELayer_Pos_HCenter;
CurrentLayer.PosY := IELayer_Pos_VCenter;
LayersMergeAll();
end;
<FM>See Also<FN>
- <A TImageEnView.LayersRepositionAll>
!!}
function TIELayer.GetPosY: integer;
begin
Result := Trunc( fPosY );
end;
procedure TIELayer.SetPosY(v: integer);
begin
if v < IELayer_Pos_Top then
fPosY := v
else
if ( fOwner = nil ) or ( TImageEnView( fOwner ).Layers[ 0 ].Height < 2 ) then
fPosY := 0
else
if v = IELayer_Pos_Top then
fPosY := TImageEnView( fOwner ).Layers[ 0 ].PosY
else
if v = IELayer_Pos_VCenter then
fPosY := TImageEnView( fOwner ).Layers[ 0 ].PosY + ( TImageEnView( fOwner ).Layers[ 0 ].Height - Height ) div 2
else
if v = IELayer_Pos_Bottom then
fPosY := TImageEnView( fOwner ).Layers[ 0 ].PosY + TImageEnView( fOwner ).Layers[ 0 ].Height - Height;
// Call LayerChange without resetting the layer cache
LayerChange( False );
end;
{!!
<FS>TIELayer.Width
<FM>Declaration<FC>
property Width: Integer;
<FM>Description<FN>
Specifies the layer size (i.e. display width when zoom is 100%).
<FM>Example<FC>
// Make all selected layers 1/3 size
ImageEnView1.LockUpdate;
for i := 0 to ImageEnView1.LayersCount - 1 do
if ImageEnView1.Layers[ I ].Selected then
begin
ImageEnView1.Layers[ I ].Width := ImageEnView1.Layers[ I ].Width div 3;
ImageEnView1.Layers[ I ].Height := ImageEnView1.Layers[ I ].Height div 3;
end;
ImageEnView1.LayersFixSizes( LYR_SELECTED_LAYERS );
ImageEnView1.UnlockUpdate;
<FM>See Also<FN>
- <A TImageEnView.LayersSizeAll>
- <A TIETextLayer.SizeToText>
- <A TIELineLayer.SizeToFit>
!!}
function TIELayer.GetWidth: integer;
begin
if ( Self is TIEImageLayer ) and ( fResizedWidth = 0 ) then
result := TIEImageLayer( Self ).fBitmap.Width
else
result := iMax( 1, Round( fResizedWidth ));
end;
procedure TIELayer.SetWidth(v: integer);
begin
SetWidthD( v );
end;
procedure TIELayer.SetWidthD(v: Double);
var
changedVal: Boolean;
begin
changedVal := Round( fResizedWidth ) <> Round ( v );
fResizedWidth := v;
if changedVal then
begin
if Self is TIELineLayer then
TIELineLayer( Self ).fLastLineLength := -1;
LayerChange();
end;
end;
{!!
<FS>TIELayer.Height
<FM>Declaration<FC>
property Height: Integer;
<FM>Description<FN>
Specifies the layer size (i.e. display height when zoom is 100%).
<FM>Example<FC>
// Make all selected layers 1/3 size
ImageEnView1.LockUpdate;
for i := 0 to ImageEnView1.LayersCount - 1 do
if ImageEnView1.Layers[ I ].Selected then
begin
ImageEnView1.Layers[ I ].Width := ImageEnView1.Layers[ I ].Width div 3;
ImageEnView1.Layers[ I ].Height := ImageEnView1.Layers[ I ].Height div 3;
end;
ImageEnView1.LayersFixSizes( LYR_SELECTED_LAYERS );
ImageEnView1.UnlockUpdate;
<FM>See Also<FN>
- <A TImageEnView.LayersSizeAll>
- <A TIETextLayer.SizeToText>
- <A TIELineLayer.SizeToFit>
!!}
function TIELayer.GetHeight: integer;
begin
if ( Self is TIEImageLayer ) and ( fResizedHeight = 0 ) then
result := TIEImageLayer( Self ).fBitmap.Height
else
result := iMax( 1, Round( fResizedHeight ));
end;
procedure TIELayer.SetHeight(v: integer);
begin
SetHeightD( v );
end;
procedure TIELayer.SetHeightD(v: Double);
var
changedVal: Boolean;
begin
changedVal := Round( fResizedHeight ) <> Round ( v );
fResizedHeight := v;
if changedVal then
begin
if Self is TIELineLayer then
TIELineLayer( Self ).fLastLineLength := -1;
LayerChange();
end;
end;
// Returns the size of the bitmap.width if an image layer, otherwise the user's specified size for the object
function TIELayer.GetOriginalWidth: integer;
begin
if Self is TIEImageLayer then
result := TIEImageLayer( Self ).fBitmap.Width
else
result := iMax( 1, Round( fResizedWidth ));
end;
// Returns the size of the bitmap.height if an image layer, otherwise the user's specified size for the object
function TIELayer.GetOriginalHeight: integer;
begin
if Self is TIEImageLayer then
result := TIEImageLayer( Self ).fBitmap.Height
else
result := iMax( 1, Round( fResizedHeight ));
end;
{!!
<FS>TIELayer.AspectRatioLocked
<FM>Declaration<FC>
property AspectRatioLocked: Boolean;
<FM>Description<FN>
When enabled the <A TIELayer.PreferredAspectRatio> for the layer will be enforced regardless of the setting for <A TImageEnView.LayersResizeAspectRatio>.
Default: False
<FM>Example<FC>
// Force aspect ratio locking if the object prefers it
ImageEnView1.CurrentLayer.AspectRatioLocked := ImageEnView1.CurrentLayer.PreferredAspectRatio <> 0;
ImageEnView1.Update();
!!}
procedure TIELayer.SetAspectRatioLocked(const Value: Boolean);
begin
fAspectRatioLocked := Value;
if Value then
begin
if Self is TIEPolylineLayer then
RestoreAspectRatio( False )
else
RestoreAspectRatio( True );
end;
LayerChange( False );
end;
procedure TIELayer.SetIsMask(const Value: Boolean);
begin
if Value and (( Self is TIEImageLayer ) = False ) then
raise EIEException.create( 'IsMask can only be applied to TIEImageLayer' );
fIsMask := Value;
LayerChange();
end;
{!!
<FS>TIELayer.Rotate
<FM>Declaration<FC>
property Rotate: Double;
<FM>Description<FN>
Specifies the layer rotation angle in degrees counter-clockwise.
Rotation and Resize cannot be used at the same time.
To allow resize after a layer rotation, it must be enacted, i.e. actually rotate the bitmap.
Conversely to allow rotation after a resize, the resizing must be enacted, actually resizing the bitmap.
To enact layer rotation, call <A TImageEnView.LayersFixRotations>.
To enact layer resizing, call <A TImageEnView.LayersFixSizes>.
Finally, multiple rotations can cause the bitmap to add an external, transparent border. To remove this border call <A TImageEnView.LayersFixBorders>.
Note: When rotation is handled by <A TImageEnView.MouseInteract> (setting miRotateLayers), you don't need to call LayersFixRotations, LayersFixSizes and LayersFixBorders.
<FM>Examples<FC>
// Rotate a line
ImageEnView1.CurrentLayer.Rotate := 235;
ImageEnView1.Update();
<IMG help_images\Line_EndShapes.gif>
// Set rotation of all selected layers
ImageEnView1.LockUpdate;
for i := 0 to ImageEnView1.LayersCount - 1 do
if ImageEnView1.Layers[ I ].Selected then
ImageEnView1.Layers[ I ].Rotate := 90;
ImageEnView1.LayersFixRotations( LYR_SELECTED_LAYERS );
ImageEnView1.UnlockUpdate;
// Apply a "Paid" stamp to image
with ImageEnView1 do
begin
LayersAdd( 'PAID', 'Arial Black', 42, clRed, [fsBold] );
CurrentLayer.Rotate := 30;
TIETextLayer( CurrentLayer ).SizeToText();
CurrentLayer.PosX := IELayer_Pos_HCenter;
CurrentLayer.PosY := IELayer_Pos_VCenter;
LayersMergeAll();
end;
<FM>Demos<FN>
<TABLE2>
<R> <C_IMG_DEMO> <C>Demos\ImageEditing\Layers\Layers.dpr </C> </R>
<R> <C_IMG_DEMO> <C>Demos\ImageEditing\Layers_AllTypes\Layers.dpr </C> </R>
<R> <C_IMG_DEMO> <C>Demos\ImageEditing\RotateLayers\RotateLayers.dpr </C> </R>
</TABLE>
<FM>See Also<FN>
- <A TImageEnView.LayersRotateAll>
- <A TIELayer.SupportsFeature>
!!}
procedure TIELayer.SetRotate(v: Double);
begin
if (frac(v) = 0) and (trunc(v) mod 360 = 0) then
fRotate := 0
else
fRotate := v;
while fRotate > 360 do
fRotate := fRotate - 360;
while fRotate < -360 do
fRotate := fRotate + 360;
LayerChange();
if ( Self is TIETextLayer ) and TIETextLayer( Self ).AutoSize then
TIETextLayer( Self ).SizeToText()
else
if ( Self is TIELineLayer ) and TIELineLayer( Self ).AutoSize then
TIELineLayer( Self ).SizeToFit();
end;
{!!
<FS>TIELayer.RotateCenterX
<FM>Declaration<FC>
property RotateCenterX: Double;
<FM>Description<FN>
Specifies the horizontal rotation center, in percentage of layer size.
0.5 means center (default), while 0 is left side and 1 is right side.
Also allowed are values less than 0 and greater than 1 (e.g. 2 would rotate at one width to the right of the image).
This value (and <A TIELayer.RotateCenterY>) is modified when user moves the central grip, when layers rotation is active.
Note: Applies only to <A TIEImageLayer>
Default: 0.5
<FM>Example<FC>
// Move rotation center to 25% in from top-left corner
ImageEnView1.CurrentLayer.RotateCenterX := 0.25;
ImageEnView1.CurrentLayer.RotateCenterY := 0.25;
ImageEnView1.Update();
<FM>See Also<FN>
- <A TIELayer.RotateCenterY>
- <A TIELayer.Rotate>
!!}
procedure TIELayer.SetRotateCenterX(v: Double);
begin
fRotateCenterX := v;
LayerChange();
end;
{!!
<FS>TIELayer.RotateCenterY
<FM>Declaration<FC>
property RotateCenterY: Double;
<FM>Description<FN>
Specifies the vertical rotation center, in percentage of layer size.
0.5 means center (default), while 0 is top side and 1 is bottom side.
Also allowed are values less than 0 and greater than 1 (e.g. 2 would rotate at one height below the image).
This value (and <A TIELayer.RotateCenterX>) is modified when user moves the central grip, when layers rotation is active.
Note: Applies only to <A TIEImageLayer>
Default: 0.5
<FM>Example<FC>
// Move rotation center to 25% in from top-left corner
ImageEnView1.CurrentLayer.RotateCenterX := 0.25;
ImageEnView1.CurrentLayer.RotateCenterY := 0.25;
ImageEnView1.Update();
<FM>See Also<FN>
- <A TIELayer.RotateCenterX>
- <A TIELayer.Rotate>
!!}
procedure TIELayer.SetRotateCenterY(v: Double);
begin
fRotateCenterY := v;
LayerChange();
end;
procedure TIELayer.SetSelected(const Value: boolean);
var
ieview : TImageEnView;
begin
ieview := (fOwner as TImageEnView);
if assigned(ieview) then
begin
if loAllowMultiSelect in ieview.LayerOptions then
if fSelected <> Value then
begin
fSelected := Value;
ieview.CallBitmapChangeEvents;
ieview.Update;
end;
end;
end;
{!!
<FS>TIELayer.ConvXScr2Bmp
<FM>Declaration<FC>
function ConvXScr2Bmp(x: Integer): Integer;
<FM>Description<FN>
Converts screen coordinates to bitmap coordinates, with consideration to the layer position and size.
<FM>See Also<FN>
- <A TImageEnView.XScr2Bmp>
- <A TIELayer.ConvYScr2Bmp>
- <A TIELayer.ConvXBmp2Scr>
- <A TIELayer.ConvYBmp2Scr>
!!}
function TIELayer.ConvXScr2Bmp(x: Integer): Integer;
var
ieview: TImageEnView;
begin
result := 0;
ieview := (fOwner as TImageEnView);
if assigned(ieview) and (Width <> 0) then
// note 1.0 required to make operation as double (otherwise overflow may occur)
result := trunc( 1.0 * ieview.XScr2Bmp(x - trunc( PosX * ieview.ZoomX / 100 ), false) * GetOriginalWidth / Width );
end;
{!!
<FS>TIELayer.ConvYScr2Bmp
<FM>Declaration<FC>
function ConvYScr2Bmp(y: Integer): Integer;
<FM>Description<FN>
Converts screen coordinates to bitmap coordinates, with consideration to the layer position and size.
<FM>See Also<FN>
- <A TImageEnView.YScr2Bmp>
- <A TIELayer.ConvXScr2Bmp>
- <A TIELayer.ConvXBmp2Scr>
- <A TIELayer.ConvYBmp2Scr>
!!}
function TIELayer.ConvYScr2Bmp(y: Integer): Integer;
var
ieview: TImageEnView;
begin
result := 0;
ieview := (fOwner as TImageEnView);
if assigned(ieview) and (Height <> 0) then
// note 1.0 required to make operation as double (otherwise overflow may occur)
result := trunc( 1.0 * ieview.YScr2Bmp(y - trunc( PosY * ieview.ZoomY / 100 ), false) * GetOriginalHeight / Height );
end;
{!!
<FS>TIELayer.ConvXBmp2Scr
<FM>Declaration<FC>
function ConvXBmp2Scr(x: Integer): Integer;
<FM>Description<FN>
Converts bitmap coordinates to screen coordinates, with consideration to the layer position and size.
<FM>See Also<FN>
- <A TImageEnView.XBmp2Scr>
- <A TIELayer.ConvYBmp2Scr>
- <A TIELayer.ConvXScr2Bmp>
- <A TIELayer.ConvYScr2Bmp>
!!}
function TIELayer.ConvXBmp2Scr(x: Integer): Integer;
var
ieview: TImageEnView;
bmpW: Integer;
begin
result := 0;
ieview := (fOwner as TImageEnView);
bmpW := GetOriginalWidth;
if assigned(ieview) and ( bmpW > 0 ) then
// note 1.0 required to make operation as double (otherwise overflow may occur)
result := ieview.XBmp2Scr(trunc(1.0 * x * Width / bmpW), false) + trunc( PosX * ieview.ZoomX / 100 );
end;
{!!
<FS>TIELayer.ConvYBmp2Scr
<FM>Declaration<FC>
function ConvYBmp2Scr(y: Integer): Integer;
<FM>Description<FN>
Converts bitmap coordinates to screen coordinates, with consideration to the layer position and size.
<FM>See Also<FN>
- <A TImageEnView.YBmp2Scr>
- <A TIELayer.ConvXBmp2Scr>
- <A TIELayer.ConvXScr2Bmp>
- <A TIELayer.ConvYScr2Bmp>
!!}
function TIELayer.ConvYBmp2Scr(y: Integer): Integer;
var
ieview: TImageEnView;
bmpH: Integer;
begin
result := 0;
ieview := (fOwner as TImageEnView);
bmpH := GetOriginalHeight;
if assigned(ieview) and ( bmpH > 0 ) then
// note 1.0 required to make operation as double (otherwise overflow may occur)
result := ieview.YBmp2Scr(trunc(1.0 * y * Height / bmpH), false) + trunc( PosY * ieview.ZoomY / 100 );
end;
procedure TIELayer.CalcClientAreaBox();
var
ieview: TImageEnView;
lyrX, lyrY, lyrW, lyrH: integer;
{}
function AlignXBmp2Scr(v: integer; ref: integer): integer;
begin
if TImageEnView( fOwner ).XScr2Bmp(v, false) < ref then
result := v + 1
else
if ieview.XScr2Bmp(v, false) > ref then
result := v - 1
else
result := v;
end;
{}
function AlignYBmp2Scr(v: integer; ref: integer): integer;
begin
if TImageEnView( fOwner ).YScr2Bmp(v, false) < ref then
result := v + 1
else
if ieview.YScr2Bmp(v, false) > ref then
result := v - 1
else
result := v;
end;
{}
begin
ieview := TImageEnView( fOwner );
if not assigned( ieview ) then
exit;
lyrX := ieview.XBmp2Scr(PosX, false);
lyrX := AlignXBmp2Scr(lyrX, PosX);
lyrY := ieview.YBmp2Scr(PosY, false);
lyrY := AlignYBmp2Scr(lyrY, PosY);
lyrW := ieview.XBmp2Scr(PosX + GetWidth, false);
lyrW := AlignXBmp2Scr(lyrW, PosX + GetWidth);
dec(lyrW, lyrX);
lyrH := ieview.YBmp2Scr(PosY + GetHeight, false);
lyrH := AlignYBmp2Scr(lyrH, PosY + GetHeight);
dec(lyrH, lyrY);
fClientAreaBox := Rect(lyrX, lyrY, lyrX + lyrW, lyrY + lyrH);
end;
// ScaleToZoom: Vector layers are created at zoom level rather than design level
procedure TIELayer.CalcPaintPos(ImgWidth, ImgHeight: Integer;
out XDst, YDst, WidthDst, HeightDst: integer;
out XSrc, YSrc, WidthSrc, HeightSrc: integer);
var
ieview: TImageEnView;
currW, currH: Integer;
layer0Left, layer0Top, layer0Right, layer0Bottom: Integer;
begin
ieview := TImageEnView( fOwner );
if not assigned( ieview ) then
exit;
XDst := fClientAreaBox.Left;
YDst := fClientAreaBox.Top;
WidthDst := fClientAreaBox.Right - XDst;
HeightDst := fClientAreaBox.Bottom - YDst;
XSrc := 0;
YSrc := 0;
WidthSrc := ImgWidth;
HeightSrc := ImgHeight;
if fCropped or ieview.LayersCropped then
begin
currW := GetWidth;
currH := GetHeight;
layer0Left := ieview.Layers[0].PosX;
layer0Top := ieview.Layers[0].PosY;
layer0Right := ieview.Layers[0].PosX + ieview.Layers[0].Width;
layer0Bottom := ieview.Layers[0].PosY + ieview.Layers[0].Height;
// cropped
if ieview.XScr2Bmp(XDst, false) < layer0Left then
begin
XSrc := - trunc(( PosX - layer0Left ) * ( ImgWidth / currW ));
WidthSrc := ImgWidth - XSrc;
XDst := ieview.XBmp2Scr( layer0Left, false );
WidthDst := ieview.XBmp2Scr( currW + PosX, false ) - XDst;
end;
if ieview.YScr2Bmp(YDst, false) < layer0Top then
begin
YSrc := - trunc(( PosY - layer0Top ) * ( ImgHeight / currH ));
HeightSrc := ImgHeight - YSrc;
YDst := ieview.YBmp2Scr( layer0Top, false );
HeightDst := ieview.YBmp2Scr( currH + PosY, false ) - YDst;
end;
if ieview.XScr2Bmp(XDst + WidthDst, false) > layer0Right then
begin
WidthDst := ieview.XBmp2Scr( layer0Right, false ) - XDst;
WidthSrc := trunc(WidthDst * ( ImgWidth / (fClientAreaBox.Right - fClientAreaBox.Left)));
end;
if ieview.YScr2Bmp(YDst + HeightDst, false) > layer0Bottom then
begin
HeightDst := ieview.YBmp2Scr( layer0Bottom, false ) - YDst;
HeightSrc := trunc(HeightDst * ( ImgHeight / (fClientAreaBox.Bottom - fClientAreaBox.Top )));
end;
end;
fDrawingInfo.XDst := XDst;
fDrawingInfo.YDst := YDst;
fDrawingInfo.WidthDst := WidthDst;
fDrawingInfo.HeightDst := HeightDst;
fDrawingInfo.XSrc := XSrc;
fDrawingInfo.YSrc := YSrc;
fDrawingInfo.WidthSrc := WidthSrc;
fDrawingInfo.HeightSrc := HeightSrc;
{$IFDEF IEDEBUG}
OutputDebugStringA(PAnsiChar('TIELayer.PaintTo'));
OutputDebugStringA(PAnsiChar(string( ' XDst='+IntToStr(lXDst)+' YDst='+IntToStr(lYDst)+
' WidthDst='+IntToStr(WidthDst)+' HeightDst='+IntToStr(HeightDst)+
' XSrc='+IntToStr(lXSrc)+' YSrc='+IntToStr(lYSrc)+
' WidthSrc='+IntToStr(WidthSrc)+' HeightSrc='+IntToStr(HeightSrc)
)));
{$ENDIF}
end;
procedure TIELayer.PaintTo(DstBitmap: TIEBitmap; LyrIdx: Integer;
XLUT, YLUT: pinteger; UpdRect: PRect; xDst, yDst, dxDst, dyDst: integer; xSrc, ySrc, dxSrc, dySrc: integer;
EnableAlpha: boolean; SolidBackground: boolean; Filter: TResampleFilter; RotationFilter: TIEAntialiasMode; ResizingLayer: Boolean);
var
lXSrc, lYSrc, lWidthSrc, lHeightSrc: integer;
lXDst, lYDst, lWidthDst, lHeightDst: integer;
dummy1, dummy2: PInteger;
fastDrawing: Boolean;
createWidth, createHeight: Integer;
layersCaching: Boolean;
function _CacheAvailable(CWidth, CHeight: Integer) : boolean;
begin
Result := layersCaching and
assigned ( fLayerCacheBitmap ) and
fLayerCacheValid and
( fLayerCacheBitmap.Width = CWidth ) and
( fLayerCacheBitmap.Height = CHeight );
end;
begin
if fOriginalAspectRatio = 0 then
fOriginalAspectRatio := OriginalWidth / OriginalHeight;
CalcClientAreaBox();
fastDrawing := Owner_FastDrawingActive();
layersCaching := False;
if assigned( fOwner ) then
layersCaching := ( TImageEnView( fOwner ).LayersCaching = -1 ) or
( LyrIdx < TImageEnView( fOwner ).LayersCaching );
createWidth := GetWidth;
createHeight := GetHeight;
if assigned( fOwner ) and ( layersCaching or not fastDrawing ) then
begin
// Scale to zoom
createWidth := Round( createWidth * TImageEnView( fOwner ).ZoomX / 100 );
createHeight := Round( createHeight * TImageEnView( fOwner ).ZoomY / 100 );
end;
CalcPaintPos(createWidth, createHeight,
lXDst, lYDst, lWidthDst, lHeightDst,
lXSrc, lYSrc, lWidthSrc, lHeightSrc);
if fAntiAlias and ( Kind = ielkShape ) then
if ( fastDrawing = False ) or
( FastDrawing and _CacheAvailable( 2 * createWidth, 2 * createHeight ) and not fLayerCachefastDrawn) then
begin
createWidth := 2 * createWidth;
createHeight := 2 * createHeight;
lXSrc := 2 * lXSrc;
lYSrc := 2 * lYSrc;
lWidthSrc := 2 * lWidthSrc;
lHeightSrc := 2 * lHeightSrc ;
if Filter = rfNone then
Filter := rfFastLinear;
end;
dummy1 := nil;
dummy2 := nil;
if layersCaching then
begin
// If we want high quality and cache bitmap is low quality then redraw
if ( fastDrawing = False ) and
assigned ( fLayerCacheBitmap ) and
fLayerCachefastDrawn then
fLayerCacheValid := False;
if _CacheAvailable( createWidth, createHeight ) = False then
begin
// cache image is not valid
CopyToBitmapEx( fLayerCacheBitmap, createWidth, createHeight, fastDrawing, EnableAlpha, False );
fLayerCachefastDrawn := fastDrawing;
end;
RenderLayerWithAdornments(DstBitmap, LyrIdx, fLayerCacheBitmap, True,
dummy1, dummy2, UpdRect,
lXDst, lYDst, lWidthDst, lHeightDst,
lXSrc, lYSrc, lWidthSrc, lHeightSrc,
EnableAlpha, SolidBackground, Filter );
fLayerCacheValid := True;
end
else
begin
CopyToBitmapEx( fGlobalCacheBitmap, createWidth, createHeight, fastDrawing, EnableAlpha, False );
RenderLayerWithAdornments(DstBitmap, LyrIdx, fGlobalCacheBitmap, True,
dummy1, dummy2, UpdRect,
lXDst, lYDst, lWidthDst, lHeightDst,
lXSrc, lYSrc, lWidthSrc, lHeightSrc,
EnableAlpha, SolidBackground, Filter );
end;
end;
{!!
<FS>TIELayer.GetLayerMask
<FM>Declaration<FC>
function GetLayerMask(): <A TIELayer>;
<FM>Description<FN>
Returns the layer mask associated with this layer. Returns "nil" if no layer mask exists.
!!}
function TIELayer.GetLayerMask(): TIELayer;
var
ieview: TImageEnView;
idx: integer;
begin
result := nil;
ieview := (fOwner as TImageEnView);
if assigned(ieview) then
begin
idx := GetIndex();
if (idx > - 1) and (idx + 1 < ieview.LayersList.Count) and (ieview.Layers[idx + 1].IsMask) then
result := ieview.Layers[idx + 1];
end;
end;
{!!
<FS>TIEImageLayer.IsMask
<FM>Declaration<FC>
property IsMask: Boolean;
<FM>Description<FN>
If True this is a layer mask. A layer mask contains a gray scale image (ie8g) which is connected to the upper layer (i.e. if Layer 3 is a mask, then it will apply to layer 2).
The layer mask specifies what parts of the upper layer is visible (i.e. mask pixels of 0 will hide the underlying image. Whereas, pixels of 255 will be fully visible).
A layer mask should be invisible (<A TIELayer.Visible>=False).
// This is an example of a mask image (right-click to save to file). The black areas will become fully transparent in the underlying image. The gray will have 50% transparency and the white will be fully opaque.
<IMG help_images\Mask.png>
Default: False
Notes:
- This property is only valid for <L TIEImageLayer>image layers</L>
- Mask layers will only affect <L TIEImageLayer>image layers</L>
<FM>Example<FC>
// Clear and load our image into Layer 0
ImageEnView1.ClearAll();
ImageEnView1.IO.LoadFromFile( 'C:\Image.jpg' );
// Now add our mask layer
ImageEnView1.LayersAdd( ielkImage );
ImageEnView1.IO.LoadFromFile( 'C:\Mask.png' );
TIEImageLayer( ImageEnView1.CurrentLayer ).IsMask := True;
ImageEnView1.CurrentLayer.Visible := False;
ImageEnView1.CurrentLayer.PosX := 0;
ImageEnView1.CurrentLayer.PosY := 0;
ImageEnView1.CurrentLayer.Width := ImageEnView1.Layers[0].Width;
ImageEnView1.CurrentLayer.Height := ImageEnView1.Layers[0].Height;
Source Image:
<IMG help_images\MaskImage.jpg>
Mask Image:
<IMG help_images\Mask.png>
Result (on a white TImageEnView):
<IMG help_images\MaskResult.jpg>
!!}
function TIELayer.GetIsMask: Boolean;
begin
Result := False;
if Self is TIEImageLayer then
Result := fIsMask;
end;
{!!
<FS>TIELayer.Selected
<FM>Declaration<FC>
property Selected: boolean;
<FM>Description<FN>
True if the layer is currently selected.
A selected text layer:
<IMG help_images\text_Selected.gif>
!!}
function TIELayer.GetSelected: boolean;
var
ieview: TImageEnView;
begin
ieview := (fOwner as TImageEnView);
if assigned(ieview) then
begin
if loAllowMultiSelect in ieview.LayerOptions then
Result := fSelected
else
Result := ieview.LayersList.IndexOf(self) = ieview.LayersCurrent;
end
else
result := false;
end;
{!!
<FS>TIELayer.GetIndex
<FM>Declaration<FC>
function GetIndex(): integer;
<FM>Description<FN>
Returns the index of this layer inside the <A TImageEnView.Layers> list. Returns -1 if not found.
!!}
// -1 = not found
function TIELayer.GetIndex(): integer;
var
ieview: TImageEnView;
begin
ieview := (fOwner as TImageEnView);
if assigned(ieview) then
result := ieview.LayersList.IndexOf(self)
else
result := -1;
end;
{!!
<FS>TIELayer.Visible
<FM>Declaration<FC>
property Visible: Boolean;
<FM>Description<FN>
Set to True to make the layer visible, or False to hide it.
Default: True
<FM>Example<FC>
// Toggle visibility of current layer
ImageEnView1.CurrentLayer.Visible := not ImageEnView1.CurrentLayer.Visible;
ImageEnView1.Update();
!!}
procedure TIELayer.SetVisible(Value: Boolean);
begin
fVisible := Value;
LayerChange( False );
end;
{!!
<FS>TIELayer.VisibleBox
<FM>Declaration<FC>
property VisibleBox: boolean;
<FM>Description<FN>
Display a selection box around the layer.
If VisibleBox is disabled, there is no visual indication that the layer is selected.
A selected text layer:
<IMG help_images\text_Selected.gif>
Default: True
Also, see: <A TImageEnView.LayersDrawBox>
<FM>Example<FC>
// Toggle box of current layer
ImageEnView1.CurrentLayer.VisibleBox := not ImageEnView1.CurrentLayer.VisibleBox;
ImageEnView1.Update();
!!}
procedure TIELayer.SetVisibleBox(Value: Boolean);
begin
fVisibleBox := Value;
LayerChange( False );
end;
{!!
<FS>TIELayer.Transparency
<FM>Declaration<FC>
property Transparency: integer;
<FM>Description<FN>
Set the overall transparency of the layer in the range from 0 (fully transparent) to 255 (totally opaque).
Use <A TIELayer.Opacity> instead of Transparency when the image has an alpha channel.
<IMG help_images\transparency.jpg>
Default: 255 (fully opaque)
<FM>See Also<FN>
- <A TIELayer.Opacity>
<FM>Example<FC>
// Make all selected layers 50% transparency
for i := 0 to ImageEnView1.LayersCount - 1 do
if ImageEnView1.Layers[ I ].Selected then
ImageEnView1.Layers[ I ].Transparency := 128;
ImageEnView1.Update();
!!}
procedure TIELayer.SetTransparency(Value: integer);
begin
fTransparency := Value;
LayerChange( False );
end;
{!!
<FS>TIELayer.Opacity
<FM>Declaration<FC>
property Opacity: double;
<FM>Description<FN>
Set the overall opacity of the layer in the range from 0 (fully transparent) to 1.0 (totally opaque).
Use Opacity instead of <A TIELayer.Transparency> when the image has an alpha channel.
<IMG help_images\transparency.jpg>
Default: 1.0 (fully opaque)
<FM>See Also<FN>
- <A TIELayer.Transparency>
- <A TIELayer.AlphaEdgeFeathering>
<FM>Example<FC>
// Make all selected layers 50% opacity
for i := 0 to ImageEnView1.LayersCount - 1 do
if ImageEnView1.Layers[ I ].Selected then
ImageEnView1.Layers[ I ].Opacity := 0.5;
ImageEnView1.Update();
!!}
procedure TIELayer.SetOpacity(Value: double);
begin
fOpacity := Value;
LayerChange( False );
end;
{!!
<FS>TIELayer.AlphaEdgeFeathering
<FM>Declaration<FC>
property AlphaEdgeFeathering: Integer;
<FM>Description<FN>
If the layer has an alpha channel then edges of the image will be "feathered." Feathering softens the edges of an image by applying alpha transparency at a rate that is proportional to the distance to the edge (specifically, adding a gradient in the alpha channel).
The value (0 to 255) indicates the depth in pixels of the feather effect.
Default: 0 (no edge feathering)
<FM>See Also<FN>
- <A TIELayer.Opacity>
- <A TImageEnView.LayersFastDrawing>
<FM>Example<FC>
// Apply alpha edge feathering to all selected layers
for i := 0 to ImageEnView1.LayersCount - 1 do
if ImageEnView1.Layers[ I ].Selected then
ImageEnView1.Layers[ I ].AlphaEdgeFeathering := 5;
ImageEnView1.Update();
!!}
procedure TIELayer.SetAlphaEdgeFeathering(Value: Integer);
begin
fAlphaEdgeFeathering := Value;
LayerChange( False );
end;
{!!
<FS>TIELayer.Cropped
<FM>Declaration<FC>
property Cropped: Boolean;
<FM>Description<FN>
When enabled, any part of the layer that is outside the background image (layer 0) area will not be displayed.
If this value is false, then <A TImageEnView.LayersCropped> controls whether layers are cropped to the background.
Default: False
<FM>Example<FC>
// Crop the display of only the current layer
ImageEnView1.LayersCropped := False;
ImageEnView1.CurrentLayer.Cropped := True;
ImageEnView1.Update();
// Crop the display of all layers
ImageEnView1.LayersCropped := True;
ImageEnView1.Update();
// Don't crop the display of any layers
ImageEnView1.UnlockUpdate();
ImageEnView1.LayersCropped := False;
for i := 0 to ImageEnView1.LayersCount - 1 do
ImageEnView1.Layers[ I ].Cropped := False;
ImageEnView1.LockUpdate();
!!}
procedure TIELayer.SetCropped(Value: boolean);
begin
fCropped := Value;
LayerChange( False );
end;
{!!
<FS>TIELayer.Locked
<FM>Declaration<FC>
property Locked: Boolean;
<FM>Description<FN>
When False the user can move or resize the layer. Also enables display of the layer border and resizing grips.
Default: False
<FM>Example<FC>
// Prevent movement of current layer
ImageEnView1.CurrentLayer.Locked := True;
!!}
procedure TIELayer.SetLocked(Value: boolean);
begin
fLocked := Value;
LayerChange( False );
end;
{!!
<FS>TIELayer.Selectable
<FM>Declaration<FC>
property Selectable: boolean;
<FM>Description<FN>
If true, the layer is selectable by the user.
A selected text layer:
<IMG help_images\text_Selected.gif>
Default: True
<FM>Example<FC>
// Prevent selection of current layer
ImageEnView1.CurrentLayer.Selectable := True;
!!}
procedure TIELayer.SetSelectable(Value: boolean);
begin
fSelectable := Value;
LayerChange( False );
end;
{!!
<FS>TIELayer.Operation
<FM>Declaration<FC>
property Operation: <A TIERenderOperation>;
<FM>Description<FN>
Specifies the color operation to execute between this layer and the background layer.
Default: ielNormal
<FM>Example<FC>
// Average current layer with background
ImageEnView1.CurrentLayer.Operation := ielAverage;
ImageEnView1.Update();
!!}
procedure TIELayer.SetOperation(Value: TIERenderOperation);
begin
fOperation := Value;
LayerChange( False );
end;
{!!
<FS>TIELayer.UserDataLen
<FM>Declaration<FC>
property UserDataLen: Integer;
<FM>Description<FN>
Specifies the length of UserData buffer.
If this value is greater than zero:
- When you save the layer (LayersSaveTo..) the content of <A TIELayer.UserData> buffer is saved (and restored with LayersLoadFrom..)
- The user data is freed when the layer is destroyed
<FM>Example<FC>
type
TMyRecord = record
SourceText: array[0..255] of AnsiChar;
SourceWidth: integer;
SourceHeight: integer;
end;
PMyRecord = ^TMyRecord;
var
rc: PMyRecord;
begin
New( rc )
With rc^ do
begin
Width := ...;
Height := ...;
Text := ...;
end;
ImageEnView1.CurrentLayer.UserData := rc;
ImageEnView1.CurrentLayer.UserDataLen := SizeOf( PMyRecord );
end;
<FM>See Also<FN>
- <A TIELayer.UserData>
!!}
procedure TIELayer.SetUserDataLen(Value: Integer);
begin
fUserDataLen := Value;
LayerChange( False );
end;
{!!
<FS>TIELayer.Name
<FM>Declaration<FC>
property Name: String;
<FM>Description<FN>
Specifes a name for the layer. This is not used by ImageEn.
<FM>Example<FC>
procedure TfrmMain.ievMainLayerNotify(Sender: TObject; layer: Integer; event: TIELayerEvent);
begin
// Give each later a date based name
ievMain.Layers[layer].Name := 'Layer created at ' + DateTimeToStr( now );
end;
!!}
procedure TIELayer.SetName(Value: String);
begin
fName := Value;
LayerChange( False );
end;
{!!
<FS>TIELayer.DrawOuter
<FM>Declaration<FC>
property DrawOuter: Boolean;
<FM>Description<FN>
If True, the unselected layers are drawn as "grayed". The current layer is drawn normally.
Default: False
Note: Only the <L TImageEnView.LayersCurrent>current layer</L> is shown as ungrayed. All other layers, even if there are multiple selected layers
<FM>Example<FC>
// Grey areas outside of current layer
ImageEnView1.CurrentLayer.DrawOuter := True;
ImageEnView1.Update();
!!}
procedure TIELayer.SetDrawOuter(Value: Boolean);
begin
fDrawOuter := Value;
LayerChange( False );
end;
{!!
<FS>TIELayer.Guid
<FM>Declaration<FC>
property Guid: TGuid;
<FM>Description<FN>
A unique identifier for this layer.
!!}
procedure TIELayer.SetGuid(Value: TGuid);
begin
fGuid := Value;
LayerChange( False );
end;
{!!
<FS>TIELayer.Tag
<FM>Declaration<FC>
property Tag: Integer;
<FM>Description<FN>
An integer value that you can use for your own purposes.
<FM>Example<FC>
procedure TfrmMain.ievMainLayerNotify(Sender: TObject; layer: Integer; event: TIELayerEvent);
begin
// Assign date to each layer
ievMain.Layers[layer].Tag := Trunc( now );
end;
!!}
procedure TIELayer.SetTag(Value: Integer);
begin
fTag := Value;
LayerChange( False );
end;
function TIELayer.Owner_EnableAlphaChannel(): Boolean;
begin
Result := true;
if assigned( fOwner ) then
Result := TImageEnView( fOwner ).EnableAlphaChannel;
end;
function TIELayer.Owner_FastDrawingActive(): Boolean;
begin
Result := False;
if assigned( fOwner ) then
Result := TImageEnView( fOwner ).LayersFastDrawingActive;
end;
function TIELayer.Owner_FastOutputActive(): Boolean;
begin
Result := False;
if assigned( fOwner ) then
Result := TImageEnView( fOwner ).LayersFastOutput;
end;
// Render SrcBitmap to DstBitmap adding a softshadow and feathering if enabled
procedure TIELayer.RenderLayerWithAdornments(DstBitmap: TIEBitmap; LyrIdx: Integer; SrcBitmap: TIEBitmap; CanModifySrc: Boolean;
XLUT, YLUT: pinteger; UpdRect: PRect; xDst, yDst, dxDst, dyDst: integer; xSrc, ySrc, dxSrc, dySrc: integer;
EnableAlpha: boolean; SolidBackground: boolean; Filter: TResampleFilter);
var
needNewBitmap: Boolean;
shadowW, shadowH: Integer;
bmpW, bmpH: Integer;
ieview: TImageEnView;
TempBmp : TIEBitmap;
fastDrawing: Boolean;
begin
ieview := (fOwner as TImageEnView);
fastDrawing := Owner_FastDrawingActive();
// If this is an image layer, we can only modify a copy of the image
needNewBitmap := False;
if fastDrawing = False then
needNewBitmap := ( fAlphaEdgeFeathering > 0 ) or (( LyrIdx > 0 ) and SoftShadow.Enabled );
if needNewBitmap and ( CanModifySrc = False ) then
begin
TempBmp := TIEBitmap.Create( SrcBitmap );
RenderLayerWithAdornments(DstBitmap, LyrIdx, TempBmp, True,
XLUT, YLUT, UpdRect,
xDst, yDst, dxDst, dyDst,
xSrc, ySrc, dxSrc, dySrc,
EnableAlpha, SolidBackground, Filter);
TempBmp.Free;
exit;
end;
if ( fAlphaEdgeFeathering > 0 ) and ( fastDrawing = False ) then
SrcBitmap.FeatherAlphaEdges( fAlphaEdgeFeathering );
if SoftShadow.Enabled and ( LyrIdx > 0 ) and ( fastDrawing = False ) then
begin
bmpW := SrcBitmap.Width;
bmpH := SrcBitmap.Height;
_IEAddSoftShadow(SrcBitmap, Trunc(SoftShadow.Radius * ( ieview.ZoomX + ieview.ZoomY ) / 200), Trunc(SoftShadow.OffsetX * ieview.ZoomX / 100), Trunc(SoftShadow.OffsetY * ieview.ZoomY / 100), SoftShadow.Intensity,
TRUE, SoftShadow.ShadowColor, nil, Nil);
shadowW := SrcBitmap.Width - bmpW;
shadowH := SrcBitmap.Height - bmpH;
XDst := XDst - Round( shadowW / 2 * GetWidth / bmpW * ieview.ZoomX / 100 );
YDst := YDst - Round( shadowH / 2 * GetHeight / bmpH * ieview.ZoomY / 100 );
dxDst := dxDst + Round( shadowW * GetWidth / bmpW * ieview.ZoomX / 100 );
dyDst := dyDst + Round( shadowH * GetHeight / bmpH * ieview.ZoomY / 100 );
XSrc := imax( 0, XSrc - shadowW div 2 );
YSrc := imax( 0, YSrc - shadowH div 2 );
dxSrc := dxSrc + shadowW;
dySrc := dySrc + shadowH;
end;
SrcBitmap.RenderToTIEBitmap(DstBitmap,
XLUT, YLUT, UpdRect,
XDst, YDst, dxDst, dyDst,
XSrc, YSrc, dxSrc, dySrc,
EnableAlpha, SolidBackground, fTransparency,
Filter, true, fOperation, fOpacity);
end;
{!!
<FS>TIELayer.ConvertToImageLayer
<FM>Declaration<FC>
procedure ConvertToImageLayer(QualityFactor: Double = 2; CropAlpha: Boolean = True);
<FM>Description<FN>
Changes the <A TIELayer.Kind>type</L> of the current layer to <A TIEImageLayer>.
This will change it from a vector-based layer to a standard bitmap layer. Bitmap layers can be edited using <L TImageEnProc>standard image modification features</L>, but the quality will be lost if you resize the layer.
<FC>QualityFactor<FN> determines the size that the layer bitmap is created. A <FC>QualityFactor<FN> of 1 will create the bitmap at the current display size, whereas a <FC>QualityFactor<FN> of 2 would create it at double the display size (allowing it to be zoomed up 200% without loss of quality).
If <FC>CropAlpha<FN> is true, then it remove any alpha from the edges of the layer.
Note:
- For text layers, a QualityFactor of 1 usually works best
- To convert multiple layers, use <A TImageEnView.LayersConvertToImageLayers>
<FM>Example<FC>
// Convert the current layer to an image, and apply a Negative effect
ImageEnView1.CurrentLayer.ConvertToImageLayer();
ImageEnView1.Proc.Negative();
!!}
procedure TIELayer.ConvertToImageLayer(QualityFactor: Double = 2; CropAlpha: Boolean = True);
var
ieview: TImageEnView;
begin
ieview := (fOwner as TImageEnView);
if assigned(ieview) then
ieview.LayersConvertToImageLayersEx( GetIndex, QualityFactor, CropAlpha, False, ieview.Proc.AutoUndo and ( loAutoUndoChangesByCode in ieview.LayerOptions ));
end;
// *************************************************************************************** //
// ** ** //
// ** TIEImageLayer ** //
// ** ** //
// *************************************************************************************** //
constructor TIEImageLayer.Create(Owner: TObject; TemplateBitmap: TIEBitmap; JustAssign: boolean);
var
bmp: TBitmap;
begin
inherited Create(Owner);
fKind := ielkImage;
if JustAssign and assigned( TemplateBitmap ) then
begin
fBitmap := TemplateBitmap;
end
else
begin
fBitmap := TIEBitmap.Create;
if assigned(TemplateBitmap) then
begin
if TemplateBitmap.EncapsulatedFromTBitmap then
begin
bmp := TBitmap.Create();
bmp.Width := 1;
bmp.Height := 1;
bmp.PixelFormat := TemplateBitmap.VclBitmap.PixelFormat;
bmp.Width := TemplateBitmap.Width;
bmp.Height := TemplateBitmap.Height;
fBitmap.EncapsulateTBitmap(bmp, true);
end
else
begin
fBitmap.Location := TemplateBitmap.Location;
fBitmap.Allocate(TemplateBitmap.Width, TemplateBitmap.Height, TemplateBitmap.PixelFormat);
end;
end;
end;
fFreeBitmapOnDestroy := true;
SetDefaults;
end;
constructor TIEImageLayer.Create(Owner: TObject; Width, Height : Integer);
begin
Create( Owner, nil, False );
fBitmap.Allocate( Width, Height );
end;
// Make a image layer clone of another layer, even if it is a non-image layer
constructor TIEImageLayer.Create(Owner: TObject; TemplateLayer: TIELayer; QualityFactor: Double = 2; CropAlpha: Boolean = True);
var
bmp: TIEBitmap;
begin
bmp := nil; // Let it auto-create
TemplateLayer.CopyToBitmap( bmp, Trunc( TemplateLayer.Width * QualityFactor ), Trunc( TemplateLayer.Height * QualityFactor ), True, False );
Create( Owner, bmp, True );
// Note: Following properties are not applied to image, but are assigned as params anyway
// Transparency, Opacity, SoftShadow, AlphaEdgeFeathering
Assign( TemplateLayer );
fRotate := 0; { rotate is already effected in the conversion }
// Remove border
BorderColor := clNone_;
if QualityFactor = 1 then
RestoreSize();
if CropAlpha then
Self.CropAlpha();
end;
destructor TIEImageLayer.Destroy;
begin
if fFreeBitmapOnDestroy then
begin
if fBitmap.EncapsulatedFromTBitmap then
begin
fBitmap.VclBitmap.Free;
fBitmap.VclBitmap := nil;
end;
FreeAndNil(fBitmap);
end;
inherited Destroy;
end;
function TIEImageLayer.GetBitmap : TIEBitmap;
begin
Result := fBitmap;
end;
{!!
<FS>TIEImageLayer.ResampleFilter
<FM>Declaration<FC>
property ResampleFilter: <A TResampleFilter>;
<FM>Description<FN>
When <A TIEImageLayer.UseResampleFilter> is true, this property specifies a resample filter to use instead of default to improve the quality of images.
The default display filter is specified by <A TImageEnView.ZoomFilter>. The filter used when merging layers is specified by <A TImageEnView.LayersMergeFilter>.
Default: rfFastLinear
Note: Only available to <A TIEImageLayer>. To improve the display quality of other layers, use <A TIELayer.AntiAlias>.
<FM>Example<FC>
// Use rfTriangle for just the current layer
TIEImageLayer( ImageEnView1.CurrentLayer ).ResampleFilter := rfTriangle;
TIEImageLayer( ImageEnView1.CurrentLayer ).UseResampleFilter := True;
ImageEnView1.Update();
<FM>See Also<FN>
- <A TIEImageLayer.UseResampleFilter>
- <A TIELayer.AntiAlias>
- <A TImageEnView.ZoomFilter>
- <A TImageEnView.LayersMergeFilter>
- <A TImageEnView.LayersFastDrawing>
!!}
{$ifndef IEIncludeDeprecatedInV6}
// Moved from TIELayer class in 7.0.0 (2016-10-26)
procedure TIEImageLayer.SetResampleFilter(Value: TResampleFilter);
begin
fResampleFilter := Value;
LayerChange();
end;
{$ENDIF}
{!!
<FS>TIEImageLayer.UseResampleFilter
<FM>Declaration<FC>
property UseResampleFilter: boolean;
<FM>Description<FN>
Enables the usage of the quality filter specified by <A TIEImageLayer.ResampleFilter> instead of the default.
The default display filter is specified by <A TImageEnView.ZoomFilter>. The filter used when merging layers is specified by <A TImageEnView.LayersMergeFilter>.
Default: False
Note: Only available to <A TIEImageLayer>. To improve the display quality of other layers, use <A TIELayer.AntiAlias>.
<FM>Example<FC>
// Use rfTriangle for just the current layer
TIEImageLayer( ImageEnView1.CurrentLayer ).ResampleFilter := rfTriangle;
TIEImageLayer( ImageEnView1.CurrentLayer ).UseResampleFilter := True;
ImageEnView1.Update();
<FM>See Also<FN>
- <A TIEImageLayer.ResampleFilter>
- <A TIELayer.AntiAlias>
- <A TImageEnView.ZoomFilter>
- <A TImageEnView.LayersMergeFilter>
- <A TImageEnView.LayersFastDrawing>
!!}
{$ifndef IEIncludeDeprecatedInV6}
// Moved from TIELayer class in 7.0.0 (2016-10-26)
procedure TIEImageLayer.SetUseResampleFilter(Value : Boolean);
begin
fUseResampleFilter := Value;
LayerChange();
end;
{$ENDIF}
{!!
<FS>TIEImageLayer.BorderColor
<FM>Declaration<FC>
property BorderColor: TColor;
<FM>Description<FN>
The color of the frame around the image.
By default, image layers do not show a border (i.e. <FC>BorderColor<FN> = clNone). Set a valid color for <FC>BorderColor<FN> to show a border.
Default: clNone
<FM>Example<FC>
// Add a thick pink border to the image layer
TIEImageLayer( ImageEnView1.CurrentLayer ).BorderColor := $008000FF;
TIEImageLayer( ImageEnView1.CurrentLayer ).BorderWidth := 3;
ImageEnView1.Update();
<IMG help_images\Image_withBorder.gif>
<FM>See Also<FN>
- <L TIELayer.BorderColor>TIELayer.BorderColor</L>
- <A TIEImageLayer.BorderWidth>
!!}
function TIEImageLayer.GetBorderColor: TColor;
begin
Result := fBorderColor;
end;
procedure TIEImageLayer.SetBorderColor(value: TColor);
begin
fBorderColor := Value;
LayerChange();
end;
{!!
<FS>TIEImageLayer.BorderWidth
<FM>Declaration<FC>
property BorderWidth: Integer;
<FM>Description<FN>
The width of the frame around the image.
Note: By default, image layers do not show a border. Set a valid color for <A TIEImageLayer.BorderColor> to show a border.
Default: 1
<FM>Example<FC>
// Add a thick pink border to the image layer
TIEImageLayer( ImageEnView1.CurrentLayer ).BorderColor := $008000FF;
TIEImageLayer( ImageEnView1.CurrentLayer ).BorderWidth := 3;
ImageEnView1.Update();
<IMG help_images\Image_withBorder.gif>
<FM>See Also<FN>
- <L TIELayer.BorderWidth>TIELayer.BorderWidth</L>
- <A TIEImageLayer.BorderColor>
!!}
function TIEImageLayer.GetBorderWidth: Integer;
begin
Result := fBorderWidth;
end;
procedure TIEImageLayer.SetBorderWidth(value: Integer);
begin
fBorderWidth := Value;
LayerChange();
end;
procedure TIEImageLayer.CopyToBitmapEx(var Dest: TIEBitmap;
CreateWidth : Integer; CreateHeight : Integer;
FastDrawing: Boolean;
EnableAlpha: Boolean; UseDisplayAR: Boolean;
UpdateSize: Boolean = False; EnlargeOnly: Boolean = False;
Zoom: Double = 1);
var
resamSize: TPoint;
begin
if CreateWidth < 1 then
CreateWidth := OriginalWidth;
if CreateHeight < 1 then
CreateHeight := OriginalHeight;
if Dest = nil then
InitBitmap( Dest, 1, 1 );
Dest.Assign( fBitmap );
if UseDisplayAR then
begin
// Size to display AR
resamSize := GetImageSizeWithinArea( Width, Height, CreateWidth, CreateHeight );
Dest.Resample( resamSize.X, resamSize.Y, fResampleFilter );
if EnableAlpha then
Dest.AlphaChannel; // create alpha channel
Dest.Resize( CreateWidth, CreateHeight, clWhite, 0, iehCenter, ievCenter );
end
else
Dest.Resample( CreateWidth, CreateHeight, fResampleFilter );
if not EnableAlpha then
Dest.RemoveAlphaChannel();
end;
procedure TIEImageLayer.CopyToBitmap(var Dest: TIEBitmap; CreateWidth : Integer = -1; CreateHeight : Integer = -1; EnableAlpha: Boolean = True; UseDisplayAR: Boolean = True);
begin
CopyToBitmapEx( Dest, CreateWidth, CreateHeight, Owner_FastOutputActive(), EnableAlpha, UseDisplayAR );
end;
procedure TIEImageLayer.PaintTo(DstBitmap: TIEBitmap; LyrIdx: Integer;
XLUT, YLUT: pinteger; UpdRect: PRect; xDst, yDst, dxDst, dyDst: integer; xSrc, ySrc, dxSrc, dySrc: integer;
EnableAlpha: boolean; SolidBackground: boolean; Filter: TResampleFilter; RotationFilter: TIEAntialiasMode; ResizingLayer: Boolean);
var
borderW: Integer;
borderBMP: TIEBitmap;
drawBorderAfter: Boolean;
j: integer;
lXSrc, lYSrc, lWidthSrc, lHeightSrc: integer;
lXDst, lYDst, lWidthDst, lHeightDst: integer;
dummy2, dummy3: PInteger;
rotbmp, tmpbmp: TIEBitmap;
lresw, lresh: Double;
lposx, lposy: integer;
w, h: integer;
ieview: TImageEnView;
x1, y1, x2, y2: integer;
lBitmap: TIEBitmap;
procedure _DrawBorder(Canvas: TIECanvas; BorderWidth: Integer; DestX, DestY, DestWidth, DestHeight: Integer);
begin
if ( BorderWidth > 0 ) and ( fBorderColor <> clNone_ ) and
( DestWidth > 0 ) and ( DestHeight > 0 ) then
with Canvas do
begin
Pen.Color := fBorderColor;
Pen.Width := BorderWidth;
Pen.Style := psSolid;
Brush.Style := bsClear;
Rectangle( DestX + BorderWidth div 2, DestY + BorderWidth div 2, DestX + DestWidth + 1 - BorderWidth div 2, DestY + DestHeight + 1 - BorderWidth div 2 );
end;
end;
begin
ieview := TImageEnView( fOwner );
if Owner_FastDrawingActive() then
begin
Filter := rfNone;
RotationFilter := ierNone;
end;
lBitmap := fBitmap;
// DRAW BORDER?
drawBorderAfter := ( LyrIdx = 0 ) or not SoftShadow.Enabled; // if drawing a soft-shadow we need the border inside the shadow
borderW := Round( fBorderWidth * min( fBitmap.Width / Width, fBitmap.Height / Height ));
if drawBorderAfter or ( borderW < 1 ) or ( fBorderColor = clNone_ ) then
borderBMP := nil
else
begin
borderBMP := TIEBitmap.create( lBitmap );
_DrawBorder( borderBMP.IECanvas, borderW, 0, 0, lBitmap.Width, lBitmap.Height );
lBitmap := borderBMP;
end;
if ((TImageEnView(fOwner).LayersCount = 1) and
(fResizedWidth = 0) and (fResizedHeight = 0) and
(PosX = 0) and (PosY = 0) and (Rotate = 0.0)) then
begin
// QUICK OUTPUT IF ADVANCED DRAW OPTIONS NOT USED
{$IFDEF IEDEBUG}
OutputDebugStringA(PAnsiChar('TIEImageLayer.PaintTo'));
OutputDebugStringA(PAnsiChar(string( ' XDst='+IntToStr( xDst )+' YDst='+IntToStr( yDst )+
' WidthDst='+IntToStr( dxDst )+' HeightDst='+IntToStr( dyDst )+
' XSrc='+IntToStr( xSrc )+' YSrc='+IntToStr( ySrc )+
' WidthSrc='+IntToStr( dxSrc )+' HeightSrc='+IntToStr( dySrc )
)));
{$ENDIF}
RenderLayerWithAdornments(DstBitmap, LyrIdx, lBitmap, False,
XLUT, YLUT, UpdRect,
xDst, yDst, dxDst, dyDst,
xSrc, ySrc, dxSrc, dySrc,
EnableAlpha, SolidBackground, Filter);
fClientAreaBox := Rect( xDst, yDst, xDst + dxDst, yDst + dyDst );
fDrawingInfo.XDst := xDst;
fDrawingInfo.YDst := yDst;
fDrawingInfo.WidthDst := dxDst;
fDrawingInfo.HeightDst := dyDst;
fDrawingInfo.XSrc := xSrc;
fDrawingInfo.YSrc := ySrc;
fDrawingInfo.WidthSrc := dxSrc;
fDrawingInfo.HeightSrc := dySrc;
end
else
begin
// ROTATION OR OTHER ADVANCED DRAW OPTIONS USED
lresw := 0;
lresh := 0;
lposx := 0;
lposy := 0;
if Rotate <> 0 then
begin
// here ResizedWidth and ResizedHeight should be 0, but anyway here we accept other values
lresw := fResizedWidth;
lresh := fResizedHeight;
lposx := PosX;
lposy := PosY;
w := Width;
h := Height;
if (w = lBitmap.Width) and (h = lBitmap.Height) then
begin
tmpbmp := lBitmap;
end
else
begin
tmpbmp := TIEBitmap.create(w, h, lBitmap.PixelFormat);
_IEResampleIEBitmap( lBitmap, tmpbmp, rfNone, nil, nil);
end;
if RotationFilter in [ ierBilinear, ierBicubic ] then
begin
tmpbmp.AlphaChannel;
rotbmp := TIEBitmap.Create();
IEQRotateTo(tmpbmp, rotbmp, Rotate, clBlack, RotationFilter, nil, nil);
IEQRotateTo8(tmpbmp.AlphaChannel, rotbmp.AlphaChannel, Rotate, clBlack, RotationFilter );
if tmpbmp <> lBitmap then
tmpbmp.Free();
rotbmp.AlphaChannel.SyncFull();
end
else
begin
rotbmp := TIEVirtualRotatedBitmap.Create(tmpbmp, Rotate, clBlack, tmpbmp <> lBitmap);
rotbmp.ReplaceAlphaChannel( TIEVirtualRotatedBitmap.Create(tmpbmp.AlphaChannel, Rotate, 0) );
rotbmp.AlphaChannel.Full := false;
end;
lBitmap := rotbmp;
fResizedWidth := lBitmap.Width;
fResizedHeight := lBitmap.Height;
with fDrawinginfo do
begin
RotatedDest[0].X := 0;
RotatedDest[0].Y := 0;
RotatedDest[1].X := w;
RotatedDest[1].Y := 0;
RotatedDest[2].X := w;
RotatedDest[2].Y := h;
RotatedDest[3].X := 0;
RotatedDest[3].Y := h;
IERotatePoints(RotatedDest, 4, Rotate, trunc(fRotateCenterX * w), trunc(fRotateCenterY * h));
PosX := lposx+imin(imin(imin(RotatedDest[0].X, RotatedDest[1].X), RotatedDest[2].X), RotatedDest[3].X);
PosY := lposy+imin(imin(imin(RotatedDest[0].Y, RotatedDest[1].Y), RotatedDest[2].Y), RotatedDest[3].Y);
for j := 0 to 3 do
begin
RotatedDest[j].X := trunc(( lposx + RotatedDest[j].X ) * ieview.ZoomX / 100 ) + ieview.OffsetX;
RotatedDest[j].Y := trunc(( lposy + RotatedDest[j].Y ) * ieview.ZoomY / 100 ) + ieview.OffsetY;
end;
end;
end
else
rotbmp := nil;
if (LyrIdx > 0) and (Magnify.Enabled) and (Magnify.Rate >= 1) then
begin
// THIS IS A MAGNIFICATION LAYER
if not ResizingLayer then // needed because aspect ratio-resizing doesn't work with magnify layers
begin
if fResizedWidth > 0 then
lBitmap.Width := Round( fResizedWidth );
if fResizedHeight > 0 then
lBitmap.Height := Round( fResizedHeight );
end;
w := trunc( lBitmap.Width / (Magnify.Rate / ( ieview.ZoomX / 100)));
h := trunc( lBitmap.Height / (Magnify.Rate / ( ieview.ZoomY / 100)));
x1 := ieview.XBmp2Scr(PosX, false) + trunc( lBitmap.Width * ieview.ZoomX / 100 / 2);
y1 := ieview.YBmp2Scr(PosY, false) + trunc( lBitmap.Height * ieview.ZoomY / 100 / 2);
x2 := x1 + w;
y2 := y1 + h;
x1 := x1 - w div 2;
y1 := y1 - h div 2;
x2 := x2 - w div 2;
y2 := y2 - h div 2;
case Magnify.Source of
iemCanvas:
begin
// gets all from current canvas (already painted layers and the background)
lBitmap.Location := ieTBitmap;
lBitmap.Canvas.CopyRect(Rect(0, 0, lBitmap.Width, lBitmap.Height), DstBitmap.Canvas, Rect(x1, y1, x2, y2));
end;
iemBackgroundLayer:
begin
// gets image from layer 0
if lBitmap.PixelFormat <> ie24RGB then
lBitmap.PixelFormat := ie24RGB;
x1 := ieview.XScr2Bmp(x1, false);
y1 := ieview.YScr2Bmp(y1, false);
x2 := ieview.XScr2Bmp(x2, false);
y2 := ieview.YScr2Bmp(y2, false);
w := x2 - x1 + 1;
h := y2 - y1 + 1;
if (y1 >= 0) and (x1 >= 0) and
(x1 < ieview.Layers[0].Bitmap.Width - w) and (y1 < ieview.Layers[0].Bitmap.Height - h) and
(w < ieview.Layers[0].Bitmap.Width) and (h < ieview.Layers[0].Bitmap.Height) then
begin
lBitmap.Fill(0);
ieview.Layers[0].Bitmap.RenderToTIEBitmapEx( lBitmap, 0, 0, lBitmap.Width, lBitmap.Height, x1, y1, w, h, True, 255, Filter, ielNormal);
end;
end;
end;
case Magnify.Style of
iemRectangle:
lBitmap.AlphaChannel.Fill(255); // do nothing
iemEllipse:
begin
lBitmap.AlphaChannel.Location := ieTBitmap;
lBitmap.AlphaChannel.Fill(0);
lBitmap.AlphaChannel.Full := false;
with lBitmap.AlphaChannel.VclBitmap.Canvas do
begin
Brush.Style := bsSolid;
Brush.Color := $01000000 or $FF;
Pen.Style := psSolid;
Pen.Mode := pmCopy;
Pen.Color := $01000000 or $FF;
Pen.Width := 1;
Ellipse(0, 0, lBitmap.Width - 1, lBitmap.Height - 1);
end;
end;
end;
end; // end of magnify layer support
CalcClientAreaBox();
CalcPaintPos(lBitmap.Width, lBitmap.Height,
lXDst, lYDst, lWidthDst, lHeightDst,
lXSrc, lYSrc, lWidthSrc, lHeightSrc);
dummy2 := nil;
dummy3 := nil;
RenderLayerWithAdornments(DstBitmap, LyrIdx, lBitmap, False,
dummy2, dummy3, UpdRect,
lXDst, lYDst, lWidthDst, lHeightDst,
lXSrc, lYSrc, lWidthSrc, lHeightSrc,
EnableAlpha, SolidBackground, Filter);
// DRAW BORDER?
borderW := Round( fBorderWidth * ieview.Zoom / 100 );
if drawBorderAfter then
_DrawBorder( DstBitmap.IECanvas, borderW, lXDst, lYDst, lWidthDst, lHeightDst );
fDrawingInfo.XDst := lXDst;
fDrawingInfo.YDst := lYDst;
fDrawingInfo.WidthDst := lWidthDst;
fDrawingInfo.HeightDst := lHeightDst;
fDrawingInfo.XSrc := lXSrc;
fDrawingInfo.YSrc := lYSrc;
fDrawingInfo.WidthSrc := lWidthSrc;
fDrawingInfo.HeightSrc := lHeightSrc;
if assigned(rotbmp) then
begin
FreeAndNil(rotbmp);
fResizedWidth := lresw;
fResizedHeight := lresh;
PosX := lposx;
PosY := lposy;
end;
end;
FreeAndNil( borderBMP );
end;
procedure TIEImageLayer.LoadFromStream(Stream: TStream);
var
bitmapSaved: boolean;
saveVer: Integer;
fmt: integer;
dw: Dword;
ms: TMemoryStream;
LZStream: TZDecompressionStream;
io: TImageEnIO;
l: Integer;
begin
l := Stream.Position;
saveVer := LoadMetaFromStream( Stream );
if saveVer < 6400 then
raise EIEException.create( 'Unknown data version' );
Stream.Read( Magnify, sizeof(Magnify));
Stream.Read( fResampleFilter, sizeof( fResampleFilter));
Stream.Read( fUseResampleFilter, sizeof( fUseResampleFilter));
Stream.Read(bitmapSaved, sizeof(boolean));
Stream.Read(fmt, sizeof(Integer));
if bitmapSaved then
begin
if (fmt = -1) or (fmt = -2) then
begin
// use internal file format
Stream.Read(dw, sizeof(dword)); // compressed stream size
ms := TMemoryStream.Create;
try
ms.SetSize(dw); // to speed up loading
if dw > 0 then
IECopyFrom(ms, Stream, dw);
ms.Position := 0;
if fmt = -1 then
begin
LZStream := TZDecompressionStream.Create(ms);
try
fBitmap.LoadRAWFromBufferOrStream(nil, LZStream);
finally
FreeAndNil(LZStream);
end;
end
else
fBitmap.LoadRAWFromBufferOrStream(nil, ms);
finally
FreeAndNil(ms);
end;
end
else
begin
// use standard file formats
io := TImageEnIO.CreateFromBitmap( fBitmap );
try
if IsMask then
io.NativePixelFormat := true;
io.LoadFromStream(Stream, fmt);
finally
io.Free;
end;
Stream.Position := l + fLayerSize; // Ensure we are positioned at end of layer record
end;
end;
fModified := False;
fBitmap.Modified := False;
end;
// warning: ioTIFF not supported
// if CompressionFormat = -1 then use internal compressed format (preserves pixelformat and transparency)
// if CompressionFormat = -2 then use internal non-compressed format (preserves pixelformat and transparency)
procedure TIEImageLayer.SaveToStream(Stream: TStream; MetaOnly: Boolean = False; CompressionFormat: TIOFileType = -2);
var
l, sz, fmt: integer;
ms: TMemoryStream;
SaveBitmap: Boolean;
LZStream: TZCompressionStream;
dw: Dword;
io : TImageEnIO;
begin
{$ifdef IEINCLUDEPNG}
if CompressionFormat = ioTIFF then
CompressionFormat := ioPNG;
{$endif}
sz := 0;
l := Stream.Position;
SaveMetaToStream( Stream );
Stream.Write( Magnify, sizeof( Magnify));
Stream.Write( fResampleFilter, sizeof( fResampleFilter));
Stream.Write( fUseResampleFilter, sizeof( fUseResampleFilter));
saveBitmap := ( MetaOnly = False ) and ( fBitmap.Width > 1 );
Stream.Write(saveBitmap, sizeof(boolean));
fmt := CompressionFormat;
Stream.Write(fmt, sizeof(Integer));
if saveBitmap then
begin
if (CompressionFormat = -1) or (CompressionFormat = -2) then
begin
// use internal format (preserves pixelformat and alpha channel). Also this is LZ compressed if CompressionFormat = -1.
ms := TMemoryStream.Create;
try
sz := fBitmap.Height * fBitmap.Rowlen div 2; // aproximated size
if fBitmap.HasAlphaChannel then
sz := sz + fBitmap.AlphaChannel.Height * fBitmap.AlphaChannel.Rowlen;
if sz < IEGetMemory(true) then
begin
try
ms.Size := sz;
except
end;
end;
if CompressionFormat = -1 then
begin
LZStream := TZCompressionStream.Create(ms, zcDefault, 15);
try
fBitmap.SaveRAWToBufferOrStream(nil, LZStream, false);
finally
FreeAndNil(LZStream);
end;
end
else
fBitmap.SaveRAWToBufferOrStream(nil, ms, true);
sz := ms.Position;
dw := sz; Stream.Write(dw, sizeof(dword)); // write compressed stream size
ms.Position := 0;
if sz > 0 then
IECopyFrom(Stream, ms, sz);
finally
FreeAndNil(ms);
end;
end
else
begin
io := TImageEnIO.CreateFromBitmap( fBitmap );
try
// use standard image formats
case fBitmap.PixelFormat of
ie1g:
begin
io.Params.BitsPerSample := 1;
io.Params.SamplesPerPixel := 1;
end;
ie8g:
begin
io.Params.BitsPerSample := 8;
io.Params.SamplesPerPixel := 1;
io.Params.JPEG_ColorSpace := ioJPEG_GRAYLEV;
end;
else
begin
io.Params.BitsPerSample := 8;
io.Params.SamplesPerPixel := 3;
io.Params.JPEG_ColorSpace := ioJPEG_YCbCr;
end;
end;
io.SaveToStream(Stream, CompressionFormat);
finally
io.Free;
end;
end;
end;
// Update position
sz := Stream.Position - l;
Stream.Position := l;
Stream.Write(sz, sizeof(integer)); // Fill size
Stream.Position := l + sz; // Position at end of layer record
fLayerSize := sz;
end;
function TIEImageLayer.GetAsSVG(): string;
var
SaveImageFormat: TIOFileType;
begin
SaveImageFormat := ioPNG;
if assigned(fOwner) then
SaveImageFormat := (fOwner as TImageEnView).IO.Params.SVG_ImageCompression;
Result := CreateSVGImageTag( fBitmap, SaveImageFormat, PosX, PosY, Width, Height, fBorderWidth, fBorderColor, Rotate, fTransparency);
end;
{!!
<FS>TIEImageLayer.Clear
<FM>Declaration<FC>
procedure Clear(FillColor: TColor = clWhite; Width: Integer = 1; Height: Integer = 1);
<FM>Description<FN>
Removes any transparent area on the edge of the layer bitmap, repositioning and resizing the resulting layer to the visible rectangle.
Result is true if the bitmap was cropped (i.e. alpha was removed).
<FM>Example<FC>
// Clear the current image, but maintain its existing size
if ImageEnView1.CurrentLayer is TIEImageLayer then
TIEImageLayer( ImageEnView1.CurrentLayer ).Clear( clWhite, ImageEnView1.CurrentLayer.Width, ImageEnView1.CurrentLayer.Height );
ImageEnView1.Update();
!!}
procedure TIEImageLayer.Clear(FillColor: TColor = clWhite; Width: Integer = 1; Height: Integer = 1);
var
oldWidth, oldHeight: Integer;
begin
oldWidth := Width;
oldHeight := Height;
fBitmap.Allocate( max( 1, Width ), Max( 1, Height ));
fBitmap.Fill( FillColor );
fResizedWidth := 0;
fResizedHeight := 0;
if Width <= 1 then
fPosX := 1
else
fPosX := fPosX + ( oldWidth - Width ) div 2;
if Height <= 1 then
fPosY := 1
else
fPosY := fPosX + ( oldHeight - Height ) div 2;
LayerChange();
end;
{!!
<FS>TIEImageLayer.CropAlpha
<FM>Declaration<FC>
function CropAlpha(): Boolean;
<FM>Description<FN>
Removes any transparent area on the edge of the layer bitmap, repositioning and resizing the resulting layer to the visible rectangle.
Result is true if the bitmap was cropped (i.e. alpha was removed).
<FM>Example<FC>
if ImageEnView1.CurrentLayer is TIEImageLayer then
TIEImageLayer( ImageEnView1.CurrentLayer ).CropAlpha();
ImageEnView1.Update();
<FM>See Also<FN>
- <A TIEBitmap.CropAlpha>
- <A TImageEnProc.CropTransparentBorder>
!!}
function TIEImageLayer.CropAlpha(): Boolean;
var
beforeWidth, beforeHeight: Integer;
scaleX, scaleY: Double;
begin
Result := False;
beforeWidth := fBitmap.Width;
beforeHeight := fBitmap.Height;
if fBitmap.CropAlpha() = False then
exit;
scaleX := 1.0;
scaleY := 1.0;
if fResizedWidth > 0 then
scaleX := fResizedWidth / beforeWidth;
if fResizedHeight > 0 then
scaleY := fResizedHeight / beforeHeight;
fPosX := fPosX + Trunc(( beforeWidth - fBitmap.Width ) / 2 * scaleX );
fPosY := fPosY + Trunc(( beforeHeight - fBitmap.Height ) / 2 * scaleY );
if fResizedWidth > 0 then
fResizedWidth := fResizedWidth * fBitmap.Width / beforeWidth;
if fResizedHeight > 0 then
fResizedHeight := fResizedHeight * fBitmap.Height / beforeHeight;
Result := True;
LayerChange();
end;
{!!
<FS>TIEImageLayer.ExecuteOpenDialog
<FM>Declaration<FC>
function ExecuteOpenDialog(): Boolean;
<FM>Description<FN>
Displays an open image dialog (using <A TImageEnIO.ExecuteOpenDialog>) to allow the user to browse for an image. It is applied to the current layer.
<FM>Example<FC>
if ImageEnView1.CurrentLayer is TIEImageLayer then
TIEImageLayer( ImageEnView1.CurrentLayer ).ExecuteOpenDialog();
!!}
function TIEImageLayer.ExecuteOpenDialog(): Boolean;
var
imgFilename: string;
ieview: TImageEnView;
begin
Result := False;
if fOwner = nil then
exit;
imgFilename := TImageEnView( fOwner ).IO.ExecuteOpenDialog('');
if imgFilename <> '' then
begin
ieview := (fOwner as TImageEnView);
if assigned(ieview) and ieview.Proc.AutoUndo and ( loAutoUndoChangesbyUser in ieview.LayerOptions ) then
ieview.Proc.SaveUndo( IEMsg( IEMsg_SelectImage ), ieuImage, True, IEOP_OTHER );
LayerChange();
Result := Bitmap.Read( imgFilename );
RestoreAspectRatio();
if Assigned( fOwner ) then
TImageEnView( fOwner ).Update();
end
end;
{!!
<FS>TIEImageLayer.RestoreSize
<FM>Declaration<FC>
procedure RestoreSize();
<FM>Description<FN>
Sizes the layer to original dimensions (i.e. display at 100% zoom).
<FM>Example<FC>
if ImageEnView1.CurrentLayer is TIEImageLayer then
ImageEnView1.CurrentLayer.RestoreSize();
ImageEnView1.Update();
<FM>See Also<FN>
- <A TIELayer.RestoreAspectRatio>
!!}
procedure TIEImageLayer.RestoreSize();
begin
fResizedWidth := 0;
fResizedHeight := 0;
end;
// *************************************************************************************** //
// ** ** //
// ** TIEShapeLayer ** //
// ** ** //
// *************************************************************************************** //
constructor TIEShapeLayer.Create(Owner: TObject);
begin
inherited Create(Owner);
fKind := ielkShape;
SetDefaults;
fResizedWidth := 100;
fResizedHeight := 100;
end;
destructor TIEShapeLayer.Destroy;
begin
//
inherited Destroy;
end;
// Bitmap is created if nil
// must be freed
procedure TIEShapeLayer.CopyToBitmapEx(var Dest: TIEBitmap;
CreateWidth : Integer; CreateHeight : Integer;
FastDrawing: Boolean;
EnableAlpha: Boolean; UseDisplayAR: Boolean;
UpdateSize: Boolean = False; EnlargeOnly: Boolean = False;
Zoom: Double = 1);
var
drawRect: TRect;
procedure _DrawShape_GDI();
var
drawLeft, drawTop, drawWidth, drawHeight: Integer;
begin
if EnableAlpha then
begin
InitBitmapRGBA( Dest, CreateWidth, CreateHeight ); // Use ie32RGB for RGBA support
Dest.IECanvas.SetCompositingMode(ieCompositingModeSourceOver, ieCompositingQualityDefault);
end
else
InitBitmap( Dest, CreateWidth, CreateHeight );
drawLeft := drawRect.Left;
drawTop := drawRect.Top;
drawWidth := drawRect.Right - drawRect.Left;
drawHeight := drawRect.Bottom - drawRect.Top;
if AspectRatioLocked = True then // Lock to 1:1
begin
if drawWidth > drawHeight then
begin
drawWidth := drawHeight;
drawLeft := ( Dest.Width - drawWidth ) div 2;
end
else
if drawWidth > drawHeight then
begin
drawHeight := drawWidth;
drawTop := ( Dest.Height - drawHeight ) div 2;
end;
end;
IEDrawSimpleShape(Dest.IECanvas, drawLeft, drawTop, drawWidth, drawHeight,
fBorderColor, fBorderWidth,
fFillColor, fFillColor2, fFillGradient,
min( CreateWidth / GetWidth, CreateWidth / GetHeight ), // = Zoom
fShape, False {Handled by scaling} );
if EnableAlpha then
Dest.SynchronizeRGBA( True, True )
else
Dest.RemoveAlphaChannel();
end;
procedure _DrawShape_RGN(Bitmap: TIEBitmap; DrawingAlpha : Boolean);
var
drawBorderColor, drawFillColor, drawFillColor2 : TColor;
drawBorderWidth: Integer;
maintainAR: TIEBooleanEx;
begin
drawBorderColor := fBorderColor;
drawFillColor := fFillColor ;
drawFillColor2 := fFillColor2 ;
if DrawingAlpha then
begin
if drawBorderColor <> clNone_ then
drawBorderColor := Full_Alpha_Color;
if drawFillColor <> clNone_ then
drawFillColor := Full_Alpha_Color;
drawFillColor2 := clNone_;
end;
// Image has been scaled to zoom level, so ensure we scale the border too
drawBorderWidth := fBorderWidth;
if drawBorderWidth > 0 then
drawBorderWidth := max( 1, Round( fBorderWidth * min( CreateWidth / GetWidth, CreateWidth / GetHeight )));
if AspectRatioLocked then
maintainAR := iebTrue
else
maintainAR := iebFalse;
IEDrawShape( Bitmap.Canvas, fShape,
drawRect.Left, drawRect.Top, drawRect.Right - drawRect.Left, drawRect.Bottom - drawRect.Top,
maintainAR,
drawBorderColor, drawBorderWidth,
drawFillColor, drawFillColor2, fFillGradient, Round( Rotate ), fShapeModifier );
end;
var
useIECanvas: Boolean;
begin
// Use TIECanvas for faster handling of unrotated rects and ellipses
useIECanvas := ( fShape in [ iesEllipse, iesRectangle, iesRoundRect ] ) and ( Round( Rotate ) mod 90 = 0 );
if useIECanvas and ( fShape <> iesRectangle ) then
useIECanvas := (( fFillColor = fFillColor2 ) or ( fFillColor = clNone_ ) or ( fFillColor2 = clNone_ )); // i.e. no gradient
if CreateWidth < 1 then
CreateWidth := OriginalWidth;
if CreateHeight < 1 then
CreateHeight := OriginalHeight;
drawRect := Rect( 0, 0, CreateWidth, CreateHeight );
if UseDisplayAR then
drawRect := GetImageRectWithinArea( Width, Height, CreateWidth, CreateHeight );
if useIECanvas then
begin
// Draw using TIECanvas
_DrawShape_GDI();
end
else
begin
// Draw using TCanvas
InitBitmap( Dest, CreateWidth, CreateHeight );
if EnableAlpha = False then
Dest.RemoveAlphaChannel()
else
begin
Dest.AlphaChannel.PixelFormat := ie8g;
Dest.AlphaChannel.VclBitmap.PixelFormat := pf8bit;
IESetGrayPalette( Dest.AlphaChannel.VclBitmap );
Dest.AlphaChannel.Fill(0);
_DrawShape_RGN( Dest.AlphaChannel, True );
end;
_DrawShape_RGN( Dest, False );
end;
end;
procedure TIEShapeLayer.CopyToBitmap(var Dest: TIEBitmap; CreateWidth : Integer = -1; CreateHeight : Integer = -1; EnableAlpha: Boolean = True; UseDisplayAR: Boolean = True);
var
antiAliasFactor: Integer;
zf: TResampleFilter;
begin
if CreateWidth < 1 then
CreateWidth := OriginalWidth;
if CreateHeight < 1 then
CreateHeight := OriginalHeight;
antiAliasFactor := 1;
if fAntiAlias and not Owner_FastOutputActive() then
antiAliasFactor := 2;
begin
CreateWidth := CreateWidth * antiAliasFactor;
CreateHeight := CreateHeight * antiAliasFactor;
end;
CopyToBitmapEx( Dest, CreateWidth, CreateHeight, Owner_FastOutputActive(), EnableAlpha, UseDisplayAR );
if antiAliasFactor <> 1 then
begin
// Halve the size to effect anti-alias
zf := fResampleFilter;
if ( zf = rfNone ) and assigned( Owner ) then
zf := TImageEnView( Owner ).LayersMergeFilter;
Dest.Resample( 1 / antiAliasFactor, zf );
end;
end;
function TIEShapeLayer.GetBitmap : TIEBitmap;
begin
CopyToBitmap( fGlobalCacheBitmap, iMax( 1, Round( fResizedWidth )), iMax( 1, Round( fResizedHeight )), Owner_EnableAlphaChannel, False );
Result := fGlobalCacheBitmap;
end;
{!!
<FS>TIEShapeLayer.BorderColor
<FM>Declaration<FC>
property BorderColor: TColor;
<FM>Description<FN>
The color of the frame around the shape.
To hide the frame set <FC>BorderColor<FN> to clNone or <A TIEShapeLayer.BorderWidth> to 0.
Default: clBlack
<FM>Example<FC>
// Add an explosion layer with an orange border and a yellow fill
ImageEnView1.LayersAdd( ielkShape );
ImageEnView1.CurrentLayer.BorderColor := $004080FF;
ImageEnView1.CurrentLayer.BorderWidth := 2;
ImageEnView1.CurrentLayer.FillColor := clYellow;
ImageEnView1.Update();
<IMG help_images\Polyline_WithBorder.gif>
// Remove the border...
ImageEnView1.CurrentLayer.BorderColor := clNone; // Same as setting BorderWidth := 0;
ImageEnView1.Update();
<IMG help_images\Polyline_NoBorder.gif>
<FM>See Also<FN>
- <L TIELayer.BorderColor>TIELayer.BorderColor</L>
- <A TIEShapeLayer.BorderWidth>
!!}
function TIEShapeLayer.GetBorderColor: TColor;
begin
Result := fBorderColor;
end;
procedure TIEShapeLayer.SetBorderColor(value: TColor);
begin
fBorderColor := Value;
LayerChange();
end;
{!!
<FS>TIEShapeLayer.BorderWidth
<FM>Declaration<FC>
property BorderWidth: Integer;
<FM>Description<FN>
The width of the frame around the shape.
To hide the frame set <FC>BorderWidth<FN> to 0 or <A TIEShapeLayer.BorderColor> to clNone.
Default: 1
<FM>Example<FC>
// Add an explosion layer with an orange border and a yellow fill
ImageEnView1.LayersAdd( ielkShape );
ImageEnView1.CurrentLayer.BorderColor := $004080FF;
ImageEnView1.CurrentLayer.BorderWidth := 2;
ImageEnView1.CurrentLayer.FillColor := clYellow;
ImageEnView1.Update();
<IMG help_images\Polyline_WithBorder.gif>
// Remove the border...
ImageEnView1.CurrentLayer.BorderWidth := 0;
ImageEnView1.Update();
<IMG help_images\Polyline_NoBorder.gif>
<FM>See Also<FN>
- <L TIELayer.BorderWidth>TIELayer.BorderWidth</L>
- <A TIEShapeLayer.BorderColor>
!!}
function TIEShapeLayer.GetBorderWidth: Integer;
begin
Result := fBorderWidth;
end;
procedure TIEShapeLayer.SetBorderWidth(value: Integer);
begin
fBorderWidth := Value;
LayerChange();
end;
{!!
<FS>TIEShapeLayer.FillColor
<FM>Declaration<FC>
property FillColor: TColor;
<FM>Description<FN>
The color of the shape.
To make the shape transparent, set <FC>FillColor<FN> to clNone. If <FC>FillColor<FN> is different from <A TIEShapeLayer.FillColor2> it will be drawn as a gradient.
Default: clRed
<FM>Example<FC>
// Set fill color for a shape to yellow
ImageEnView1.CurrentLayer.FillColor := clYellow;
ImageEnView1.Update();
<IMG help_images\Shape_WithFill.jpg>
// Remove fill color from shape
ImageEnView1.CurrentLayer.FillColor := clNone;
ImageEnView1.Update();
<IMG help_images\Shape_NoFill.jpg>
<FM>See Also<FN>
- <L TIELayer.FillColor>TIELayer.FillColor</L>
- <A TIEShapeLayer.FillColor2>
- <A TIEShapeLayer.FillGradient>
!!}
function TIEShapeLayer.GetFillColor: TColor;
begin
Result := fFillColor;
end;
procedure TIEShapeLayer.SetFillColor(value: TColor);
begin
fFillColor := Value;
LayerChange();
end;
{!!
<FS>TIEShapeLayer.FillColor2
<FM>Declaration<FC>
property FillColor2: TColor;
<FM>Description<FN>
The end color for the shape gradient.
If <FC>FillColor2<FN> is clNone, the shape is filled by a solid color specified by <A TIEShapeLayer.FillColor>. If <FC>FillColor2<FN> is different from <A TIEShapeLayer.FillColor> it is drawn as a gradient.
The direction of the gradient is specified by <A TIEShapeLayer.FillGradient>.
Default: clNone
<FM>Example<FC>
// Set a vertical gradient fill for an ellipse
ImageEnView1.CurrentLayer.FillColor2 := clRed;
ImageEnView1.CurrentLayer.FillColor := clYellow;
ImageEnView1.CurrentLayer.FillGradient := clVertical;
ImageEnView1.CurrentLayer.BorderWidth := 0;
ImageEnView1.Update();
<IMG help_images\Shape_Ellipse.gif>
// Disable the gradient fill
TIEShapeLayer( ImageEnView1.CurrentLayer ).FillColor2 := clNone;
ImageEnView1.Update();
<IMG help_images\Shape_NoFill.jpg>
<FM>See Also<FN>
- <L TIELayer.FillColor2>TIELayer.FillColor2</L>
- <A TIEShapeLayer.FillColor>
- <A TIEShapeLayer.FillGradient>
!!}
function TIEShapeLayer.GetFillColor2: TColor;
begin
Result := fFillColor2;
end;
procedure TIEShapeLayer.SetFillColor2(value: TColor);
begin
fFillColor2 := Value;
LayerChange();
end;
{!!
<FS>TIEShapeLayer.FillGradient
<FM>Declaration<FC>
property FillGradient: <A TIEGradientDir>;
<FM>Description<FN>
The direction of the gradient used for the shape fill.
If <A TIEShapeLayer.FillColor> is different from <A TIEShapeLayer.FillColor2> the shape is filled with a gradient. <FC>FillGradient<FN> specifies the direction.
Default: gdVertical
<FM>Example<FC>
// Set a vertical gradient fill for an ellipse
ImageEnView1.CurrentLayer.FillColor2 := clRed;
ImageEnView1.CurrentLayer.FillColor := clYellow;
ImageEnView1.CurrentLayer.FillGradient := clVertical;
ImageEnView1.CurrentLayer.BorderWidth := 0;
ImageEnView1.Update();
<IMG help_images\Shape_Ellipse.gif>
<FM>See Also<FN>
- <L TIELayer.FillGradient>TIELayer.FillGradient</L>
- <A TIEShapeLayer.FillColor>
- <A TIEShapeLayer.FillColor2>
!!}
function TIEShapeLayer.GetFillGradient: TIEGradientDir;
begin
Result := fFillGradient;
end;
procedure TIEShapeLayer.SetFillGradient(value: TIEGradientDir);
begin
fFillGradient := Value;
LayerChange();
end;
{!!
<FS>TIEShapeLayer.Shape
<FM>Declaration<FC>
property Shape: <A TIEShape>;
<FM>Description<FN>
The shape displayed by the layer. Over <L TIEShape>sixty shapes</L> are available.
The style of some shapes can be modified using <A TIEShapeLayer.ShapeModifier>
Default: iesEllipse
<FM>Examples<FC>
// Append a Star layer
ImageEnView1.LayersAdd( ielkShape );
TIEShapeLayer( ImageEnView1.CurrentLayer ).Shape := iesStar5;
TIEShapeLayer( ImageEnView1.CurrentLayer ).AspectRatioLocked := True;
ImageEnView1.CurrentLayer.FillColor := clRed;
ImageEnView1.Update();
<IMG help_images\Polyline_Star.gif>
// Explosion Shape
ImageEnView1.CurrentLayer.Shape := iesExplosion;
<IMG help_images\Polyline_WithBorder.gif>
// Triangle Shape
ImageEnView1.CurrentLayer.Shape := iesTriangle;
<IMG help_images\Polyline_Closed.gif>
// Arrow Shape
ImageEnView1.CurrentLayer.Shape := iesShootingArrowSW;
<IMG help_images\Polyline_Arrow.gif>
// Ellipse Shape
ImageEnView1.CurrentLayer.Shape := iesEllipse;
<IMG help_images\Shape_Ellipse.gif>
// Lightning Shape
ImageEnView1.CurrentLayer.Shape := iesLightningLeft;
<IMG help_images\Shape_Lightning.gif>
!!}
procedure TIEShapeLayer.SetShape(value: TIEShape);
begin
fShape := Value;
LayerChange();
end;
{!!
<FS>TIEShapeLayer.ShapeModifier
<FM>Declaration<FC>
property ShapeModifier: Integer;
<FM>Description<FN>
Changes the display of certain shapes.
<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>
Default: 0 (uses the default for that shape)
<FM>Example<FC>
// Append a 12-pointed star layer
ImageEnView1.LayersAdd( ielkShape );
TIEShapeLayer( ImageEnView1.CurrentLayer ).Shape := iesCustomStar;
TIEShapeLayer( ImageEnView1.CurrentLayer ).ShapeModifier := 12;
ImageEnView1.Update();
// Append a 30 point explosion layer
ImageEnView1.LayersAdd( ielkShape );
TIEShapeLayer( ImageEnView1.CurrentLayer ).Shape := iesCustomExplosion;
TIEShapeLayer( ImageEnView1.CurrentLayer ).ShapeModifier := 30;
ImageEnView1.Update();
<IMG help_images\Polyline_WithBorder.gif>
!!}
procedure TIEShapeLayer.SetShapeModifier(value: Integer);
begin
fShapeModifier := Value;
LayerChange();
end;
procedure TIEShapeLayer.LoadFromStream(Stream: TStream);
var
saveVer: Integer;
begin
saveVer := LoadMetaFromStream( Stream );
if saveVer < 6400 then
raise EIEException.create( 'Unknown data version' );
// Other props
Stream.Read( fShape, SizeOf( TIEShape ));
Stream.Read( fShapeModifier, SizeOf( Integer ));
fModified := False;
end;
procedure TIEShapeLayer.SaveToStream(Stream: TStream; MetaOnly: Boolean = False; CompressionFormat: TIOFileType = -2);
var
l, sz: integer;
begin
l := Stream.Position;
SaveMetaToStream( Stream);
// other props
Stream.Write( fShape, SizeOf( TIEShape ));
Stream.Write( fShapeModifier, SizeOf( Integer ));
// Update position
sz := Stream.Position - l;
Stream.Position := l;
Stream.Write(sz, sizeof(integer)); // Fill size
Stream.Position := l + sz; // Position at end of layer record
end;
function TIEShapeLayer.GetAsSVG(): string;
var
aLayer: TIEImageLayer;
begin
Result := CreateSVGShapeTag( fShape, PosX, PosY, Width, Height, fBorderWidth, fBorderColor, fFillColor, Rotate, fTransparency );
if Result = '' then
begin
// it will be a shape type that cannot be converted to points
aLayer := TIEImageLayer.Create( nil, Self, 2, False );
Result := aLayer.AsSVG;
aLayer.Free;
end;
end;
// *************************************************************************************** //
// ** ** //
// ** TIELineLayer ** //
// ** ** //
// *************************************************************************************** //
constructor TIELineLayer.Create(Owner: TObject);
begin
inherited Create(Owner);
fKind := ielkLine;
fLabelFont := TFont.Create;
SetDefaults;
fResizedWidth := 100;
fResizedHeight := 100;
SizeToFit();
fLineRect := Rect( 0, 0, 0, 0 );
fLabelRect := Rect( 0, 0, 0, 0 );
fStartShapePoints.Shape := ieesNone;
fEndShapePoints.Shape := ieesNone;
end;
destructor TIELineLayer.Destroy;
begin
FreeAndNil( fLabelFont );
inherited;
end;
procedure IEDrawLineEndShape(Canvas: TIECanvas; x1, y1, x2, y2: integer; Shape: TIELineEndShape; Size: integer; Zoom: Double; out DrawInfo: TIEEndShapeDrawInfo);
const
Angle_Divisor = 12;
var
pp: array[0..2] of TPoint;
dx, dy, dsq, udx, udy: Double;
begin
Size := Round( Size * Zoom );
if Size < 2 then
exit;
DrawInfo.Shape := Shape;
case Shape of
ieesArrow :
begin
dx := x1 - x2;
dy := y1 - y2;
dsq := Sqrt( dx * dx + dy * dy );
if dsq = 0 then
exit;
udx := dx / dsq;
udy := dy / dsq;
pp[0].x := Round( x2 + Size / 2 * ( udx * Sqrt( Angle_Divisor ) / 2 - udy * 1/2 ));
pp[0].y := Round( y2 + Size / 2 * ( udx * 1/2 + udy * Sqrt( Angle_Divisor ) / 2 ));
pp[1].x := Round( x2 + Size / 2 * ( udx * Sqrt( Angle_Divisor ) / 2 + udy * 1/2 ));
pp[1].y := Round( y2 + Size / 2 * ( - udx * 1/2 + udy * Sqrt( Angle_Divisor ) / 2 ));
pp[2].x := x2;
pp[2].y := y2;
Canvas.Polygon(pp);
DrawInfo.Pt1 := Point( Round( pp[0].X / Zoom ), Round( pp[0].Y / Zoom ));
DrawInfo.Pt2 := Point( Round( pp[1].X / Zoom ), Round( pp[1].Y / Zoom ));
DrawInfo.Pt3 := Point( Round( pp[2].X / Zoom ), Round( pp[2].Y / Zoom ));
end;
ieesCircle:
begin
Canvas.Ellipse( x2 - Size div 2,
y2 - Size div 2,
x2 + Size div 2,
y2 + Size div 2 );
DrawInfo.pt1 := Point( Round(( x2 - Size / 2 ) / Zoom ), Round(( y2 - Size / 2 ) / Zoom )); // top left of ellipse rect
DrawInfo.pt2 := Point( Round(( x2 + Size / 2 ) / Zoom ), Round(( y2 + Size / 2 ) / Zoom )); // bottom right of ellipse
end;
end;
end;
function IEDrawLine(Canvas: TIECanvas;
PosX, PosY, Width, Height: Integer;
Zoom: Double;
Angle: Integer;
LineColor: TColor; LineWidth: Integer;
StartingShape, EndingShape: TIELineEndShape; ShapeSize: Integer;
ShapeFillColor: TColor; // Shape uses LineColor and LineWidth for Pen
LabelPosition: TIELineLabelPos;
LabelText: String;
LabelAlign: TIEAlignment;
LabelFont: TFont;
LabelShape: TIEShape; // only iesRectangle, iesRoundRect, iesEllipse
LabelBorderColor: TColor; LabelBorderWidth: Integer;
LabelFillColor: TColor; LabelFillColor2: TColor; LabelFillGradient: TIEGradientDir;
AntiAlias: boolean;
TextAntiAlias: boolean;
out LineRect: TRect;
out LabelRect: TRect;
out StartShapePoints: TIEEndShapeDrawInfo;
out EndShapePoints: TIEEndShapeDrawInfo;
UpdateSize: Boolean = False;
DesiredLineLength: Double = -1): TSize;
const
Arrow_Angle = 30;
var
Pt1, Pt2: TPoint;
prevSmoothingMode : TIECanvasSmoothingMode;
startShapeAtLeft, startShapeAtTop, endShapeAtLeft, endShapeAtTop: Boolean;
labelAtLeft, labelAtTop: Boolean;
leftPadding, topPadding, rightPadding, bottomPadding: Integer;
LabelSize: TSize;
labelVisible: Boolean;
offPt: TPoint;
sizeToLineLength: Boolean;
spaceForShapes: Boolean;
labelLeft, labelTop: Integer;
procedure _ResetPadding();
begin
leftPadding := 0;
topPadding := 0;
rightPadding := 0;
bottomPadding := 0;
end;
function _GetLineBounds() : TSize;
var
linePt1, linePt2: TPoint;
begin
CalcLineWithinRect( Rect( PosX, PosY, PosX + Width, PosY + Height ),
Angle, linePt1, linePt2 );
result.cX := abs( linePt1.X - linePt2.X );
result.cY := abs( linePt1.Y - linePt2.Y );
end;
procedure _GetShapePadding(Shape: TIELineEndShape; ShapeAtLeft, ShapeAtTop: Boolean);
var
adjShapeSize: Double;
lineBounds: TSize;
begin
if not ( Shape in [ ieesArrow, ieesCircle ]) then
exit;
adjShapeSize := ( ShapeSize + LineWidth / 2 ) * Zoom;
if Shape = ieesArrow then
adjShapeSize := 0.8 * adjShapeSize;
lineBounds := _GetLineBounds;
if ( lineBounds.cX < adjShapeSize ) or ( lineBounds.cX < LabelSize.cX ) then
begin
leftPadding := max( leftPadding, Trunc( LineWidth / 2 ) + Trunc( adjShapeSize / 2 ));
rightPadding := max( rightPadding, Ceil( LineWidth / 2 ) + Ceil( adjShapeSize / 2 ));
end
else
if ShapeAtLeft then
begin
inc( leftPadding, LineWidth + Round( adjShapeSize / 2 ));
end
else
// Right
begin
inc( rightPadding, LineWidth + Round( adjShapeSize / 2 ));
end;
if ( lineBounds.cY < adjShapeSize ) or ( lineBounds.cY < LabelSize.cY ) then
begin
topPadding := Max( topPadding, Trunc( LineWidth / 2 ) + Trunc( adjShapeSize / 2 ));
bottomPadding := Max( bottomPadding, Ceil( LineWidth / 2 ) + Ceil( adjShapeSize / 2 ));
end
else
if ShapeAtTop then
begin
inc( topPadding, LineWidth + Round( adjShapeSize / 2 ));
end
else
// Bottom
begin
inc( bottomPadding, LineWidth + Round( adjShapeSize / 2 ));
end;
end;
procedure _GetLabelPadding();
var
lineBounds: TSize;
begin
lineBounds := _GetLineBounds;
if lineBounds.cX < LabelSize.cX then
begin end
else
if labelAtLeft then
inc( leftPadding, LabelSize.cX div 2 )
else
// Right
inc( rightPadding, LabelSize.cX div 2 );
if lineBounds.cY < LabelSize.cY then
begin end
else
if LabelAtTop then
inc( topPadding, LabelSize.cY div 2 )
else
// Bottom
inc( bottomPadding, LabelSize.cY div 2 );
end;
// Result is false if padding for shapes exceeds bounds
function _CalcPadding(StartShape, EndShape: TIELineEndShape; IncludeLabel: Boolean = True): Boolean;
begin
_ResetPadding();
// Shapes
_GetShapePadding( StartShape, startShapeAtLeft, startShapeAtTop );
_GetShapePadding( EndShape, endShapeAtLeft, endShapeAtTop );
Result := ( leftPadding + rightPadding <= Width ) and
( topPadding + bottomPadding <= Height );
// Label
if IncludeLabel then
_GetLabelPadding();
end;
function CalcLabelSize(): TSize;
begin
Result := IEDrawText( Canvas,
PosX, PosY, PosX + Width, PosX + Height,
Zoom,
LabelText,
LabelFont,
LabelAlign,
ielCenter,
0, {Angle }
LabelBorderColor, LabelBorderWidth,
LabelFillColor, LabelFillColor2, LabelFillGradient,
True,
AntiAlias,
LabelShape,
True);
end;
begin
LineRect := Rect( 0, 0, 0, 0 );
LabelRect := Rect( 0, 0, 0, 0 );
StartShapePoints.Shape := ieesNone;
EndShapePoints.Shape := ieesNone;
Result.cX := -1;
Result.cY := -1;
sizeToLineLength := UpdateSize and ( DesiredLineLength > 0 );
if sizeToLineLength then
begin
// Get the box needed to display the line
offPt := OffsetPoint( Point( 0, 0 ), DesiredLineLength * Zoom, Angle );
Width := iMax( 1, Round( abs( offPt.X )));
Height := iMax( 1, Round( abs( offPt.Y )));
end;
labelVisible := ( LabelText <> '' ) and ( LabelPosition <> ielpHide );
if LineWidth > 0 then
LineWidth := imax( 1, Round( LineWidth * Zoom ));
// Don't allow clear backgrounds as we must erase white lines
if LabelFillColor = clNone_ then
LabelFillColor := clWhite;
if ShapeFillColor = clNone_ then
ShapeFillColor := clWhite;
LabelSize.cX := 0;
LabelSize.cY := 0;
if labelVisible then
begin
LabelSize := CalcLabelSize();
if UpdateSize = False then
begin
if LabelSize.cX > Width then
LabelSize.cX := Width;
if LabelSize.cY > Height then
LabelSize.cY := Height;
end;
// Cannot have a label and a shape in some position
case LabelPosition of
ielpAtStart : StartingShape := ieesNone;
ielpAtEnd : EndingShape := ieesNone;
end;
end;
while Angle < 0 do
Angle := Angle + 360;
while Angle >= 360 do
Angle := Angle - 360;
startShapeAtLeft := ( Angle >= 90 ) and ( Angle < 270 );
startShapeAtTop := ( Angle < 180 );
endShapeAtLeft := not startShapeAtLeft;
endShapeAtTop := not startShapeAtTop;
labelAtLeft := startShapeAtLeft;
labelAtTop := startShapeAtTop;
if LabelPosition = ielpAtEnd then
begin
labelAtLeft := not LabelAtLeft;
labelAtTop := not LabelAtTop;
end;
spaceForShapes := _CalcPadding( StartingShape, EndingShape );
if (spaceForShapes = False ) and
(UpdateSize = False) then
begin
// Not enough space to show shapes, so HIDE
StartingShape := ieesNone;
EndingShape := ieesNone;
_CalcPadding( ieesNone, ieesNone );
end;
prevSmoothingMode := Canvas.SmoothingMode;
if AntiAlias then
Canvas.SmoothingMode := iesmAntialias
else
Canvas.SmoothingMode := iesmBestPerformance;
try
if sizeToLineLength then
_CalcPadding( ieesNone, ieesNone, False )
else
if UpdateSize then
begin
if Width - leftPadding - rightPadding < LineWidth then
Width := LineWidth + leftPadding + rightPadding;
if Height - topPadding - bottomPadding < LineWidth then
Height := LineWidth + topPadding + bottomPadding;
_CalcPadding( ieesNone, ieesNone, True );
end;
CalcLineWithinRect( Rect( PosX + leftPadding,
PosY + topPadding,
PosX + Width - rightPadding,
PosY + Height - bottomPadding ),
Angle,
Pt1, Pt2 );
if ( Pt1.X = -1 ) and ( Pt1.Y = -1 ) and
( Pt2.X = -1 ) and ( Pt2.Y = -1 ) then
exit; // invalid rect
// Re-calc padding with start/end shapes
if UpdateSize then
_CalcPadding( StartingShape, EndingShape );
Result.cX := abs( Pt1.X - Pt2.X ) + leftPadding + rightPadding;
if sizeToLineLength then
Result.cX := Result.cX + LabelSize.cX div 2;
if Result.cX < LabelSize.cX then
Result.cX := LabelSize.cX;
Result.cY := abs( Pt1.Y - Pt2.Y ) + topPadding + bottomPadding;
if sizeToLineLength then
Result.cY := Result.cY + LabelSize.cY div 2;
if Result.cY < LabelSize.cY then
Result.cY := LabelSize.cY;
LineRect := Rect( Round( Pt1.x / Zoom ), Round( Pt1.y / Zoom ), Round( Pt2.x / Zoom ), Round( Pt2.Y / Zoom ));
if UpdateSize then
exit;
// NOW PAINTING
with Canvas do
begin
Pen.Color := $01010101; // needed otherwise next Pen.Color is not set (gdi bug workaround?)
if ( LineWidth > 0 ) and ( LineColor <> clNone_ ) then
begin
Pen.Style := psSolid;
Pen.Width := LineWidth;
Pen.Color := LineColor;
end
else
Pen.Style := psClear;
Pen.Mode := pmCopy;
Brush.Style := bsClear;
end;
// DRAW LINE
Canvas.DrawLine(Pt1.X, Pt1.Y, Pt2.X, Pt2.Y);
// DRAW ARROWS
Canvas.Brush.Color := ShapeFillColor;
Canvas.Brush.Style := bsSolid;
IEDrawLineEndShape( Canvas, Pt1.X, Pt1.Y, Pt2.X, Pt2.Y, StartingShape, ShapeSize, Zoom, StartShapePoints);
IEDrawLineEndShape( Canvas, Pt2.X, Pt2.Y, Pt1.X, Pt1.Y, EndingShape, ShapeSize, Zoom, EndShapePoints);
// DRAW TEXT
if labelVisible then
begin
// Get rect of label
if labelAtLeft then
labelLeft := min( Pt1.X, Pt2.X ) - LabelSize.cX div 2
else
labelLeft := max( Pt1.X, Pt2.X ) - Ceil( LabelSize.cX / 2 );
if labelLeft + LabelSize.cX > PosX + Width then
labelLeft := PosX + Width - LabelSize.cX;
if labelLeft < PosX then
labelLeft := PosX;
if LabelAtTop then
labelTop := min( Pt1.Y, Pt2.Y ) - LabelSize.cY div 2
else
labelTop := max( Pt1.Y, Pt2.Y ) - Ceil( LabelSize.cY / 2 );
if labelTop < PosY then
labelTop := PosY
else
if labelTop + labelSize.cY > PosY + Height then
labelTop := PosY + Height - labelSize.cY;
IEDrawText( Canvas,
labelLeft, labelTop, labelLeft + labelSize.cX, labelTop + labelSize.cY,
Zoom,
LabelText,
LabelFont,
LabelAlign,
ielCenter,
0, {Angle }
LabelBorderColor, LabelBorderWidth,
LabelFillColor, LabelFillColor2, LabelFillGradient,
True,
AntiAlias,
LabelShape,
UpdateSize);
LabelRect := Rect( Round( labelLeft / Zoom ),
Round( labelTop / Zoom ),
Round(( labelLeft + labelSize.cX ) / Zoom ),
Round(( labelTop + labelSize.cY ) / Zoom ));
end;
finally
Canvas.SmoothingMode := prevSmoothingMode;
end;
end;
// Bitmap is created if nil
// must be freed
procedure TIELineLayer.CopyToBitmapEx(var Dest: TIEBitmap;
CreateWidth : Integer; CreateHeight : Integer;
FastDrawing: Boolean;
EnableAlpha: Boolean; UseDisplayAR: Boolean;
UpdateSize: Boolean = False; EnlargeOnly: Boolean = False;
Zoom: Double = 1);
var
newWidth, newHeight, minSize: Double;
OutSize: TSize;
sizeChanged: Boolean;
begin
if CreateWidth < 1 then
CreateWidth := OriginalWidth;
if CreateHeight < 1 then
CreateHeight := OriginalHeight;
if EnableAlpha then
begin
InitBitmapRGBA( Dest, CreateWidth, CreateHeight ); // Use ie32RGB for RGBA support
Dest.IECanvas.SetCompositingMode(ieCompositingModeSourceOver, ieCompositingQualityDefault);
end
else
InitBitmap( Dest, CreateWidth, CreateHeight );
OutSize := IEDrawLine( Dest.IECanvas,
0, 0, Dest.Width, Dest.Height,
Zoom,
Round( Rotate ),
fLineColor, fLineWidth,
fStartShape, fEndShape, fShapeSize,
fLineFillColor,
fLabelPosition, fLabelText, fLabelAlignment, fLabelFont,
fLabelShape, fBorderColor, fBorderWidth,
fFillColor, fFillColor2, fFillGradient,
fAntiAlias and not FastDrawing,
fAntiAlias, // Ignore fast drawing for text
fLineRect,
fLabelRect,
fStartShapePoints,
fEndShapePoints,
UpdateSize,
fLastLineLength );
fLineLength := _DistPoint2Point( fLineRect.Left, fLineRect.Top, fLineRect.Right, fLineRect.Bottom );
if fLastLineLength <= 0 then
fLastLineLength := fLineLength;
if UpdateSize then
begin
if ( OutSize.cX < 0 ) or ( OutSize.cY < 0 ) then
exit;
// "LineWidth" padding on each side of line
minSize := 3 * fLineWidth;
newWidth := max( minSize, OutSize.cX );
newHeight := max( minSize, OutSize.cY );
sizeChanged := ( fResizedWidth <> newWidth ) or
( fResizedHeight <> newHeight );
fPosX := fPosX + ( fResizedWidth - newWidth ) / 2;
fResizedWidth := newWidth;
fPosY := fPosY + ( fResizedHeight - newHeight ) / 2 ;
fResizedHeight := newHeight;
if sizeChanged then
LayerChange();
end
else
begin
if EnableAlpha then
Dest.SynchronizeRGBA( True, True )
else
Dest.RemoveAlphaChannel()
end;
end;
// Don't need UseDisplayAR. AR is always maintained for line layers
procedure TIELineLayer.CopyToBitmap(var Dest: TIEBitmap; CreateWidth : Integer = -1; CreateHeight : Integer = -1; EnableAlpha: Boolean = True; UseDisplayAR: Boolean = True);
var
Zoom: Double;
wasLineRect: TRect;
wasLabelRect: TRect;
wasStartShapePoints: TIEEndShapeDrawInfo;
wasEndShapePoints: TIEEndShapeDrawInfo;
wasLineLength, wasLastLineLength: Double;
begin
Zoom := 1;
if ( CreateWidth > 0 ) and ( CreateHeight > 0 ) then
Zoom := min( CreateWidth / OriginalWidth, CreateHeight / OriginalHeight );
wasLineRect := fLineRect;
wasLabelRect := fLabelRect;
wasStartShapePoints := fStartShapePoints;
wasEndShapePoints := fEndShapePoints;
wasLineLength := fLineLength;
wasLastLineLength := fLastLineLength;
CopyToBitmapEx( Dest, CreateWidth, CreateHeight, Owner_FastOutputActive(), EnableAlpha, UseDisplayAR, False, False, Zoom );
// Don't update layout vars because bitmap may be different size
fLineRect := wasLineRect;
fLabelRect := wasLabelRect;
fStartShapePoints := wasStartShapePoints;
fEndShapePoints := wasEndShapePoints;
fLineLength := wasLineLength;
fLastLineLength := wasLastLineLength;
end;
{!!
<FS>TIELineLayer.SizeToFit
<FM>Declaration<FC>
procedure TIELineLayer.SizeToFit();
<FM>Description<FN>
Updates the size of the layer to fit the displayed angle.
This is useful if you have manually set the width/height of the layer.
<FM>Example<FN>
with ImageEnView1 do
begin
LayersAdd( ielkLine );
CurrentLayer.Rotate := 30;
CurrentLayer.Width := 500;
CurrentLayer.Height := 500;
TIELineLayer( CurrentLayer ).SizeToFit();
Update();
end;
!!}
procedure TIELineLayer.SizeToFit();
begin
CopyToBitmapEx( fGlobalCacheBitmap, Round( fResizedWidth ), Round( fResizedHeight ), True, False, True, True )
end;
function TIELineLayer.GetBitmap : TIEBitmap;
begin
CopyToBitmap( fGlobalCacheBitmap, iMax( 1, Round( fResizedWidth )), iMax( 1, Round( fResizedHeight )), Owner_EnableAlphaChannel, False );
Result := fGlobalCacheBitmap;
end;
procedure TIELineLayer.LoadFromStream(Stream: TStream);
var
saveVer: Integer;
dDummy: Double;
begin
saveVer := LoadMetaFromStream( Stream );
if saveVer < 6400 then
raise EIEException.create( 'Unknown data version' );
// Other props
Stream.Read( fLineColor, SizeOf( TColor ));
Stream.Read( fLineWidth, SizeOf( Integer ));
Stream.Read( fLineFillColor, SizeOf( TColor ));
IELoadFontFromStream(Stream, fLabelFont );
IELoadStringFromStreamW(Stream, fLabelText);
Stream.Read( fLabelAlignment, SizeOf( TIEAlignment ));
Stream.Read( fLabelPosition, SizeOf( TIELineLabelPos ));
Stream.Read( fLabelShape, SizeOf( TIEShape ));
Stream.Read( fReadOnly, SizeOf( Boolean ));
Stream.Read( fShapeSize, sizeof( integer ));
Stream.Read( fStartShape, sizeof( TIELineEndShape ));
Stream.Read( fEndShape, sizeof( TIELineEndShape ));
if saveVer <= 7001 then
begin
fLastLineLength := -1;
Stream.Read( dDummy, sizeof( Double ));
Stream.Read( dDummy, sizeof( Double ));
end
else
Stream.Read( fLastLineLength, sizeof( Double ));
if saveVer >= 7001 then
Stream.Read( fAutoSize , SizeOf( Boolean ));
fModified := False;
end;
procedure TIELineLayer.SaveToStream(Stream: TStream; MetaOnly: Boolean = False; CompressionFormat: TIOFileType = -2);
var
l, sz: integer;
begin
l := Stream.Position;
SaveMetaToStream( Stream);
// other props
Stream.Write( fLineColor, SizeOf( TColor ));
Stream.Write( fLineWidth, SizeOf( Integer ));
Stream.Write( fLineFillColor, SizeOf( TColor ));
IESaveFontToStream(Stream, fLabelFont );
IESaveStringToStreamW(Stream, fLabelText);
Stream.Write( fLabelAlignment, SizeOf( TIEAlignment ));
Stream.Write( fLabelPosition, SizeOf( TIELineLabelPos ));
Stream.Write( fLabelShape, SizeOf( TIEShape ));
Stream.Write( fReadOnly, SizeOf( Boolean ));
Stream.Write( fShapeSize, sizeof( integer ));
Stream.Write( fStartShape, sizeof( TIELineEndShape ));
Stream.Write( fEndShape, sizeof( TIELineEndShape ));
Stream.Write( fLastLineLength, sizeof( Double ));
Stream.Write( fAutoSize , SizeOf( Boolean ));
// Update position
sz := Stream.Position - l;
Stream.Position := l;
Stream.Write(sz, sizeof(integer)); // Fill size
Stream.Position := l + sz; // Position at end of layer record
end;
function TIELineLayer.GetAsSVG(): string;
function _DrawShape(ShapePoints: TIEEndShapeDrawInfo): string;
var
pp: array[0..2] of TPoint;
begin
case ShapePoints.Shape of
ieesCircle :
begin
Result := CreateSVGShapeTag( iesEllipse,
PosX + ShapePoints.Pt1.X,
PosY + ShapePoints.Pt1.Y,
ShapePoints.Pt2.X - ShapePoints.Pt1.X,
ShapePoints.Pt2.Y - ShapePoints.Pt1.Y,
LineWidth, LineColor, LabelFillColor, 0 {Rotate}, fTransparency );
end;
ieesArrow :
begin
pp[ 0 ]:= Point( PosX + ShapePoints.Pt1.X, PosY + ShapePoints.Pt1.Y );
pp[ 1 ]:= Point( PosX + ShapePoints.Pt2.X, PosY + ShapePoints.Pt2.Y );
pp[ 2 ]:= Point( PosX + ShapePoints.Pt3.X, PosY + ShapePoints.Pt3.Y );
Result := CreateSVGPolylineTag( pp, 3, True, LineWidth, LineColor, LabelFillColor, 0 {Rotate}, Point(0,0), fTransparency );
end;
end;
end;
var
labelVisible: Boolean;
lineTag, startShapeTag, endShapeTag, textTag: string;
begin
Result := '';
if ( fLineRect.Left = 0 ) and ( fLineRect.Right = 0 ) and ( fLineRect.Top = 0 ) and ( fLineRect.Bottom = 0 ) then
CopyToBitmapEx( fGlobalCacheBitmap, -1, -1, True, False, True ); // So fLineRect is updated
lineTag := CreateSVGLineTag( Point( PosX + fLineRect.Left, PosY + fLineRect.Top ),
Point( PosX + fLineRect.Right, PosY + fLineRect.Bottom ),
LineWidth, LineColor, fTransparency );
startShapeTag := _DrawShape( fStartShapePoints );
endShapeTag := _DrawShape( fEndShapePoints );
textTag := '';
labelVisible := fLabelText <> '';
if ( fLabelRect.Left = 0 ) and ( fLabelRect.Right = 0 ) then
labelVisible := False;
if labelVisible then
textTag := CreateSVGTextTag( fLabelText, LabelFont,
PosX + fLabelRect.Left,
PosY + fLabelRect.Top,
fLabelRect.Right - fLabelRect.Left,
fLabelRect.Bottom - fLabelRect.Top,
fLabelAlignment, ielCenter, 0 { TextAngle },
LabelBorderWidth, LabelBorderColor, LabelFillColor,
fLabelShape, fTransparency );
Result := lineTag + startShapeTag + endShapeTag + textTag;
end;
{!!
<FS>TIELineLayer.LabelFont
<FM>Declaration<FC>
property LabelFont: TFont;
<FM>Description<FN>
Specifies the font of the label text.
<FM>Example<FC>
// Sets 'Arial' as font type for the current line layer
TIELineLayer( ImageEnView1.CurrentLayer ).LabelFont.Name := 'Arial';
ImageEnView1.Update();
<IMG help_images\Line_withLabel.gif>
<FM>See Also<FN>
- <A TIELineLayer.LabelAlignment>
- <A TIELineLayer.LabelPosition>
- <A TIELineLayer.LabelShape>
- <A TIELineLayer.LabelText>
!!}
procedure TIELineLayer.SetLabelFont(const Value: TFont);
begin
fLabelFont := Value;
LayerChange();
if fAutoSize then
SizeToFit();
end;
{!!
<FS>TIELineLayer.LabelBorderColor
<FM>Declaration<FC>
property LabelBorderColor: TColor;
<FM>Description<FN>
The color of the frame around the <L TIELineLayer.LabelText>text label</L>.
To hide the border set <FC>BorderColor<FN> to clNone or <A TIELineLayer.LabelBorderWidth> to 0.
Default: clBlack
<FM>Example<FC>
// Add text label to our arrow (with black border and gradient fill)
TIELineLayer( ImageEnView1.CurrentLayer ).LabelPosition := ielpAtEnd;
TIELineLayer(ImageEnView1.CurrentLayer).LabelFillColor := clRed;
TIELineLayer(ImageEnView1.CurrentLayer).LabelFillColor2 := clYellow;
TIELineLayer(ImageEnView1.CurrentLayer).LabelFillGradient := clHorizontal;
TIELineLayer(ImageEnView1.CurrentLayer).LabelBorderColor := clBlack;
TIELineLayer(ImageEnView1.CurrentLayer).LabelBorderWidth := 3;
ImageEnView1.Update();
<IMG help_images\Line_withLabel.gif>
<FM>See Also<FN>
- <L TIELayer.BorderColor>TIELayer.BorderColor</L>
- <A TIELineLayer.LabelBorderWidth>
- <A TIELineLayer.LineWidth>
!!}
function TIELineLayer.GetLabelBorderColor: TColor;
begin
Result := fBorderColor;
end;
procedure TIELineLayer.SetLabelBorderColor(value: TColor);
begin
fBorderColor := Value;
LayerChange();
end;
{!!
<FS>TIELineLayer.LabelBorderWidth
<FM>Declaration<FC>
property LabelBorderWidth: Integer;
<FM>Description<FN>
The width of the frame around the <L TIELineLayer.LabelText>text label</L>.
To hide the border, set <FC>LabelBorderColor<FN> to clNone or <A TIELineLayer.LabelBorderWidth> to 0.
Default: 1
<FM>Example<FC>
// Add text label to our arrow (with black border and gradient fill)
TIELineLayer( ImageEnView1.CurrentLayer ).LabelPosition := ielpAtEnd;
TIELineLayer(ImageEnView1.CurrentLayer).LabelFillColor := clRed;
TIELineLayer(ImageEnView1.CurrentLayer).LabelFillColor2 := clYellow;
TIELineLayer(ImageEnView1.CurrentLayer).LabelFillGradient := clHorizontal;
TIELineLayer(ImageEnView1.CurrentLayer).LabelBorderColor := clBlack;
TIELineLayer(ImageEnView1.CurrentLayer).LabelBorderWidth := 3;
ImageEnView1.Update();
<IMG help_images\Line_withLabel.gif>
<FM>See Also<FN>
- <L TIELayer.BorderWidth>TIELayer.BorderWidth</L>
- <A TIELineLayer.LabelBorderColor>
- <A TIELineLayer.LineColor>
!!}
function TIELineLayer.GetLabelBorderWidth: Integer;
begin
Result := fBorderWidth;
end;
procedure TIELineLayer.SetLabelBorderWidth(value: Integer);
begin
fBorderWidth := Value;
LayerChange();
end;
{!!
<FS>TIELineLayer.LabelFillColor
<FM>Declaration<FC>
property LabelFillColor: TColor;
<FM>Description<FN>
The color of the <L TIELineLayer.LabelText>text label</L>.
The fill color must be valid (i.e. clNone is not supported). If <FC>LabelFillColor<FN> is different from <A TIELineLayer.LabelFillColor2> it will be drawn as a gradient.
Default: clWhite
<FM>Example<FC>
// Add text label to our arrow (with black border and gradient fill)
TIELineLayer( ImageEnView1.CurrentLayer ).LabelPosition := ielpAtEnd;
TIELineLayer(ImageEnView1.CurrentLayer).LabelFillColor := clRed;
TIELineLayer(ImageEnView1.CurrentLayer).LabelFillColor2 := clYellow;
TIELineLayer(ImageEnView1.CurrentLayer).LabelFillGradient := clHorizontal;
TIELineLayer(ImageEnView1.CurrentLayer).LabelBorderColor := clBlack;
TIELineLayer(ImageEnView1.CurrentLayer).LabelBorderWidth := 3;
ImageEnView1.Update();
<IMG help_images\Line_withLabel.gif>
<FM>See Also<FN>
- <L TIELayer.FillColor>TIELayer.FillColor</L>
- <A TIELineLayer.LabelFillColor2>
- <A TIELineLayer.LabelFillGradient>
- <A TIELineLayer.FillColor>
!!}
function TIELineLayer.GetLabelFillColor: TColor;
begin
Result := fFillColor;
end;
procedure TIELineLayer.SetLabelFillColor(value: TColor);
begin
fFillColor := Value;
LayerChange();
end;
{!!
<FS>TIELineLayer.LabelFillColor2
<FM>Declaration<FC>
property LabelFillColor2: TColor;
<FM>Description<FN>
The end color for the <L TIELineLayer.LabelText>text label</L> gradient.
If <FC>LabelFillColor2<FN> is clNone, the text box is filled by a solid color specified by <A TIELineLayer.LabelFillColor>. If <FC>LabelFillColor2<FN> is different from <A TIELineLayer.LabelFillColor> it is drawn as a gradient.
The direction of the gradient is specified by <A TIELineLayer.LabelFillGradient>.
Default: clNone
<FM>Example<FC>
// Set a horizontal gradient fill for the label of a line layer
TIELineLayer(ImageEnView1.CurrentLayer).LabelFillColor := clRed;
TIELineLayer(ImageEnView1.CurrentLayer).LabelFillColor2 := clYellow;
TIELineLayer(ImageEnView1.CurrentLayer).LabelFillGradient := clHorizontal;
TIELineLayer(ImageEnView1.CurrentLayer).LabelBorderColor := clBlack;
TIELineLayer(ImageEnView1.CurrentLayer).LabelBorderWidth := 3;
ImageEnView1.Update();
// Which is the same as...
ImageEnView1.CurrentLayer.FillColor := clRed;
ImageEnView1.CurrentLayer.FillColor2 := clYellow;
ImageEnView1.CurrentLayer.FillGradient := clHorizontal;
ImageEnView1.CurrentLayer.BorderColor := clBlack;
ImageEnView1.CurrentLayer.BorderWidth := 3;
ImageEnView1.Update();
<IMG help_images\Line_withLabel.gif>
// Disable the gradient fill of the label
TIELineLayer( ImageEnView1.CurrentLayer ).LabelFillColor2 := clNone;
ImageEnView1.Update();
<FM>See Also<FN>
- <L TIELayer.FillColor2>TIELayer.FillColor2</L>
- <A TIELineLayer.LabelFillColor>
- <A TIELineLayer.LabelFillGradient>
!!}
function TIELineLayer.GetLabelFillColor2: TColor;
begin
Result := fFillColor2;
end;
procedure TIELineLayer.SetLabelFillColor2(value: TColor);
begin
fFillColor2 := Value;
LayerChange();
end;
{!!
<FS>TIELineLayer.LabelFillGradient
<FM>Declaration<FC>
property LabelFillGradient: <A TIEGradientDir>;
<FM>Description<FN>
The direction of the gradient used for the <L TIELineLayer.LabelText>text label</L> fill.
If <A TIELineLayer.LabelFillColor> is different from <A TIELineLayer.LabelFillColor2> the text box is filled with a gradient. <FC>LabelFillGradient<FN> specifies the direction.
Default: gdVertical
<FM>Example<FC>
// Set a horizontal gradient fill for the label of a line layer
TIELineLayer(ImageEnView1.CurrentLayer).LabelFillColor := clRed;
TIELineLayer(ImageEnView1.CurrentLayer).LabelFillColor2 := clYellow;
TIELineLayer(ImageEnView1.CurrentLayer).LabelFillGradient := clHorizontal;
TIELineLayer(ImageEnView1.CurrentLayer).LabelBorderColor := clBlack;
TIELineLayer(ImageEnView1.CurrentLayer).LabelBorderWidth := 3;
ImageEnView1.Update();
// Which is the same as...
ImageEnView1.CurrentLayer.FillColor := clRed;
ImageEnView1.CurrentLayer.FillColor2 := clYellow;
ImageEnView1.CurrentLayer.FillGradient := clHorizontal;
ImageEnView1.CurrentLayer.BorderColor := clBlack;
ImageEnView1.CurrentLayer.BorderWidth := 3;
ImageEnView1.Update();
<IMG help_images\Line_withLabel.gif>
<FM>See Also<FN>
- <L TIELayer.FillGradient>TIELayer.FillGradient</L>
- <A TIELineLayer.LabelFillColor>
- <A TIELineLayer.LabelFillColor2>
!!}
function TIELineLayer.GetLabelFillGradient: TIEGradientDir;
begin
Result := fFillGradient;
end;
{!!
<FS>TIELineLayer.LineLength
<FM>Declaration<FC>
property LineLength: Integer;
<FM>Description<FN>
Provides an alternative way to set the size of the line (other than setting the rectangle via <A TIELayer.Width> and <A TIELayer.Height>).
<FM>Comparison<FN>
TIELineLayer provides three ways to position the line depending on your requirements. All the following create a 45 deg. line from 100,100 to 300,300
1. Standard TIELayer methods
<FC>
ImageEnView1.CurrentLayer.PosX := 100;
ImageEnView1.CurrentLayer.PosY := 100;
ImageEnView1.CurrentLayer.Width := 200;
ImageEnView1.CurrentLayer.Height := 200;
<FN>
2. Setting starting and end points
<FC>
TIELineLayer( ImageEnView1.CurrentLayer ).LinePoints := Rect( 100, 100, 300, 300 );
<FN>
2. Setting line length
<FC>
TIELineLayer( ImageEnView1.CurrentLayer ).AutoSize := False;
ImageEnView1.CurrentLayer.PosX := 100;
ImageEnView1.CurrentLayer.PosY := 100;
ImageEnView1.CurrentLayer.Rotate := -45;
TIELineLayer( ImageEnView1.CurrentLayer ).LineLength := 280;<FN>
<FM>Example<FC>
// Create a layer 100 pixels long at 45 degrees
ImageEnView1.LayersAdd( ielkLine );
TIELineLayer( ImageEnView1.CurrentLayer ).LineLength := 100;
TIELineLayer( ImageEnView1.CurrentLayer ).Rotate := 45;
ImageEnView1.Update();
<FM>See Also<FN>
- <A TIELineLayer.LinePoints>
!!}
function TIELineLayer.GetLineLength: Integer;
begin
Result := Round( fLineLength );
end;
procedure TIELineLayer.SetLineLength(const Value: Integer);
var
wasPosX, wasPosY: Integer;
begin
wasPosX := PosX;
wasPosY := PosY;
fLastLineLength := Value;
SizeToFit();
// Size from top, left
PosX := wasPosX;
PosY := wasPosY;
end;
{!!
<FS>TIELineLayer.LinePoints
<FM>Declaration<FC>
property LineLength: TRect;
<FM>Description<FN>
Provides an alternate method to set the position of a line, by specifying its two end points. The points are expressed within a rect, i.e. Point 1 is (Left, Top) and Point 2 is (Right, Bottom).
Note: When setting <FC>LinePoints<FN>, <TIELineLayer.EndShape>end shapes</L> and <TIELineLayer.LabelText>label</L> are not taken into account
<FM>Comparison<FN>
TIELineLayer provides three ways to position the line depending on your requirements. All the following create a 45 deg. line from 100,100 to 300,300
1. Standard TIELayer methods
<FC>
ImageEnView1.CurrentLayer.PosX := 100;
ImageEnView1.CurrentLayer.PosY := 100;
ImageEnView1.CurrentLayer.Width := 200;
ImageEnView1.CurrentLayer.Height := 200;
<FN>
2. Setting starting and end points
<FC>
TIELineLayer( ImageEnView1.CurrentLayer ).LinePoints := Rect( 100, 100, 300, 300 );
<FN>
2. Setting line length
<FC>
TIELineLayer( ImageEnView1.CurrentLayer ).AutoSize := False;
ImageEnView1.CurrentLayer.PosX := 100;
ImageEnView1.CurrentLayer.PosY := 100;
ImageEnView1.CurrentLayer.Rotate := -45;
TIELineLayer( ImageEnView1.CurrentLayer ).LineLength := 280;<FN>
<FM>Example<FC>
// Create a line from 100,100 to 200,200
ImageEnView1.LayersAdd( ielkLine );
TIELineLayer( ImageEnView1.CurrentLayer ).LinePoints := Rect( 100, 100, 200, 200 );
ImageEnView1.Update();
// Display points of the current line layer
with TIELineLayer( ImageEnView1.CurrentLayer ) do
begin
lblPoint1.Caption := Format( 'Point 1: %d, %d', [ LinePoints.Left, LinePoints.Top ]);
lblPoint2.Caption := Format( 'Point 2: %d, %d', [ LinePoints.Right, LinePoints.Bottom ]);
end;
<FM>See Also<FN>
- <A TIELineLayer.LineLength>
!!}
function TIELineLayer.GetLinePoints: TRect;
begin
if ( fLineRect.Left = 0 ) and ( fLineRect.Right = 0 ) and ( fLineRect.Top = 0 ) and ( fLineRect.Bottom = 0 ) then
CopyToBitmapEx( fGlobalCacheBitmap, -1, -1, True, False, True ); // So fLineRect is updated
result := fLineRect;
end;
procedure TIELineLayer.SetLinePoints(Value: TRect);
var
lineLength: Double;
begin
fRotate := IERadiansToDegrees( IEAngle2( Value.Left, Value.Top, Value.Right, Value.Bottom ));
lineLength := _DistPoint2Point( Value.Left, Value.Top, Value.Right, Value.Bottom );
SetLineLength( Round( lineLength ));
PosX := min( Value.Left, Value.Right );
PosY := min( Value.Top, Value.Bottom );
end;
procedure TIELineLayer.SetLabelFillGradient(value: TIEGradientDir);
begin
fFillGradient := Value;
LayerChange();
end;
{!!
<FS>TIELineLayer.FillColor
<FM>Declaration<FC>
property FillColor: TColor;
<FM>Description<FN>
The fill for the <A TIELineLayer.StartShape> and <A TIELineLayer.EndShape>.
Notes:
- The border style is the same as for the line (<A TIELineLayer.LineColor> and <A TIELineLayer.LineWidth>
- Gradients are not supported
Default: clWhite
<FM>Example<FC>
// Add yellow filled arrows and circle ends to our current line layer
TIELineLayer( ImageEnView1.CurrentLayer ).StartShape := ieesArrow;
TIELineLayer( ImageEnView1.CurrentLayer ).EndShape := ieesCircle;
TIELineLayer( ImageEnView1.CurrentLayer ).FillColor := clYellow;
TIELineLayer( ImageEnView1.CurrentLayer ).ShapeSize := 25;
ImageEnView1.Update();
<IMG help_images\Line_EndShapes.gif>
<FM>See Also<FN>
- <L TIELayer.FillColor>TIELayer.FillColor</L>
- <A TIELineLayer.LabelFillColor>
!!}
procedure TIELineLayer.SetLineFillColor(const Value: TColor);
begin
fLineFillColor := Value;
LayerChange();
end;
{!!
<FS>TIELineLayer.LineColor
<FM>Declaration<FC>
property LineColor: TColor;
<FM>Description<FN>
The color of the line and the border of <A TIELineLayer.StartShape> and <A TIELineLayer.EndShape>.
Default: clBlack
<FM>Example<FC>
// Add a thick green line layer
ImageEnView1.LayersAdd( ielkLine );
TIELineLayer( ImageEnView1.CurrentLayer ).LineColor := clGreen;
TIELineLayer( ImageEnView1.CurrentLayer ).LineWidth := 5;
ImageEnView1.Update();
<FM>See Also<FN>
- <L TIELayer.BorderColor>TIELayer.BorderColor</L>
- <A TIELineLayer.LineWidth>
- <A TIELineLayer.LabelBorderColor>
!!}
procedure TIELineLayer.SetLineColor(const value: TColor);
begin
fLineColor := Value;
LayerChange();
end;
{!!
<FS>TIELineLayer.LineWidth
<FM>Declaration<FC>
property LineWidth: Integer;
<FM>Description<FN>
The width of the line and the border of <A TIELineLayer.StartShape> and <A TIELineLayer.EndShape>.
Default: 1
<FM>Example<FC>
// Add a thick green line layer
ImageEnView1.LayersAdd( ielkLine );
TIELineLayer( ImageEnView1.CurrentLayer ).LineColor := clGreen;
TIELineLayer( ImageEnView1.CurrentLayer ).LineWidth := 5;
ImageEnView1.Update();
<FM>See Also<FN>
- <L TIELayer.BorderWidth>TIELayer.BorderWidth</L>
- <A TIELineLayer.LineColor>
- <A TIELineLayer.LabelBorderWidth>
!!}
procedure TIELineLayer.SetLineWidth(const value: Integer);
begin
fLineWidth := Value;
LayerChange();
end;
{!!
<FS>TIELineLayer.LabelShape
<FM>Declaration<FC>
property LabelShape: <A TIEShape>;
<FM>Description<FN>
The shape of the <L TIELineLayer.LabelText>text label</L>.
Note: Only the following shapes are supported: iesRectangle, iesRoundRect, iesEllipse
Default: iesRectangle
<FM>Example<FC>
// Add a circular "Here" label
ImageEnView1.LayersAdd( ielkLine );
TIELineLayer( ImageEnView1.CurrentLayer ).LabelShape := iesEllipse;
TIELineLayer( ImageEnView1.CurrentLayer ).LabelText := 'Here';
ImageEnView1.Update();
// Add rectangular text label to our line
TIELineLayer( ImageEnView1.CurrentLayer ).LabelPosition := ielpAtEnd;
TIELineLayer(ImageEnView1.CurrentLayer).LabelFillColor := clRed;
TIELineLayer(ImageEnView1.CurrentLayer).LabelFillColor2 := clYellow;
TIELineLayer(ImageEnView1.CurrentLayer).LabelFillGradient := clHorizontal;
TIELineLayer(ImageEnView1.CurrentLayer).LabelBorderColor := clBlack;
TIELineLayer(ImageEnView1.CurrentLayer).LabelBorderWidth := 3;
ImageEnView1.Update();
<IMG help_images\Line_withLabel.gif>
<FM>See Also<FN>
- <A TIELineLayer.LabelAlignment>
- <A TIELineLayer.LabelFont>
- <A TIELineLayer.LabelPosition>
- <A TIELineLayer.LabelText>
!!}
procedure TIELineLayer.SetLabelShape(Value: TIEShape);
begin
fLabelShape := Value;
LayerChange();
end;
{!!
<FS>TIELineLayer.LabelAlignment
<FM>Declaration<FC>
property LabelAlignment: <A TIEAlignment>;
<FM>Description<FN>
Specifies the alignment of the <L TIELineLayer.LabelText>text label</L>.
Notes: <FC>iejJustify<FN> is unsupported for TIELineLayers
Default: iejLeft
<FM>Example<FC>
// Center the text for the label of the current line
TIELineLayer( ImageEnView1.CurrentLayer ).LabelAlignment := iejCenter;
ImageEnView1.Update();
<IMG help_images\Line_withLabel.gif>
<FM>See Also<FN>
- <A TIELineLayer.LabelFont>
- <A TIELineLayer.LabelPosition>
- <A TIELineLayer.LabelShape>
- <A TIELineLayer.LabelText>
!!}
procedure TIELineLayer.SetLabelAlignment(Value: TIEAlignment);
begin
fLabelAlignment := Value;
LayerChange();
end;
{!!
<FS>TIELineLayer.LabelText
<FM>Declaration<FC>
property LabelText: String;
<FM>Description<FN>
When a value is specified for <FC>LabelText<FN>, a text label will be displayed at the end of the line.
<FM>Example<FC>
TIELineLayer( ImageEnView1.CurrentLayer ).LabelPosition := ielpAtEnd;
TIELineLayer( ImageEnView1.CurrentLayer ).LabelText := 'Test Label';
ImageEnView1.Update();
<IMG help_images\Line_withLabel.gif>
<FM>See Also<FN>
- <A TIELineLayer.LabelAlignment>
- <A TIELineLayer.LabelFont>
- <A TIELineLayer.LabelPosition>
- <A TIELineLayer.LabelShape>
!!}
procedure TIELineLayer.SetLabelText(const Value: string);
begin
fLabelText := Value;
LayerChange();
if fAutoSize then
SizeToFit();
end;
{!!
<FS>TIELineLayer.LabelPosition
<FM>Declaration<FC>
property LabelPosition: <A TIELineLabelPos>;
<FM>Description<FN>
Specifies the position and visibility of the <L TIELineLayer.LabelText>text label</L>.
<TABLE>
<R> <H>Value</H> <H>Description</H> </R>
<R> <C>ielpHide</C> <C>Does not show the text label even if text has been specified</C> </R>
<R> <C>ielpAtStart</C> <C>Shows the text label at the start of the line</C> </R>
<R> <C>ielpAtEnd</C> <C>Shows the text label at the end of the line</C> </R>
</TABLE>
Default: ielpAtEnd
<FM>Examples<FC>
// Move the label to the start of the line
TIELineLayer( ImageEnView1.CurrentLayer ).LabelPosition := ielpAtStart;
// Hide labels of all line layers when user clicks a check box
procedure Tfmain.chkShowLabelsClick(Sender: TObject);
var
I: integer;
begin
ImageEnView1.LockUpdate();
for I := 0 to ImageEnView1.LayersCount - 1 do
if ImageEnView1.Layers[ I ].Kind = ielkLine then
begin
if chkShowLabels.Checked then
TIELineLayer( ImageEnView1.Layers[ I ]).LabelPosition := ielpAtEnd
else
TIELineLayer( ImageEnView1.Layers[ I ]).LabelPosition := ielpHide;
end;
ImageEnView1.UnlockUpdate();
end;
<FM>See Also<FN>
- <A TIELineLayer.LabelAlignment>
- <A TIELineLayer.LabelFont>
- <A TIELineLayer.LabelShape>
- <A TIELineLayer.LabelText>
!!}
procedure TIELineLayer.SetLabelPosition(const Value: TIELineLabelPos);
begin
fLabelPosition := Value;
LayerChange();
if fAutoSize then
SizeToFit();
end;
{!!
<FS>TIELineLayer.ActivateEditor
<FM>Declaration<FC>
procedure ActivateEditor();
<FM>Description<FN>
Activates editing of the <L TIELineLayer.LabelText>text label</L> by the user (i.e. user can begin typing to change the text)
Note: Has no effecr if the label is not <L TIELineLayer.LabelPosition>visible</L>
<FM>Example<FC>
// Display the text editor for the current layer
if Layer is TIELineLayer
TIELineLayer( ImageEnView1.CurrentLayer ).ActivateEditor()
else
if Layer is TIETextLayer
TIETextLayer( ImageEnView1.CurrentLayer ).ActivateEditor();
<FM>See Also<FN>
- <A TImageEnView.LayersCancelEditor>
!!}
procedure TIELineLayer.ActivateEditor();
begin
if assigned( fOwner ) and (( fLabelRect.Right - fLabelRect.Left ) > 0 ) then
TImageEnView( fOwner ).LayersActivateTextEditor( GetIndex );
end;
{!!
<FS>TIELineLayer.StartShape
<FM>Declaration<FC>
property StartShape: <A TIELineEndShape>;
<FM>Description<FN>
Specifies the shape that is displayed at the start of the line.
Notes:
- The border width and color of the arrow will be the same as the line (i.e. specified by <A TIELineLayer.LineColor> and <A TIELineLayer.LineWidth>)
- The fill is specified by <A TIELineLayer.FillColor> (Gradients are not supported)
- If a <L TIELineLayer.LabelText>label is displayed</L> and <L TIELineLayer.LabelPosition>= ielpAtStart, then the <FC>StartShape<FN> will not be shown
Default: ieesNone
<FM>Example<FC>
// Add yellow filled arrows and circle ends to our current line layer
TIELineLayer( ImageEnView1.CurrentLayer ).StartShape := ieesArrow;
TIELineLayer( ImageEnView1.CurrentLayer ).EndShape := ieesCircle;
TIELineLayer( ImageEnView1.CurrentLayer ).FillColor := clYellow;
TIELineLayer( ImageEnView1.CurrentLayer ).ShapeSize := 25;
ImageEnView1.Update();
<IMG help_images\Line_EndShapes.gif>
<FM>See Also<FN>
- <A TIELineLayer.EndShape>
- <A TIELineLayer.ShapeSize>
!!}
procedure TIELineLayer.SetStartShape(const Value: TIELineEndShape);
begin
fStartShape := Value;
LayerChange();
if fAutoSize then
SizeToFit();
end;
{!!
<FS>TIELineLayer.EndShape
<FM>Declaration<FC>
property EndShape: <A TIELineEndShape>;
<FM>Description<FN>
Specifies the shape that is displayed at the end of the line.
Notes:
- The border width and color of the arrow will be the same as the line (i.e. specified by <A TIELineLayer.LineColor> and <A TIELineLayer.LineWidth>)
- The fill is specified by <A TIELineLayer.FillColor> (Gradients are not supported)
- If a <L TIELineLayer.LabelText>label is displayed</L> and <L TIELineLayer.LabelPosition>= ielpAtEnd, then the <FC>EndShape<FN> will not be shown
Default: ieesNone
<FM>Example<FC>
// Add yellow filled arrows and circle ends to our current line layer
TIELineLayer( ImageEnView1.CurrentLayer ).StartShape := ieesArrow;
TIELineLayer( ImageEnView1.CurrentLayer ).EndShape := ieesCircle;
TIELineLayer( ImageEnView1.CurrentLayer ).FillColor := clYellow;
TIELineLayer( ImageEnView1.CurrentLayer ).ShapeSize := 25;
ImageEnView1.Update();
<IMG help_images\Line_EndShapes.gif>
<FM>See Also<FN>
- <A TIELineLayer.StartShape>
- <A TIELineLayer.ShapeSize>
!!}
procedure TIELineLayer.SetEndShape(const Value: TIELineEndShape);
begin
fEndShape := Value;
LayerChange();
if fAutoSize then
SizeToFit();
end;
{!!
<FS>TIELineLayer.ShapeSize
<FM>Declaration<FC>
property ShapeSize: integer;
<FM>Description<FN>
Specifies the size of the arrows at the start and end of the line.
Notes:
- The border width and color of the arrow will be the same as the line (i.e. specified by <A TIELineLayer.LineColor> and <A TIELineLayer.LineWidth>)
- The fill is specified by <A TIELineLayer.FillColor> (Gradients are not supported)
Default: 20
<FM>Example<FC>
// Enlarge the arrows
TIELineLayer( ImageEnView1.CurrentLayer ).ShapeSize := 25;
ImageEnView1.Update();
<IMG help_images\Line_EndShapes.gif>
<FM>See Also<FN>
- <A TIELineLayer.StartShape>
- <A TIELineLayer.EndShape>
!!}
procedure TIELineLayer.SetShapeSize(const Value: Integer);
begin
fShapeSize := Value;
LayerChange();
if fAutoSize then
SizeToFit();
end;
procedure TIELineLayer.SetAutoSize(const Value: boolean);
begin
fAutoSize := Value;
LayerChange( False );
if fAutoSize then
SizeToFit();
end;
{!!
<FS>TIELineLayer.ReadOnly
<FM>Declaration<FC>
property ReadOnly: Boolean;
<FM>Description<FN>
Prevents the user from editing the text of the label.
When <FC>ReadOnly<FN> is false, the user can double-click the label or click F2 to start editing of the label text. <FC>ReadOnly<FN> prevents the user from editing the text.
Default: False
<FM>Example<FC>
// Prevent editing of the current layer text
TIELineLayer( ImageEnView1.CurrentLayer ).ReadOnly := False;
!!}
procedure TIELineLayer.SetReadOnly(const Value: boolean);
begin
fReadOnly := Value;
LayerChange( False );
end;
// *************************************************************************************** //
// ** ** //
// ** TIEPolylineLayer ** //
// ** ** //
// *************************************************************************************** //
constructor TIEPolylineLayer.Create(Owner: TObject);
begin
inherited Create(Owner);
fKind := ielkPolyline;
fPolyPoints := nil;
fPolyPointCount := 0;
fPolyPointsAllocated := 0;
fDrawnPoints := nil;
fDrawnPointCount := 0;
fDrawnPointsAllocated := 0;
SetDefaults;
fResizedWidth := 100;
fResizedHeight := 100;
end;
destructor TIEPolylineLayer.Destroy;
begin
if fDrawnPoints <> nil then
begin
freemem(fDrawnPoints);
fDrawnPoints := nil;
end;
fDrawnPointCount := 0;
fDrawnPointsAllocated := 0;
ClearAllPoints();
inherited;
end;
procedure IEDrawPolyline(Canvas: TIECanvas;
PosX, PosY, Width, Height: Integer;
ZoomX, ZoomY: Double;
Layer: TIEPolylineLayer;
PolyPoints: pointer; // array of TPoint. Coordinates are in bitmap pixels, they are never translated or resized.
// C++Builder doesn't work with PolyPoints as PPointArray
PolyPointCount: integer; // PolyPoints count
PolyPointsAllocated: integer; // allocated polyline points
PolylineClosed: boolean; // the polygon is closes (filled with a brush)
var fDrawnPoints: pointer;
var fDrawnPointCount: integer;
var fDrawnPointsAllocated: integer;
LineColor: TColor; LineWidth: Integer;
FillColor: TColor; FillColor2: TColor; FillGradient: TIEGradientDir;
AntiAlias: Boolean;
Angle: Integer; AspectRatioLocked: Boolean);
var
currX, currY: Integer;
i: Integer;
pts: PPointArray;
prevSmoothingMode : TIECanvasSmoothingMode;
flipHorz, flipVert, invertDir: Boolean;
tempWidth, tempHeight: Integer;
begin
// ImageEn angles are counter-clockwise
Angle := 360 - Angle;
while Angle >= 360 do
Dec( Angle, 360 );
while Angle < 0 do
Inc( Angle, 360 );
if LineWidth > 0 then
LineWidth := imax( 1, Round( LineWidth * ( ZoomX + ZoomY ) / 2 ));
prevSmoothingMode := Canvas.SmoothingMode;
if AntiAlias then
Canvas.SmoothingMode := iesmAntialias
else
Canvas.SmoothingMode := iesmBestPerformance;
try
with Canvas do
begin
Pen.Color := $01010101; // needed otherwise next Pen.Color is not set (gdi bug workaround?)
if LineColor = clNone_ then
LineWidth := 0;
if LineWidth > 0 then
begin
Pen.Style := psSolid;
Pen.Width := LineWidth;
Pen.Color := LineColor;
end
else
Pen.Style := psClear;
Pen.Mode := pmCopy;
Pen.LineJoin := ieljRound;
if FillColor = clNone_ then
Brush.Style := bsClear
else
begin
Brush.Color := FillColor;
Brush.Style := bsSolid;
end;
if fDrawnPointCount <> PolyPointCount then
begin
fDrawnPointCount := PolyPointCount;
if fDrawnPointCount > fDrawnPointsAllocated then
begin
if assigned(fDrawnPoints) then
freemem(fDrawnPoints);
fDrawnPointsAllocated := fDrawnPointCount * 2;
getmem(fDrawnPoints, fDrawnPointsAllocated * sizeof(TPoint));
end;
end;
// 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 );
if invertDir and AspectRatioLocked then
begin
if Width > Height then
begin
tempWidth := Width;
Width := Round( Height * Height / Width ) ;
PosX := PosX + ( tempWidth - Width ) div 2;
end
else
begin
tempHeight := Height;
Height := Round( Width * Width / Height ) ;
PosY := PosY + ( tempHeight - Height ) div 2;
end;
end;
pts := ppointarray(fDrawnPoints);
for i := 0 to PolyPointCount - 1 do
begin
currX := PPointArray(PolyPoints)[ i ].x;
currY := PPointArray(PolyPoints)[ i ].y;
// FLIP HORZ
if flipHorz then
currX := 1000 - currX;
// FLIP VERT
if flipVert then
currY := 1000 - currY;
if invertDir then
begin
pts[i].x := PosX + LineWidth div 2 + round( currY / 1000 * ( Width - LineWidth ));
pts[i].y := PosY + LineWidth div 2 + round( currX / 1000 * ( Height - LineWidth ));
end
else
begin
pts[i].x := PosX + LineWidth div 2 + round( currX / 1000 * ( Width - LineWidth ));
pts[i].y := PosY + LineWidth div 2 + round( currY / 1000 * ( Height - LineWidth ));
end;
end;
// Free rotation
if Angle mod 90 <> 0 then
begin
IERotatePoints( slice( pts^, PolyPointCount ), PolyPointCount, - Angle, PosX + LineWidth div 2 + Width div 2, PosY + LineWidth div 2 + Height div 2 );
IEScalePoints( slice( pts^, PolyPointCount ), PolyPointCount, PosX + LineWidth div 2, PosY + LineWidth div 2, PosX + Width - LineWidth, PosY + Height - LineWidth, AspectRatioLocked );
end;
if PolylineClosed then
Polygon( slice( pts^, PolyPointCount ))
else
Polyline( slice( pts^, PolyPointCount ));
end;
finally
Canvas.SmoothingMode := prevSmoothingMode;
end;
end;
// Bitmap is created if nil
// must be freed
procedure TIEPolylineLayer.CopyToBitmapEx(var Dest: TIEBitmap;
CreateWidth : Integer; CreateHeight : Integer;
FastDrawing: Boolean;
EnableAlpha: Boolean; UseDisplayAR: Boolean;
UpdateSize: Boolean = False; EnlargeOnly: Boolean = False;
Zoom: Double = 1);
var
drawRect: TRect;
begin
if CreateWidth < 1 then
CreateWidth := OriginalWidth;
if CreateHeight < 1 then
CreateHeight := OriginalHeight;
if EnableAlpha then
begin
InitBitmapRGBA( Dest, CreateWidth, CreateHeight ); // Use ie32RGB for RGBA support
Dest.IECanvas.SetCompositingMode(ieCompositingModeSourceOver, ieCompositingQualityDefault);
end
else
InitBitmap( Dest, CreateWidth, CreateHeight );
drawRect := Rect( 0, 0, Dest.Width, Dest.Height );
if UseDisplayAR then
drawRect := GetImageRectWithinArea( Width, Height, Dest.Width, Dest.Height );
IEDrawPolyline( Dest.IECanvas,
drawRect.Left, drawRect.Top, drawRect.Right - drawRect.Left, drawRect.Bottom - drawRect.Top,
CreateWidth / GetWidth, CreateHeight / GetHeight,
Self,
fPolyPoints, fPolyPointCount, fPolyPointsAllocated,
fPolylineClosed,
fDrawnPoints, fDrawnPointCount, fDrawnPointsAllocated,
fBorderColor, fBorderWidth,
fFillColor, fFillColor2, fFillGradient,
fAntiAlias and not FastDrawing,
Round( Rotate ), fAspectRatioLocked );
if EnableAlpha then
Dest.SynchronizeRGBA( True, True )
else
Dest.RemoveAlphaChannel()
end;
procedure TIEPolylineLayer.CopyToBitmap(var Dest: TIEBitmap; CreateWidth : Integer = -1; CreateHeight : Integer = -1; EnableAlpha: Boolean = True; UseDisplayAR: Boolean = True);
begin
CopyToBitmapEx( Dest, CreateWidth, CreateHeight, Owner_FastOutputActive(), EnableAlpha, UseDisplayAR );
end;
function TIEPolylineLayer.GetBitmap : TIEBitmap;
begin
CopyToBitmap( fGlobalCacheBitmap, iMax( 1, Round( fResizedWidth )), iMax( 1, Round( fResizedHeight )), Owner_EnableAlphaChannel, False );
Result := fGlobalCacheBitmap;
end;
{!!
<FS>TIEPolylineLayer.FillColor
<FM>Declaration<FC>
property FillColor: TColor;
<FM>Description<FN>
The color of the polygon. To create a polygon you must close the polyline using <A TIEPolylineLayer.PolylineClosed>.
To make the text box transparent set <FC>FillColor<FN> to clNone. Gradients are not supported.
Default: clWhite
<FM>Example<FC>
// Set fill color to yellow
ImageEnView1.CurrentLayer.FillColor := clYellow;
ImageEnView1.Update();
<IMG help_images\Shape_WithFill.jpg>
// Remove fill color
ImageEnView1.CurrentLayer.FillColor := clNone;
ImageEnView1.Update();
<IMG help_images\Shape_NoFill.jpg>
<FM>See Also<FN>
- <L TIELayer.FillColor>TIELayer.FillColor</L>
!!}
function TIEPolylineLayer.GetFillColor: TColor;
begin
Result := fFillColor;
end;
procedure TIEPolylineLayer.SetFillColor(value: TColor);
begin
fFillColor := Value;
LayerChange();
end;
{!!
<FS>TIEPolylineLayer.LineColor
<FM>Declaration<FC>
property LineColor: TColor;
<FM>Description<FN>
The color of the polyline.
Default: clBlack
<FM>Example<FC>
// Add a pink polyline
ImageEnView1.LayersAdd( ielkPolyline );
TIEPolylineLayer( ImageEnView1.CurrentLayer ).SetPoints( iesShootingArrowSW, True );
TIEPolylineLayer( ImageEnView1.CurrentLayer ).LineColor := $00C080FF;
TIEPolylineLayer( ImageEnView1.CurrentLayer ).LineWidth := 3;
ImageEnView1.Update();
<IMG help_images\Polyline_Arrow.gif>
<FM>See Also<FN>
- <L TIELayer.BorderColor>TIELayer.BorderColor</L>
- <A TIEPolylineLayer.LineWidth>
!!}
function TIEPolylineLayer.GetLineColor: TColor;
begin
Result := fBorderColor;
end;
procedure TIEPolylineLayer.SetLineColor(value: TColor);
begin
fBorderColor := value;
LayerChange();
end;
{!!
<FS>TIEPolylineLayer.LineWidth
<FM>Declaration<FC>
property LineWidth: Integer;
<FM>Description<FN>
The width of the polyline.
Default: 1
<FM>Example<FC>
// Add a pink polyline
ImageEnView1.LayersAdd( ielkPolyline );
TIEPolylineLayer( ImageEnView1.CurrentLayer ).SetPoints( iesShootingArrowSW, True );
TIEPolylineLayer( ImageEnView1.CurrentLayer ).LineColor := $00C080FF;
TIEPolylineLayer( ImageEnView1.CurrentLayer ).LineWidth := 3;
ImageEnView1.Update();
<IMG help_images\Polyline_Arrow.gif>
<FM>See Also<FN>
- <L TIELayer.BorderWidth>TIELayer.BorderWidth</L>
- <A TIEPolylineLayer.LineColor>
!!}
function TIEPolylineLayer.GetLineWidth: Integer;
begin
Result := fBorderWidth;
end;
procedure TIEPolylineLayer.SetLineWidth(value: Integer);
begin
fBorderWidth := value;
LayerChange();
end;
{!!
<FS>TIEPolylineLayer.PolylineClosed
<FM>Declaration<FC>
property PolylineClosed: boolean;
<FM>Description<FN>
Set PolylineClosed to True to connect the first and final points of the polyline. This will create a polygon.
If the polygon is closed it will be filled using <A TIEPolylineLayer.FillColor>.
Default: False
<FM>Example<FC>
// Draw a polyline
With TIEPolylineLayer( ImageEnView1.CurrentLayer ) do
begin
ClearAllPoints();
AddPoint( 500, 0 );
AddPoint( 1000, 1000 );
AddPoint( 0, 1000 );
end;
ImageEnView1.Update();
<IMG help_images\Polyline_Open.gif>
// Close the polyline, to create a polygon
TIEPolylineLayer( ImageEnView1.CurrentLayer ).PolylineClosed := True;
ImageEnView1.CurrentLayer.FillColor := clYellow;
ImageEnView1.Update();
<IMG help_images\Polyline_Closed.gif>
!!}
procedure TIEPolylineLayer.SetPolylineClosed(value: Boolean);
begin
fPolylineClosed := value;
LayerChange();
end;
procedure TIEPolylineLayer.LoadFromStream(Stream: TStream);
var
saveVer: Integer;
begin
saveVer := LoadMetaFromStream( Stream );
if saveVer < 6400 then
raise EIEException.create( 'Unknown data version' );
// Other props
// todo: @FAB: This code OK?
ClearAllPoints();
Stream.Read(fPolyPointCount, sizeof(integer));
fPolyPointsAllocated := fPolyPointCount;
getmem(fPolyPoints, sizeof(TPoint) * fPolyPointCount);
Stream.Read(pbyte(fPolyPoints)^, sizeof(TPoint) * fPolyPointCount);
Stream.Read(fPolylineClosed, sizeof(boolean));
fModified := False;
end;
procedure TIEPolylineLayer.SaveToStream(Stream: TStream; MetaOnly: Boolean = False; CompressionFormat: TIOFileType = -2);
var
l, sz: integer;
begin
l := Stream.Position;
SaveMetaToStream( Stream);
// other props
// todo: @FAB: This code OK?
Stream.Write(fPolyPointCount, sizeof(integer));
Stream.Write(pbyte(fPolyPoints)^, sizeof(TPoint) * fPolyPointCount);
Stream.Write(fPolylineClosed, sizeof(boolean));
// Update position
sz := Stream.Position - l;
Stream.Position := l;
Stream.Write(sz, sizeof(integer)); // Fill size
Stream.Position := l + sz; // Position at end of layer record
end;
function TIEPolylineLayer.GetAsSVG(): string;
var
pts: TIEArrayOfTPoint;
i: Integer;
RotateCenter: TPoint;
begin
SetLength( pts, fPolyPointCount );
for i := 0 to fPolyPointCount - 1 do
begin
pts[i].X := PPointArray(fPolyPoints)[ i ].x;
pts[i].Y := PPointArray(fPolyPoints)[ i ].y;
end;
RotateCenter := Point( PosX + Width div 2, PosY + Height div 2 );
IEScalePoints( pts, fPolyPointCount, PosX + fBorderWidth div 2, PosY + fBorderWidth div 2, PosX + Width - fBorderWidth, PosY + Height - fBorderWidth, AspectRatioLocked );
Result := CreateSVGPolylineTag( pts, fPolyPointCount, fPolylineClosed, BorderWidth, BorderColor, FillColor, Rotate, RotateCenter, fTransparency );
end;
{!!
<FS>TIEPolylineLayer.Points
<FM>Declaration<FC>
property Points[index: integer]: TPoint;
<FM>Description<FN>
Returns the points of the polyline.
Each point of the polyline is represented by an x and y value in the range 0 to 1000. Where (0, 0) is the top-left pixel of the layer and (1000, 1000) is the bottom-right.
Use <A TIEPolylineLayer.PointCount> to determine the number of points in the Polyline.
<FM>See Also<FN>
- <A TIEPolylineLayer.SetPoints>
- <A TIEPolylineLayer.AddPoint>
- <A TIEPolylineLayer.RemovePoint>
!!}
function TIEPolylineLayer.GetPoints(index: integer): TPoint;
begin
Result := Point(-1, -1);
if index < fPolyPointCount then
begin
result.x := PPointArray(fPolyPoints)[index].x;
result.y := PPointArray(fPolyPoints)[index].y;
end;
end;
{!!
<FS>TIEPolylineLayer.PointCount
<FM>Declaration<FC>
property PointCount: integer;
<FM>Description<FN>
Returns the count of points of the polyline.
Use <A TIEPolylineLayer.Points> to obtain the coordinates of point that compose the Polyline.
!!}
function TIEPolylineLayer.GetPointCount(): integer;
begin
result := fPolyPointCount;
end;
{!!
<FS>TIEPolylineLayer.SetPoints
<FM>Declaration<FC>
procedure SetPoints(Points: array of TPoint); overload;
procedure SetPoints(Points: array of TPoint; ClosePolyline: Boolean); overload;
procedure SetPoints(Shape: <A TIEShape>; ClosePolyline: Boolean = True); overload;
<FM>Description<FN>
Set the points of the polyline.
Each point of the polyline is represented by an x and y value in the range 0 to 1000. Where (0, 0) is the top-left pixel of the layer and (1000, 1000) is the bottom-right.
If you use the Shape overload, the point array will be filled with a <A TIEShape>. Not all shapes are supported. Shapes that are not included in <A Supported_Generate_Points_Shapes> will raise an exception.
<A TIEPolylineLayer.PolylineClosed> will be set to <FC>ClosePolyline<FN>.
<FM>Example<FC>
// Draw a triangle polygon
With TIEPolylineLayer( ImageEnView1.CurrentLayer ) do
begin
ClearAllPoints();
AddPoint( 500, 0 );
AddPoint( 1000, 1000 );
AddPoint( 0, 1000 );
PolylineClosed := True;
end;
ImageEnView1.Update();
// Which is the same as...
TIEPolylineLayer( ImageEnView1.CurrentLayer ).SetPoints( [ Point(500, 0), Point(1000, 1000), Point(0, 1000) ], True );
ImageEnView1.Update();
// Which is the same as...
TIEPolylineLayer( ImageEnView1.CurrentLayer ).SetPoints( iesTriangle, True );
ImageEnView1.Update();
<IMG help_images\Polyline_Closed.gif>
// If PolylineClosed is not enabled, we get a polyline, instead of a polygon
TIEPolylineLayer( ImageEnView1.CurrentLayer ).PolylineClosed := False;
ImageEnView1.Update();
<IMG help_images\Polyline_Open.gif>
// Fill points with Star shape
TIEPolylineLayer( ImageEnView1.CurrentLayer ).SetPoints( iesStar5, True );
<IMG help_images\Polyline_Star.gif>
// Fill points with Explosion shape
TIEPolylineLayer( ImageEnView1.CurrentLayer ).SetPoints( iesExplosion, True );
<IMG help_images\Polyline_WithBorder.gif>
// Fill points with Arrow shape
TIEPolylineLayer( ImageEnView1.CurrentLayer ).SetPoints( iesShootingArrowSW, True );
<IMG help_images\Polyline_Arrow.gif>
// Fill points with Lightning shape
TIEPolylineLayer( ImageEnView1.CurrentLayer ).SetPoints( iesLightningLeft, True );
<IMG help_images\Shape_Lightning.gif>
<FM>See Also<FN>
- <A TIEPolylineLayer.Points>
- <A TIEPolylineLayer.AddPoint>
- <A TIEPolylineLayer.RemovePoint>
!!}
procedure TIEPolylineLayer.SetPoints(Points: array of TPoint; ClosePolyline: Boolean);
begin
SetPoints( Points );
fPolylineClosed := ClosePolyline;
end;
procedure TIEPolylineLayer.SetPoints(Points: array of TPoint);
var
i: integer;
begin
ClearAllPoints();
for i := 0 to High(Points) do
AddPoint(Points[i].x, Points[i].y);
end;
procedure TIEPolylineLayer.SetPoints(Shape: TIEShape; ClosePolyline: Boolean = True);
var
arPts : Array[ 0 .. Shape_Array_Max_Points ] of TPoint;
pts: Integer;
i: integer;
begin
IEGenerateShapePoints( arPts, pts, Shape, 0, 0, 1000, 1000 );
ClearAllPoints();
for i := 0 to pts - 1 do
AddPoint( arPts[i].x, arPts[i].y );
fPolylineClosed := ClosePolyline;
fOriginalAspectRatio := IEShapePreferredAspectRatio( Shape );
end;
{!!
<FS>TIEPolylineLayer.AddPoint
<FM>Declaration<FC>
procedure AddPoint(X, Y: integer);
<FM>Description<FN>
Add a point to the end of a polyline.
Each point of the polyline is represented by an x and y value in the range 0 to 1000. Where (0, 0) is the top-left pixel of the layer and (1000, 1000) is the bottom-right.
<FM>Example<FC>
// Draw a polyline
With TIEPolylineLayer( ImageEnView1.CurrentLayer ) do
begin
ClearAllPoints();
AddPoint( 500, 0 );
AddPoint( 1000, 1000 );
AddPoint( 0, 1000 );
end;
ImageEnView1.Update();
<IMG help_images\Polyline_Open.gif>
// Draw a triangle polygon
With TIEPolylineLayer( ImageEnView1.CurrentLayer ) do
begin
ClearAllPoints();
AddPoint( 500, 0 );
AddPoint( 1000, 1000 );
AddPoint( 0, 1000 );
PolylineClosed := True;
end;
ImageEnView1.Update();
<IMG help_images\Polyline_Closed.gif>
<FM>See Also<FN>
- <A TIEPolylineLayer.RemovePoint>
- <A TIEPolylineLayer.SetPoints>
- <A TIEPolylineLayer.Points>
!!}
// changes Points, PolylineCount, x1,y1,x2,y2, fPolyBaseWidth, fPolyBaseHeight
// x,y must be in bitmap coordinates
procedure TIEPolylineLayer.AddPoint(X, Y: integer);
var
nn: PPointArray;
begin
if X < 0 then
X := 0;
if X > 1000 then
X := 1000;
if Y < 0 then
Y := 0;
if Y > 1000 then
Y := 1000;
if ( fPolyPointCount = 0 ) or ( X <> PPointarray(fPolyPoints)[fPolyPointCount - 1].X ) or ( Y <> PPointarray(fPolyPoints)[fPolyPointCount - 1].Y ) then
begin
inc(fPolyPointCount);
if fPolyPointCount > fPolyPointsAllocated then
begin
fPolyPointsAllocated := fPolyPointCount * 2;
getmem(nn, fPolyPointsAllocated * sizeof(TPoint));
move(PPointArray(fPolyPoints)[0], nn[0], (fPolyPointCount - 1) * sizeof(TPoint));
freemem(fPolyPoints);
fPolyPoints := nn;
end;
PPointArray(fPolyPoints)[fPolyPointCount - 1].x := X;
PPointArray(fPolyPoints)[fPolyPointCount - 1].y := Y;
end;
LayerChange();
end;
{!!
<FS>TIEPolylineLayer.ClearAllPoints
<FM>Declaration<FC>
procedure ClearAllPoints();
<FM>Description<FN>
Removes all points from the polyline.
<FM>Example<FC>
// Draw a triangle polygon
With TIEPolylineLayer( ImageEnView1.CurrentLayer ) do
begin
ClearAllPoints();
AddPoint( 500, 0 );
AddPoint( 1000, 1000 );
AddPoint( 0, 1000 );
PolylineClosed := True;
end;
ImageEnView1.Update();
<FM>See Also<FN>
- <A TIEPolylineLayer.RemovePoint>
- <A TIEPolylineLayer.AddPoint>
- <A TIEPolylineLayer.SetPoints>
- <A TIEPolylineLayer.Points>
!!}
procedure TIEPolylineLayer.ClearAllPoints();
begin
if fPolyPoints <> nil then
freemem( fPolyPoints );
fPolyPoints := nil;
fPolyPointsAllocated := 0;
fPolyPointCount := 0;
LayerChange();
end;
{!!
<FS>TIEPolylineLayer.RemovePoint
<FM>Declaration<FC>
procedure RemovePoint(Index: integer);
<FM>Description<FN>
Removes point of <FC>Index<FN> from a Polyline.
<FM>Example<FC>
// Remove the last point from the selected Polyline
TIEPolylineLayer( ImageEnView1.CurrentLayer ).RemovePoint( TIEPolylineLayer( ImageEnView1.CurrentLayer ).PointCount - 1 );
ImageEnView1.Update();
<FM>See Also<FN>
- <A TIEPolylineLayer.AddPoint>
- <A TIEPolylineLayer.SetPoints>
- <A TIEPolylineLayer.Points>
!!}
procedure TIEPolylineLayer.RemovePoint(Index: integer);
var
i, idx: integer;
pts: array of TPoint;
begin
if ( Index < 0 ) or ( Index > fPolyPointCount - 1 ) then
exit;
SetLength( pts, fPolyPointCount - 1 );
idx := 0;
for i := 0 to fPolyPointCount - 1 do
if I <> Index then
begin
pts[ idx ].x := PPointArray(fPolyPoints)[ I ].x;
pts[ idx ].y := PPointArray(fPolyPoints)[ I ].y;
inc( idx );
end;
SetPoints( pts );
end;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Polyline simplify
type
Vector = record
x, y: double;
end;
type
Segment = record
P0, P1: Vector;
end;
// difference
function diff(u, v: Vector): Vector;
begin
result.x := u.x - v.x;
result.y := u.y - v.y;
end;
// dot product
function dot(u, v: Vector): double;
begin
result := u.x * v.x + u.y * v.y;
end;
// squared length of vector
function norm2(v: Vector): double;
begin
result := dot(v, v);
end;
// length of vector
function norm(v: Vector): double;
begin
result := sqrt(norm2(v));
end;
// distance squared
function d2(u, v: Vector): double;
begin
result := norm2(diff(u, v));
end;
// distance
function d(u, v: Vector): double;
begin
result := norm(diff(u, v));
end;
// sum
function sum(u, v: Vector): Vector;
begin
result.x := u.x + v.x;
result.y := u.y + v.y;
end;
// vector*scalar
function mulvs(u: Vector; s: double): Vector;
begin
result.x := u.x * s;
result.y := u.y * s;
end;
// TPoint to Vector
function tpv(p: TPoint): Vector;
begin
result.x := p.x;
result.y := p.y;
end;
// This is the Douglas-Peucker recursive simplification routine
procedure simplifyDP(tol: double; v: TIEArrayOfTPoint; j, k: integer; mk: TIEArrayOfInteger);
var
maxi, i: integer;
maxd2: double;
tol2: double;
S: Segment;
u: Vector;
cu: double;
w: Vector;
Pb: Vector;
b, cw, dv2: double;
begin
if (k <= j + 1) then
exit;
maxi := j;
maxd2 := 0;
tol2 := tol * tol;
S.P0 := tpv(v[j]);
S.P1 := tpv(v[k]);
u := diff(S.P1, S.P0);
cu := dot(u, u);
for i := j + 1 to k - 1 do
begin
w := diff(tpv(v[i]), S.P0);
cw := dot(w, u);
if (cw <= 0) then
dv2 := d2(tpv(v[i]), S.P0)
else
if (cu <= cw) then
dv2 := d2(tpv(v[i]), S.P1)
else
begin
b := cw / cu;
Pb := sum(S.P0, mulvs(u, b));
dv2 := d2(tpv(v[i]), Pb);
end;
if (dv2 <= maxd2) then
continue;
maxi := i;
maxd2 := dv2;
end;
if (maxd2 > tol2) then
begin
mk[maxi] := 1;
simplifyDP(tol, v, j, maxi, mk);
simplifyDP(tol, v, maxi, k, mk);
end;
end;
// tol = tolerance
// V : input array
function IESimplifyPolygon(tol: double; V: array of TPoint): TIEArrayOfTPoint;
var
i, k, m, pv: integer;
tol2: double;
vt: TIEArrayOfTPoint;
mk: TIEArrayOfInteger;
n: integer;
begin
n := length(V);
SetLength(result, n);
SetLength(vt, n);
SetLength(mk, n);
FillChar(mk[0], n * sizeof(integer), 0);
tol2 := tol * tol;
// Vertex Reduction within tolerance of prior vertex cluster
vt[0] := V[0];
k := 1;
pv := 0;
for i := 1 to n - 1 do
begin
if d2(tpv(V[i]), tpv(V[pv])) < tol2 then
continue;
vt[k] := V[i];
inc(k);
pv := i;
end;
if (pv < n - 1) then
begin
vt[k] := V[n - 1];
inc(k);
end;
// Douglas-Peucker Polyline simplification
mk[k - 1] := 1;
mk[0] := mk[k - 1];
simplifyDP(tol, vt, 0, k - 1, mk);
//
m := 0;
for i := 0 to k - 1 do
if (mk[i] <> 0) then
begin
result[m] := vt[i];
inc(m);
end;
SetLength(result, m); // resize output array
end;
// End of Polyline simplify
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
{!!
<FS>TIEPolylineLayer.SimplifyPolygon
<FM>Declaration<FC>
procedure SimplifyPolygon(MaxPoints: integer);
<FM>Description<FN>
Replaces a high resolution polyline with a lower resolution polyline with fewer vertices (MaxPoints).
<FM>Example<FC>
TIEPolylineLayer( ImageEnView1.CurrentLayer ).SimplifyPolygon(30); // simplify the polygon to max 30 points
ImageEnView1.Update();
!!}
procedure TIEPolylineLayer.SimplifyPolygon(MaxPoints: integer);
var
i: integer;
ia, oa: TIEArrayOfTPoint;
tolerance: double;
begin
tolerance := 0.1;
repeat
SetLength(ia, fPolyPointCount);
for i := 0 to fPolyPointCount - 1 do
begin
ia[i].x := PPointArray(fPolyPoints)[i].x;
ia[i].y := PPointArray(fPolyPoints)[i].y;
end;
oa := IESimplifyPolygon(tolerance, ia);
SetPoints(oa);
tolerance := tolerance + 0.1;
until length(oa) <= MaxPoints;
end;
// *************************************************************************************** //
// ** ** //
// ** TIETextLayer ** //
// ** ** //
// *************************************************************************************** //
constructor TIETextLayer.Create(Owner: TObject);
begin
inherited Create(Owner);
fKind := ielkText;
fFont := TFont.Create;
SetDefaults;
fResizedWidth := 100;
fResizedHeight := 100;
end;
destructor TIETextLayer.Destroy;
begin
FreeAndNil( fFont );
inherited;
end;
// Bitmap is created if nil
// must be freed
procedure TIETextLayer.CopyToBitmapEx(var Dest: TIEBitmap;
CreateWidth : Integer; CreateHeight : Integer;
FastDrawing: Boolean;
EnableAlpha: Boolean; UseDisplayAR: Boolean;
UpdateSize: Boolean = False; EnlargeOnly: Boolean = False;
Zoom: Double = 1);
var
drawRect: TRect;
textSize: TSize;
begin
if CreateWidth < 1 then
CreateWidth := OriginalWidth;
if CreateHeight < 1 then
CreateHeight := OriginalHeight;
if EnableAlpha then
begin
InitBitmapRGBA( Dest, CreateWidth, CreateHeight ); // Use ie32RGB for RGBA support
Dest.IECanvas.SetCompositingMode(ieCompositingModeSourceOver, ieCompositingQualityDefault);
end
else
InitBitmap( Dest, CreateWidth, CreateHeight );
drawRect := Rect( 0, 0, Dest.Width, Dest.Height );
if UseDisplayAR then
drawRect := GetImageRectWithinArea( Width, Height, Dest.Width, Dest.Height );
textSize := IEDrawText( Dest.IECanvas,
drawRect.Left, drawRect.Top, drawRect.Right, drawRect.Bottom,
min( CreateWidth / GetWidth, CreateHeight / GetHeight ),
WideString( fText ),
fFont,
fAlignment,
fLayout,
Round( Rotate ),
fBorderColor, fBorderWidth,
fFillColor, fFillColor2, fFillGradient,
fAutosize,
fAntiAlias, // Use anti-alias for text regardless of FastDrawing
fBorderShape,
UpdateSize );
if UpdateSize then
begin
if EnlargeOnly then
begin
Width := max( Width, textSize.cX );
Height := max( Height, textSize.cY );
end
else
begin
Width := textSize.cX;
Height := textSize.cY;
end;
end
else
begin
if EnableAlpha then
Dest.SynchronizeRGBA( True, True )
else
Dest.RemoveAlphaChannel()
end;
end;
procedure TIETextLayer.CopyToBitmap(var Dest: TIEBitmap; CreateWidth : Integer = -1; CreateHeight : Integer = -1; EnableAlpha: Boolean = True; UseDisplayAR: Boolean = True);
var
wasPixelFormat: TIEPixelFormat;
begin
wasPixelFormat := ie24RGB;
if assigned( Dest ) and ( Dest.PixelFormat <> ieNull ) then
wasPixelFormat := Dest.PixelFormat;
CopyToBitmapEx(Dest, CreateWidth, CreateHeight, Owner_FastOutputActive(), EnableAlpha, UseDisplayAR, False );
Dest.PixelFormat := wasPixelFormat;
end;
function TIETextLayer.GetBitmap : TIEBitmap;
begin
CopyToBitmap( fGlobalCacheBitmap, iMax( 1, Round( fResizedWidth )), iMax( 1, Round( fResizedHeight )), Owner_EnableAlphaChannel, False );
Result := fGlobalCacheBitmap;
end;
{!!
<FS>TIETextLayer.BorderColor
<FM>Declaration<FC>
property BorderColor: TColor;
<FM>Description<FN>
The color of the frame around the text box.
To hide the text box frame set <FC>BorderColor<FN> to clNone or <A TIETextLayer.BorderWidth> to 0.
Default: clNone
<FM>Example<FC>
// Add a text layer with a black border and a white fill
ImageEnView1.LayersAdd( ielkText );
TIETextLayer( ImageEnView1.CurrentLayer ).Text := 'Text in Yellow box';
TIETextLayer( ImageEnView1.CurrentLayer ).BorderColor := clBlack;
TIETextLayer( ImageEnView1.CurrentLayer ).BorderWidth := 1;
TIETextLayer( ImageEnView1.CurrentLayer ).FillColor := clWhite;
ImageEnView1.Update();
<IMG help_images\TextLayer.gif>
<FM>See Also<FN>
- <L TIELayer.BorderColor>TIELayer.BorderColor</L>
- <A TIETextLayer.BorderWidth>
- <A TIETextLayer.BorderShape>
!!}
function TIETextLayer.GetBorderColor: TColor;
begin
Result := fBorderColor;
end;
procedure TIETextLayer.SetBorderColor(value: TColor);
begin
fBorderColor := Value;
LayerChange();
end;
{!!
<FS>TIETextLayer.BorderWidth
<FM>Declaration<FC>
property BorderWidth: Integer;
<FM>Description<FN>
The width of the frame around the text box.
To hide the text box frame set <FC>BorderWidth<FN> to 0 or <A TIETextLayer.BorderColor> to clNone.
Default: 1
<FM>Example<FC>
// Add a text layer with a black border and a white fill
ImageEnView1.LayersAdd( ielkText );
TIETextLayer( ImageEnView1.CurrentLayer ).Text := 'Text in Yellow box';
TIETextLayer( ImageEnView1.CurrentLayer ).BorderColor := clBlack;
TIETextLayer( ImageEnView1.CurrentLayer ).BorderWidth := 1;
TIETextLayer( ImageEnView1.CurrentLayer ).FillColor := clWhite;
ImageEnView1.Update();
<IMG help_images\TextLayer.gif>
<FM>See Also<FN>
- <L TIELayer.BorderWidth>TIELayer.BorderWidth</L>
- <A TIETextLayer.BorderColor>
- <A TIETextLayer.BorderShape>
!!}
function TIETextLayer.GetBorderWidth: Integer;
begin
Result := fBorderWidth;
end;
procedure TIETextLayer.SetBorderWidth(value: Integer);
begin
fBorderWidth := Value;
LayerChange();
end;
{!!
<FS>TIETextLayer.FillColor
<FM>Declaration<FC>
property FillColor: TColor;
<FM>Description<FN>
The color of the text box.
To make the text box transparent set <FC>FillColor<FN> to clNone. If <FC>FillColor<FN> is different from <A TIETextLayer.FillColor2> it will be drawn as a gradient.
Default: clNone
<FM>Example<FC>
// Add a text layer with a black border and a white fill
ImageEnView1.LayersAdd( ielkText );
TIETextLayer( ImageEnView1.CurrentLayer ).Text := 'Text in Yellow box';
TIETextLayer( ImageEnView1.CurrentLayer ).BorderColor := clBlack;
TIETextLayer( ImageEnView1.CurrentLayer ).BorderWidth := 1;
TIETextLayer( ImageEnView1.CurrentLayer ).FillColor := clWhite;
ImageEnView1.Update();
<IMG help_images\TextLayer.gif>
<FM>See Also<FN>
- <L TIELayer.FillColor>TIELayer.FillColor</L>
- <A TIETextLayer.FillColor2>
- <A TIETextLayer.FillGradient>
!!}
function TIETextLayer.GetFillColor: TColor;
begin
Result := fFillColor;
end;
procedure TIETextLayer.SetFillColor(value: TColor);
begin
fFillColor := Value;
LayerChange();
end;
{!!
<FS>TIETextLayer.FillColor2
<FM>Declaration<FC>
property FillColor2: TColor;
<FM>Description<FN>
The end color for the text box gradient.
If <FC>FillColor2<FN> is clNone, the text box is filled by a solid color specified by <A TIETextLayer.FillColor>. If <FC>FillColor2<FN> is different from <A TIETextLayer.FillColor> it is drawn as a gradient.
The direction of the gradient is specified by <A TIETextLayer.FillGradient>.
Note: Gradients are not supported if <A TIETextLayer.BorderShape> is <FC>iesEllipse<FN>
Default: clNone
<FM>Example<FC>
// Disable the gradient fill
TIETextLayer( ImageEnView1.CurrentLayer ).FillColor2 := clNone;
// Add a red/blue horizontal gradient
TIETextLayer( ImageEnView1.CurrentLayer ).FillColor := clRed;
TIETextLayer( ImageEnView1.CurrentLayer ).FillColor2 := clBlue;
TIETextLayer( ImageEnView1.CurrentLayer ).FillGradient := gdHorizontal;
ImageEnView1.Update();
<FM>See Also<FN>
- <L TIELayer.FillColor2>TIELayer.FillColor2</L>
- <A TIETextLayer.FillColor>
- <A TIETextLayer.FillGradient>
!!}
function TIETextLayer.GetFillColor2: TColor;
begin
Result := fFillColor2;
end;
procedure TIETextLayer.SetFillColor2(value: TColor);
begin
fFillColor2 := Value;
LayerChange();
end;
{!!
<FS>TIETextLayer.FillGradient
<FM>Declaration<FC>
property FillGradient: <A TIEGradientDir>;
<FM>Description<FN>
The direction of the gradient used for the text box fill.
If <A TIETextLayer.FillColor> is different from <A TIETextLayer.FillColor2> the text box is filled with a gradient. <FC>FillGradient<FN> specifies the direction.
Note: Gradients are not supported if <A TIETextLayer.BorderShape> is <FC>iesEllipse<FN>
Default: gdVertical
<FM>Example<FC>
// Add a red/blue horizontal gradient
TIETextLayer( ImageEnView1.CurrentLayer ).FillColor := clRed;
TIETextLayer( ImageEnView1.CurrentLayer ).FillColor2 := clBlue;
TIETextLayer( ImageEnView1.CurrentLayer ).FillGradient := gdHorizontal;
ImageEnView1.Update();
<FM>See Also<FN>
- <L TIELayer.FillGradient>TIELayer.FillGradient</L>
- <A TIETextLayer.FillColor>
- <A TIETextLayer.FillColor2>
!!}
function TIETextLayer.GetFillGradient: TIEGradientDir;
begin
Result := fFillGradient;
end;
procedure TIETextLayer.SetFillGradient(value: TIEGradientDir);
begin
fFillGradient := Value;
LayerChange();
end;
{!!
<FS>TIETextLayer.Alignment
<FM>Declaration<FC>
property Alignment: <A TIEAlignment>;
<FM>Description<FN>
Specifies the text alignment.
Notes:
- <FC>iejJustify<FN> is unsupported for TIETextLayers
- <FC>iejCenter<FN> is always used if <A TIETextLayer.BorderShape> is <FC>iesEllipse<FN>
Default: iejLeft
<FM>Example<FC>
// Center the text for the current text layer
TIETextLayer( ImageEnView1.CurrentLayer ).Alignment := iejCenter;
ImageEnView1.Update();
<IMG help_images\text_Selected.gif>
<FM>See Also<FN>
- <A TIETextLayer.Layout>
!!}
procedure TIETextLayer.SetAlignment(value: TIEAlignment);
begin
fAlignment := Value;
LayerChange();
end;
{!!
<FS>TIETextLayer.Layout
<FM>Declaration<FC>
property Layout: <A TIELayout>;
<FM>Description<FN>
Specifies the vertical alignment of text.
Note: <FC>ielCenter<FN> is always used if <A TIETextLayer.BorderShape> is <FC>iesEllipse<FN>
Default: ielTop
<FM>Example<FC>
// Center the text for the current text layer
TIETextLayer( ImageEnView1.CurrentLayer ).Alignment := iejCenter;
ImageEnView1.Update();
<IMG help_images\text_Selected.gif>
<FM>See Also<FN>
- <A TIETextLayer.Alignment>
!!}
procedure TIETextLayer.SetLayout(value: TIELayout);
begin
fLayout := Value;
LayerChange();
end;
procedure TIETextLayer.LoadFromStream(Stream: TStream);
var
saveVer: Integer;
begin
saveVer := LoadMetaFromStream( Stream );
if saveVer < 6400 then
raise EIEException.create( 'Unknown data version' );
// Other props
IELoadStringFromStreamW(Stream, fText);
Stream.Read( fBorderShape, SizeOf( TIEShape ));
IELoadFontFromStream(Stream, fFont );
Stream.Read( fAutoSize , SizeOf( Boolean ));
Stream.Read( fReadOnly , SizeOf( Boolean ));
Stream.Read( fAlignment , SizeOf( TIEAlignment ));
Stream.Read( fLayout , SizeOf( TIELayout ));
fModified := False;
end;
procedure TIETextLayer.SaveToStream(Stream: TStream; MetaOnly: Boolean = False; CompressionFormat: TIOFileType = -2);
var
l, sz: integer;
begin
l := Stream.Position;
SaveMetaToStream( Stream);
// other props
IESaveStringToStreamW(Stream, fText);
Stream.Write( fBorderShape, SizeOf( TIEShape ));
IESaveFontToStream(Stream, fFont );
Stream.Write( fAutoSize , SizeOf( Boolean ));
Stream.Write( fReadOnly , SizeOf( Boolean ));
Stream.Write( fAlignment , SizeOf( TIEAlignment ));
Stream.Write( fLayout , SizeOf( TIELayout ));
// Update position
sz := Stream.Position - l;
Stream.Position := l;
Stream.Write(sz, sizeof(integer)); // Fill size
Stream.Position := l + sz; // Position at end of layer record
end;
function TIETextLayer.GetAsSVG(): string;
begin
Result := CreateSVGTextTag( Text, Font, PosX, PosY, Width, Height, fAlignment, fLayout, Rotate,
fBorderWidth, fBorderColor, fFillColor, fBorderShape, fTransparency );
end;
{!!
<FS>TIETextLayer.Font
<FM>Declaration<FC>
property Font: TFont;
<FM>Description<FN>
Specifies the font of the text.
<FM>Example<FC>
// Sets 'Arial' as font type for the current text layer
TIETextLayer( ImageEnView1.CurrentLayer ).Font.Name := 'Arial';
ImageEnView1.Update();
<IMG help_images\TextLayer.gif>
!!}
procedure TIETextLayer.SetFont(const Value: TFont);
begin
fFont := Value;
LayerChange();
if fAutoSize then
SizeToText();
end;
{!!
<FS>TIETextLayer.Text
<FM>Declaration<FC>
property Text: String;
<FM>Description<FN>
Specifies the displayed text.
Note: The default text for new layers is specified by <A TIEImageEnGlobalSettings.DefaultLayerText>
<FM>Example<FC>
// Append a text layer
ImageEnView1.LayersAdd( ielkText );
TIETextLayer( ImageEnView1.CurrentLayer ).Text := 'This is a Text Layer';
TIETextLayer( ImageEnView1.CurrentLayer ).BorderColor := clBlack;
TIETextLayer( ImageEnView1.CurrentLayer ).BorderWidth := 1;
TIETextLayer( ImageEnView1.CurrentLayer ).FillColor := clWhite;
ImageEnView1.Update();
<IMG help_images\TextLayer.gif>
!!}
procedure TIETextLayer.SetText(const Value: string);
begin
fText := Value;
LayerChange();
if fAutoSize then
SizeToText();
end;
{!!
<FS>TIETextLayer.AutoSize
<FM>Declaration<FC>
property AutoSize: boolean;
<FM>Description<FN>
Use <FC>AutoSize<FN> to make the layer automatically adjust the size to accommodate the width of the text.
When <FC>AutoSize<FN> is <FC>false<FN>, the text object has a fixed width.
When <FC>AutoSize<FN> is <FC>true<FN>, the size of the object is re-adjusted whenever the user edits the text.
Default: False
<FM>See Also<FN>
- <A TIETextLayer.SizeToText>
!!}
procedure TIETextLayer.SetAutoSize(const Value: boolean);
begin
fAutoSize := Value;
LayerChange( False );
if fAutoSize then
SizeToText();
end;
{!!
<FS>TIETextLayer.ReadOnly
<FM>Declaration<FC>
property ReadOnly: Boolean;
<FM>Description<FN>
Prevents the user from editing the text of the layer.
When <FC>ReadOnly<FN> is false, the user can double-click a text layer or click F2 to start editing of the layer text. <FC>ReadOnly<FN> prevents the user from editing the text.
Default: False
<FM>Example<FC>
// Prevent editing of the current layer text
TIETextLayer( ImageEnView1.CurrentLayer ).ReadOnly := False;
!!}
procedure TIETextLayer.SetReadOnly(const Value: boolean);
begin
fReadOnly := Value;
LayerChange( False );
end;
{!!
<FS>TIETextLayer.BorderShape
<FM>Declaration<FC>
property BorderShape: <A TIEShape>;
<FM>Description<FN>
The shape around the text.
Note: Only the following shapes are supported: iesRectangle, iesRoundRect, iesEllipse
Default: iesRectangle
<FM>Example<FC>
// Add an elliptical text layer
ImageEnView1.LayersAdd( ielkText );
TIETextLayer( ImageEnView1.CurrentLayer ).Text := 'Text in Ellipse';
TIETextLayer( ImageEnView1.CurrentLayer ).BorderShape := iesEllipse;
ImageEnView1.Update();
<FM>See Also<FN>
- <A TIETextLayer.BorderWidth>
- <A TIETextLayer.BorderColor>
!!}
procedure TIETextLayer.SetBorderShape(const Value: TIEShape);
begin
fBorderShape := Value;
LayerChange();
if fAutoSize then
SizeToText();
end;
{!!
<FS>TIETextLayer.SizeToText
<FM>Declaration<FC>
procedure TIETextLayer.SizeToText(EnlargeOnly: Boolean = False);
<FM>Description<FN>
Updates the size of the layer to fit the displayed text.
If <FC>EnlargeOnly<FN> is true, the layer will not be reduced in size to fit the text more tightly, only enlarged to ensure all text is visible.
<FM>Example<FN>
// Apply a "Paid" stamp to image
with ImageEnView1 do
begin
LayersAdd( 'PAID', 'Arial Black', 42, clRed, [fsBold] );
CurrentLayer.Rotate := 30;
TIETextLayer( CurrentLayer ).SizeToText();
CurrentLayer.PosX := IELayer_Pos_HCenter;
CurrentLayer.PosY := IELayer_Pos_VCenter;
LayersMergeAll();
end;
<FM>See Also<FN>
- <A TIETextLayer.AutoSize>
!!}
procedure TIETextLayer.SizeToText(EnlargeOnly: Boolean = False);
begin
CopyToBitmapEx( fGlobalCacheBitmap, iMax( 1, Round( fResizedWidth )), iMax( 1, Round( fResizedHeight )), True, False, False, True, EnlargeOnly );
end;
{!!
<FS>TIETextLayer.ActivateEditor
<FM>Declaration<FC>
procedure ActivateEditor();
<FM>Description<FN>
Activates editing of the layer text by the user (i.e. user can begin typing to change the text)
<FM>Example<FC>
// Display the text editor for the current layer
if Layer is TIELineLayer
TIELineLayer( ImageEnView1.CurrentLayer ).ActivateEditor()
else
if Layer is TIETextLayer
TIETextLayer( ImageEnView1.CurrentLayer ).ActivateEditor();
<FM>See Also<FN>
- <A TImageEnView.LayersCancelEditor>
!!}
procedure TIETextLayer.ActivateEditor();
begin
if assigned( fOwner ) then
TImageEnView( fOwner ).LayersActivateTextEditor( GetIndex );
end;
initialization
fGlobalCacheBitmap := nil;
finalization
end.