Skip to content

Commit

Permalink
Merge pull request #14 from papauorg/feature/use-custom-svg-creation
Browse files Browse the repository at this point in the history
Feature/use custom svg creation
  • Loading branch information
papauorg authored Jan 13, 2025
2 parents ec8a342 + 08f87d8 commit 16d772a
Show file tree
Hide file tree
Showing 135 changed files with 8,039 additions and 7,137 deletions.
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
FROM mcr.microsoft.com/devcontainers/dotnet:1-8.0-bookworm AS dev
RUN apt-get update -y && apt install -y vim pipx ruby-full build-essential zlib1g-dev
RUN apt-get update -y && apt install -y vim pipx ruby-full build-essential zlib1g-dev libfontconfig

RUN dotnet tool install -g dotnet-format \
&& dotnet tool install -g dotnet-outdated-tool
Expand All @@ -23,14 +23,14 @@ RUN gem install jekyll bundler
USER root



FROM dev as build
WORKDIR /build
COPY . .
RUN find ./scales/definitions/*.json | xargs -I % check-jsonschema % --schemafile ./scales/definitions/schemas/scale-config
RUN dotnet build --configuration=Release && dotnet test --no-build --configuration=Release

FROM mcr.microsoft.com/dotnet/runtime:8.0
RUN apt-get update && apt-get install -y libfontconfig
WORKDIR /app
COPY --from=build /build/src/dotnet-levelmeter/bin/Release/net8.0 .
WORKDIR /config
Expand Down
2 changes: 1 addition & 1 deletion scales/definitions/cylinder_mm_d360_h335_1-9gal-us_i1.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"family": "./fonts/BigShoulderStencilText/static/BigShouldersStencilText-ExtraBold.ttf",
"size": 8,
"offsetX": -2,
"offsetY": -5,
"offsetY": -7,
"textAlignment": "Right"
}
}
Expand Down
37 changes: 37 additions & 0 deletions scales/definitions/cyliner_mm_d600_h600_1-170l_i5.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"$schema": "./schemas/scale-config",
"scale-config": {
"containerForm": "cylinder",
"lengthUnit": "mm",
"volumeUnit": "l",
"diameter": 600,
"height": 600,
"minVolume": 1,
"maxVolume": 170,
"output": "./scales/svgs/{0}.svg",
"description": "Scale for 600mm diameter cylindric container. 1-170 l in 5 l intervals with text every 10 l.",
"sucessfullyAppliedTo": "",
"requiresTransferTape": false,
"graduationMarkSettings": [
{
"interval": 5,
"length": 10,
"height": 1.5,
"indentation": 0,
"textTemplate": ""
},
{
"interval": 10,
"length": 25,
"height": 1.5,
"font": {
"family": "./fonts/BigShoulderStencilText/static/BigShouldersStencilText-ExtraBold.ttf",
"size": 8,
"offsetX": -2,
"offsetY": -5,
"textAlignment": "Right"
}
}
]
}
}
37 changes: 37 additions & 0 deletions scales/definitions/cyliner_mm_d600_h600_1-170l_i5_bigger.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"$schema": "./schemas/scale-config",
"scale-config": {
"containerForm": "cylinder",
"lengthUnit": "mm",
"volumeUnit": "l",
"diameter": 600,
"height": 600,
"minVolume": 1,
"maxVolume": 170,
"output": "./scales/svgs/{0}.svg",
"description": "Scale for 600mm diameter cylindric container. 1-170 l in 5 l intervals with text every 10 l.",
"sucessfullyAppliedTo": "",
"requiresTransferTape": false,
"graduationMarkSettings": [
{
"interval": 5,
"length": 20,
"height": 1.5,
"indentation": 0,
"textTemplate": ""
},
{
"interval": 10,
"length": 50,
"height": 2.5,
"font": {
"family": "./fonts/BigShoulderStencilText/static/BigShouldersStencilText-ExtraBold.ttf",
"size": 15,
"offsetX": -2,
"offsetY": -10,
"textAlignment": "Right"
}
}
]
}
}
35 changes: 18 additions & 17 deletions scales/svgs/cylinder_mm_d070_h080_1-200ml_i20.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
45 changes: 23 additions & 22 deletions scales/svgs/cylinder_mm_d138_h110_2-15dl_i1.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
47 changes: 24 additions & 23 deletions scales/svgs/cylinder_mm_d216_h409_1-15l_i1.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
47 changes: 24 additions & 23 deletions scales/svgs/cylinder_mm_d218_h402_1-15l_i1.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
47 changes: 24 additions & 23 deletions scales/svgs/cylinder_mm_d245_h318_1-15l_i1.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
59 changes: 30 additions & 29 deletions scales/svgs/cylinder_mm_d250_h408_1-20l_i1.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
59 changes: 30 additions & 29 deletions scales/svgs/cylinder_mm_d265_h363_1-20l_i1.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
47 changes: 24 additions & 23 deletions scales/svgs/cylinder_mm_d277_h249_1-15l_i1.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
59 changes: 30 additions & 29 deletions scales/svgs/cylinder_mm_d277_h332_1-20l_i1.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
47 changes: 24 additions & 23 deletions scales/svgs/cylinder_mm_d280_h244_1-15l_i1.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
41 changes: 21 additions & 20 deletions scales/svgs/cylinder_mm_d281_h180_1-10L_i1.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
83 changes: 42 additions & 41 deletions scales/svgs/cylinder_mm_d282_h480_1-30l_i1.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
83 changes: 42 additions & 41 deletions scales/svgs/cylinder_mm_d284_h474_1-30l_i1.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
59 changes: 30 additions & 29 deletions scales/svgs/cylinder_mm_d295_h294_1-20l_i1.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
71 changes: 36 additions & 35 deletions scales/svgs/cylinder_mm_d295_h366_1-25l_i1.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
83 changes: 42 additions & 41 deletions scales/svgs/cylinder_mm_d295_h439_1-30l_i1.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
95 changes: 48 additions & 47 deletions scales/svgs/cylinder_mm_d295_h512_1-35l_i1.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
71 changes: 36 additions & 35 deletions scales/svgs/cylinder_mm_d298_h358_1-25l_i1.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
71 changes: 36 additions & 35 deletions scales/svgs/cylinder_mm_d298_h502_1-25l_i1.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
59 changes: 30 additions & 29 deletions scales/svgs/cylinder_mm_d300_h283_1-20l_i1.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
71 changes: 36 additions & 35 deletions scales/svgs/cylinder_mm_d300_h353_1-25l_i1.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
83 changes: 42 additions & 41 deletions scales/svgs/cylinder_mm_d300_h424_1-30l_i1.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
95 changes: 48 additions & 47 deletions scales/svgs/cylinder_mm_d300_h495_1-35l_i1.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
59 changes: 30 additions & 29 deletions scales/svgs/cylinder_mm_d302_h279_1-20l_i1.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
95 changes: 48 additions & 47 deletions scales/svgs/cylinder_mm_d308_h470_1-35l_i1.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
71 changes: 36 additions & 35 deletions scales/svgs/cylinder_mm_d310_h331_1-25l_i1.svg

Large diffs are not rendered by default.

95 changes: 48 additions & 47 deletions scales/svgs/cylinder_mm_d315_h449_1-35l_i1.svg

Large diffs are not rendered by default.

71 changes: 36 additions & 35 deletions scales/svgs/cylinder_mm_d318_h318_1-25l_i1.svg

Large diffs are not rendered by default.

59 changes: 30 additions & 29 deletions scales/svgs/cylinder_mm_d320_h249_1-20l_i1.svg

Large diffs are not rendered by default.

83 changes: 42 additions & 41 deletions scales/svgs/cylinder_mm_d320_h373_1-30l_i1.svg

Large diffs are not rendered by default.

83 changes: 42 additions & 41 deletions scales/svgs/cylinder_mm_d325_h362_1-30l_i1.svg

Large diffs are not rendered by default.

95 changes: 48 additions & 47 deletions scales/svgs/cylinder_mm_d340_h400_1-35l_i1.svg

Large diffs are not rendered by default.

83 changes: 42 additions & 41 deletions scales/svgs/cylinder_mm_d345_h321_1-30l_i1.svg

Large diffs are not rendered by default.

95 changes: 48 additions & 47 deletions scales/svgs/cylinder_mm_d345_h374_1-35l_i1.svg

Large diffs are not rendered by default.

107 changes: 54 additions & 53 deletions scales/svgs/cylinder_mm_d345_h428_1-40l_i1.svg

Large diffs are not rendered by default.

83 changes: 42 additions & 41 deletions scales/svgs/cylinder_mm_d346_h335_1-30l_i1.svg

Large diffs are not rendered by default.

107 changes: 54 additions & 53 deletions scales/svgs/cylinder_mm_d347_h421_1-40l_i1.svg

Large diffs are not rendered by default.

119 changes: 60 additions & 59 deletions scales/svgs/cylinder_mm_d347_h476_1-45l_i1.svg

Large diffs are not rendered by default.

71 changes: 36 additions & 35 deletions scales/svgs/cylinder_mm_d350_h280_1-30l_i1.svg

Large diffs are not rendered by default.

83 changes: 42 additions & 41 deletions scales/svgs/cylinder_mm_d350_h312_1-30l_i1.svg

Large diffs are not rendered by default.

95 changes: 48 additions & 47 deletions scales/svgs/cylinder_mm_d350_h364_1-35l_i1.svg

Large diffs are not rendered by default.

107 changes: 54 additions & 53 deletions scales/svgs/cylinder_mm_d350_h416_1-40l_i1.svg

Large diffs are not rendered by default.

131 changes: 66 additions & 65 deletions scales/svgs/cylinder_mm_d350_h520_1-50l_i1.svg

Large diffs are not rendered by default.

83 changes: 42 additions & 41 deletions scales/svgs/cylinder_mm_d353_h353_1-30l_i1.svg

Large diffs are not rendered by default.

95 changes: 48 additions & 47 deletions scales/svgs/cylinder_mm_d355_h354_1-35l_i1.svg

Large diffs are not rendered by default.

83 changes: 42 additions & 41 deletions scales/svgs/cylinder_mm_d357_h350_1-30l_i1.svg

Large diffs are not rendered by default.

83 changes: 42 additions & 41 deletions scales/svgs/cylinder_mm_d357_h360_1-30l_i1.svg

Large diffs are not rendered by default.

107 changes: 54 additions & 53 deletions scales/svgs/cylinder_mm_d358_h397_1-40l_i1.svg

Large diffs are not rendered by default.

83 changes: 42 additions & 41 deletions scales/svgs/cylinder_mm_d360_h295_1-30l_i1.svg

Large diffs are not rendered by default.

189 changes: 95 additions & 94 deletions scales/svgs/cylinder_mm_d360_h335_1-30l_i0-5.svg

Large diffs are not rendered by default.

83 changes: 42 additions & 41 deletions scales/svgs/cylinder_mm_d360_h335_1-30l_i1.svg

Large diffs are not rendered by default.

47 changes: 24 additions & 23 deletions scales/svgs/cylinder_mm_d360_h335_1-9gal-us_i1.svg

Large diffs are not rendered by default.

95 changes: 48 additions & 47 deletions scales/svgs/cylinder_mm_d360_h350_1-35l_i1.svg

Large diffs are not rendered by default.

107 changes: 54 additions & 53 deletions scales/svgs/cylinder_mm_d360_h393_1-40l_i1.svg

Large diffs are not rendered by default.

131 changes: 66 additions & 65 deletions scales/svgs/cylinder_mm_d360_h490_1-50l_i1.svg

Large diffs are not rendered by default.

83 changes: 42 additions & 41 deletions scales/svgs/cylinder_mm_d362_h291_1-30l_i1.svg

Large diffs are not rendered by default.

131 changes: 66 additions & 65 deletions scales/svgs/cylinder_mm_d362_h486_1-50l_i1.svg

Large diffs are not rendered by default.

107 changes: 54 additions & 53 deletions scales/svgs/cylinder_mm_d365_h382_1-40l_i1.svg

Large diffs are not rendered by default.

131 changes: 66 additions & 65 deletions scales/svgs/cylinder_mm_d367_h473_1-50l_i1.svg

Large diffs are not rendered by default.

83 changes: 42 additions & 41 deletions scales/svgs/cylinder_mm_d368_h282_1-30l_i1.svg

Large diffs are not rendered by default.

81 changes: 41 additions & 40 deletions scales/svgs/cylinder_mm_d370_h330_1-30l_i1.svg

Large diffs are not rendered by default.

131 changes: 66 additions & 65 deletions scales/svgs/cylinder_mm_d370_h465_1-50l_i1.svg

Large diffs are not rendered by default.

83 changes: 42 additions & 41 deletions scales/svgs/cylinder_mm_d375_h272_1-30l_i1.svg

Large diffs are not rendered by default.

131 changes: 66 additions & 65 deletions scales/svgs/cylinder_mm_d380_h441_1-50l_i1.svg

Large diffs are not rendered by default.

119 changes: 60 additions & 59 deletions scales/svgs/cylinder_mm_d385_h387_1-45l_i1.svg

Large diffs are not rendered by default.

131 changes: 66 additions & 65 deletions scales/svgs/cylinder_mm_d385_h429_1-50l_i1.svg

Large diffs are not rendered by default.

143 changes: 72 additions & 71 deletions scales/svgs/cylinder_mm_d385_h473_1-55l_i1.svg

Large diffs are not rendered by default.

131 changes: 66 additions & 65 deletions scales/svgs/cylinder_mm_d390_h419_1-50l_i1.svg

Large diffs are not rendered by default.

107 changes: 54 additions & 53 deletions scales/svgs/cylinder_mm_d394_h328_1-40l_i1.svg

Large diffs are not rendered by default.

143 changes: 72 additions & 71 deletions scales/svgs/cylinder_mm_d394_h451_1-55l_i1.svg

Large diffs are not rendered by default.

131 changes: 66 additions & 65 deletions scales/svgs/cylinder_mm_d395_h408_1-50l_i1.svg

Large diffs are not rendered by default.

155 changes: 78 additions & 77 deletions scales/svgs/cylinder_mm_d396_h487_1-60l_i1.svg

Large diffs are not rendered by default.

131 changes: 66 additions & 65 deletions scales/svgs/cylinder_mm_d397_h404_1-50l_i1.svg

Large diffs are not rendered by default.

143 changes: 72 additions & 71 deletions scales/svgs/cylinder_mm_d397_h444_1-55l_i1.svg

Large diffs are not rendered by default.

131 changes: 66 additions & 65 deletions scales/svgs/cylinder_mm_d398_h402_1-50l_i1.svg

Large diffs are not rendered by default.

107 changes: 54 additions & 53 deletions scales/svgs/cylinder_mm_d400_h318_1-40l_i1.svg

Large diffs are not rendered by default.

131 changes: 66 additions & 65 deletions scales/svgs/cylinder_mm_d400_h400_1-50l_i1.svg

Large diffs are not rendered by default.

155 changes: 78 additions & 77 deletions scales/svgs/cylinder_mm_d400_h477_1-60l_i1.svg

Large diffs are not rendered by default.

155 changes: 78 additions & 77 deletions scales/svgs/cylinder_mm_d403_h470_1-60l_i1.svg

Large diffs are not rendered by default.

167 changes: 84 additions & 83 deletions scales/svgs/cylinder_mm_d410_h495_1-80l_i1.svg

Large diffs are not rendered by default.

155 changes: 78 additions & 77 deletions scales/svgs/cylinder_mm_d415_h444_1-60l_i1.svg

Large diffs are not rendered by default.

131 changes: 66 additions & 65 deletions scales/svgs/cylinder_mm_d420_h361_1-50l_i1.svg

Large diffs are not rendered by default.

131 changes: 66 additions & 65 deletions scales/svgs/cylinder_mm_d425_h353_1-50l_i1.svg

Large diffs are not rendered by default.

167 changes: 84 additions & 83 deletions scales/svgs/cylinder_mm_d427_h454_1-65l_i1.svg

Large diffs are not rendered by default.

131 changes: 66 additions & 65 deletions scales/svgs/cylinder_mm_d440_h329_1-50l_i1.svg

Large diffs are not rendered by default.

179 changes: 90 additions & 89 deletions scales/svgs/cylinder_mm_d440_h460_1-70l_i1.svg

Large diffs are not rendered by default.

215 changes: 108 additions & 107 deletions scales/svgs/cylinder_mm_d440_h559_1-85l_i1.svg

Large diffs are not rendered by default.

131 changes: 66 additions & 65 deletions scales/svgs/cylinder_mm_d442_h326_1-50l_i1.svg

Large diffs are not rendered by default.

131 changes: 66 additions & 65 deletions scales/svgs/cylinder_mm_d445_h321_1-50l_i1.svg

Large diffs are not rendered by default.

167 changes: 84 additions & 83 deletions scales/svgs/cylinder_mm_d445_h418_1-65l_i1.svg

Large diffs are not rendered by default.

179 changes: 90 additions & 89 deletions scales/svgs/cylinder_mm_d445_h450_1-70l_i1.svg

Large diffs are not rendered by default.

179 changes: 90 additions & 89 deletions scales/svgs/cylinder_mm_d447_h446_1-70l_i1.svg

Large diffs are not rendered by default.

203 changes: 102 additions & 101 deletions scales/svgs/cylinder_mm_d448_h507_1-80l_i1.svg

Large diffs are not rendered by default.

155 changes: 78 additions & 77 deletions scales/svgs/cylinder_mm_d450_h375_1-60l_i1.svg

Large diffs are not rendered by default.

167 changes: 84 additions & 83 deletions scales/svgs/cylinder_mm_d450_h430_1-65l_i1.svg

Large diffs are not rendered by default.

179 changes: 90 additions & 89 deletions scales/svgs/cylinder_mm_d450_h440_1-70l_i1.svg

Large diffs are not rendered by default.

191 changes: 96 additions & 95 deletions scales/svgs/cylinder_mm_d450_h472_1-75l_i1.svg

Large diffs are not rendered by default.

203 changes: 102 additions & 101 deletions scales/svgs/cylinder_mm_d450_h503_1-80l_i1.svg

Large diffs are not rendered by default.

155 changes: 78 additions & 77 deletions scales/svgs/cylinder_mm_d455_h369_1-60l_i1.svg

Large diffs are not rendered by default.

155 changes: 78 additions & 77 deletions scales/svgs/cylinder_mm_d455_h431_1-60l_i1.svg

Large diffs are not rendered by default.

203 changes: 102 additions & 101 deletions scales/svgs/cylinder_mm_d455_h492_1-80l_i1.svg

Large diffs are not rendered by default.

155 changes: 78 additions & 77 deletions scales/svgs/cylinder_mm_d460_h361_1-60l_i1.svg

Large diffs are not rendered by default.

203 changes: 102 additions & 101 deletions scales/svgs/cylinder_mm_d460_h487_1-80l_i1.svg

Large diffs are not rendered by default.

155 changes: 78 additions & 77 deletions scales/svgs/cylinder_mm_d470_h346_1-60l_i1.svg

Large diffs are not rendered by default.

203 changes: 102 additions & 101 deletions scales/svgs/cylinder_mm_d470_h461_1-80l_i1.svg

Large diffs are not rendered by default.

203 changes: 102 additions & 101 deletions scales/svgs/cylinder_mm_d475_h508_1-80l_i1.svg

Large diffs are not rendered by default.

227 changes: 114 additions & 113 deletions scales/svgs/cylinder_mm_d477_h504_1-90l_i1.svg

Large diffs are not rendered by default.

227 changes: 114 additions & 113 deletions scales/svgs/cylinder_mm_d485_h487_1-90l_i1.svg

Large diffs are not rendered by default.

251 changes: 126 additions & 125 deletions scales/svgs/cylinder_mm_d490_h531_1-100l_i1.svg

Large diffs are not rendered by default.

227 changes: 114 additions & 113 deletions scales/svgs/cylinder_mm_d495_h468_1-90l_i1.svg

Large diffs are not rendered by default.

239 changes: 120 additions & 119 deletions scales/svgs/cylinder_mm_d495_h494_1-95l_i1.svg

Large diffs are not rendered by default.

239 changes: 120 additions & 119 deletions scales/svgs/cylinder_mm_d497_h490_1-95l_i1.svg

Large diffs are not rendered by default.

128 changes: 128 additions & 0 deletions scales/svgs/cylinder_mm_d500_h510_1-100l_i1.svg

Large diffs are not rendered by default.

131 changes: 66 additions & 65 deletions scales/svgs/cylinder_mm_d500_h510_2-100l_i2.svg

Large diffs are not rendered by default.

251 changes: 126 additions & 125 deletions scales/svgs/cylinder_mm_d505_h499_1-100l_i1.svg

Large diffs are not rendered by default.

251 changes: 126 additions & 125 deletions scales/svgs/cylinder_mm_d510_h490_1-100l_i1.svg

Large diffs are not rendered by default.

179 changes: 90 additions & 89 deletions scales/svgs/cylinder_mm_d545_h310_1-70l_i1.svg

Large diffs are not rendered by default.

59 changes: 59 additions & 0 deletions scales/svgs/cyliner_mm_d600_h600_1-170l_i5.svg

Large diffs are not rendered by default.

59 changes: 59 additions & 0 deletions scales/svgs/cyliner_mm_d600_h600_1-170l_i5_bigger.svg

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ private void CalculateGraduationMark(Dictionary<Volume, GraduationMark> results,
Position = (Length.From(setting.Indentation, LengthUnit), currentHeight * -1),
Text = PrepareText(setting, currentVolume, maxVolume),
Volume = currentVolume,
Font = setting.Font
Font = setting.Font,
ReferenceSetting = setting
};

results[currentVolume] = mark;
Expand Down Expand Up @@ -91,7 +92,7 @@ private Volume GetMaximumScaleVolume(Length diameter, Length height, Volume maxV
// use the maxVolume for even end of the scale
if (maxVolume.Equals(maximumVolumeByHeight, maxVolume / 100))
return maxVolume.ToUnit(VolumeUnit);

// limit to max volume if the volume by height would be more
if (maxVolume < maximumVolumeByHeight)
return maxVolume.ToUnit(VolumeUnit);
Expand Down
5 changes: 5 additions & 0 deletions src/dotnet-levelmeter/LevelMeter/GraduationMark.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,9 @@ public record GraduationMark
/// Font name or path to font file. Defines the font to write texts for the graduation mark.
/// </summary>
public required GraduationMarkSettings.FontSettings Font { get; init; }

/// <summary>
/// References the settings used to calculate this graduation mark
/// </summary>
public required GraduationMarkSettings ReferenceSetting { get; init; }
}
2 changes: 1 addition & 1 deletion src/dotnet-levelmeter/LevelMeter/GraduationMarkSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ internal void Validate()
{
if (Length <= 0)
throw new ArgumentOutOfRangeException(nameof(Length), Length, "Value must be greater than 0;");

if (Height <= 0)
throw new ArgumentOutOfRangeException(nameof(Height), Height, "Value must be greater than 0");
}
Expand Down
140 changes: 64 additions & 76 deletions src/dotnet-levelmeter/LevelMeter/SvgScalePainter.cs
Original file line number Diff line number Diff line change
@@ -1,132 +1,120 @@
using System.Collections.Concurrent;
using System.ComponentModel;
using System.Drawing;
using System.Text;
using System.Threading.Tasks.Sources;
using System.Xml;

using Papau.Levelmeter.SvgHelper;

using SkiaSharp;

using UnitsNet;
using UnitsNet.Units;

using VectSharp;
using VectSharp.SVG;

namespace Papau.Levelmeter.LevelMeter;

public class SvgScalePainter
{
private double _topTextOverflow = 0;
private double _bottomTextOverflow = 0;

public Task PaintAsync(GraduationMark[] graduationMarks, Stream outputStream, CancellationToken cancellationToken)
public async Task PaintAsync(GraduationMark[] graduationMarks, Stream outputStream, CancellationToken cancellationToken)
{
_topTextOverflow = 0;

if (!graduationMarks.Any())
return Task.CompletedTask;
return;

var svgPage = new Page(1, 1)
var svg = new SvgModel()
{
Background = Colours.White
Background = Color.White
};

var unit = LengthUnit.Millimeter;
foreach (var mark in graduationMarks.Reverse())
{
DrawGraduationMark(svgPage, mark);
DrawGraduationMark(svg, mark);
unit = mark.Length.Unit;
}

var padding = Length.FromMillimeters(5).ToUnit(unit).Value;
PaintCuttingRectangle(padding, graduationMarks, svgPage);

var svgDoc = svgPage.SaveAsSVG(SVGContextInterpreter.TextOptions.ConvertIntoPaths);
SetSvgDimensionsInXml(svgPage, unit, svgDoc);
svgDoc.Save(outputStream);
var padding = Length.FromMillimeters(5).ToUnit(unit).Value;
svg.Padding = new SizeF((float)padding, (float)padding);

return Task.CompletedTask;
await svg.SaveToStream(outputStream, unit, cancellationToken).ConfigureAwait(false);
}

private void PaintCuttingRectangle(double padding, GraduationMark[] graduationMarks, Page svgPage)
private readonly static ConcurrentDictionary<string, SKTypeface> FontCache = [];

private void DrawGraduationMark(SvgModel scale, GraduationMark mark)
{
svgPage.Crop();
var page = svgPage.Graphics.GetBounds();
// assume middle of the marker marks the spot. This helps avoiding differences in spacing due to different marker heights.
var markerPos = new PointF((float)mark.Position.X.Value, (float)(mark.Position.Y.Value - mark.Height.Value / 2));

var topMarker = graduationMarks.MinBy(m => m.Position.Y)!;
var topYBound = (_topTextOverflow + (topMarker.Height.Value / 2)) * -1;
var bottomMarker = graduationMarks.MaxBy(m => m.Position.Y)!;
var bottomYBound = _bottomTextOverflow;
scale.FillRectangle(markerPos, new SizeF((float)mark.Length.Value, (float)mark.Height.Value), Color.Black, $"mark_{mark.Volume.Value}");

// top left corner moved by padding to top and left
var pos = new Point(0 - padding, topYBound - padding);
if (!string.IsNullOrWhiteSpace(mark.Text))
{
var font = GetFont(mark);
var textPath = CreateTextPath(mark, font);
var textSize = new SizeF(textPath.Bounds.Size.Width, textPath.Bounds.Size.Height);
var textPosition = GetTextPosition(mark, markerPos, textSize, font);

var size = new Size(page.Size.Width + 2 * padding, page.Size.Height + bottomYBound + 2 * padding);
svgPage.Graphics.StrokeRectangle(pos, size, Colours.Red, 0.1);
scale.FillPath(textPath, textPosition, Color.Black);

svgPage.Crop();
// bounding box for debugging
// scale.StrokeRectangle(textPosition, textSize, Color.Green, 0.05f);
}
}

private static void SetSvgDimensionsInXml(Page page, LengthUnit unit, XmlDocument svgDoc)
private static SKPath CreateTextPath(GraduationMark mark, SKFont font)
{
var size = page.Graphics.GetBounds();

var widthAttribute = svgDoc.CreateAttribute("width");
widthAttribute.Value = $"{size.Size.Width}{Length.GetAbbreviation(unit)}";
var heightAttribute = svgDoc.CreateAttribute("height");
heightAttribute.Value = $"{size.Size.Height}{Length.GetAbbreviation(unit)}";
var rootAttributes = svgDoc.GetElementsByTagName("svg")[0]!.Attributes!;
rootAttributes.Append(widthAttribute);
rootAttributes.Append(heightAttribute);
}
using var textPath = font.GetTextPath(mark.Text);

private readonly static ConcurrentDictionary<string, FontFamily?> FontCache = [];
// Get the current bounds of the path
SKRect currentBounds = textPath.Bounds;

private void DrawGraduationMark(Page scale, GraduationMark mark)
{
// assume middle of the marker marks the spot. This helps avoiding differences in spacing due to different marker heights.
var markerPos = new Point(mark.Position.X.Value, mark.Position.Y.Value - mark.Height.Value / 2);
var markerSize = new Size(mark.Length.Value, mark.Height.Value);
scale.Graphics.FillRectangle(markerPos, markerSize, Colours.Black, "mark" + mark.Volume.ToString());
// Calculate the translation to move the top-left corner to (0, 0)
float translateX = -currentBounds.Left;
float translateY = -currentBounds.Top;

if (!string.IsNullOrWhiteSpace(mark.Text))
{
var font = GetFont(mark);
var textSize = font.MeasureText(mark.Text);
var textPosition = GetTextPosition(mark, markerPos, textSize);

_topTextOverflow = Math.Max(_topTextOverflow, markerPos.Y - textPosition.Y + (textSize.Height / 2));
_bottomTextOverflow = Math.Max(_bottomTextOverflow, markerPos.Y - textPosition.Y - (textSize.Height / 2));
// Create a transformation matrix for cropping
SKMatrix cropMatrix = SKMatrix.CreateTranslation(translateX, translateY);

scale.Graphics.FillText(textPosition, mark.Text, font, Colours.Black, TextBaselines.Middle, "text" + mark.Volume.ToString());
}
// Apply the transformation to the path
var croppedPath = new SKPath();
textPath.Transform(cropMatrix, croppedPath);
return croppedPath;
}

private static Point GetTextPosition(GraduationMark mark, Point markerPos, Size textSize)
private static PointF GetTextPosition(GraduationMark mark, PointF markerPos, SizeF textSize, SKFont font)
{
var fontX = mark.Position.X.Value + mark.Length.Value + mark.Font.OffsetX;

// the position of the text is calculated by the top left corner of the path.
// but we want to align the text by its baseline so we need to calculate the
// offset between the top and the baseline
var fontBaselineOffset = font.Metrics.StrikeoutPosition + font.Metrics.StrikeoutThickness / 2;
if (!fontBaselineOffset.HasValue)
fontBaselineOffset = (textSize.Height / 2) * -1; // fallback to half height of the path

// align in the middle of the marker
var fontY = markerPos.Y + mark.Height.Value / 2 + mark.Font.OffsetY;
var fontY = markerPos.Y + mark.Height.Value / 2 + mark.Font.OffsetY + fontBaselineOffset;

// change text alignment
fontX = ApplyAlignment(fontX, textSize, mark.Font.TextAlignment);

return new Point(fontX, fontY);
return new PointF((float)fontX, (float)fontY);
}

private static Font GetFont(GraduationMark mark)
private static SKFont GetFont(GraduationMark mark)
{
var fontFamily = FontCache.GetOrAdd(mark.Font.Family, f =>
{
var result = FontFamily.ResolveFontFamily(f);

if (result is null || result.TrueTypeFile is null)
throw new InvalidOperationException($"Font '{mark.Font}' not found or not a valid font!");
var fontFamily = FontCache.GetOrAdd(mark.Font.Family, f => SKTypeface.FromFile(mark.Font.Family));

return result;
});

var font = new Font(fontFamily, mark.Font.Size);
return font;
return new SKFont
{
Typeface = fontFamily,
Size = (float)mark.Font.Size,
Edging = SKFontEdging.Antialias
};
}

private static double ApplyAlignment(double xPos, Size textSize, GraduationMarkSettings.TextAlignment textAlignment)
private static double ApplyAlignment(double xPos, SizeF textSize, GraduationMarkSettings.TextAlignment textAlignment)
{
return textAlignment switch
{
Expand Down
Loading

0 comments on commit 16d772a

Please sign in to comment.