Skip to content

Commit

Permalink
update CHANGELOG
Browse files Browse the repository at this point in the history
  • Loading branch information
ashahabov committed Nov 14, 2022
1 parent 0b6af41 commit bdb8653
Show file tree
Hide file tree
Showing 6 changed files with 155 additions and 78 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Changelog

## Version 0.37.0 - Unreleased
## Version 0.37.0 - 2022-11-14
- Added `IPicture.SvgContent` property to read SVG graphic content [#344](https://github.com/ShapeCrawler/ShapeCrawler/issues/355)
- Added `ITextFrame.LeftMargin`, `ITextFrame.RightMargin`, `ITextFrame.TopMargin` and `ITextFrame.BottomMargin` properties to get margins of text box [#375](https://github.com/ShapeCrawler/ShapeCrawler/issues/375)
- Added `IParagraph.IndentLevel` to get indent level of paragraph [#377](https://github.com/ShapeCrawler/ShapeCrawler/issues/377)
Expand Down
20 changes: 19 additions & 1 deletion ShapeCrawler.Tests/TextFrameTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,24 @@ public void TextWrapped_Getter_returns_value_indicating_whether_text_is_wrapped_
textWrapped.Should().Be(isTextWrapped);
}

[Fact (Skip = "In Progress: https://github.com/ShapeCrawler/ShapeCrawler/issues/360")]
public void Autofit_Setter_sets_text_autofit_type()
{
// Arrange
var pptxStream = GetTestStream("autoshape-case003.pptx");
var pres = SCPresentation.Open(pptxStream);
var textFrame = pres.Slides[0].Shapes.GetByName<IAutoShape>("AutoShape 6").TextFrame!;

// Act
textFrame.AutofitType = SCAutofitType.Resize;
pres.SaveAs(@"c:\temp\output.pptx");

// Assert
textFrame.AutofitType.Should().Be(SCAutofitType.Resize);
var errors = PptxValidator.Validate(pres);
errors.Should().BeEmpty();
}

[Fact]
public void AutofitType_Getter_returns_text_autofit_type()
{
Expand All @@ -301,7 +319,7 @@ public void AutofitType_Getter_returns_text_autofit_type()
var autofitType = textBox.AutofitType;

// Assert
autofitType.Should().Be(SCAutoFitType.Shrink);
autofitType.Should().Be(SCAutofitType.Shrink);
}

[Fact]
Expand Down
65 changes: 56 additions & 9 deletions ShapeCrawler/AutoShapes/ITextFrame.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ public interface ITextFrame
string Text { get; set; }

/// <summary>
/// Gets Autofit type.
/// Gets or sets Autofit type.
/// </summary>
SCAutoFitType AutofitType { get; }
SCAutofitType AutofitType { get; set; }

/// <summary>
/// Gets left margin of text frame in centimeters.
Expand Down Expand Up @@ -89,7 +89,11 @@ public string Text
set => this.SetText(value);
}

public SCAutoFitType AutofitType => this.GetAutoFitType();
public SCAutofitType AutofitType
{
get => this.GetAutofitType();
set => this.SetAutofitType(value);
}

public double LeftMargin => this.GetLeftMargin();

Expand Down Expand Up @@ -124,6 +128,49 @@ internal void Draw(SKCanvas slideCanvas, SKRect shapeRect)
throw new System.NotImplementedException();
}

private void SetAutofitType(SCAutofitType newType)
{
var currentType = this.AutofitType;
if (currentType == newType)
{
return;
}

var aBodyPr = this.TextBodyElement.GetFirstChild<A.BodyProperties>() !;
var dontAutofit = aBodyPr.GetFirstChild<A.NoAutoFit>();
var shrink = aBodyPr.GetFirstChild<A.NormalAutoFit>();
var resize = aBodyPr.GetFirstChild<A.ShapeAutoFit>();

switch (newType)
{
case SCAutofitType.None:
shrink?.Remove();
resize?.Remove();
dontAutofit = new A.NoAutoFit();
aBodyPr.Append(dontAutofit);
break;
case SCAutofitType.Shrink:
dontAutofit?.Remove();
resize?.Remove();
shrink = new A.NormalAutoFit();
aBodyPr.Append(shrink);
break;
case SCAutofitType.Resize:
{
dontAutofit?.Remove();
shrink?.Remove();
resize = new A.ShapeAutoFit();
aBodyPr.Append(resize);
var parentAutoShape = (SlideAutoShape)this.TextFrameContainer.Shape;
parentAutoShape.ResizeShape();
break;
}

default:
throw new ArgumentOutOfRangeException(nameof(newType), newType, null);
}
}

private double GetLeftMargin()
{
var bodyProperties = this.TextBodyElement.GetFirstChild<A.BodyProperties>() !;
Expand Down Expand Up @@ -163,25 +210,25 @@ private ParagraphCollection GetParagraphs()
return new ParagraphCollection(this);
}

