Example #1
0
cairo_surface_t *
CairoSurface::Cairo ()
{
	return cairo_surface_create_for_rectangle (surface,
						   0,
						   0,
						   size[0],
						   size[1]);
}
static cairo_test_status_t
test_cairo_surface_create_for_rectangle (cairo_surface_t *surface)
{
    cairo_surface_t *similar;
    
    similar = cairo_surface_create_for_rectangle (surface, 1, 1, 8, 8);
    
    cairo_surface_destroy (similar);
    return CAIRO_TEST_SUCCESS;
}
Example #3
0
void
workrave_timerbox_update_time_bars(WorkraveTimerbox *self, cairo_t *cr)
{
  WorkraveTimerboxPrivate *priv = self->priv;

  if (priv->enabled)
    {
      int x = 0, y = 0;
      int bar_width, bar_height;

      workrave_timebar_get_dimensions(priv->slot_to_time_bar[0], &bar_width, &bar_height);

      int icon_width = gdk_pixbuf_get_width(priv->break_to_icon[0]);
      int icon_height = gdk_pixbuf_get_height(priv->break_to_icon[0]);

      int icon_bar_width = icon_width + 2 * PADDING_X + bar_width;
      int icon_dy = 0;
      int bar_dy = 0;

      if (bar_height > icon_height)
        {
          icon_dy = (bar_height - icon_height + 1) / 2;
        }
      else
        {
          bar_dy = (icon_height - bar_height + 1) / 2;
        }

      for (int i = 0; i < BREAK_ID_SIZEOF; i++)
        {
          WorkraveBreakId bid = priv->slot_to_break[i];

          if (bid != BREAK_ID_NONE)
            {
              WorkraveTimebar *bar = priv->slot_to_time_bar[bid];

              cairo_surface_t *surface =  cairo_get_target(cr);
              cairo_surface_t *bar_surface = cairo_surface_create_for_rectangle(surface, x+icon_width+PADDING_X, y + bar_dy,
                                                                                bar_width, bar_height);
              cairo_t *bar_cr = cairo_create(bar_surface);
              workrave_timebar_draw(bar, bar_cr);
              cairo_surface_destroy(bar_surface);
              cairo_destroy(bar_cr);

              gdk_cairo_set_source_pixbuf(cr, priv->break_to_icon[bid], x, y + icon_dy);
              cairo_fill(cr);
              cairo_paint(cr);

              x += icon_bar_width + 2 * PADDING_X;
            }
        }
    }
}
Example #4
0
static cairo_test_status_t
draw (cairo_t *cr, int width, int height)
{
    cairo_surface_t *region[5];
    const char *text = "Cairo";
    int i;

    cairo_set_source_rgb (cr, 1, 1, 1);
    cairo_paint (cr);
    cairo_set_source_rgb (cr, 0, 0, 0);

    for (i = 0; i < 5; i++) {
	cairo_t *cr_region;
	cairo_text_extents_t extents;
	char buf[2] = { text[i], '\0' };

        region[i] = cairo_surface_create_for_rectangle (cairo_get_target (cr),
                                                        20 * i, 0, 20, 20);

	cr_region = cairo_create (region[i]);
	cairo_surface_destroy (region[i]);

	cairo_select_font_face (cr_region, "@cairo:",
				CAIRO_FONT_WEIGHT_NORMAL,
				CAIRO_FONT_SLANT_NORMAL);
	cairo_set_font_size (cr_region, 20);
	cairo_text_extents (cr_region, buf, &extents);
	cairo_move_to (cr_region,
		       10 - (extents.width/2 + extents.x_bearing),
		       10 - (extents.height/2 + extents.y_bearing));
	cairo_show_text (cr_region, buf);

	region[i] = cairo_surface_reference (cairo_get_target (cr_region));
	cairo_destroy (cr_region);
    }

    for (i = 0; i < 5; i++) {
	cairo_set_source_surface (cr, region[5-i-1], 20 * i, 20);
	cairo_paint (cr);
    }

    for (i = 0; i < 5; i++) {
	cairo_set_source_surface (cr, region[5-i-1], 20 * i, 40);
	cairo_paint_with_alpha (cr, .5);
    }

    for (i = 0; i < 5; i++)
	cairo_surface_destroy (region[i]);

    return CAIRO_TEST_SUCCESS;
}
Example #5
0
static int
create_for_rectangle(lua_State *L)
{
    SurfaceUserdata *surface;
    cairo_surface_t **obj = luaL_checkudata(L, 1, OOCAIRO_MT_NAME_SURFACE);
    double x = luaL_checknumber(L, 2);
    double y = luaL_checknumber(L, 3);
    double width = luaL_checknumber(L, 4);
    double height = luaL_checknumber(L, 5);

    luaL_argcheck(L, width >= 0, 3, "surface width cannot be negative");
    luaL_argcheck(L, height >= 0, 4, "surface height cannot be negative");

    surface = create_surface_userdata(L);
    surface->surface = cairo_surface_create_for_rectangle(*obj, x, y, width, height);
    return 1;
}
Example #6
0
static void
dv_export_viewports_to_img_r(dv_viewport_t * VP, cairo_surface_t * surface, double x, double y) {
  if (!VP) {
    return;
  } else if (!VP->split) {
    /* resize to remove ruler areas */
    double surface_width = VP->vpw;// - 2 * DVG->opts.ruler_width;
    double surface_height = VP->vph;// - 2 * DVG->opts.ruler_width;
    cairo_surface_t * surface_child = cairo_surface_create_for_rectangle(surface, x, y, surface_width, surface_height);
    dv_viewport_export_to_surface(VP, surface_child);
  } else {
    double w1, h1;
    dv_export_viewports_get_size_r(VP->vp1, &w1, &h1);
    if (VP->orientation == GTK_ORIENTATION_HORIZONTAL) {
      dv_export_viewports_to_img_r(VP->vp1, surface, x, y);
      dv_export_viewports_to_img_r(VP->vp2, surface, x + w1, y);
    } else {
      dv_export_viewports_to_img_r(VP->vp1, surface, x, y);
      dv_export_viewports_to_img_r(VP->vp2, surface, x, y + h1);
    }
  }
}
Example #7
0
static void
brush_end_element (GMarkupParseContext  *context,
                   const gchar          *element_name,
                   gpointer              user_data,
                   GError              **error)
{
        GXPSBrush *brush = (GXPSBrush *)user_data;

        if (strcmp (element_name, "SolidColorBrush") == 0) {
        } else if (strcmp (element_name, "LinearGradientBrush") == 0) {
                g_markup_parse_context_pop (context);
        } else if (strcmp (element_name, "RadialGradientBrush") == 0) {
                g_markup_parse_context_pop (context);
        } else if (strcmp (element_name, "ImageBrush") == 0) {
                GXPSBrushImage  *brush_image;
                GXPSImage       *image;
                GError          *err = NULL;

                brush_image = g_markup_parse_context_pop (context);

                GXPS_DEBUG (g_message ("set_fill_pattern (image)"));
                image = gxps_page_get_image (brush->ctx->page, brush_image->image_uri, &err);
                if (image) {
                        cairo_matrix_t   matrix;
                        gdouble          x_scale, y_scale;
                        cairo_surface_t *clip_surface;

                        /* viewbox units is 1/96 inch, convert to pixels */
                        brush_image->viewbox.x *= image->res_x / 96;
                        brush_image->viewbox.y *= image->res_y / 96;
                        brush_image->viewbox.width *= image->res_x / 96;
                        brush_image->viewbox.height *= image->res_y / 96;

                        clip_surface = cairo_surface_create_for_rectangle (image->surface,
                                                                           brush_image->viewbox.x,
                                                                           brush_image->viewbox.y,
                                                                           brush_image->viewbox.width,
                                                                           brush_image->viewbox.height);
                        brush_image->brush->pattern = cairo_pattern_create_for_surface (clip_surface);
                        cairo_pattern_set_extend (brush_image->brush->pattern, brush_image->extend);

                        x_scale = brush_image->viewport.width / brush_image->viewbox.width;
                        y_scale = brush_image->viewport.height / brush_image->viewbox.height;
                        cairo_matrix_init (&matrix, x_scale, 0, 0, y_scale,
                                           brush_image->viewport.x, brush_image->viewport.y);
                        cairo_matrix_multiply (&matrix, &matrix, &brush_image->matrix);
                        cairo_matrix_invert (&matrix);
                        cairo_pattern_set_matrix (brush_image->brush->pattern, &matrix);

                        if (brush->opacity != 1.0) {
                                cairo_push_group (brush->ctx->cr);
                                cairo_set_source (brush->ctx->cr, brush_image->brush->pattern);
                                cairo_pattern_destroy (brush_image->brush->pattern);
                                cairo_paint_with_alpha (brush->ctx->cr, brush->opacity);
                                brush_image->brush->pattern = cairo_pop_group (brush->ctx->cr);
                        }

                        if (cairo_pattern_status (brush_image->brush->pattern)) {
                                GXPS_DEBUG (g_debug ("%s", cairo_status_to_string (cairo_pattern_status (brush_image->brush->pattern))));
                                cairo_pattern_destroy (brush_image->brush->pattern);
                                brush_image->brush->pattern = NULL;
                        }
                        cairo_surface_destroy (clip_surface);
                } else if (err) {
                        GXPS_DEBUG (g_debug ("%s", err->message));
                        g_error_free (err);
                }
                gxps_brush_image_free (brush_image);
        } else if (strcmp (element_name, "VisualBrush") == 0) {
                GXPSRenderContext *sub_ctx;
                GXPSBrushVisual   *visual;
                cairo_matrix_t     matrix;

                sub_ctx = g_markup_parse_context_pop (context);
                visual = sub_ctx->visual;
                g_slice_free (GXPSRenderContext, sub_ctx);

                GXPS_DEBUG (g_message ("set_fill_pattern (visual)"));
                visual->brush->pattern = cairo_pop_group (brush->ctx->cr);
                /* Undo the clip */
                cairo_restore (brush->ctx->cr);
                cairo_pattern_set_extend (visual->brush->pattern, visual->extend);
                cairo_pattern_get_matrix (visual->brush->pattern, &matrix);
                cairo_matrix_multiply (&matrix, &visual->matrix, &matrix);
                cairo_pattern_set_matrix (visual->brush->pattern, &matrix);
                if (cairo_pattern_status (visual->brush->pattern)) {
                        GXPS_DEBUG (g_debug ("%s", cairo_status_to_string (cairo_pattern_status (visual->brush->pattern))));
                        cairo_pattern_destroy (visual->brush->pattern);
                        visual->brush->pattern = NULL;
                }

                gxps_brush_visual_free (visual);
        } else {
                gxps_parse_error (context,
                                  brush->ctx->page->priv->source,
                                  G_MARKUP_ERROR_UNKNOWN_ELEMENT,
                                  element_name, NULL, NULL, error);

        }
}
Example #8
0
/* We double buffer the image.  It looks nice and it enables
 * grabbing the graph with the pointer and translating it.
 * We draw on our own larger surface and then copy part of that
 * to the gdk surface.
 *
 * We assume that this function is drawing to an exposed/showing
 * drawing area, so the status update will reflect the current
 * exposed/showing drawing area. */
