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.

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

mercurial