private SCAutoFitType GetAutoFitType()
private SCAutofitType GetAutofitType()
{
if (this.TextBodyElement == null)
{
return SCAutoFitType.None;
return SCAutofitType.None;
}

var aBodyPr = this.TextBodyElement.GetFirstChild<A.BodyProperties>();
if (aBodyPr!.GetFirstChild<A.NormalAutoFit>() != null)
{
return SCAutoFitType.Shrink;
return SCAutofitType.Shrink;
}

if (aBodyPr.GetFirstChild<A.ShapeAutoFit>() != null)
{
return SCAutoFitType.Resize;
return SCAutofitType.Resize;
}

return SCAutoFitType.None;
return SCAutofitType.None;
}

private void SetText(string newText)
Expand All @@ -203,7 +250,7 @@ private void SetText(string newText)

baseParagraph.Text = newText;

if (this.AutofitType == SCAutoFitType.Shrink)
if (this.AutofitType == SCAutofitType.Shrink)
{
this.ShrinkText(newText, baseParagraph);
}
Expand Down
132 changes: 72 additions & 60 deletions ShapeCrawler/AutoShapes/SlideAutoShape.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ internal class SlideAutoShape : SlideShape, IAutoShape, ITextFrameContainer
private readonly ResettableLazy<Dictionary<int, FontData>> lvlToFontData;
private readonly P.Shape pShape;

internal SlideAutoShape(P.Shape pShape, OneOf<SCSlide, SCSlideLayout, SCSlideMaster> oneOfSlide, SCGroupShape groupShape)
internal SlideAutoShape(P.Shape pShape, OneOf<SCSlide, SCSlideLayout, SCSlideMaster> oneOfSlide,
SCGroupShape groupShape)
: base(pShape, oneOfSlide, groupShape)
{
this.pShape = pShape;
Expand Down Expand Up @@ -71,6 +72,76 @@ internal override void Draw(SKCanvas canvas)
}
}

internal void ResizeShape()
{
if (this.TextFrame!.AutofitType != SCAutofitType.Resize)
{
return;
}

var baseParagraph = this.TextFrame.Paragraphs.First();
var popularPortion = baseParagraph.Portions.GroupBy(p => p.Font.Size).OrderByDescending(x => x.Count())
.First().First();
var font = popularPortion.Font;

var paint = new SKPaint();
var fontSize = font.Size;
paint.TextSize = fontSize;
paint.Typeface = SKTypeface.FromFamilyName(font.Name);
paint.IsAntialias = true;

var lMarginPixel = UnitConverter.CentimeterToPixel(this.TextFrame.LeftMargin);
var rMarginPixel = UnitConverter.CentimeterToPixel(this.TextFrame.RightMargin);
var tMarginPixel = UnitConverter.CentimeterToPixel(this.TextFrame.TopMargin);
var bMarginPixel = UnitConverter.CentimeterToPixel(this.TextFrame.BottomMargin);

var newTextRect = default(SKRect);
var newText = this.TextFrame.Text;
paint.MeasureText(newText, ref newTextRect);
var newTextW = newTextRect.Width;
var newTextH = paint.TextSize;
var textBlockW = this.Width - lMarginPixel - rMarginPixel;
var shapeTextBlockH = this.Height - tMarginPixel - bMarginPixel;

var hasTextBlockEnoughWidth = textBlockW > newTextW;
if (hasTextBlockEnoughWidth)
{
return;
}

var neededRowsCount = newTextW / textBlockW;
var integerPart = (int)neededRowsCount;
var fractionalPart = neededRowsCount - integerPart;
if (fractionalPart > 0)
{
integerPart++;
}

var neededShapeH = (integerPart * newTextH) + tMarginPixel + bMarginPixel;
if (!(shapeTextBlockH < neededShapeH))
{
return;
}

this.Height = (int)neededShapeH + tMarginPixel + bMarginPixel + tMarginPixel + bMarginPixel;

// We should raise the shape up by the amount which is half of the increased offset.
// PowerPoint does the same thing.
var yOffset = (neededShapeH - shapeTextBlockH) / 2;
this.Y -= (int)yOffset;

if (!this.TextFrame.TextWrapped)
{
var longerText = this.TextFrame.Paragraphs
.Select(x => new { x.Text, x.Text.Length })
.OrderByDescending(x => x.Length)
.First().Text;
var paraTextRect = default(SKRect);
var widthInPixels = paint.MeasureText(longerText, ref paraTextRect);
this.Width = (int)widthInPixels + lMarginPixel + rMarginPixel;
}
}

internal void FillFontData(int paragraphLvl, ref FontData fontData)
{
if (this.lvlToFontData.Value.TryGetValue(paragraphLvl, out FontData layoutFontData))
Expand Down Expand Up @@ -133,65 +204,6 @@ private Dictionary<int, FontData> GetLvlToFontData()
return newTextFrame;
}

