diff --git a/Resources/Image/Reader.cs b/Resources/Image/Reader.cs index d71290a..97dc1af 100644 --- a/Resources/Image/Reader.cs +++ b/Resources/Image/Reader.cs @@ -118,11 +118,11 @@ namespace Resources.Image var bitReader = new BitReader(rowBytes); for (var x = 0; x < _width; x++) { - var firstByte = bitReader.ReadByte(); - var secondByte = bitReader.ReadByte(); - var b = ((secondByte >> 3) & 0x1f) << 3; - var g = ((secondByte & (0x07 << 2)) | (firstByte & (0x40 >> 5))) << 3; - var r = (firstByte & 0x1f) << 3; + var firstByte = (int)bitReader.ReadByte(); + var secondByte = (int)bitReader.ReadByte(); + var b = (byte)(secondByte >> 3 & 0x1f) << 3; + var g = (byte)(((firstByte >> 5) & 0x7) | ((secondByte & 0x07) << 3)) << 2; + var r = (byte)(firstByte & 0x1f) << 3; var color = Color.FromArgb(0xff, r, g, b); context.SetPixel(x, y, color); } diff --git a/WatchFace.Parser/Elements/Activity.cs b/WatchFace.Parser/Elements/Activity.cs index 79d4cc8..6f093ae 100644 --- a/WatchFace.Parser/Elements/Activity.cs +++ b/WatchFace.Parser/Elements/Activity.cs @@ -19,6 +19,9 @@ namespace WatchFace.Parser.Elements public CompositeNumber Pulse { get; set; } [ParameterId(5)] - public FormattedNumber Distance { get; set; } + public DistanceNumber Distance { get; set; } + + [ParameterId(6)] + public StepsWithGoalNumber StepsWithGoal { get; set; } } } \ No newline at end of file diff --git a/WatchFace.Parser/Elements/ActivityElements/FormattedNumber.cs b/WatchFace.Parser/Elements/ActivityElements/DistanceNumber.cs similarity index 92% rename from WatchFace.Parser/Elements/ActivityElements/FormattedNumber.cs rename to WatchFace.Parser/Elements/ActivityElements/DistanceNumber.cs index 9207003..da3f4ea 100644 --- a/WatchFace.Parser/Elements/ActivityElements/FormattedNumber.cs +++ b/WatchFace.Parser/Elements/ActivityElements/DistanceNumber.cs @@ -3,7 +3,7 @@ using WatchFace.Parser.Elements.BasicElements; namespace WatchFace.Parser.Elements.ActivityElements { - public class FormattedNumber + public class DistanceNumber { [ParameterId(1)] public Number Number { get; set; } diff --git a/WatchFace.Parser/Elements/ActivityElements/StepsWithGoalNumber.cs b/WatchFace.Parser/Elements/ActivityElements/StepsWithGoalNumber.cs new file mode 100644 index 0000000..ae72d92 --- /dev/null +++ b/WatchFace.Parser/Elements/ActivityElements/StepsWithGoalNumber.cs @@ -0,0 +1,15 @@ +using WatchFace.Parser.Attributes; +using WatchFace.Parser.Elements.BasicElements; + +namespace WatchFace.Parser.Elements.ActivityElements +{ + public class StepsWithGoalNumber + { + [ParameterId(1)] + public Number Number { get; set; } + + [ParameterId(2)] + [ParameterImageIndex] + public long? DelimiterImageIndex { get; set; } + } +} \ No newline at end of file diff --git a/WatchFace.Parser/Elements/Battery.cs b/WatchFace.Parser/Elements/Battery.cs index 8f9ece9..73728b9 100644 --- a/WatchFace.Parser/Elements/Battery.cs +++ b/WatchFace.Parser/Elements/Battery.cs @@ -1,12 +1,13 @@ using WatchFace.Parser.Attributes; using WatchFace.Parser.Elements.BasicElements; +using WatchFace.Parser.Elements.BatteryElements; namespace WatchFace.Parser.Elements { public class Battery { [ParameterId(1)] - public CompositeNumber Text { get; set; } + public BatteryNumber Text { get; set; } [ParameterId(2)] public ImageSet Icon { get; set; } diff --git a/WatchFace.Parser/Elements/BatteryElements/BatteryNumber.cs b/WatchFace.Parser/Elements/BatteryElements/BatteryNumber.cs new file mode 100644 index 0000000..ee3b377 --- /dev/null +++ b/WatchFace.Parser/Elements/BatteryElements/BatteryNumber.cs @@ -0,0 +1,23 @@ +using WatchFace.Parser.Attributes; +using WatchFace.Parser.Elements.BasicElements; + +namespace WatchFace.Parser.Elements.BatteryElements +{ + public class BatteryNumber + { + [ParameterId(1)] + public Number Number { get; set; } + + [ParameterId(2)] + [ParameterImageIndex] + public CircleScale CircleScale { get; set; } + + [ParameterId(3)] + [ParameterImageIndex] + public long? PrefixImageIndex { get; set; } + + [ParameterId(4)] + [ParameterImageIndex] + public long? SuffixImageIndex { get; set; } + } +} \ No newline at end of file diff --git a/WatchFace.Parser/Models/Elements/Activity/StepsWithGoalElement.cs b/WatchFace.Parser/Models/Elements/Activity/StepsWithGoalElement.cs new file mode 100644 index 0000000..d721b28 --- /dev/null +++ b/WatchFace.Parser/Models/Elements/Activity/StepsWithGoalElement.cs @@ -0,0 +1,40 @@ +using System.Collections.Generic; +using System.Drawing; +using WatchFace.Parser.Helpers; +using WatchFace.Parser.Interfaces; + +namespace WatchFace.Parser.Models.Elements.Activity +{ + public class StepsWithGoalElement : CompositeElement, IDrawable + { + public StepsWithGoalElement(Parameter parameter, Element parent, string name = null) : + base(parameter, parent, name) { } + + public NumberElement Number { get; set; } + public long DelimiterImageIndex { get; set; } + + public void Draw(Graphics drawer, Bitmap[] resources, WatchState state) + { + var images = new List(); + images.AddRange(Number.GetImagesForNumber(resources, state.Steps)); + images.Add(resources[DelimiterImageIndex]); + images.AddRange(Number.GetImagesForNumber(resources, state.Goal)); + DrawerHelper.DrawImages(drawer, images, (int)Number.Spacing, Number.Alignment, Number.GetBox()); + } + + protected override Element CreateChildForParameter(Parameter parameter) + { + switch (parameter.Id) + { + case 1: + Number = new NumberElement(parameter, this, nameof(Number)); + return Number; + case 2: + DelimiterImageIndex = parameter.Value; + return new ValueElement(parameter, this, nameof(DelimiterImageIndex)); + default: + return base.CreateChildForParameter(parameter); + } + } + } +} \ No newline at end of file diff --git a/WatchFace.Parser/Models/Elements/ActivityElement.cs b/WatchFace.Parser/Models/Elements/ActivityElement.cs index c2db10a..dc3028b 100644 --- a/WatchFace.Parser/Models/Elements/ActivityElement.cs +++ b/WatchFace.Parser/Models/Elements/ActivityElement.cs @@ -1,4 +1,6 @@ -namespace WatchFace.Parser.Models.Elements +using WatchFace.Parser.Models.Elements.Activity; + +namespace WatchFace.Parser.Models.Elements { public class ActivityElement : ContainerElement { @@ -10,6 +12,7 @@ public CaloriesElement Calories { get; set; } public PulseElement Pulse { get; set; } public DistanceElement Distance { get; set; } + public StepsWithGoalElement StepsWithGoal { get; set; } protected override Element CreateChildForParameter(Parameter parameter) { @@ -30,6 +33,9 @@ case 5: Distance = new DistanceElement(parameter, this); return Distance; + case 6: + StepsWithGoal = new StepsWithGoalElement(parameter, this); + return StepsWithGoal; default: return base.CreateChildForParameter(parameter); } diff --git a/WatchFace.Parser/Models/Elements/AnalogDialBitmapElement.cs b/WatchFace.Parser/Models/Elements/AnalogDialBitmapElement.cs index 50c6dbf..0aad89f 100644 --- a/WatchFace.Parser/Models/Elements/AnalogDialBitmapElement.cs +++ b/WatchFace.Parser/Models/Elements/AnalogDialBitmapElement.cs @@ -1,6 +1,4 @@ -using System; -using System.Drawing; -using System.Drawing.Imaging; +using System.Drawing; using BumpKit; using WatchFace.Parser.Interfaces; @@ -32,22 +30,23 @@ namespace WatchFace.Parser.Models.Elements { var angle = DegreeFromValues(state.Time.Minute, 60); var hoursImage = RotateImage( - resources[Minutes.ImageIndex], new Point((int)Minutes.X, (int)Minutes.Y), angle + resources[Minutes.ImageIndex], new Point((int) Minutes.X, (int) Minutes.Y), angle ); - drawer.DrawImage(hoursImage, new Point((int)RedrawArea.X, (int)RedrawArea.Y)); + drawer.DrawImage(hoursImage, new Point((int) RedrawArea.X, (int) RedrawArea.Y)); } if (Seconds != null) { var angle = DegreeFromValues(state.Time.Second, 60); var hoursImage = RotateImage( - resources[Seconds.ImageIndex], new Point((int)Seconds.X, (int)Seconds.Y), angle + resources[Seconds.ImageIndex], new Point((int) Seconds.X, (int) Seconds.Y), angle ); - drawer.DrawImage(hoursImage, new Point((int)RedrawArea.X, (int)RedrawArea.Y)); + drawer.DrawImage(hoursImage, new Point((int) RedrawArea.X, (int) RedrawArea.Y)); } if (CenterImage != null) - drawer.DrawImage(resources[CenterImage.ImageIndex], new Point((int)CenterImage.X, (int)CenterImage.Y)); + drawer.DrawImage(resources[CenterImage.ImageIndex], + new Point((int) CenterImage.X, (int) CenterImage.Y)); } private static double DegreeFromValues(double value, double total) @@ -55,24 +54,19 @@ namespace WatchFace.Parser.Models.Elements return value * 360 / total - 90; } - private Bitmap RotateImage(Image image, Point ImageCoords, double degrees) + private Bitmap RotateImage(Image image, Point imageCoords, double degrees) { - var radians = degrees / 180 * Math.PI; - var sin = Math.Sin(radians); - var cos = Math.Cos(radians); - var drawBox = RedrawArea.GetBox(); var newImage = new Bitmap(drawBox.Width, drawBox.Height); using (var graphics = Graphics.FromImage(newImage)) { - graphics.DrawImage(image, new Point(ImageCoords.X - drawBox.X, ImageCoords.Y - drawBox.Y)); + graphics.DrawImage(image, new Point(imageCoords.X - drawBox.X, imageCoords.Y - drawBox.Y)); } while (degrees < 0) degrees += 360; while (degrees > 360) degrees -= 360; var rotated = newImage.Rotate(degrees); - rotated.Save("tmp.png"); - return rotated as Bitmap; + return rotated as Bitmap; } protected override Element CreateChildForParameter(Parameter parameter) diff --git a/WatchFace.Parser/Models/Elements/Battery/BatteryNumberElement.cs b/WatchFace.Parser/Models/Elements/Battery/BatteryNumberElement.cs index fe635bc..a06d812 100644 --- a/WatchFace.Parser/Models/Elements/Battery/BatteryNumberElement.cs +++ b/WatchFace.Parser/Models/Elements/Battery/BatteryNumberElement.cs @@ -1,16 +1,55 @@ -using System.Drawing; +using System.Collections.Generic; +using System.Drawing; +using WatchFace.Parser.Helpers; using WatchFace.Parser.Interfaces; +using WatchFace.Parser.Models.Elements.Common; namespace WatchFace.Parser.Models.Elements.Battery { - public class BatteryNumberElement : CompositeNumberElement, IDrawable + public class BatteryNumberElement : CompositeElement, IDrawable { public BatteryNumberElement(Parameter parameter, Element parent, string name = null) : base(parameter, parent, name) { } + + public NumberElement Number { get; set; } + public CircularProgressElement CircularProgress { get; set; } + public long? PrefixImageIndex { get; set; } + public long? SuffixImageIndex { get; set; } + public void Draw(Graphics drawer, Bitmap[] resources, WatchState state) { - Draw(drawer, resources, state.BatteryLevel); + var images = new List(); + if (PrefixImageIndex != null) + images.Add(resources[PrefixImageIndex.Value]); + images.AddRange(Number.GetImagesForNumber(resources, state.BatteryLevel)); + if (SuffixImageIndex != null) + images.Add(resources[SuffixImageIndex.Value]); + + DrawerHelper.DrawImages(drawer, images, (int)Number.Spacing, Number.Alignment, Number.GetBox()); + + CircularProgress?.Draw(drawer, resources, state); + } + + protected override Element CreateChildForParameter(Parameter parameter) + { + switch (parameter.Id) + { + case 1: + Number = new NumberElement(parameter, this, nameof(Number)); + return Number; + case 2: + CircularProgress = new CircularBatteryProgressElement(parameter, this); + return CircularProgress; + case 3: + PrefixImageIndex = parameter.Value; + return new ValueElement(parameter, this, nameof(PrefixImageIndex)); + case 4: + SuffixImageIndex = parameter.Value; + return new ValueElement(parameter, this, nameof(SuffixImageIndex)); + default: + return base.CreateChildForParameter(parameter); + } } } } \ No newline at end of file diff --git a/WatchFace.Parser/Models/Elements/Battery/CircularBatteryProgressElement.cs b/WatchFace.Parser/Models/Elements/Battery/CircularBatteryProgressElement.cs new file mode 100644 index 0000000..faade64 --- /dev/null +++ b/WatchFace.Parser/Models/Elements/Battery/CircularBatteryProgressElement.cs @@ -0,0 +1,16 @@ +using System.Drawing; +using WatchFace.Parser.Models.Elements.Common; + +namespace WatchFace.Parser.Models.Elements.Battery +{ + public class CircularBatteryProgressElement : CircularProgressElement + { + public CircularBatteryProgressElement(Parameter parameter, Element parent, string name = null) : + base(parameter, parent, name) { } + + public override void Draw(Graphics drawer, Bitmap[] resources, WatchState state) + { + Draw(drawer, resources, state.BatteryLevel, 100); + } + } +} \ No newline at end of file diff --git a/WatchFace.Parser/Models/Elements/Common/CircularProgressElement.cs b/WatchFace.Parser/Models/Elements/Common/CircularProgressElement.cs index 85072ce..f8e950f 100644 --- a/WatchFace.Parser/Models/Elements/Common/CircularProgressElement.cs +++ b/WatchFace.Parser/Models/Elements/Common/CircularProgressElement.cs @@ -1,7 +1,7 @@ using System.Drawing; using WatchFace.Parser.Interfaces; -namespace WatchFace.Parser.Models.Elements.GoalProgress +namespace WatchFace.Parser.Models.Elements.Common { public abstract class CircularProgressElement : CoordinatesElement, IDrawable { @@ -19,7 +19,8 @@ namespace WatchFace.Parser.Models.Elements.GoalProgress public void Draw(Graphics drawer, Bitmap[] resources, int value, int total) { - var sectorAngle = (EndAngle - StartAngle) * value / total; + var part = value >= total ? 1.0f : (float) value / total; + var sectorAngle = (EndAngle - StartAngle) * part; var pen = new Pen(Color, Width); var rect = new Rectangle((int) (X - RadiusX), (int) (Y - RadiusY), (int) (RadiusX * 2), (int) (RadiusY * 2)); diff --git a/WatchFace.Parser/Models/Elements/GoalProgress/CircularGoalProgressElement.cs b/WatchFace.Parser/Models/Elements/GoalProgress/CircularGoalProgressElement.cs index 513ee2e..77f3d5d 100644 --- a/WatchFace.Parser/Models/Elements/GoalProgress/CircularGoalProgressElement.cs +++ b/WatchFace.Parser/Models/Elements/GoalProgress/CircularGoalProgressElement.cs @@ -1,4 +1,5 @@ using System.Drawing; +using WatchFace.Parser.Models.Elements.Common; namespace WatchFace.Parser.Models.Elements.GoalProgress { diff --git a/WatchFace.Parser/WatchFace.Parser.csproj b/WatchFace.Parser/WatchFace.Parser.csproj index e820a6d..e01541d 100644 --- a/WatchFace.Parser/WatchFace.Parser.csproj +++ b/WatchFace.Parser/WatchFace.Parser.csproj @@ -51,8 +51,9 @@ + - + @@ -64,6 +65,7 @@ + @@ -91,6 +93,7 @@ + @@ -101,6 +104,7 @@ +