From d0477fb6730fcd57d0e354b93c83bca8493841aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20A=C3=9Fmus?= Date: Thu, 6 Feb 2014 17:13:36 +0100 Subject: [PATCH] Painter: Support transformation in gradient code paths. Clipping paths (or rather alpha masks) and affine view transformations seem to be generally supported for all drawing operations now. There might still be bugs that have not yet been exposed by the current set of tests. These could be related to scrolling, origin and scale as well as stacked view states. --- src/servers/app/drawing/Painter/Painter.cpp | 353 ++++++-------------- src/servers/app/drawing/Painter/Painter.h | 36 +- 2 files changed, 113 insertions(+), 276 deletions(-) diff --git a/src/servers/app/drawing/Painter/Painter.cpp b/src/servers/app/drawing/Painter/Painter.cpp index e9f8132209..3600901e46 100644 --- a/src/servers/app/drawing/Painter/Painter.cpp +++ b/src/servers/app/drawing/Painter/Painter.cpp @@ -2856,49 +2856,117 @@ template BRect Painter::_FillPath(VertexSource& path, const BGradient& gradient) const { - GTRACE("Painter::_FillPath\n"); + if (fIdentityTransform) + return _RasterizePath(path, gradient); + + agg::conv_transform transformedPath(path, fTransform); + return _RasterizePath(transformedPath, gradient); +} + + +// _FillPath +template +BRect +Painter::_RasterizePath(VertexSource& path, const BGradient& gradient) const +{ + GTRACE("Painter::_RasterizePath\n"); + + agg::trans_affine gradientTransform; switch(gradient.GetType()) { - case BGradient::TYPE_LINEAR: { + case BGradient::TYPE_LINEAR: + { GTRACE(("Painter::_FillPath> type == TYPE_LINEAR\n")); - _FillPathGradientLinear(path, *((const BGradientLinear*) &gradient)); + const BGradientLinear& linearGradient + = (const BGradientLinear&) gradient; + agg::gradient_x gradientFunction; + _CalcLinearGradientTransform(linearGradient.Start(), + linearGradient.End(), gradientTransform); + _RasterizePath(path, gradient, gradientFunction, gradientTransform); break; } - case BGradient::TYPE_RADIAL: { + case BGradient::TYPE_RADIAL: + { GTRACE(("Painter::_FillPathGradient> type == TYPE_RADIAL\n")); - _FillPathGradientRadial(path, - *((const BGradientRadial*) &gradient)); + const BGradientRadial& radialGradient + = (const BGradientRadial&) gradient; + agg::gradient_radial gradientFunction; + _CalcRadialGradientTransform(radialGradient.Center(), + gradientTransform); + _RasterizePath(path, gradient, gradientFunction, gradientTransform); break; } - case BGradient::TYPE_RADIAL_FOCUS: { + case BGradient::TYPE_RADIAL_FOCUS: + { GTRACE(("Painter::_FillPathGradient> type == TYPE_RADIAL_FOCUS\n")); - _FillPathGradientRadialFocus(path, - *((const BGradientRadialFocus*) &gradient)); + const BGradientRadialFocus& radialGradient + = (const BGradientRadialFocus&) gradient; + agg::gradient_radial_focus gradientFunction; + _CalcRadialGradientTransform(radialGradient.Center(), + gradientTransform); + _RasterizePath(path, gradient, gradientFunction, gradientTransform); break; } - case BGradient::TYPE_DIAMOND: { + case BGradient::TYPE_DIAMOND: + { GTRACE(("Painter::_FillPathGradient> type == TYPE_DIAMOND\n")); - _FillPathGradientDiamond(path, - *((const BGradientDiamond*) &gradient)); + const BGradientDiamond& diamontGradient + = (const BGradientDiamond&) gradient; + agg::gradient_diamond gradientFunction; + _CalcRadialGradientTransform(diamontGradient.Center(), + gradientTransform); + _RasterizePath(path, gradient, gradientFunction, gradientTransform); break; } - case BGradient::TYPE_CONIC: { + case BGradient::TYPE_CONIC: + { GTRACE(("Painter::_FillPathGradient> type == TYPE_CONIC\n")); - _FillPathGradientConic(path, - *((const BGradientConic*) &gradient)); + const BGradientConic& conicGradient + = (const BGradientConic&) gradient; + agg::gradient_conic gradientFunction; + _CalcRadialGradientTransform(conicGradient.Center(), + gradientTransform); + _RasterizePath(path, gradient, gradientFunction, gradientTransform); break; } - case BGradient::TYPE_NONE: { - GTRACE(("Painter::_FillPathGradient> type == TYPE_NONE\n")); + + default: + case BGradient::TYPE_NONE: + GTRACE(("Painter::_FillPathGradient> type == TYPE_NONE/unkown\n")); break; - } } return _Clipped(_BoundingBox(path)); } -// _MakeGradient +void +Painter::_CalcLinearGradientTransform(BPoint startPoint, BPoint endPoint, + agg::trans_affine& matrix, float gradient_d2) const +{ + float dx = endPoint.x - startPoint.x; + float dy = endPoint.y - startPoint.y; + + matrix.reset(); + matrix *= agg::trans_affine_scaling(sqrt(dx * dx + dy * dy) / gradient_d2); + matrix *= agg::trans_affine_rotation(atan2(dy, dx)); + matrix *= agg::trans_affine_translation(startPoint.x, startPoint.y); + matrix *= fTransform; + matrix.invert(); +} + + +void +Painter::_CalcRadialGradientTransform(BPoint center, + agg::trans_affine& matrix, float gradient_d2) const +{ + matrix.reset(); + matrix *= agg::trans_affine_translation(center.x, center.y); + matrix *= fTransform; + matrix.invert(); +} + + void Painter::_MakeGradient(const BGradient& gradient, int32 colorCount, uint32* colors, int32 arrayOffset, int32 arraySize) const @@ -2978,7 +3046,6 @@ Painter::_MakeGradient(const BGradient& gradient, int32 colorCount, } -// _MakeGradient template void Painter::_MakeGradient(Array& array, const BGradient& gradient) const @@ -3009,57 +3076,33 @@ Painter::_MakeGradient(Array& array, const BGradient& gradient) const } -// _CalcLinearGradientTransform -void Painter::_CalcLinearGradientTransform(BPoint startPoint, BPoint endPoint, - agg::trans_affine& matrix, float gradient_d2) const -{ - float dx = endPoint.x - startPoint.x; - float dy = endPoint.y - startPoint.y; - - matrix.reset(); - matrix *= agg::trans_affine_scaling(sqrt(dx * dx + dy * dy) / gradient_d2); - matrix *= agg::trans_affine_rotation(atan2(dy, dx)); - matrix *= agg::trans_affine_translation(startPoint.x, startPoint.y); - matrix.invert(); -} - - -// _FillPathGradientLinear -template +template void -Painter::_FillPathGradientLinear(VertexSource& path, - const BGradientLinear& linear) const +Painter::_RasterizePath(VertexSource& path, const BGradient& gradient, + GradientFunction function, agg::trans_affine& gradientTransform) const { - GTRACE("Painter::_FillPathGradientLinear\n"); - - BPoint start = linear.Start(); - BPoint end = linear.End(); + GTRACE("Painter::_RasterizePath\n"); typedef agg::span_interpolator_linear<> interpolator_type; typedef agg::pod_auto_array color_array_type; typedef agg::span_allocator span_allocator_type; - typedef agg::gradient_x gradient_func_type; typedef agg::span_gradient span_gradient_type; + GradientFunction, color_array_type> span_gradient_type; typedef agg::renderer_scanline_aa renderer_gradient_type; - gradient_func_type gradientFunc; - agg::trans_affine gradientMatrix; - interpolator_type spanInterpolator(gradientMatrix); + interpolator_type spanInterpolator(gradientTransform); span_allocator_type spanAllocator; color_array_type colorArray; - _MakeGradient(colorArray, linear); + _MakeGradient(colorArray, gradient); - span_gradient_type spanGradient(spanInterpolator, gradientFunc, colorArray, + span_gradient_type spanGradient(spanInterpolator, function, colorArray, 0, 100); renderer_gradient_type gradientRenderer(fBaseRenderer, spanAllocator, spanGradient); - _CalcLinearGradientTransform(start, end, gradientMatrix); - fRasterizer.reset(); fRasterizer.add_path(path); if (fMaskedUnpackedScanline == NULL) @@ -3070,209 +3113,3 @@ Painter::_FillPathGradientLinear(VertexSource& path, } } - -// _FillPathGradientRadial -template -void -Painter::_FillPathGradientRadial(VertexSource& path, - const BGradientRadial& radial) const -{ - GTRACE("Painter::_FillPathGradientRadial\n"); - - BPoint center = radial.Center(); -// TODO: finish this -// float radius = radial.Radius(); - - typedef agg::span_interpolator_linear<> interpolator_type; - typedef agg::pod_auto_array color_array_type; - typedef agg::span_allocator span_allocator_type; - typedef agg::gradient_radial gradient_func_type; - typedef agg::span_gradient span_gradient_type; - typedef agg::renderer_scanline_aa renderer_gradient_type; - - gradient_func_type gradientFunc; - agg::trans_affine gradientMatrix; - interpolator_type spanInterpolator(gradientMatrix); - span_allocator_type spanAllocator; - color_array_type colorArray; - - _MakeGradient(colorArray, radial); - - span_gradient_type spanGradient(spanInterpolator, gradientFunc, colorArray, - 0, 100); - - renderer_gradient_type gradientRenderer(fBaseRenderer, spanAllocator, - spanGradient); - - gradientMatrix.reset(); - gradientMatrix *= agg::trans_affine_translation(center.x, center.y); - gradientMatrix.invert(); - -// _CalcLinearGradientTransform(start, end, gradientMtx); - - fRasterizer.reset(); - fRasterizer.add_path(path); - if (fMaskedUnpackedScanline == NULL) - agg::render_scanlines(fRasterizer, fPackedScanline, gradientRenderer); - else { - agg::render_scanlines(fRasterizer, *fMaskedUnpackedScanline, - gradientRenderer); - } -} - - -// _FillPathGradientRadialFocus -template -void -Painter::_FillPathGradientRadialFocus(VertexSource& path, - const BGradientRadialFocus& focus) const -{ - GTRACE("Painter::_FillPathGradientRadialFocus\n"); - - BPoint center = focus.Center(); -// TODO: finish this. -// BPoint focal = focus.Focal(); -// float radius = focus.Radius(); - - typedef agg::span_interpolator_linear<> interpolator_type; - typedef agg::pod_auto_array color_array_type; - typedef agg::span_allocator span_allocator_type; - typedef agg::gradient_radial_focus gradient_func_type; - typedef agg::span_gradient span_gradient_type; - typedef agg::renderer_scanline_aa renderer_gradient_type; - - gradient_func_type gradientFunc; - agg::trans_affine gradientMatrix; - interpolator_type spanInterpolator(gradientMatrix); - span_allocator_type spanAllocator; - color_array_type colorArray; - - _MakeGradient(colorArray, focus); - - span_gradient_type spanGradient(spanInterpolator, gradientFunc, colorArray, - 0, 100); - - renderer_gradient_type gradientRenderer(fBaseRenderer, spanAllocator, - spanGradient); - - gradientMatrix.reset(); - gradientMatrix *= agg::trans_affine_translation(center.x, center.y); - gradientMatrix.invert(); - - // _CalcLinearGradientTransform(start, end, gradientMatrix); - - fRasterizer.reset(); - fRasterizer.add_path(path); - if (fMaskedUnpackedScanline == NULL) - agg::render_scanlines(fRasterizer, fPackedScanline, gradientRenderer); - else { - agg::render_scanlines(fRasterizer, *fMaskedUnpackedScanline, - gradientRenderer); - } -} - - -// _FillPathGradientDiamond -template -void -Painter::_FillPathGradientDiamond(VertexSource& path, - const BGradientDiamond& diamond) const -{ - GTRACE("Painter::_FillPathGradientDiamond\n"); - - BPoint center = diamond.Center(); -// float radius = diamond.Radius(); - - typedef agg::span_interpolator_linear<> interpolator_type; - typedef agg::pod_auto_array color_array_type; - typedef agg::span_allocator span_allocator_type; - typedef agg::gradient_diamond gradient_func_type; - typedef agg::span_gradient span_gradient_type; - typedef agg::renderer_scanline_aa renderer_gradient_type; - - gradient_func_type gradientFunc; - agg::trans_affine gradientMatrix; - interpolator_type spanInterpolator(gradientMatrix); - span_allocator_type spanAllocator; - color_array_type colorArray; - - _MakeGradient(colorArray, diamond); - - span_gradient_type spanGradient(spanInterpolator, gradientFunc, colorArray, - 0, 100); - - renderer_gradient_type gradientRenderer(fBaseRenderer, spanAllocator, - spanGradient); - - gradientMatrix.reset(); - gradientMatrix *= agg::trans_affine_translation(center.x, center.y); - gradientMatrix.invert(); - - // _CalcLinearGradientTransform(start, end, gradientMatrix); - - fRasterizer.reset(); - fRasterizer.add_path(path); - if (fMaskedUnpackedScanline == NULL) - agg::render_scanlines(fRasterizer, fPackedScanline, gradientRenderer); - else { - agg::render_scanlines(fRasterizer, *fMaskedUnpackedScanline, - gradientRenderer); - } -} - - -// _FillPathGradientConic -template -void -Painter::_FillPathGradientConic(VertexSource& path, - const BGradientConic& conic) const -{ - GTRACE("Painter::_FillPathGradientConic\n"); - - BPoint center = conic.Center(); -// float radius = conic.Radius(); - - typedef agg::span_interpolator_linear<> interpolator_type; - typedef agg::pod_auto_array color_array_type; - typedef agg::span_allocator span_allocator_type; - typedef agg::gradient_conic gradient_func_type; - typedef agg::span_gradient span_gradient_type; - typedef agg::renderer_scanline_aa renderer_gradient_type; - - gradient_func_type gradientFunc; - agg::trans_affine gradientMatrix; - interpolator_type spanInterpolator(gradientMatrix); - span_allocator_type spanAllocator; - color_array_type colorArray; - - _MakeGradient(colorArray, conic); - - span_gradient_type spanGradient(spanInterpolator, gradientFunc, colorArray, - 0, 100); - - renderer_gradient_type gradientRenderer(fBaseRenderer, spanAllocator, - spanGradient); - - gradientMatrix.reset(); - gradientMatrix *= agg::trans_affine_translation(center.x, center.y); - gradientMatrix.invert(); - - // _CalcLinearGradientTransform(start, end, gradientMatrix); - - fRasterizer.reset(); - fRasterizer.add_path(path); - if (fMaskedUnpackedScanline == NULL) - agg::render_scanlines(fRasterizer, fPackedScanline, gradientRenderer); - else { - agg::render_scanlines(fRasterizer, *fMaskedUnpackedScanline, - gradientRenderer); - } -} diff --git a/src/servers/app/drawing/Painter/Painter.h b/src/servers/app/drawing/Painter/Painter.h index 2a24fdc3aa..6e5a09ef3e 100644 --- a/src/servers/app/drawing/Painter/Painter.h +++ b/src/servers/app/drawing/Painter/Painter.h @@ -302,9 +302,20 @@ private: BRect _FillPath(VertexSource& path) const; template BRect _RasterizePath(VertexSource& path) const; + + template + BRect _FillPath(VertexSource& path, + const BGradient& gradient) const; + template + BRect _RasterizePath(VertexSource& path, + const BGradient& gradient) const; + void _CalcLinearGradientTransform(BPoint startPoint, BPoint endPoint, agg::trans_affine& mtx, float gradient_d2 = 100.0f) const; + void _CalcRadialGradientTransform(BPoint center, + agg::trans_affine& mtx, + float gradient_d2 = 100.0f) const; void _MakeGradient(const BGradient& gradient, int32 colorCount, uint32* colors, @@ -313,25 +324,14 @@ private: template void _MakeGradient(Array& array, const BGradient& gradient) const; - template - BRect _FillPath(VertexSource& path, - const BGradient& gradient) const; - template - void _FillPathGradientLinear(VertexSource& path, - const BGradientLinear& linear) const; - template - void _FillPathGradientRadial(VertexSource& path, - const BGradientRadial& radial) const; - template - void _FillPathGradientRadialFocus(VertexSource& path, - const BGradientRadialFocus& focus) const; - template - void _FillPathGradientDiamond(VertexSource& path, - const BGradientDiamond& diamond) const; - template - void _FillPathGradientConic(VertexSource& path, - const BGradientConic& conic) const; + template + void _RasterizePath(VertexSource& path, + const BGradient& gradient, + GradientFunction function, + agg::trans_affine& gradientTransform) const; + +private: mutable agg::rendering_buffer fBuffer; // AGG rendering and rasterization classes