|
Lines 205-212
void drawPatternToCairoContext(cairo_t* cr, cairo_surface_t* image, const IntSiz
a/Source/WebCore/platform/graphics/cairo/CairoUtilities.cpp_sec1
|
| 205 |
cairo_pattern_t* pattern = cairo_pattern_create_for_surface(image); |
205 |
cairo_pattern_t* pattern = cairo_pattern_create_for_surface(image); |
| 206 |
cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT); |
206 |
cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT); |
| 207 |
|
207 |
|
|
|
208 |
// Due to a limitation in pixman, cairo cannot handle transformation matrices with values bigger than 32768. If the value is |
| 209 |
// bigger, cairo is not able to paint anything, and this is the reason for the missing backgrounds reported in |
| 210 |
// https://bugs.webkit.org/show_bug.cgi?id=154283. |
| 211 |
|
| 212 |
// When drawing a pattern there are 2 matrices that can overflow this limitation, and they are the current transformation |
| 213 |
// matrix (which translates user space coordinates to coordinates of the output device) and the pattern matrix (which translates |
| 214 |
// user space coordinates to pattern coordinates). The overflow happens only in the translation components of the matrices. |
| 215 |
|
| 216 |
// To avoid the problem in the transformation matrix what we do is remove the translation components of the transformation matrix |
| 217 |
// and perform the translation by moving the destination rectangle instead. For this, we get its translation components (which are in |
| 218 |
// device coordinates) and divide them by the scale factor to take them to user space coordinates. Then we move the transformation |
| 219 |
// matrix by the opposite of that amount (which will zero the translation components of the transformation matrix), and move |
| 220 |
// the destination rectangle by the same amount. We also need to apply the same translation to the pattern matrix, so we get the |
| 221 |
// same pattern coordinates for the new destination rectangle. |
| 222 |
|
| 223 |
cairo_matrix_t ctm; |
| 224 |
cairo_get_matrix(cr, &ctm); |
| 225 |
double dx = 0, dy = 0; |
| 226 |
cairo_matrix_transform_point(&ctm, &dx, &dy); |
| 227 |
double xScale = 1, yScale = 1; |
| 228 |
cairo_matrix_transform_distance(&ctm, &xScale, &yScale); |
| 229 |
|
| 230 |
dx = dx / xScale; |
| 231 |
dy = dy / yScale; |
| 232 |
cairo_translate(cr, -dx, -dy); |
| 233 |
FloatRect adjustedDestRect(destRect); |
| 234 |
adjustedDestRect.move(dx, dy); |
| 235 |
|
| 236 |
// Regarding the pattern matrix, what we do is reduce the translation component of the matrix taking advantage of the fact that we |
| 237 |
// are drawing a repeated pattern. This means that, assuming that (w, h) is the size of the pattern, samplig it at (x, y) is the same |
| 238 |
// than sampling it at (x mod w, y mod h), so we transform the translation component of the pattern matrix in that way. |
| 239 |
|
| 208 |
cairo_matrix_t patternMatrix = cairo_matrix_t(patternTransform); |
240 |
cairo_matrix_t patternMatrix = cairo_matrix_t(patternTransform); |
| 209 |
cairo_matrix_t phaseMatrix = {1, 0, 0, 1, phase.x() + tileRect.x() * patternTransform.a(), phase.y() + tileRect.y() * patternTransform.d()}; |
241 |
// dx and dy are added here as well to compensate the previous translation of the destination rectangle. |
|
|
242 |
double phaseOffsetX = phase.x() + tileRect.x() * patternTransform.a() + dx; |
| 243 |
double phaseOffsetY = phase.y() + tileRect.y() * patternTransform.d() + dy; |
| 244 |
// this is where we perform the (x mod w, y mod h) metioned above, but with floats instead of integers. |
| 245 |
phaseOffsetX -= std::trunc(phaseOffsetX / (tileRect.width() * patternTransform.a())) * tileRect.width() * patternTransform.a(); |
| 246 |
phaseOffsetY -= std::trunc(phaseOffsetY / (tileRect.height() * patternTransform.d())) * tileRect.height() * patternTransform.d(); |
| 247 |
cairo_matrix_t phaseMatrix = {1, 0, 0, 1, phaseOffsetX, phaseOffsetY}; |
| 210 |
cairo_matrix_t combined; |
248 |
cairo_matrix_t combined; |
| 211 |
cairo_matrix_multiply(&combined, &patternMatrix, &phaseMatrix); |
249 |
cairo_matrix_multiply(&combined, &patternMatrix, &phaseMatrix); |
| 212 |
cairo_matrix_invert(&combined); |
250 |
cairo_matrix_invert(&combined); |
|
Lines 215-221
void drawPatternToCairoContext(cairo_t* cr, cairo_surface_t* image, const IntSiz
a/Source/WebCore/platform/graphics/cairo/CairoUtilities.cpp_sec2
|
| 215 |
cairo_set_operator(cr, op); |
253 |
cairo_set_operator(cr, op); |
| 216 |
cairo_set_source(cr, pattern); |
254 |
cairo_set_source(cr, pattern); |
| 217 |
cairo_pattern_destroy(pattern); |
255 |
cairo_pattern_destroy(pattern); |
| 218 |
cairo_rectangle(cr, destRect.x(), destRect.y(), destRect.width(), destRect.height()); |
256 |
cairo_rectangle(cr, adjustedDestRect.x(), adjustedDestRect.y(), adjustedDestRect.width(), adjustedDestRect.height()); |
| 219 |
cairo_fill(cr); |
257 |
cairo_fill(cr); |
| 220 |
|
258 |
|
| 221 |
cairo_restore(cr); |
259 |
cairo_restore(cr); |