Beispiel #1
0
 public static double Calc(string formula)
 {
     try
     {
         if (string.IsNullOrEmpty(formula))
         {
             return(0);
         }
         var    resolvedFormula = FacerTags.ResolveTags(formula).Replace(" ", string.Empty);
         double dblVal;
         if (double.TryParse(resolvedFormula, out dblVal))
         {
             return(dblVal);
         }
         else if (!formula.Contains('#') && !formula.Contains('$'))
         {
             throw new Exception("Not Numeric");
         }
         //convert formula to c#
         resolvedFormula = ConditionalRegex.Replace(resolvedFormula, "($1)");
         resolvedFormula = resolvedFormula
                           .Replace("=", "==")
                           .Replace('[', '(')
                           .Replace(']', ')')
                           .Replace(">==", ">=")
                           .Replace("<==", "<=")
                           .Replace("!==", "!=");
         var expression = new CompiledExpression(resolvedFormula);
         var result     = expression.Eval();
         return(Convert.ToDouble(result));
     }
     catch
     {
         throw new Exception("Couldn't parse '" + Convert.ToString(formula) + "'");
     }
 }
Beispiel #2
0
        public static Bitmap Render(FacerWatchface watchface, EWatchType watchtype, EWatchfaceOverlay overlay, bool checkForErrors, List <WatchfaceRendererError> errors, bool showSelected = true)
        {
            Size dimensions;

            if (!WatchType.Dimensions.TryGetValue(watchtype, out dimensions))
            {
                dimensions = new Size(320, 320); //unknown
            }
            var bmp = new Bitmap(dimensions.Width, dimensions.Height);

            using (var g = Graphics.FromImage(bmp))
            {
                g.InterpolationMode  = InterpolationMode.HighQualityBicubic;
                g.TextRenderingHint  = TextRenderingHint.AntiAlias;
                g.SmoothingMode      = SmoothingMode.HighQuality;
                g.TextContrast       = 1;
                g.PixelOffsetMode    = PixelOffsetMode.None;
                g.PageUnit           = GraphicsUnit.Pixel;
                g.CompositingQuality = CompositingQuality.HighQuality;

                g.Clear(Color.Black);

                var    outRect           = Rectangle.Empty;
                var    selectedRectangle = Rectangle.Empty;
                Matrix selectedTransform = null;

                foreach (var layer in watchface.Layers)
                {
                    try
                    {
                        if (Properties.Settings.Default.LowPowerMode && !layer.low_power)
                        {
                            continue;                                                               //don't show on dimmed
                        }
                        var opacity = (float)ExpressionCalculator.Calc(layer.opacity);
                        if (opacity == 0)
                        {
                            continue;
                        }

                        var x = (float)ExpressionCalculator.Calc(layer.x);
                        var y = (float)ExpressionCalculator.Calc(layer.y);

                        var rotation = layer.r != "0" ? (float)ExpressionCalculator.Calc(layer.r) : 0.0F;

                        g.TranslateTransform(x, y);
                        g.RotateTransform(rotation);

                        var alp = new PointF(0, 0);;
                        int width, height;

                        if (layer.type == "image")
                        {
                            var imageAtt = new ImageAttributes();

                            if (opacity < 100 || (layer.is_tinted ?? false))
                            {
                                var tint_color = (layer.is_tinted ?? false) && layer.tint_color != null?Color.FromArgb(layer.tint_color.Value) : Color.Empty;

                                const float intensity = 0.3f;

                                var colorMatrix = new ColorMatrix();
                                if (opacity < 100)
                                {
                                    colorMatrix.Matrix33 = opacity / 100f;
                                }
                                if (tint_color != Color.Empty)
                                {
                                    colorMatrix.Matrix40 = tint_color.R / 255 * intensity;
                                    colorMatrix.Matrix41 = tint_color.G / 255 * intensity;
                                    colorMatrix.Matrix42 = tint_color.B / 255 * intensity;
                                }
                                imageAtt.SetColorMatrix(colorMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
                            }

                            width  = (int)ExpressionCalculator.Calc(layer.width);
                            height = (int)ExpressionCalculator.Calc(layer.height);
                            alp    = AlignedPoint(width, height, layer.alignment.Value);

                            Image img;
                            if (!watchface.Images.TryGetValue(layer.hash, out img))
                            {
                                AppendError(checkForErrors, errors,
                                            WatchfaceRendererErrorSeverity.Error,
                                            layer.GetIdentifier(),
                                            "The image \"" + layer.hash + "\" was not found in the images folder.");
                                img = ImageNotFound;
                            }
                            outRect = new Rectangle((int)alp.X, (int)alp.Y, width, height);
                            g.DrawImage(img, outRect, 0, 0, img.Width, img.Height, GraphicsUnit.Pixel, imageAtt);
                        }
                        else if (layer.type == "text")
                        {
                            var colorToUse = Properties.Settings.Default.LowPowerMode ? layer.low_power_color : layer.color;
                            var foreColor  = Color.FromArgb(((int)ExpressionCalculator.Calc(colorToUse) & 0xFFFFFF) + ((int)(opacity / 100f * 255) << 24));
                            var fontSize   = DpToPx((float)ExpressionCalculator.Calc(layer.size));

                            Font layerFont;
                            if (layer.font_family == (int)FacerFont.Custom)
                            {
                                FacerCustomFont customFont;
                                if (!watchface.CustomFonts.TryGetValue(layer.font_hash, out customFont))
                                {
                                    AppendError(checkForErrors, errors, WatchfaceRendererErrorSeverity.Error,
                                                layer.GetIdentifier(),
                                                "The font \"" + layer.hash + "\" was not found in the fonts folder.");
                                    var fontPair = FacerFontConfig[FacerFont.Roboto];
                                    layerFont = new Font(fontPair.Item1.Families[0], fontSize, fontPair.Item2, GraphicsUnit.Point);
                                }
                                else
                                {
                                    var fontStyle = (layer.bold ?? false) && (layer.italic ?? false) ? FontStyle.Bold | FontStyle.Italic :
                                                    ((layer.bold ?? false) && !(layer.italic ?? false) ? FontStyle.Bold :
                                                     (!(layer.bold ?? false) && (layer.italic ?? false) ? FontStyle.Italic : FontStyle.Regular));
                                    layerFont = new Font(customFont.FontFamily, fontSize, customFont.GetAvailableFontStyle(fontStyle));
                                }
                            }
                            else
                            {
                                var facerFontKey = layer.font_family + 100 * (layer.bold ?? false ? 1 : 0) + 200 * (layer.italic ?? false ? 1 : 0);
                                var fontPair     = FacerFontConfig[(FacerFont)facerFontKey];
                                layerFont = new Font(fontPair.Item1.Families[0], fontSize, fontPair.Item2, GraphicsUnit.Point);
                            }

                            var resolvedText = FacerTags.ResolveTags(layer.text)
                                               .Replace("\n", string.Empty)
                                               .Replace("\x10", string.Empty).Replace("\x13", string.Empty); //remove new lines

                            if (layer.transform == (int)FacerTextTransform.AllUppercase)
                            {
                                resolvedText = resolvedText.ToUpper();
                            }
                            else if (layer.transform == (int)FacerTextTransform.AllLowercase)
                            {
                                resolvedText = resolvedText.ToLower();
                            }

                            var textBrush  = new SolidBrush(foreColor);
                            var textAlign  = (FacerTextAlignment)layer.alignment.Value;
                            var textFormat = StringFormat.GenericTypographic; //ToStringFormat(textAlign);
                            textFormat.LineAlignment = StringAlignment.Far;
                            textFormat.Trimming      = StringTrimming.None;
                            textFormat.FormatFlags   = StringFormatFlags.NoWrap;

                            var measurements     = TextRenderer.MeasureText(g, resolvedText, layerFont, bmp.Size, TextFormatFlags.Top | TextFormatFlags.NoClipping | TextFormatFlags.NoPadding | TextFormatFlags.SingleLine);
                            var drawMeasurements = g.MeasureString(resolvedText, layerFont, bmp.Width, textFormat);
                            width  = measurements.Width;
                            height = measurements.Height;

                            var xOffset = textAlign == FacerTextAlignment.Left ? 0 :
                                          textAlign == FacerTextAlignment.Center ? width / 2 :
                                          width;

                            var baselineOffset = layerFont.SizeInPoints / layerFont.FontFamily.GetEmHeight(layerFont.Style) * layerFont.FontFamily.GetCellAscent(layerFont.Style);
                            var yOffset        = (int)(g.DpiY / 72f * baselineOffset);

                            var textPoint = new PointF(-(int)(drawMeasurements.Width - measurements.Width) - xOffset, height - yOffset);
                            g.DrawString(resolvedText, layerFont, textBrush, textPoint, textFormat);

                            outRect = new Rectangle((int)textPoint.X, (int)textPoint.Y - height, width, height);
                        }
                        else if (layer.type == "shape")
                        {
                            var   foreColor    = Color.FromArgb(((int)ExpressionCalculator.Calc(layer.color) & 0xFFFFFF) + ((int)(opacity / 100f * 255) << 24));
                            var   radius       = string.IsNullOrEmpty(layer.radius) ? 0 : (float)ExpressionCalculator.Calc(layer.radius);
                            var   shapeOptions = layer.shape_opt == ((int)FacerShapeOptions.Stroke).ToString(CultureInfo.InvariantCulture) ? FacerShapeOptions.Stroke : FacerShapeOptions.Fill;
                            var   strokeSize   = (float)ExpressionCalculator.Calc(layer.stroke_size) / 2;
                            Pen   penToUse     = shapeOptions == FacerShapeOptions.Stroke ? new Pen(foreColor, strokeSize) : null;
                            Brush brushToUse   = shapeOptions == FacerShapeOptions.Fill ? new SolidBrush(foreColor) : null;

                            switch (layer.shape_type)
                            {
                            case (int)FacerShapeType.Circle:
                                outRect = new Rectangle((int)(-radius), (int)(-radius), (int)(2 * radius), (int)(2 * radius));
                                if (shapeOptions == FacerShapeOptions.Stroke)
                                {
                                    g.DrawEllipse(penToUse, outRect);
                                    outRect.Inflate((int)strokeSize, (int)strokeSize);
                                    outRect.Offset((int)(-strokeSize / 2f + 0.5f), (int)(-strokeSize / 2f + 0.5f));
                                }
                                else
                                {
                                    g.FillEllipse(brushToUse, outRect);
                                }
                                break;

                            case (int)FacerShapeType.Line:
                            case (int)FacerShapeType.Square:
                                width  = (int)ExpressionCalculator.Calc(layer.width);
                                height = (int)ExpressionCalculator.Calc(layer.height);

                                outRect = new Rectangle(0, 0, width, height);
                                if (shapeOptions == FacerShapeOptions.Stroke)
                                {
                                    g.DrawRectangle(penToUse, outRect);
                                }
                                else
                                {
                                    g.FillRectangle(brushToUse, outRect);
                                }
                                break;

                            case (int)FacerShapeType.Triangle:
                            case (int)FacerShapeType.Polygon:
                                outRect = new Rectangle((int)(-radius), (int)(-radius), (int)(2 * radius), (int)(2 * radius));
                                var polyN      = layer.shape_type == (int)FacerShapeType.Triangle ? 3 : (int)ExpressionCalculator.Calc(layer.sides);
                                var polyPoints = new Point[polyN];
                                for (var i = 0; i < polyN; i++)
                                {
                                    polyPoints[i] = new Point(
                                        (int)(radius * Math.Cos(2 * Math.PI * i / polyN)),
                                        (int)(radius * Math.Sin(2 * Math.PI * i / polyN)));
                                }
                                if (shapeOptions == FacerShapeOptions.Stroke)
                                {
                                    g.DrawPolygon(penToUse, polyPoints);
                                    outRect.Inflate((int)strokeSize, (int)strokeSize);
                                    outRect.Offset((int)(-strokeSize / 2f + 0.5f), (int)(-strokeSize / 2f + 0.5f));
                                }
                                else
                                {
                                    g.FillPolygon(brushToUse, polyPoints);
                                }
                                break;
                            }
                        }

                        if (layer == watchface.SelectedLayer)
                        {
                            selectedRectangle = outRect;
                            selectedTransform = g.Transform;
                        }

                        g.ResetTransform();
                    }
                    catch (NullReferenceException)
                    {
                        AppendError(checkForErrors, errors, WatchfaceRendererErrorSeverity.Error,
                                    layer.GetIdentifier(),
                                    "General Error"
                                    );
                    }
                    catch (Exception ex)
                    {
                        AppendError(checkForErrors, errors, WatchfaceRendererErrorSeverity.Error,
                                    layer.GetIdentifier(),
                                    ex.Message
                                    );
                    }
                }

                g.ResetTransform();

                if (showSelected && selectedRectangle != Rectangle.Empty)
                {
                    g.Transform = selectedTransform;
                    g.DrawXorRectangle(bmp, selectedRectangle);
                    g.ResetTransform();
                }

                if (overlay.HasFlag(EWatchfaceOverlay.Card))
                {
                    var card = Properties.Resources.TestCard;
                    g.DrawImage(card, 0, 0, dimensions.Width, dimensions.Height);
                }
                if (overlay.HasFlag(EWatchfaceOverlay.WearIcons))
                {
                    var icons = Properties.Resources.TestWearStatus;
                    g.DrawImage(icons, dimensions.Width / 2f - icons.Width / 2f, 0.05f * dimensions.Height,
                                icons.Width * dimensions.Width / 320f, icons.Height * dimensions.Height / 320f);
                }
                Bitmap mask;
                if (WatchType.Masks.TryGetValue(watchtype, out mask))
                {
                    CopyChannel(mask, bmp, ChannelARGB.Alpha, ChannelARGB.Alpha);
                }
            }



            return(bmp);
        }