Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GH-34 Allow more flexible slicing #35

Merged
merged 25 commits into from
Mar 26, 2024

Conversation

henrik-dmg
Copy link
Contributor

Background

This PR changes the process of slicing the final canvas into slices to not rely on the size of the supplied screenshots anymore but rather the user specifying a desired number of slices.
It also fixes a couple of other things, like remove a bunch of dead code and QOL updates

Changes

Changes relevant to #34

  • added new key numberOfSlices to DeviceData
  • added SliceSizeCalculator type and tests for it
  • adapted the validate() method in DeviceData to verify a couple things
    • gap width is >= 0
    • number of slices is >= 1
    • resulting slice size is valid

Other changes

  • updated swift-argument-parser to 1.3.0
  • bumped minimum Swift version to 5.9 and minimum platform to macOS 13
  • fixed CI by specifying which macOS version to use and also set the Xcode version before running/building tests
  • updated example config files to contain the new required keys
  • added inversion: .prefixedNo to two flags that had an inverted name, this makes it easier to reason about them without doing the mental inversion based on the name
  • bumped version to 6.0.0 as the new slicing mechanism requires an update to the config files, which is therefore a breaking change
  • moved regex parsing from NSRegularExpression to modern Regex
  • removed old clearDirectories and outputWholeImage keys from parsing
  • added tests for a bunch of things that were previously untested
  • updated the benchmark.py script to not rely on any third-party libraries
  • remove a lot of dead code and made many things internal that did not need to be public

How to Test

  • run swift run swiftframe render Example/example.yaml --verbose --manual-validation
  • check that the manual validation info contains the new key Number of slices and also that the Output slice size is displayed
  • run tests

Closes #34

Signed-off-by: Henrik Panhans <[email protected]>
Signed-off-by: Henrik Panhans <[email protected]>
Signed-off-by: Henrik Panhans <[email protected]>
Signed-off-by: Henrik Panhans <[email protected]>
Signed-off-by: Henrik Panhans <[email protected]>
Signed-off-by: Henrik Panhans <[email protected]>
Signed-off-by: Henrik Panhans <[email protected]>
Signed-off-by: Henrik Panhans <[email protected]>
Signed-off-by: Henrik Panhans <[email protected]>
Signed-off-by: Henrik Panhans <[email protected]>
This reverts commit 052763b.

Signed-off-by: Henrik Panhans <[email protected]>
Negative sizes are not possible anymore

Signed-off-by: Henrik Panhans <[email protected]>
@Pispa339 Pispa339 self-requested a review March 26, 2024 11:24
@Pispa339 Pispa339 self-assigned this Mar 26, 2024
@@ -55,8 +57,8 @@ struct Render: ParsableCommand {
verbose: verbose,
shouldValidateManually: manualValidation,
shouldOutputWholeImage: outputWholeImage,
shouldClearDirectories: !noClearDirectories,
shouldColorOutput: !noColorOutput
shouldClearDirectories: clearDirectories,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes so much more sense now that I'm seeing this :D

guard numberOfSlices > 0 else {
throw NSError(
description: "Invalid numberOfSlices value",
expectation: "numberOfSlices value should be >= 1",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know this means the same as the actual condition, but to me it would make sense to have the condition and the expectation's textual description be the exact same

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this follows the pattern of NSError, it has localizedFailureReason, localizedDescription and localizedRecoverySuggestion which this kind of mimics a bit 🤔

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I mean is that I find it odd that the condition is numberOfSlices > 0 but then the textual description is numberOfSlices value should be >= 1 instead of it being numberOfSlices value should be > 0 :D

}

if let templateImage {
_ = try SliceSizeCalculator.calculateSliceSize(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we do the above check for numberOfSlices > 0 when we do the same again in SliceSizeCalculator.calculateSliceSize? I'd suggest extracting the validation conditions into another static method e.g. validateSliceSizeCalculationInput(templateImageSize: CGSize, numberOfSlices: Int, gapWidth: Int?) -> Result which we could then call from here and from inside SliceSizeCalculator.calculateSliceSize

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Result could e.g. be an enum such as

enum Result {
    case valid
    case invalid(error: NSError)
}

 ¯_(ツ)_/¯

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or well, now looking at the method itself, the calculation logic would be almost the same as the method itself so idk 😅

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I see where you're coming from though, I wasn't super happy about this either 😅 using a static value would have to be a bit more complex though as there can be multiple DeviceData in a single configuration file

@@ -1,24 +1,15 @@
import Foundation

extension Array where Element == URL {
extension [URL] {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Neat!

@@ -110,14 +99,17 @@ public class ConfigProcessor: VerbosePrintable {

try deviceData.screenshotsGroupedByLocale.forEach { locale, imageDict in
group.enter()
defer { group.leave() }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wait what this works 🤯 I always thought one can only do this for a method, not a loop

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A defer statement is used for executing code just before transferring program control outside of the scope that the statement appears in.

Honestly I didn't think about it when I wrote it, the compiler didn't complain 😄 but I verified that it's not accidentally using method-scope but the for-loop-scope with this code:

func deferTest() {
    let values = [1, 2, 3, 4]
    for value in values {
        defer { print(value) }
        print("Loop")
    }
}

prints:

Loop
1
Loop
2
Loop
3
Loop
4

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤯 the more you know

Copy link
Contributor

@Pispa339 Pispa339 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codewise looks good and the tests instructed in the PR description are all looking good. Kind of tempted to test this with our screenshot pipeline but it feels like a bit too much of effort. We'll find out once we merge this to master anyways 😅

Signed-off-by: Henrik Panhans <[email protected]>
@henrik-dmg henrik-dmg merged commit 88c7bb9 into main Mar 26, 2024
1 check passed
@henrik-dmg henrik-dmg deleted the feature/GH-34-more-flexible-slicing branch March 26, 2024 13:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Allow more flexible slicing
2 participants