Skip to content

Commit

Permalink
#111 aliasing for shapes
Browse files Browse the repository at this point in the history
  • Loading branch information
circular17 committed Jun 2, 2024
1 parent 9d6e02d commit cff3eb6
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 51 deletions.
1 change: 0 additions & 1 deletion lazpaint/tools/utooltext.pas
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,6 @@ procedure TToolText.AssignShapeStyle(AMatrix: TAffineMatrix; AAlwaysFit: boolean
FontEmHeight:= zoom*Manager.TextFontSize*Manager.Image.DPI/72;
FontName:= Manager.TextFontName;
FontStyle:= Manager.TextFontStyle;
Aliased := Manager.ShapeOptionAliasing;
LightPosition := AMatrix*Manager.LightPosition;
AltitudePercent:= Manager.PhongShapeAltitude;
if FontBidiMode <> Manager.TextBidiMode then
Expand Down
16 changes: 12 additions & 4 deletions lazpaint/tools/utoolvectorial.pas
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,8 @@ function ContextualToolbarsFromShape(AShapeClass: TVectorShapeAny; AShape: TVect
result := result + [ctText,ctAliasing];
if TTextShape(AShape).PenPhong then include(result, ctAltitude);
end;
if vsfAliased in f then
result += [ctAliasing];
end;

procedure AlignShape(AShape: TVectorShape; ACommand: TToolCommand; const AMatrix: TAffineMatrix; const ARect: TRect);
Expand Down Expand Up @@ -440,6 +442,12 @@ procedure TEditShapeTool.UpdateToolManagerFromShape(AShape: TVectorShape);
AShape.Usermode := vsuEdit;
opt := Manager.ShapeOptions;
f := AShape.MultiFields;
if vsfAliased in f then
begin
if AShape.Aliased then
include(opt,toAliasing)
else exclude(opt,toAliasing);
end;
doDraw := vsfPenFill in f;
doFill := vsfBackFill in f;
if vsfPenStyle in f then
Expand Down Expand Up @@ -510,9 +518,6 @@ procedure TEditShapeTool.UpdateToolManagerFromShape(AShape: TVectorShape);
Manager.TextVerticalAlign:= VerticalAlignment;
Manager.SetTextFont(FontName, FontEmHeight*zoom*72/Manager.Image.DPI, FontStyle);
Manager.TextShadow:= false;
if Aliased then
include(opt,toAliasing)
else exclude(opt,toAliasing);
end;
Manager.ShapeOptions := opt;

Expand Down Expand Up @@ -667,6 +672,8 @@ function TEditShapeTool.DoToolUpdate(toolDest: TBGRABitmap): TRect;
m := AffineMatrixInverse(Manager.Image.LayerOriginalMatrix[Manager.Image.CurrentLayerIndex]);
zoom := (VectLen(m[1,1],m[2,1])+VectLen(m[1,2],m[2,2]))/2;
f := shape.MultiFields;
if vsfAliased in f then
shape.Aliased := Manager.ShapeOptionAliasing;
if f*[vsfPenFill,vsfBackFill,vsfPenStyle] = [vsfPenFill,vsfBackFill,vsfPenStyle] then
begin
doDraw := toDrawShape in Manager.ShapeOptions;
Expand Down Expand Up @@ -725,7 +732,6 @@ function TEditShapeTool.DoToolUpdate(toolDest: TBGRABitmap): TRect;
FontName:= Manager.TextFontName;
FontEmHeight:= Manager.TextFontSize*zoom*Manager.Image.DPI/72;
FontStyle := Manager.TextFontStyle;
Aliased := Manager.ShapeOptionAliasing;
end;
if shape is TPhongShape then
with TPhongShape(shape) do
Expand Down Expand Up @@ -1974,6 +1980,8 @@ procedure TVectorialTool.AssignShapeStyle(AMatrix: TAffineMatrix; AAlwaysFit: bo
zoom := (VectLen(AMatrix[1,1],AMatrix[2,1])+VectLen(AMatrix[1,2],AMatrix[2,2]))/2;
f := FShape.MultiFields;
gradBox := FShape.SuggestGradientBox(AffineMatrixIdentity);
if vsfAliased in f then
FShape.Aliased:= Manager.ShapeOptionAliasing;
if vsfPenFill in f then
begin
if HasPen then
Expand Down
40 changes: 37 additions & 3 deletions lazpaintcontrols/lcvectororiginal.pas
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ TVectorShapeDiff = class;

TRenderBoundsOption = (rboAssumePenFill, rboAssumeBackFill);
TRenderBoundsOptions = set of TRenderBoundsOption;
TVectorShapeField = (vsfPenFill, vsfPenWidth, vsfPenStyle, vsfJoinStyle, vsfBackFill, vsfOutlineFill, vsfOutlineWidth);
TVectorShapeField = (vsfPenFill, vsfPenWidth, vsfPenStyle, vsfJoinStyle,
vsfBackFill, vsfOutlineFill, vsfOutlineWidth, vsfAliased);
TVectorShapeFields = set of TVectorShapeField;
TVectorShapeUsermode = (vsuEdit, vsuCreate, vsuEditPenFill, vsuEditBackFill, vsuEditOutlineFill,
vsuCurveSetAuto, vsuCurveSetCurve, vsuCurveSetAngle,
Expand Down Expand Up @@ -117,10 +118,12 @@ TVectorShapeEmbeddedFillDiff = class(TVectorShapeDiff)

TVectorShapeCommonDiff = class(TVectorShapeDiff)
protected
FStartAliased: boolean;
FStartPenWidth: single;
FStartPenStyle: TBGRAPenStyle;
FStartOutlineWidth: single;
FStartJoinStyle: TPenJoinStyle;
FEndAliased: boolean;
FEndPenWidth: single;
FEndPenStyle: TBGRAPenStyle;
FEndOutlineWidth: single;
Expand Down Expand Up @@ -201,13 +204,16 @@ TVectorShape = class
FDiffs: TVectorShapeDiffList;
FFillBeforeChangeBounds: TRectF;
function GetIsUpdating: boolean;
procedure SetAliased(AValue: boolean);
procedure SetContainer(AValue: TVectorOriginal);
function GetFill(var AFillVariable: TVectorialFill): TVectorialFill;
procedure SetFill(var AFillVariable: TVectorialFill; AValue: TVectorialFill; AUpdate: boolean);
procedure SetId(AValue: integer);
protected
FPenWidth: single;
FAliased: boolean;
FOutlineWidth: single;
FPenWidth: single;

FFillChangeWithoutUpdate: boolean;
procedure BeginEditingUpdate;
procedure EndEditingUpdate;
Expand Down Expand Up @@ -257,6 +263,7 @@ TVectorShape = class
ADefs: TSVGDefine; ANamePrefix: string): string;
procedure ApplyStrokeStyleToSVG(AElement: TSVGElement; ADefs: TSVGDefine);
procedure ApplyFillStyleToSVG(AElement: TSVGElement; ADefs: TSVGDefine);
procedure ApplyAliasingToSVG(AElement: TSVGElement);
property Stroker: TBGRAPenStroker read GetStroker;
public
constructor Create(AContainer: TVectorOriginal); virtual;
Expand Down Expand Up @@ -331,6 +338,7 @@ TVectorShape = class
property Id: integer read FId write SetId;
property IsFollowingMouse: boolean read GetIsFollowingMouse;
property IsUpdating: boolean read GetIsUpdating;
property Aliased: boolean read FAliased write SetAliased;
property BackVisible: boolean read GetBackVisible;
property PenVisible: boolean read GetPenVisibleNow;
property OutlineVisible: boolean read GetOutlineVisible;
Expand Down Expand Up @@ -1011,6 +1019,7 @@ constructor TVectorShapeCommonDiff.Create(AStartShape: TVectorShape);
begin
with AStartShape do
begin
FStartAliased:= Aliased;
FStartPenWidth:= PenWidth;
FStartPenStyle:= DuplicatePenStyle(PenStyle);
FStartOutlineWidth:= OutlineWidth;
Expand All @@ -1022,6 +1031,7 @@ procedure TVectorShapeCommonDiff.ComputeDiff(AEndShape: TVectorShape);
begin
with AEndShape do
begin
FEndAliased:= Aliased;
FEndPenWidth:= PenWidth;
FEndPenStyle:= DuplicatePenStyle(PenStyle);
FEndOutlineWidth:= OutlineWidth;
Expand All @@ -1034,6 +1044,7 @@ procedure TVectorShapeCommonDiff.Apply(AStartShape: TVectorShape);
with AStartShape do
begin
BeginUpdate;
FAliased:= FEndAliased;
FPenWidth := FEndPenWidth;
Stroker.CustomPenStyle := DuplicatePenStyle(FEndPenStyle);
FOutlineWidth := FEndOutlineWidth;
Expand All @@ -1047,6 +1058,7 @@ procedure TVectorShapeCommonDiff.Unapply(AEndShape: TVectorShape);
with AEndShape do
begin
BeginUpdate;
FAliased:= FStartAliased;
FPenWidth := FStartPenWidth;
Stroker.CustomPenStyle := DuplicatePenStyle(FStartPenStyle);
FOutlineWidth := FStartOutlineWidth;
Expand All @@ -1060,6 +1072,7 @@ procedure TVectorShapeCommonDiff.Append(ADiff: TVectorShapeDiff);
next: TVectorShapeCommonDiff;
begin
next := ADiff as TVectorShapeCommonDiff;
FEndAliased:= next.FEndAliased;
FEndPenWidth:= next.FEndPenWidth;
FEndPenStyle:= DuplicatePenStyle(next.FEndPenStyle);
FEndOutlineWidth:= next.FEndOutlineWidth;
Expand All @@ -1068,7 +1081,8 @@ procedure TVectorShapeCommonDiff.Append(ADiff: TVectorShapeDiff);

function TVectorShapeCommonDiff.IsIdentity: boolean;
begin
result := (FStartPenWidth = FEndPenWidth) and
result := (FStartAliased = FEndAliased) and
(FStartPenWidth = FEndPenWidth) and
PenStyleEqual(FStartPenStyle, FEndPenStyle) and
(FStartOutlineWidth = FEndOutlineWidth) and
(FStartJoinStyle = FEndJoinStyle);
Expand Down Expand Up @@ -1775,6 +1789,14 @@ function TVectorShape.GetIsUpdating: boolean;
result := FUpdateCount > 0;
end;

procedure TVectorShape.SetAliased(AValue: boolean);
begin
if FAliased=AValue then Exit;
BeginUpdate(TVectorShapeCommonDiff);
FAliased:=AValue;
EndUpdate;
end;

function TVectorShape.GetOutlineWidth: single;
begin
result := FOutlineWidth;
Expand Down Expand Up @@ -1940,6 +1962,12 @@ procedure TVectorShape.ApplyFillStyleToSVG(AElement: TSVGElement; ADefs: TSVGDef
else AElement.fillNone;
end;

procedure TVectorShape.ApplyAliasingToSVG(AElement: TSVGElement);
begin
if Aliased then
AElement.shapeRendering:= 'crispEdges';
end;

procedure TVectorShape.TransformFill(const AMatrix: TAffineMatrix; ABackOnly: boolean);
begin
BeginUpdate;
Expand Down Expand Up @@ -2430,6 +2458,7 @@ procedure TVectorShape.LoadFromStorage(AStorage: TBGRACustomOriginalStorage);
if vsfBackFill in f then LoadFill(AStorage, 'back', FBackFill);
if vsfOutlineFill in f then LoadFill(AStorage, 'outline', FOutlineFill);
if vsfOutlineWidth in f then OutlineWidth := AStorage.FloatDef['outline-width', DefaultShapeOutlineWidth];
if vsfAliased in f then Aliased:= AStorage.BoolDef['aliased', false];
EndUpdate;
end;
end;
Expand Down Expand Up @@ -2462,6 +2491,11 @@ procedure TVectorShape.SaveToStorage(AStorage: TBGRACustomOriginalStorage);
AStorage.RemoveAttribute('outline-color');
AStorage.RemoveAttribute('outline-width');
end;
if vsfAliased in f then
begin
if not Aliased then AStorage.RemoveAttribute('aliased')
else AStorage.Bool['aliased'] := Aliased;
end;
end;

procedure TVectorShape.MouseMove(Shift: TShiftState; X, Y: single; var
Expand Down
7 changes: 4 additions & 3 deletions lazpaintcontrols/lcvectorpolyshapes.pas
Original file line number Diff line number Diff line change
Expand Up @@ -1258,7 +1258,7 @@ procedure TCustomPolypointShape.TransformFrame(const AMatrix: TAffineMatrix);

class function TPolylineShape.Fields: TVectorShapeFields;
begin
Result:= [vsfPenFill, vsfPenWidth, vsfPenStyle, vsfJoinStyle, vsfBackFill];
Result:= [vsfPenFill, vsfPenWidth, vsfPenStyle, vsfJoinStyle, vsfBackFill, vsfAliased];
end;

procedure TPolylineShape.Render(ADest: TBGRABitmap; AMatrix: TAffineMatrix;
Expand All @@ -1274,7 +1274,7 @@ procedure TPolylineShape.Render(ADest: TBGRABitmap; AMatrix: TAffineMatrix;
if BackFill.FillType = vftSolid then backScan := nil
else backScan := BackFill.CreateScanner(AMatrix, ADraft);

if ADraft then
if ADraft or Aliased then
begin
if Assigned(backScan) then
ADest.FillPoly(pts, backScan, dmDrawWithTransparency) else
Expand All @@ -1295,7 +1295,7 @@ procedure TPolylineShape.Render(ADest: TBGRABitmap; AMatrix: TAffineMatrix;
else penScan := PenFill.CreateScanner(AMatrix, ADraft);

pts := ComputeStroke(pts, Closed, AMatrix);
if ADraft and (PenWidth > 4) then
if (ADraft and (PenWidth > 4)) or Aliased then
begin
if Assigned(penScan) then
ADest.FillPoly(pts, penScan, dmDrawWithTransparency) else
Expand Down Expand Up @@ -1323,6 +1323,7 @@ function TPolylineShape.AppendToSVG(AContent: TSVGContent; ADefs: TSVGDefine): T
if PenVisible then
result.strokeLineCapLCL := LineCap;
ApplyFillStyleToSVG(result, ADefs);
ApplyAliasingToSVG(result);
end;

function TPolylineShape.GetRenderBounds(ADestRect: TRect; AMatrix: TAffineMatrix; AOptions: TRenderBoundsOptions): TRectF;
Expand Down
28 changes: 15 additions & 13 deletions lazpaintcontrols/lcvectorrectshapes.pas
Original file line number Diff line number Diff line change
Expand Up @@ -927,7 +927,7 @@ function TRectShape.GetIsSlow(const AMatrix: TAffineMatrix): boolean;

class function TRectShape.Fields: TVectorShapeFields;
begin
Result:= [vsfPenFill, vsfPenWidth, vsfPenStyle, vsfJoinStyle, vsfBackFill];
Result:= [vsfPenFill, vsfPenWidth, vsfPenStyle, vsfJoinStyle, vsfBackFill, vsfAliased];
end;

function TRectShape.AppendToSVG(AContent: TSVGContent; ADefs: TSVGDefine): TSVGElement;
Expand Down Expand Up @@ -973,6 +973,7 @@ function TRectShape.AppendToSVG(AContent: TSVGContent; ADefs: TSVGDefine): TSVGE
result.Matrix[cuPixel] := m;
ApplyStrokeStyleToSVG(result, ADefs);
ApplyFillStyleToSVG(result, ADefs);
ApplyAliasingToSVG(result);
end;
end;

Expand All @@ -995,7 +996,7 @@ procedure TRectShape.Render(ADest: TBGRABitmap; AMatrix: TAffineMatrix;

if GetOrthoRect(AMatrix, orthoRect) then
begin
if ADraft then
if ADraft or Aliased then
begin
r:= rect(round(orthoRect.Left+0.5),round(orthoRect.Top+0.5),round(orthoRect.Right+0.5),round(orthoRect.Bottom+0.5));
if Assigned(backScan) then
Expand Down Expand Up @@ -1023,7 +1024,7 @@ procedure TRectShape.Render(ADest: TBGRABitmap; AMatrix: TAffineMatrix;
end;
end else
begin
if ADraft then
if ADraft or Aliased then
begin
if Assigned(backScan) then
ADest.FillPoly(pts, backScan, dmDrawWithTransparency) else
Expand Down Expand Up @@ -1059,7 +1060,7 @@ procedure TRectShape.Render(ADest: TBGRABitmap; AMatrix: TAffineMatrix;
else penScan := PenFill.CreateScanner(AMatrix, ADraft);

pts := ComputeStroke(pts,true, AMatrix);
if ADraft and (PenWidth > 4) then
if (ADraft and (PenWidth > 4)) or Aliased then
begin
if Assigned(penScan) then
ADest.FillPoly(pts, penScan, dmDrawWithTransparency) else
Expand Down Expand Up @@ -1195,7 +1196,7 @@ constructor TEllipseShape.Create(AContainer: TVectorOriginal);

class function TEllipseShape.Fields: TVectorShapeFields;
begin
Result:= [vsfPenFill, vsfPenWidth, vsfPenStyle, vsfBackFill];
Result:= [vsfPenFill, vsfPenWidth, vsfPenStyle, vsfBackFill, vsfAliased];
end;

function TEllipseShape.AppendToSVG(AContent: TSVGContent; ADefs: TSVGDefine): TSVGElement;
Expand All @@ -1219,6 +1220,7 @@ function TEllipseShape.AppendToSVG(AContent: TSVGContent; ADefs: TSVGDefine): TS
end;
ApplyStrokeStyleToSVG(result, ADefs);
ApplyFillStyleToSVG(result, ADefs);
ApplyAliasingToSVG(result);
end;

function TEllipseShape.GetAlignBounds(const ALayoutRect: TRect;
Expand Down Expand Up @@ -1264,7 +1266,7 @@ procedure TEllipseShape.Render(ADest: TBGRABitmap; AMatrix: TAffineMatrix;
pts: Array of TPointF;
orthoRect: TRectF;
center, radius: TPointF;
draftPen, isOrtho: Boolean;
aliasedPen, isOrtho: Boolean;
r: TRect;
backScan, penScan: TBGRACustomScanner;
penZoom: Single;
Expand All @@ -1280,7 +1282,7 @@ procedure TEllipseShape.Render(ADest: TBGRABitmap; AMatrix: TAffineMatrix;
if BackFill.FillType = vftSolid then backScan := nil
else backScan := BackFill.CreateScanner(AMatrix, ADraft);

if ADraft then
if ADraft or Aliased then
begin
r := rect(round(orthoRect.Left),round(orthoRect.Top),round(orthoRect.Right),round(orthoRect.Bottom));
if Assigned(backScan) then
Expand All @@ -1300,13 +1302,13 @@ procedure TEllipseShape.Render(ADest: TBGRABitmap; AMatrix: TAffineMatrix;
begin
if PenFill.FillType = vftSolid then penScan := nil
else penScan := PenFill.CreateScanner(AMatrix, ADraft);
draftPen := ADraft and (PenWidth > 4);
aliasedPen := (ADraft and (PenWidth > 4)) or Aliased;

if IsAffineMatrixScaledRotation(AMatrix) and not (draftPen and Assigned(penScan)) then
if IsAffineMatrixScaledRotation(AMatrix) and not (aliasedPen and Assigned(penScan)) then
begin
penZoom := VectLen(AMatrix[1,1],AMatrix[2,1]);
ADest.CustomPenStyle := PenStyle;
if draftPen then
if aliasedPen then
ADest.Ellipse(center.x, center.y, radius.x, radius.y, PenColor, PenWidth*penZoom, dmDrawWithTransparency)
else
begin
Expand All @@ -1320,7 +1322,7 @@ procedure TEllipseShape.Render(ADest: TBGRABitmap; AMatrix: TAffineMatrix;
m:= MatrixForPixelCentered(AMatrix);
pts := ComputeEllipse(m*FOrigin, m*FXAxis, m*FYAxis);
pts := ComputeStroke(pts,true, AMatrix);
if draftPen then
if aliasedPen then
begin
if Assigned(penScan) then
ADest.FillPoly(pts, penScan, dmDrawWithTransparency) else
Expand All @@ -1345,7 +1347,7 @@ procedure TEllipseShape.Render(ADest: TBGRABitmap; AMatrix: TAffineMatrix;
if BackFill.FillType = vftSolid then backScan := nil
else backScan := BackFill.CreateScanner(AMatrix, ADraft);

if ADraft then
if ADraft or Aliased then
begin
if Assigned(backScan) then
ADest.FillPoly(pts, backScan, dmDrawWithTransparency) else
Expand All @@ -1366,7 +1368,7 @@ procedure TEllipseShape.Render(ADest: TBGRABitmap; AMatrix: TAffineMatrix;
else penScan := PenFill.CreateScanner(AMatrix, ADraft);

pts := ComputeStroke(pts,true, AMatrix);
if ADraft and (PenWidth > 4) then
if (ADraft and (PenWidth > 4)) or Aliased then
begin
if Assigned(penScan) then
ADest.FillPoly(pts, penScan, dmDrawWithTransparency) else
Expand Down
Loading

0 comments on commit cff3eb6

Please sign in to comment.