void qp_graph_draw(struct qp_graph *gr, cairo_t *gdk_cr)
{
  GtkAllocation allocation;

  if(gr->waiting_to_resize_draw && !gr->qp->shape)
  {
    //WARN("gr=%p gr->name=\"%s\" gr->ref_count=%d\n", gr, gr->name, gr->ref_count);
    cairo_set_source_rgba(gdk_cr, gr->background_color.r,
      gr->background_color.g, gr->background_color.b,
      gr->background_color.a);

    cairo_paint(gdk_cr);

    g_idle_add_full(G_PRIORITY_LOW, idle_callback, gr, NULL);
    /* fight qp_graph_destroy() race condition with flag */
    ++gr->ref_count;
    /* We draw after the other widgets are drawn, in case drawing
     * takes a long time.  This waiting also gives a chance
     * for the watch cursor to show.  But that seems to only
     * show if the window had focus at the right time. */
    return;
  }

  gtk_widget_get_allocation(gr->drawing_area, &allocation);
  
  if(gr->pixbuf_needs_draw)
  {
    cairo_t *db_cr; /* double buffer cr */

    db_cr = cairo_create(gr->pixbuf_surface);
    graph_draw(gr, db_cr, gr->pixbuf_x, gr->pixbuf_y,
                  gr->pixbuf_width, gr->pixbuf_height);
    cairo_destroy(db_cr);
    // debuging
    //cairo_surface_write_to_png(gr->pixbuf_surface, "x.png");
    qp_win_set_status(gr->qp);
  }

  /* the GTK cairo_t *gdk_cr has no alpha bits so all the
   * alpha drawn to it will be smushed. */
  //WARN("content=0x%lx\n", (unsigned long)cairo_get_target(gdk_cr));


  if(!gr->qp->shape)
  {
    /* Not using the shape X11 extension */

    /* This is where we go from the back buffer to the drawing area */
    draw_from_pixbuf(gdk_cr, gr, allocation.width, allocation.height);

    if(gr->draw_zoom_box == 1)
      draw_zoom_box(gdk_cr, gr);
    if(gr->draw_value_pick)
      draw_value_pick_line(gdk_cr, gr, allocation.width, allocation.height);


    if(gr->pixbuf_needs_draw)
    {
      gdk_window_set_cursor(gtk_widget_get_window(gr->qp->window), NULL);
      gr->pixbuf_needs_draw = 0;
      // gr->qp->wait_warning_showing = 0;
    }
  }
  else
  {
    /* Use the X11 shape extension */


    /* TODO: This is a resource pig.  Fix it. */

    cairo_region_t *reg_draw_area, *window_region;
    /* empty flag */ 
    int empty;
    cairo_surface_t *mask_surface;
    GtkAllocation all;

    /* Make sure the surface is up to date */
    //cairo_surface_flush(gr->pixbuf_surface);

    /* make a sub surface that is the size of the graph drawing area */
    mask_surface = cairo_surface_create_for_rectangle(gr->pixbuf_surface,
        INT(gr->pixbuf_x+gr->grab_x),
        INT(gr->pixbuf_y+gr->grab_y),
        allocation.width, allocation.height);
    
    reg_draw_area = get_cairo_region_create_from_surface(gr,
        mask_surface, allocation.width, allocation.height);

    cairo_surface_destroy(mask_surface);

    cairo_region_translate(reg_draw_area, allocation.x, allocation.y);

    gtk_widget_get_allocation(gr->qp->window, &all);
    all.x = all.y = 0;

    window_region = cairo_region_create_rectangle(&all);

    cairo_region_subtract_rectangle(window_region, &allocation);

    empty = cairo_region_is_empty(reg_draw_area);

    if(!empty)  
      cairo_region_union(window_region, reg_draw_area);

    cairo_region_destroy(reg_draw_area);

    /* window_region is a region with a hole in it the
     * size of the drawing area with the graph and grid added back. */


    if(gr->draw_zoom_box && !empty)
    {
      cairo_rectangle_int_t rec;
      rec.x = allocation.x + gr->z_x;
      rec.y = allocation.y + gr->z_y;
      rec.width = gr->z_w;
      rec.height = gr->z_h;
      /* regions do not like negitive values or
       * maybe shapes do not like negitive values
       * in any case we keep width and height
       * positive */
      if(rec.width < 0)
      {
        rec.width *= -1;
        rec.x -= rec.width;
      }
      if(rec.height < 0)
      {
        rec.height *= -1;
        rec.y -= rec.height;
      }
        
      cairo_region_union_rectangle(window_region, &rec);
      /* now we have the zoom box added to window_region */
    }


    /* This is where we go from the back buffer to the drawing area */
    draw_from_pixbuf(gdk_cr, gr, allocation.width, allocation.height);
    if(gr->draw_zoom_box)
      draw_zoom_box(gdk_cr, gr);
    if(gr->draw_value_pick)
      draw_value_pick_line(gdk_cr, gr, allocation.width, allocation.height);


    if(empty)
    {
      /* we have nothing to make a shape with */
      if(gr->qp->last_shape_region)
      {
        cairo_region_destroy(gr->qp->last_shape_region);
        gr->qp->last_shape_region = NULL;
      }
      cairo_region_destroy(window_region);
      /* remove the old shape region */
      gtk_widget_shape_combine_region(gr->qp->window, NULL);
    }
    else if(!gr->qp->last_shape_region ||
        !cairo_region_equal(gr->qp->last_shape_region, window_region))
    {
      // DEBUG("creating new shape region\n");
      
      /* We need to undo the old shape first */
      gtk_widget_shape_combine_region(gr->qp->window, NULL);

      gtk_widget_shape_combine_region(gr->qp->window, window_region);

      if(gr->qp->last_shape_region)
        cairo_region_destroy(gr->qp->last_shape_region);

      gr->qp->last_shape_region = window_region;
    }
    else
      cairo_region_destroy(window_region);


    gr->pixbuf_needs_draw = 0;

    gdk_window_set_cursor(gtk_widget_get_window(gr->qp->window), NULL);
    // debuging
    //cairo_surface_write_to_png(cairo_get_target(gdk_cr), "y.png");
  }

  if(gr->qp->update_graph_detail && gr->qp->graph_detail)
  {
    gr->qp->update_graph_detail = 0;
    /* make the graph configure window show stuff about this graph */
    qp_win_graph_detail_init(gr->qp);
  }
}
Example #9
0
static void
gtk_border_image_render (GtkBorderImage   *image,
                         const double      border_width[4],
                         cairo_t          *cr,
                         gdouble           x,
                         gdouble           y,
                         gdouble           width,
                         gdouble           height)
{
  cairo_surface_t *surface, *slice;
  GtkBorderImageSliceSize vertical_slice[3], horizontal_slice[3];
  GtkBorderImageSliceSize vertical_border[3], horizontal_border[3];
  double source_width, source_height;
  int h, v;

  _gtk_css_image_get_concrete_size (image->source,
                                    0, 0,
                                    width, height,
                                    &source_width, &source_height);

  /* XXX: Optimize for (source_width == width && source_height == height) */

  surface = _gtk_css_image_get_surface (image->source,
                                        cairo_get_target (cr),
                                        source_width, source_height);

  gtk_border_image_compute_slice_size (horizontal_slice,
                                       source_width, 
                                       _gtk_css_number_value_get (_gtk_css_border_value_get_left (image->slice), source_width),
                                       _gtk_css_number_value_get (_gtk_css_border_value_get_right (image->slice), source_width));
  gtk_border_image_compute_slice_size (vertical_slice,
                                       source_height, 
                                       _gtk_css_number_value_get (_gtk_css_border_value_get_top (image->slice), source_height),
                                       _gtk_css_number_value_get (_gtk_css_border_value_get_bottom (image->slice), source_height));
  gtk_border_image_compute_border_size (horizontal_border,
                                        x,
                                        width,
                                        border_width[GTK_CSS_LEFT],
                                        border_width[GTK_CSS_RIGHT],
                                        _gtk_css_border_value_get_left (image->width),
                                        _gtk_css_border_value_get_right (image->width));
  gtk_border_image_compute_border_size (vertical_border,
                                        y,
                                        height,
                                        border_width[GTK_CSS_TOP],
                                        border_width[GTK_CSS_BOTTOM],
                                        _gtk_css_border_value_get_top (image->width),
                                        _gtk_css_border_value_get_bottom(image->width));
  
  for (v = 0; v < 3; v++)
    {
      if (vertical_slice[v].size == 0 ||
          vertical_border[v].size == 0)
        continue;

      for (h = 0; h < 3; h++)
        {
          if (horizontal_slice[h].size == 0 ||
              horizontal_border[h].size == 0)
            continue;

          if (h == 1 && v == 1)
            continue;

          slice = cairo_surface_create_for_rectangle (surface,
                                                      horizontal_slice[h].offset,
                                                      vertical_slice[v].offset,
                                                      horizontal_slice[h].size,
                                                      vertical_slice[v].size);

          gtk_border_image_render_slice (cr,
                                         slice,
                                         horizontal_slice[h].size,
                                         vertical_slice[v].size,
                                         horizontal_border[h].offset,
                                         vertical_border[v].offset,
                                         horizontal_border[h].size,
                                         vertical_border[v].size,
                                         h == 1 ? _gtk_css_border_repeat_value_get_x (image->repeat) : GTK_CSS_REPEAT_STYLE_STRETCH,
                                         v == 1 ? _gtk_css_border_repeat_value_get_y (image->repeat) : GTK_CSS_REPEAT_STYLE_STRETCH);

          cairo_surface_destroy (slice);
        }
    }

  cairo_surface_destroy (surface);
}
Example #10
0
static cairo_test_status_t
draw (cairo_t *cr, int width, int height)
{
    cairo_surface_t *region, *similar;
    cairo_t *cr_region, *cr_similar;

    cairo_set_source_rgb (cr, .5, .5, .5);
    cairo_paint (cr);

    similar = cairo_surface_create_similar (cairo_get_target (cr),
					    CAIRO_CONTENT_COLOR_ALPHA,
					    20, 20);

    /* copy the centre */
    cr_similar = cairo_create (similar);
    cairo_surface_destroy (similar);
    cairo_set_source_surface (cr_similar, cairo_get_target (cr), -20, -20);
    cairo_paint (cr_similar);
    similar = cairo_surface_reference (cairo_get_target (cr_similar));
    cairo_destroy (cr_similar);

    /* fill the centre */
    region = cairo_surface_create_for_rectangle (cairo_get_target (cr),
						 20, 20, 20, 20);
    cr_region = cairo_create (region);
    cairo_surface_destroy (region);

    cairo_set_source_rgb (cr_region, 1, 1, 1);
    cairo_rectangle (cr_region, 0, 0, 10, 10);
    cairo_fill (cr_region);

    cairo_set_source_rgb (cr_region, 1, 0, 0);
    cairo_rectangle (cr_region, 10, 0, 10, 10);
    cairo_fill (cr_region);

    cairo_set_source_rgb (cr_region, 0, 1, 0);
    cairo_rectangle (cr_region, 0, 10, 10, 10);
    cairo_fill (cr_region);

    cairo_set_source_rgb (cr_region, 0, 0, 1);
    cairo_rectangle (cr_region, 10, 10, 10, 10);
    cairo_fill (cr_region);

    cairo_destroy (cr_region);

    /* copy the centre, again */
    cr_similar = cairo_create (similar);
    cairo_surface_destroy (similar);
    cairo_set_source_surface (cr_similar, cairo_get_target (cr), -20, -20);
    cairo_paint (cr_similar);
    similar = cairo_surface_reference (cairo_get_target (cr_similar));
    cairo_destroy (cr_similar);

    /* repeat the pattern around the outside, but do not overwrite...*/
    cairo_set_source_surface (cr, similar, 20, 20);
    cairo_pattern_set_extend (cairo_get_source (cr), CAIRO_EXTEND_REPEAT);
    cairo_rectangle (cr, 0, 0, width, height);
    cairo_rectangle (cr, 20, 40, 20, -20);
    cairo_fill (cr);

    cairo_surface_destroy (similar);

    return CAIRO_TEST_SUCCESS;
}
void PlatformContextCairo::drawSurfaceToContext(cairo_surface_t* surface, const FloatRect& destRect, const FloatRect& originalSrcRect, GraphicsContext* context)
{
    FloatRect srcRect = originalSrcRect;

    // We need to account for negative source dimensions by flipping the rectangle.
    if (originalSrcRect.width() < 0) {
        srcRect.setX(originalSrcRect.x() + originalSrcRect.width());
        srcRect.setWidth(std::fabs(originalSrcRect.width()));
    }
    if (originalSrcRect.height() < 0) {
        srcRect.setY(originalSrcRect.y() + originalSrcRect.height());
        srcRect.setHeight(std::fabs(originalSrcRect.height()));
    }

    // Cairo subsurfaces don't support floating point boundaries well, so we expand the rectangle.
    IntRect expandedSrcRect(enclosingIntRect(srcRect));

    // We use a subsurface here so that we don't end up sampling outside the originalSrcRect rectangle.
    // See https://bugs.webkit.org/show_bug.cgi?id=58309
    RefPtr<cairo_surface_t> subsurface = adoptRef(cairo_surface_create_for_rectangle(
        surface, expandedSrcRect.x(), expandedSrcRect.y(), expandedSrcRect.width(), expandedSrcRect.height()));
    RefPtr<cairo_pattern_t> pattern = adoptRef(cairo_pattern_create_for_surface(subsurface.get()));

    ASSERT(m_state);
    switch (m_state->m_imageInterpolationQuality) {
    case InterpolationNone:
    case InterpolationLow:
        cairo_pattern_set_filter(pattern.get(), CAIRO_FILTER_FAST);
        break;
    case InterpolationMedium:
    case InterpolationHigh:
        cairo_pattern_set_filter(pattern.get(), CAIRO_FILTER_BILINEAR);
        break;
    case InterpolationDefault:
        cairo_pattern_set_filter(pattern.get(), CAIRO_FILTER_BILINEAR);
        break;
    }
    cairo_pattern_set_extend(pattern.get(), CAIRO_EXTEND_PAD);

    // The pattern transformation properly scales the pattern for when the source rectangle is a
    // different size than the destination rectangle. We also account for any offset we introduced
    // by expanding floating point source rectangle sizes. It's important to take the absolute value
    // of the scale since the original width and height might be negative.
    float scaleX = std::fabs(srcRect.width() / destRect.width());
    float scaleY = std::fabs(srcRect.height() / destRect.height());
    float leftPadding = static_cast<float>(expandedSrcRect.x()) - floorf(srcRect.x());
    float topPadding = static_cast<float>(expandedSrcRect.y()) - floorf(srcRect.y());
    cairo_matrix_t matrix = { scaleX, 0, 0, scaleY, leftPadding, topPadding };
    cairo_pattern_set_matrix(pattern.get(), &matrix);

    ShadowBlur& shadow = context->platformContext()->shadowBlur();
    if (shadow.type() != ShadowBlur::NoShadow) {
        if (GraphicsContext* shadowContext = shadow.beginShadowLayer(context, destRect)) {
            drawPatternToCairoContext(shadowContext->platformContext()->cr(), pattern.get(), destRect, 1);
            shadow.endShadowLayer(context);
        }
    }

    cairo_save(m_cr.get());
    drawPatternToCairoContext(m_cr.get(), pattern.get(), destRect, globalAlpha());
    cairo_restore(m_cr.get());
}