| 119 | | if (!m_source.initialized()) |
| 120 | | return; |
| 121 | | |
| 122 | | cairo_surface_t* image = frameAtIndex(m_currentFrame); |
| 123 | | if (!image) // If it's too early we won't have an image yet. |
| 124 | | return; |
| 125 | | |
| 126 | | IntSize intrinsicImageSize = size(); |
| 127 | | FloatRect srcRect(srcPoint, intrinsicImageSize); |
| 128 | | FloatPoint point = srcPoint; |
| 129 | | |
| 130 | | // Check and see if a single draw of the image can cover the entire area we are supposed to tile. |
| 131 | | float tileWidth = size().width(); |
| 132 | | float tileHeight = size().height(); |
| 133 | | |
| 134 | | // If the scale is not equal to the intrinsic size of the image, set transform matrix |
| 135 | | // to the appropriate scalar matrix, scale the source point, and set the size of the |
| 136 | | // scaled tile. |
| 137 | | float scaleX = 1.0; |
| 138 | | float scaleY = 1.0; |
| 139 | | cairo_matrix_t mat; |
| 140 | | cairo_matrix_init_identity(&mat); |
| 141 | | if (tileSize.width() != intrinsicImageSize.width() || tileSize.height() != intrinsicImageSize.height()) { |
| 142 | | scaleX = intrinsicImageSize.width() / tileSize.width(); |
| 143 | | scaleY = intrinsicImageSize.height() / tileSize.height(); |
| 144 | | cairo_matrix_init_scale(&mat, scaleX, scaleY); |
| 145 | | |
| 146 | | tileWidth = tileSize.width(); |
| 147 | | tileHeight = tileSize.height(); |
| 148 | | } |
| 149 | | |
| 150 | | // We could get interesting source offsets (negative ones or positive ones. Deal with both |
| 151 | | // out of bounds cases. |
| 152 | | float dstTileX = dstRect.x() + fmodf(fmodf(-point.x(), tileWidth) - tileWidth, tileWidth); |
| 153 | | float dstTileY = dstRect.y() + fmodf(fmodf(-point.y(), tileHeight) - tileHeight, tileHeight); |
| 154 | | FloatRect dstTileRect(dstTileX, dstTileY, tileWidth, tileHeight); |
| 155 | | |
| 156 | | float srcX = dstRect.x() - dstTileRect.x(); |
| 157 | | float srcY = dstRect.y() - dstTileRect.y(); |
| 158 | | |
| 159 | | // If the single image draw covers the whole area, then just draw once. |
| 160 | | if (dstTileRect.contains(dstRect)) { |
| 161 | | draw(ctxt, dstRect, |
| 162 | | FloatRect(srcX * scaleX, srcY * scaleY, dstRect.width() * scaleX, dstRect.height() * scaleY), op); |
| 163 | | return; |
| 164 | | } |
| 165 | | |
| 166 | | // We have to tile. |
| 167 | | cairo_t* context = ctxt->platformContext(); |
| 168 | | |
| 169 | | cairo_save(context); |
| 170 | | |
| 171 | | // Set the compositing operation. |
| 172 | | setCompositingOperation(context, op, frameHasAlphaAtIndex(m_currentFrame)); |
| 173 | | |
| 174 | | cairo_translate(context, dstTileRect.x(), dstTileRect.y()); |
| 175 | | cairo_pattern_t* pattern = cairo_pattern_create_for_surface(image); |
| 176 | | cairo_pattern_set_matrix(pattern, &mat); |
| 177 | | cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT); |
| 178 | | |
| 179 | | // Draw the image. |
| 180 | | cairo_set_source(context, pattern); |
| 181 | | cairo_rectangle(context, srcX, srcY, dstRect.width(), dstRect.height()); |
| 182 | | cairo_fill(context); |
| 183 | | cairo_restore(context); |
| 184 | | |
| 185 | | startAnimation(); |
| | 112 | // FIXME: It's easy to implement this optimization. Just need to check the RGBA32 buffer to see if it is 1x1. |
| | 113 | m_isSolidColor = false; |