gfx/cairo/d2d-repeating-gradients.patch

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

michael@0 1 From: Robert O'Callahan <robert@ocallahan.org>
michael@0 2 Bug 768775. Improve the precision of the calculation of the number of stops that need to be added to handle 'repeat' and 'reflect', when we're filling a path. r=bas
michael@0 3
michael@0 4 diff --git a/gfx/cairo/cairo/src/cairo-d2d-surface.cpp b/gfx/cairo/cairo/src/cairo-d2d-surface.cpp
michael@0 5 --- a/gfx/cairo/cairo/src/cairo-d2d-surface.cpp
michael@0 6 +++ b/gfx/cairo/cairo/src/cairo-d2d-surface.cpp
michael@0 7 @@ -1411,17 +1411,17 @@ static RefPtr<ID2D1Brush>
michael@0 8
michael@0 9 gradient_center.x = _cairo_fixed_to_float(source_pattern->c1.x);
michael@0 10 gradient_center.y = _cairo_fixed_to_float(source_pattern->c1.y);
michael@0 11
michael@0 12 // Transform surface corners into pattern coordinates.
michael@0 13 cairo_matrix_transform_point(&source_pattern->base.base.matrix, &top_left.x, &top_left.y);
michael@0 14 cairo_matrix_transform_point(&source_pattern->base.base.matrix, &top_right.x, &top_right.y);
michael@0 15 cairo_matrix_transform_point(&source_pattern->base.base.matrix, &bottom_left.x, &bottom_left.y);
michael@0 16 - cairo_matrix_transform_point(&source_pattern->base.base.matrix, &bottom_right.x, &top_left.y);
michael@0 17 + cairo_matrix_transform_point(&source_pattern->base.base.matrix, &bottom_right.x, &bottom_right.y);
michael@0 18
michael@0 19 // Find the corner furthest away from the gradient center in pattern space.
michael@0 20 double largest = MAX(_cairo_d2d_point_dist(top_left, gradient_center), _cairo_d2d_point_dist(top_right, gradient_center));
michael@0 21 largest = MAX(largest, _cairo_d2d_point_dist(bottom_left, gradient_center));
michael@0 22 largest = MAX(largest, _cairo_d2d_point_dist(bottom_right, gradient_center));
michael@0 23
michael@0 24 unsigned int minSize = (unsigned int)ceil(largest);
michael@0 25
michael@0 26 @@ -1531,16 +1531,17 @@ static RefPtr<ID2D1Brush>
michael@0 27 stopCollection,
michael@0 28 &brush);
michael@0 29 delete [] stops;
michael@0 30 return brush;
michael@0 31 }
michael@0 32
michael@0 33 static RefPtr<ID2D1Brush>
michael@0 34 _cairo_d2d_create_linear_gradient_brush(cairo_d2d_surface_t *d2dsurf,
michael@0 35 + cairo_path_fixed_t *fill_path,
michael@0 36 cairo_linear_pattern_t *source_pattern)
michael@0 37 {
michael@0 38 if (source_pattern->p1.x == source_pattern->p2.x &&
michael@0 39 source_pattern->p1.y == source_pattern->p2.y) {
michael@0 40 // Cairo behavior in this situation is to draw a solid color the size of the last stop.
michael@0 41 RefPtr<ID2D1SolidColorBrush> brush;
michael@0 42 d2dsurf->rt->CreateSolidColorBrush(
michael@0 43 _cairo_d2d_color_from_cairo_color_stop(source_pattern->base.stops[source_pattern->base.n_stops - 1].color),
michael@0 44 @@ -1564,35 +1565,46 @@ static RefPtr<ID2D1Brush>
michael@0 45 p1.x = _cairo_fixed_to_float(source_pattern->p1.x);
michael@0 46 p1.y = _cairo_fixed_to_float(source_pattern->p1.y);
michael@0 47 p2.x = _cairo_fixed_to_float(source_pattern->p2.x);
michael@0 48 p2.y = _cairo_fixed_to_float(source_pattern->p2.y);
michael@0 49
michael@0 50 D2D1_GRADIENT_STOP *stops;
michael@0 51 int num_stops = source_pattern->base.n_stops;
michael@0 52 if (source_pattern->base.base.extend == CAIRO_EXTEND_REPEAT || source_pattern->base.base.extend == CAIRO_EXTEND_REFLECT) {
michael@0 53 -
michael@0 54 - RefPtr<IDXGISurface> surf;
michael@0 55 - d2dsurf->surface->QueryInterface(&surf);
michael@0 56 - DXGI_SURFACE_DESC desc;
michael@0 57 - surf->GetDesc(&desc);
michael@0 58 -
michael@0 59 // Get this when the points are not transformed yet.
michael@0 60 double gradient_length = _cairo_d2d_point_dist(p1, p2);
michael@0 61 -
michael@0 62 - // Calculate the repeat count needed;
michael@0 63 - cairo_point_double_t top_left, top_right, bottom_left, bottom_right;
michael@0 64 - top_left.x = bottom_left.x = top_left.y = top_right.y = 0;
michael@0 65 - top_right.x = bottom_right.x = desc.Width;
michael@0 66 - bottom_right.y = bottom_left.y = desc.Height;
michael@0 67 + cairo_point_double_t top_left, top_right, bottom_left, bottom_right;
michael@0 68 +
michael@0 69 + if (fill_path) {
michael@0 70 + // Calculate the repeat count needed;
michael@0 71 + cairo_box_t fill_extents;
michael@0 72 + _cairo_path_fixed_extents (fill_path, &fill_extents);
michael@0 73 +
michael@0 74 + top_left.x = bottom_left.x = _cairo_fixed_to_double (fill_extents.p1.x);
michael@0 75 + top_left.y = top_right.y = _cairo_fixed_to_double (fill_extents.p1.y);
michael@0 76 + top_right.x = bottom_right.x = _cairo_fixed_to_double (fill_extents.p2.x);
michael@0 77 + bottom_right.y = bottom_left.y = _cairo_fixed_to_double (fill_extents.p2.y);
michael@0 78 + } else {
michael@0 79 + RefPtr<IDXGISurface> surf;
michael@0 80 + d2dsurf->surface->QueryInterface(&surf);
michael@0 81 + DXGI_SURFACE_DESC desc;
michael@0 82 + surf->GetDesc(&desc);
michael@0 83 +
michael@0 84 + top_left.x = bottom_left.x = 0;
michael@0 85 + top_left.y = top_right.y = 0;
michael@0 86 + top_right.x = bottom_right.x = desc.Width;
michael@0 87 + bottom_right.y = bottom_left.y = desc.Height;
michael@0 88 + }
michael@0 89 +
michael@0 90 // Transform the corners of our surface to pattern space.
michael@0 91 cairo_matrix_transform_point(&source_pattern->base.base.matrix, &top_left.x, &top_left.y);
michael@0 92 cairo_matrix_transform_point(&source_pattern->base.base.matrix, &top_right.x, &top_right.y);
michael@0 93 cairo_matrix_transform_point(&source_pattern->base.base.matrix, &bottom_left.x, &bottom_left.y);
michael@0 94 - cairo_matrix_transform_point(&source_pattern->base.base.matrix, &bottom_right.x, &top_left.y);
michael@0 95 + cairo_matrix_transform_point(&source_pattern->base.base.matrix, &bottom_right.x, &bottom_right.y);
michael@0 96
michael@0 97 cairo_point_double_t u;
michael@0 98 // Unit vector of the gradient direction.
michael@0 99 u = _cairo_d2d_subtract_point(p2, p1);
michael@0 100 _cairo_d2d_normalize_point(&u);
michael@0 101
michael@0 102 // (corner - p1) . u = |corner - p1| cos(a) where a is the angle between the two vectors.
michael@0 103 // Coincidentally |corner - p1| cos(a) is actually also the distance our gradient needs to cover since
michael@0 104 @@ -1701,17 +1713,18 @@ static RefPtr<ID2D1Brush>
michael@0 105 * \param d2dsurf Surface to create a brush for
michael@0 106 * \param pattern The pattern to create a brush for
michael@0 107 * \param unique We cache the bitmap/color brush for speed. If this
michael@0 108 * needs a brush that is unique (i.e. when more than one is needed),
michael@0 109 * this will make the function return a seperate brush.
michael@0 110 * \return A brush object
michael@0 111 */
michael@0 112 static RefPtr<ID2D1Brush>
michael@0 113 -_cairo_d2d_create_brush_for_pattern(cairo_d2d_surface_t *d2dsurf,
michael@0 114 +_cairo_d2d_create_brush_for_pattern(cairo_d2d_surface_t *d2dsurf,
michael@0 115 + cairo_path_fixed_t *fill_path,
michael@0 116 const cairo_pattern_t *pattern,
michael@0 117 bool unique = false)
michael@0 118 {
michael@0 119 HRESULT hr;
michael@0 120
michael@0 121 if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) {
michael@0 122 cairo_solid_pattern_t *sourcePattern =
michael@0 123 (cairo_solid_pattern_t*)pattern;
michael@0 124 @@ -1729,17 +1742,17 @@ static RefPtr<ID2D1Brush>
michael@0 125 d2dsurf->solidColorBrush->SetColor(color);
michael@0 126 }
michael@0 127 return d2dsurf->solidColorBrush;
michael@0 128 }
michael@0 129
michael@0 130 } else if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR) {
michael@0 131 cairo_linear_pattern_t *source_pattern =
michael@0 132 (cairo_linear_pattern_t*)pattern;
michael@0 133 - return _cairo_d2d_create_linear_gradient_brush(d2dsurf, source_pattern);
michael@0 134 + return _cairo_d2d_create_linear_gradient_brush(d2dsurf, fill_path, source_pattern);
michael@0 135 } else if (pattern->type == CAIRO_PATTERN_TYPE_RADIAL) {
michael@0 136 cairo_radial_pattern_t *source_pattern =
michael@0 137 (cairo_radial_pattern_t*)pattern;
michael@0 138 return _cairo_d2d_create_radial_gradient_brush(d2dsurf, source_pattern);
michael@0 139 } else if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
michael@0 140 cairo_matrix_t mat = pattern->matrix;
michael@0 141 cairo_matrix_invert(&mat);
michael@0 142
michael@0 143 @@ -3228,17 +3241,17 @@ static cairo_int_status_t
michael@0 144
michael@0 145 if (unlikely(status))
michael@0 146 return status;
michael@0 147 }
michael@0 148 #endif
michael@0 149
michael@0 150 target_rt->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED);
michael@0 151
michael@0 152 - RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(d2dsurf,
michael@0 153 + RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(d2dsurf, NULL,
michael@0 154 source);
michael@0 155
michael@0 156 if (!brush) {
michael@0 157 return CAIRO_INT_STATUS_UNSUPPORTED;
michael@0 158 }
michael@0 159
michael@0 160 D2D1_SIZE_F size = target_rt->GetSize();
michael@0 161 target_rt->FillRectangle(D2D1::RectF((FLOAT)0,
michael@0 162 @@ -3349,17 +3362,17 @@ static cairo_int_status_t
michael@0 163 source->filter,
michael@0 164 solidAlphaValue);
michael@0 165 if (rv != CAIRO_INT_STATUS_UNSUPPORTED) {
michael@0 166 return rv;
michael@0 167 }
michael@0 168 }
michael@0 169 }
michael@0 170
michael@0 171 - RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(d2dsurf, source);
michael@0 172 + RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(d2dsurf, NULL, source);
michael@0 173 if (!brush) {
michael@0 174 return CAIRO_INT_STATUS_UNSUPPORTED;
michael@0 175 }
michael@0 176
michael@0 177 RefPtr<ID2D1RenderTarget> target_rt = d2dsurf->rt;
michael@0 178 #ifndef ALWAYS_MANUAL_COMPOSITE
michael@0 179 if (op != CAIRO_OPERATOR_OVER) {
michael@0 180 #endif
michael@0 181 @@ -3389,17 +3402,17 @@ static cairo_int_status_t
michael@0 182 brush->SetOpacity(1.0);
michael@0 183
michael@0 184 if (target_rt.get() != d2dsurf->rt.get()) {
michael@0 185 return _cairo_d2d_blend_temp_surface(d2dsurf, op, target_rt, clip);
michael@0 186 }
michael@0 187 return CAIRO_INT_STATUS_SUCCESS;
michael@0 188 }
michael@0 189
michael@0 190 - RefPtr<ID2D1Brush> opacityBrush = _cairo_d2d_create_brush_for_pattern(d2dsurf, mask, true);
michael@0 191 + RefPtr<ID2D1Brush> opacityBrush = _cairo_d2d_create_brush_for_pattern(d2dsurf, NULL, mask, true);
michael@0 192 if (!opacityBrush) {
michael@0 193 return CAIRO_INT_STATUS_UNSUPPORTED;
michael@0 194 }
michael@0 195
michael@0 196 if (!d2dsurf->maskLayer) {
michael@0 197 d2dsurf->rt->CreateLayer(&d2dsurf->maskLayer);
michael@0 198 }
michael@0 199 target_rt->PushLayer(D2D1::LayerParameters(D2D1::InfiniteRect(),
michael@0 200 @@ -3475,17 +3488,17 @@ static cairo_int_status_t
michael@0 201 D2D1_FIGURE_BEGIN_FILLED);
michael@0 202
michael@0 203 bool transformed = true;
michael@0 204
michael@0 205 if (_cairo_matrix_is_identity(ctm)) {
michael@0 206 transformed = false;
michael@0 207 }
michael@0 208
michael@0 209 - RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(d2dsurf,
michael@0 210 + RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(d2dsurf, NULL,
michael@0 211 source);
michael@0 212 if (!brush) {
michael@0 213 return CAIRO_INT_STATUS_UNSUPPORTED;
michael@0 214 }
michael@0 215
michael@0 216 D2D1::Matrix3x2F mat;
michael@0 217 if (transformed) {
michael@0 218 // If we are transformed we will draw the geometry multiplied by the
michael@0 219 @@ -3602,31 +3615,31 @@ static cairo_int_status_t
michael@0 220 }
michael@0 221
michael@0 222 if (is_box) {
michael@0 223 float x1 = _cairo_fixed_to_float(box.p1.x);
michael@0 224 float y1 = _cairo_fixed_to_float(box.p1.y);
michael@0 225 float x2 = _cairo_fixed_to_float(box.p2.x);
michael@0 226 float y2 = _cairo_fixed_to_float(box.p2.y);
michael@0 227 RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(d2dsurf,
michael@0 228 - source);
michael@0 229 + path, source);
michael@0 230 if (!brush) {
michael@0 231 return CAIRO_INT_STATUS_UNSUPPORTED;
michael@0 232 }
michael@0 233
michael@0 234 target_rt->FillRectangle(D2D1::RectF(x1,
michael@0 235 y1,
michael@0 236 x2,
michael@0 237 y2),
michael@0 238 brush);
michael@0 239 } else {
michael@0 240 RefPtr<ID2D1Geometry> d2dpath = _cairo_d2d_create_path_geometry_for_path(path, fill_rule, D2D1_FIGURE_BEGIN_FILLED);
michael@0 241
michael@0 242 RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(d2dsurf,
michael@0 243 - source);
michael@0 244 + path, source);
michael@0 245 if (!brush) {
michael@0 246 return CAIRO_INT_STATUS_UNSUPPORTED;
michael@0 247 }
michael@0 248 target_rt->FillGeometry(d2dpath, brush);
michael@0 249 }
michael@0 250
michael@0 251 if (target_rt.get() != d2dsurf->rt.get()) {
michael@0 252 double x1, y1, x2, y2;
michael@0 253 @@ -4138,17 +4151,17 @@ static cairo_int_status_t
michael@0 254 DWRITE_TEXTURE_ALIASED_1x1 : DWRITE_TEXTURE_CLEARTYPE_3x1,
michael@0 255 &bounds);
michael@0 256 fontArea.x = bounds.left;
michael@0 257 fontArea.y = bounds.top;
michael@0 258 fontArea.width = bounds.right - bounds.left;
michael@0 259 fontArea.height = bounds.bottom - bounds.top;
michael@0 260 }
michael@0 261
michael@0 262 - RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(dst,
michael@0 263 + RefPtr<ID2D1Brush> brush = _cairo_d2d_create_brush_for_pattern(dst, NULL,
michael@0 264 source);
michael@0 265
michael@0 266 if (!brush) {
michael@0 267 return CAIRO_INT_STATUS_UNSUPPORTED;
michael@0 268 }
michael@0 269
michael@0 270 if (transform) {
michael@0 271 D2D1::Matrix3x2F mat_inverse = _cairo_d2d_matrix_from_matrix(&dwritesf->mat_inverse);

mercurial