10595 lines
336 KiB
Plaintext
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.
|
|
|
|
|