private void ResizeShape()
{
if (this.TextFrame!.AutofitType != SCAutoFitType.Resize)
{
return;
}

var baseParagraph = this.TextFrame.Paragraphs.First();
var popularPortion = baseParagraph.Portions.GroupBy(p => p.Font.Size).OrderByDescending(x => x.Count())
.First().First();
var font = popularPortion.Font;

var paint = new SKPaint();
var fontSize = font.Size;
paint.TextSize = fontSize;
paint.Typeface = SKTypeface.FromFamilyName(font.Name);
paint.IsAntialias = true;

var lMarginPixel = UnitConverter.CentimeterToPixel(this.TextFrame.LeftMargin);
var rMarginPixel = UnitConverter.CentimeterToPixel(this.TextFrame.RightMargin);
var tMarginPixel = UnitConverter.CentimeterToPixel(this.TextFrame.TopMargin);
var bMarginPixel = UnitConverter.CentimeterToPixel(this.TextFrame.BottomMargin);

var newTextRect = new SKRect();
var newText = this.TextFrame.Text;
paint.MeasureText(newText, ref newTextRect);
var newTextW = newTextRect.Width;
var newTextH = paint.TextSize;
var textBlockW = this.Width - lMarginPixel - rMarginPixel;
var shapeTextBlockH = this.Height - tMarginPixel - bMarginPixel;

var hasEnoughTextBlockSpaces = textBlockW > newTextW;
if (hasEnoughTextBlockSpaces)
{
return;
}

var neededRowsCount = newTextW / textBlockW;
var integerPart = (int)neededRowsCount;
var fractionalPart = neededRowsCount - integerPart;
if (fractionalPart > 0)
{
integerPart++;
}

var neededShapeH = (integerPart * newTextH) + tMarginPixel + bMarginPixel;
if (!(shapeTextBlockH < neededShapeH))
{
return;
}

this.Height = (int)neededShapeH + tMarginPixel + bMarginPixel + tMarginPixel + bMarginPixel;

// We should raise the shape up by the amount which is half of the increased offset.
// PowerPoint does the same thing.
var yOffset = (neededShapeH - shapeTextBlockH) / 2;
this.Y -= (int)yOffset;
}

private ShapeFill GetFill()
{
return new ShapeFill(this);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
/// <summary>
/// Autofit type.
/// </summary>
public enum SCAutoFitType
public enum SCAutofitType
{
/// <summary>
/// Do not Autofit.
Expand Down
12 changes: 6 additions & 6 deletions ShapeCrawler/ShapeCrawler.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ This library provides a simplified object model on top of the Open XML SDK for m
<Copyright>MIT</Copyright>
<LangVersion>10</LangVersion>
<ApplicationIcon>logo.ico</ApplicationIcon>
<PackageReleaseNotes>- Added `IPicture.SvgContent` property to read SVG graphic content [#344](https://github.com/ShapeCrawler/ShapeCrawler/issues/355)
- Added `ITextFrame.LeftMargin`, `ITextFrame.RightMargin`, `ITextFrame.TopMargin` and `ITextFrame.BottomMargin` properties to get margins of text box [#375](https://github.com/ShapeCrawler/ShapeCrawler/issues/375)
- Added processing "Resize shape to fit text" flag.</PackageReleaseNotes>
<PackageReleaseNotes>- Added `IPicture.SvgContent` property to read SVG graphic content.
- Added `ITextFrame.LeftMargin`, `ITextFrame.RightMargin`, `ITextFrame.TopMargin` and `ITextFrame.BottomMargin` properties to get margins of text box.
- Added `IParagraph.IndentLevel` to get indent level of paragraph.</PackageReleaseNotes>
<PackageProjectUrl>https://github.com/ShapeCrawler/ShapeCrawler</PackageProjectUrl>
<RunAnalyzersDuringBuild>true</RunAnalyzersDuringBuild>
<RepositoryType>Git</RepositoryType>
Expand All @@ -28,10 +28,10 @@ This library provides a simplified object model on top of the Open XML SDK for m
<EnableNETAnalyzers>true</EnableNETAnalyzers>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
<nullable>enable</nullable>
<AssemblyVersion>0.36.0</AssemblyVersion>
<FileVersion>0.36.0</FileVersion>
<AssemblyVersion>0.37.0</AssemblyVersion>
<FileVersion>0.37.0</FileVersion>
<GenerateResourceUsePreserializedResources>true</GenerateResourceUsePreserializedResources>
<PackageVersion>0.37.0-beta.2</PackageVersion>
<PackageVersion>0.37.0</PackageVersion>
<Title>ShapeCrawler</Title>
<Configurations>Debug;Release;Test</Configurations>
<Platforms>AnyCPU</Platforms>
Expand Down

0 comments on commit bdb8653

Please sign in to comment.