Лучший способ получить эффект свечения Windows Phone 7 - PullRequest
8 голосов
/ 15 сентября 2010

Я возился с Windows Phone 7 SDK и пытаюсь сделать экран похожим на старый цифровой дисплей.Прямо сейчас я пытаюсь понять, как заставить текст «светиться», как один из тех крутых цифровых часов.Такого рода вещи я бы хотел использовать для шейдеров, но кажется, что шейдеры отключены для использования в ОС Windows Phone 7.Есть идеи?Чтобы быть более конкретным, я хочу, чтобы текст выглядел так, как если бы он был источником света, и чтобы цвет немного «выбивался» из фактического шрифта.

Ответы [ 3 ]

12 голосов
/ 26 марта 2011

Я бы сказал, что выбор между использованием изображения в качестве шрифта или размытием с помощью WriteableBitmap.

Использование готового изображения шрифта позволяет сделать буквы сложными, как вы хотите, и должны хорошо работать. SpriteFont2 удобен, так как он может генерировать SpriteSheet с такими эффектами, как свечение, штрих, тень и экспортировать XML-файл, содержащий позиции букв. Добавьте сгенерированные файлы png и xml в свое решение и измените действие Build на содержимое, а также проверьте, что вы ссылались на System.Xml.Linq.

Затем можно использовать следующий класс.

public static class BitmapFont
{
    private class FontInfo
    {
        public FontInfo(WriteableBitmap image, Dictionary<char, Rect> metrics)
        {
            this.Image = image;
            this.Metrics = metrics;
        }
        public WriteableBitmap Image { get; private set; }
        public Dictionary<char, Rect> Metrics { get; private set; }
    }

    private static Dictionary<string, FontInfo> fonts = new Dictionary<string, FontInfo>();
    public static void RegisterFont(string fontFile, string fontMetricsFile)
    {
        string name = System.IO.Path.GetFileNameWithoutExtension(fontFile);
        BitmapImage image = new BitmapImage();

        image.SetSource(App.GetResourceStream(new Uri(fontFile,UriKind.Relative)).Stream);
        var metrics = XDocument.Load(fontMetricsFile);
        var dict = (from c in metrics.Root.Elements()
                    let key = (char)((int)c.Attribute("key"))
                    let rect = new Rect((int)c.Element("x"), (int)c.Element("y"), (int)c.Element("width"), (int)c.Element("height"))
                    select new { Char = key, Metrics = rect }).ToDictionary(x => x.Char, x => x.Metrics);

        fonts.Add(name,new FontInfo(new WriteableBitmap(image),dict));
    }

    public static WriteableBitmap DrawFont(string text, string fontName)
    {
        var font = fonts[fontName];

        var letters = text.Select(x => font.Metrics[x]).ToArray();
        var height = (int)letters.Max(x => x.Height);
        var width = (int)letters.Sum(x => x.Width);

        WriteableBitmap bmp = new WriteableBitmap(width, height);

        int[] source = font.Image.Pixels, dest = bmp.Pixels;
        int sourceWidth = font.Image.PixelWidth;
        int destX = 0;
        foreach (var letter in letters)
        {
            for (int sourceY = (int)letter.Y, destY = 0; destY < letter.Height; sourceY++, destY++)
            {
                Array.Copy(source, (sourceY * sourceWidth) + (int)letter.X, dest, (destY * width) + destX, (int)letter.Width);
            }
            destX += (int)letter.Width;
        }

        return bmp;
    }

    public static Rectangle[] GetElements(string text, string fontName)
    {
        var font = fonts[fontName];

        return (from c in text
                let r = font.Metrics[c]
                select new Rectangle
                {
                    Width = r.Width,
                    Height = r.Height,

                    Fill = new ImageBrush { 
                        ImageSource = font.Image, 
                        AlignmentX=AlignmentX.Left,
                        AlignmentY=AlignmentY.Top,
                        Transform = new TranslateTransform { X = -r.X, Y = -r.Y },
                        Stretch=Stretch.None                        
                    },
                }).ToArray();
    }
}

Использование

//Register the font once.
BitmapFont.RegisterFont("Font.png", "Metrics.xml");

//Draws the text to a new bitmap, font name is image name without extension.
image.Source = BitmapFont.DrawFont(DateTime.Now.ToLongTimeString(), "Font");

//Alternatively put these elements in a horizontal StackPanel, or ItemsControl
//This doesn't create any new bitmaps and should be more efficient.
//You could alter the method to transform each letter too.
BitmapFont.GetElements(DateTime.Now.ToLongTimeString(), "Font");

Если вы хотите размыть, посмотрите реализацию BoxBlur здесь или используйте WriteableBitmapEx.Convolute .

0 голосов
/ 26 марта 2011
0 голосов
/ 28 ноября 2010

Вы должны сделать копию TextBlock, которому хотите дать свечение. Свяжите свойство text нового элемента со свойством text исходного элемента (используя привязку ElementName). Сделайте то же самое для местоположения / высоты / ширины и т. Д. Или любого другого свойства, которое, по вашему мнению, изменится в исходном элементе. Установите прозрачность для нового элемента, а также эффект размытия. Это даст вам крутой эффект свечения, который вы хотите.

...