WPF TileBrush и DrawingContext.DrawRectangle - относительно верхнего левого угла прямоугольника? - PullRequest
1 голос
/ 14 августа 2011

При использовании DrawingContext . DrawRectangle с TileBrush я заметил, что верхний левый угол прямоугольника не является верхним левым краем базового изображения,Это происходит как с DrawingBrush , так и с ImageBrush с источником в качестве DrawingImage .Есть ли способ заставить DrawRectangle всегда привязывать основную кисть к верхнему левому углу?Вот изображение:

An image of the brush alignment issues

Два прямоугольника используют одну и ту же кисть, но находятся в разных точках на экране.Как вы можете видеть, происхождение кисти отличается (кажется, что кисть является непрерывной на гораздо большей площади).Вот минимальное повторение:

    private static readonly Brush _brush;

    static CustomControl()
    {
        Uri uri = new Uri(@"pack://application:,,,/WpfApplication1;component/image.png", UriKind.Absolute);
        BitmapImage img = new BitmapImage(uri);
        Rect rect = new Rect(0, 0, img.Width, img.Height);
        ImageDrawing drawing = new ImageDrawing(img, rect);
        _brush = new DrawingBrush
        {
            Drawing = drawing, 
            Viewport = rect,
            ViewportUnits = BrushMappingMode.Absolute,
            TileMode = TileMode.Tile 
        };
        _brush.Freeze();
    }

    protected override void OnRender(DrawingContext dc)
    {
        dc.DrawRectangle(_brush, null, new Rect(70, 70, 100, 150));
        dc.DrawRectangle(_brush, null, new Rect(200, 200, 80, 120));
    }

* В этом случае ImageBrush даст правильные результаты, но в моей программе я имею дело с DrawingBrush с пользовательским GeometryDrawing .

Я пытался использовать перо вместо кисти, меняя режим TileMode, устанавливая растяжение на Uniform, изменяя AlignmentX и AlignmentY ... похоже, ничего не работает,Начало координат кисти никогда не устанавливается на начало прямоугольника.

Ответы [ 2 ]

1 голос
/ 16 августа 2011

Решение, которое я использовал, состояло в том, чтобы отобразить его в (0,0) с помощью TranslateTransform .Таким образом, вместо ...

dc.DrawRectangle(_brush, null, new Rect(70, 70, 100, 150));

Вы можете использовать:

TranslateTransform transform = new TranslateTransform(70, 70);
transform.Freeze();
dc.PushTransform(transform);
dc.DrawRectangle(_brush, null, new Rect(0, 0, 100, 150));
dc.Pop();

Это не идеально, поскольку вам нужно выделить новый TranslateTransform (и, следовательно, другой базовый DUCEресурс) каждый раз, когда вы рисуете новый прямоугольник, но он достаточно хорошо работает в моих тестах.

ВАЖНОЕ ПРИМЕЧАНИЕ: Вы все еще можете столкнуться с некоторыми странными (но тонкими) искажениями при повторном рендерингенапример, при прокрутке.Это может быть вызвано системой рендеринга субпикселей.Вы можете поиграть с GuidelineSet s или просто округлить начальную точку X и Y до ближайшего целочисленного значения.

1 голос
/ 15 августа 2011

По моему опыту, мозаичные кисти очень зависят от соотношения между Viewbox, ViewboxUnits, Viewport и ViewportUnits свойствами кисти.

Оба свойства для единиц должны быть установлены на Absolute; Viewport и Viewbox должны быть одинакового размера (99% случаев).

Чтобы уточнить, это не что-то "официальное", что я читал, это только из (большого количества) наблюдений: Viewbox - размер, рассматриваемый для отрисовки чертежа. Если он не установлен, Data пути будет определять размер Viewbox. С другой стороны, Viewport - это размер, учитываемый при укладке кисти.

Установка Viewbox на меньший размер, чем Viewport, приведет к расстоянию между каждой из «плиток» кисти. Установка Viewbox больше Viewport приведет к тому, что «плитки» будут перекрываться (логически, на экране «плитка» будет казаться обрезанной).

...