void ChromeClient::scroll(const IntSize& delta, const IntRect& rectToScroll, const IntRect& clipRect)
{
    GdkWindow* window = GTK_WIDGET(m_webView)->window;
    if (!window)
        return;

    // We cannot use gdk_window_scroll here because it is only able to
    // scroll the whole window at once, and we often need to scroll
    // portions of the window only (think frames).
    GdkRectangle area = clipRect;
    GdkRectangle moveRect;

    GdkRectangle sourceRect = area;
    sourceRect.x -= delta.width();
    sourceRect.y -= delta.height();

    GdkRegion* invalidRegion = gdk_region_rectangle(&area);

    if (gdk_rectangle_intersect(&area, &sourceRect, &moveRect)) {
        GdkRegion* moveRegion = gdk_region_rectangle(&moveRect);
        gdk_window_move_region(window, moveRegion, delta.width(), delta.height());
        gdk_region_offset(moveRegion, delta.width(), delta.height());
        gdk_region_subtract(invalidRegion, moveRegion);
        gdk_region_destroy(moveRegion);
    }

    gdk_window_invalidate_region(window, invalidRegion, FALSE);
    gdk_region_destroy(invalidRegion);
}
Exemple #2
0
void ChromeClient::scroll(const IntSize& delta, const IntRect& rectToScroll, const IntRect& clipRect)
{
    if (!m_webView)
        return;

    GdkWindow* window = GTK_WIDGET(m_webView)->window;
    if (!window)
        return;

    GdkRectangle area = clipRect;
    GdkRectangle moveRect;

    GdkRectangle sourceRect = area;
    sourceRect.x -= delta.width();
    sourceRect.y -= delta.height();

    GdkRegion* invalidRegion = gdk_region_rectangle(&area);

    if (gdk_rectangle_intersect(&area, &sourceRect, &moveRect)) {
        GdkRegion* moveRegion = gdk_region_rectangle(&moveRect);
        gdk_window_move_region(window, moveRegion, delta.width(), delta.height());
        gdk_region_offset(moveRegion, delta.width(), delta.height());
        gdk_region_subtract(invalidRegion, moveRegion);
        gdk_region_destroy(moveRegion);
    }

    gdk_window_invalidate_region(window, invalidRegion, FALSE);
    gdk_region_destroy(invalidRegion);
}
//__________________________________________________________________
void		_HYPlatformButton::_Paint (Ptr p)
{	
	_HYButton * theParent = (_HYButton*)this;

	GdkRectangle    	cRect = HYRect2GDKRect(*(_HYRect*)p);
	
	if (!(theParent->settings.width&HY_COMPONENT_TRANSP_BG))
	{
		if (theParent->parentWindow->window)
		{
			GdkGC *buttonGC				 = gdk_gc_new (theParent->parentWindow->window);
			gdk_gc_set_foreground(buttonGC,&bgColor);
			GdkRegion * r1 = gdk_region_rectangle(&cRect), 
					  * r2 = gdk_region_rectangle (&buttonRect);

			gdk_region_subtract	   (r1,r2);
			gdk_region_offset	   (r1,theParent->parentWindow->allocation.x,theParent->parentWindow->allocation.y);
			gdk_gc_set_clip_region (buttonGC,r1);
			gdk_draw_rectangle(theParent->parentWindow->window,buttonGC,true,cRect.x+theParent->parentWindow->allocation.x, 
							   cRect.y+theParent->parentWindow->allocation.y, cRect.width, cRect.height);
			gdk_region_destroy(r1);
			gdk_region_destroy(r2);
			g_object_unref (buttonGC);
		}
	}
		
  	(*theParent)._HYPlatformComponent::_Paint(p);
}
Exemple #4
0
static void port_display_expose(GdkEventExpose *ev,
	GtkWidget *widget, GdkRectangle *rect, gdouble sliderstate, GdkPixbuf *image)
{
	cairo_t *cr = gdk_cairo_create(gtk_widget_get_window(widget));
    GxPortDisplay *port_display = GX_PORT_DISPLAY(widget);
    GdkRegion *region;
	region = gdk_region_rectangle (&widget->allocation);
	gdk_region_intersect (region, ev->region);
    gdk_cairo_region (cr, region);
    cairo_clip (cr);
	gdk_cairo_set_source_pixbuf(cr, image, rect->x - (rect->width-(gint)sliderstate), rect->y);
	cairo_rectangle(cr, rect->x, rect->y, rect->width, rect->height);
	cairo_fill(cr);
    if (port_display->cutoff_low + port_display->cutoff_high) {
      cairo_set_source_rgba (cr, 0.8, 0.1, 0.1, 0.4);
      cairo_set_line_width(cr, rect->height);
      gint low = rect->width * port_display->cutoff_low * 0.01;
      gint high = (rect->width* port_display->cutoff_high * 0.01)-2;
      gint lw = rect->height/2;
      cairo_move_to(cr,rect->x, rect->y+lw);
      cairo_line_to(cr,rect->x + low, rect->y+lw);
      cairo_stroke (cr);
      cairo_move_to(cr,rect->width - high, rect->y+lw);
      cairo_line_to(cr,rect->width+2, rect->y+lw);
      cairo_stroke (cr);
      cairo_set_source_rgba (cr, 0.1, 0.6, 0.1, 0.4);
      cairo_move_to(cr,rect->x+ low, rect->y+lw);
      cairo_line_to(cr,rect->width - high, rect->y+lw);
      cairo_stroke (cr);
      
    }
	cairo_destroy(cr);
    gdk_region_destroy (region);
}
Exemple #5
0
bool wxRegion::DoUnionWithRect(const wxRect& r)
{
    // workaround for a strange GTK/X11 bug: taking union with an empty
    // rectangle results in an empty region which is definitely not what we
    // want
    if ( r.IsEmpty() )
        return TRUE;

    if ( !m_refData )
    {
        InitRect(r.x, r.y, r.width, r.height);
    }
    else
    {
        AllocExclusive();

        GdkRectangle rect;
        rect.x = r.x;
        rect.y = r.y;
        rect.width = r.width;
        rect.height = r.height;

        GdkRegion *reg = gdk_region_union_with_rect( M_REGIONDATA->m_region, &rect );
        gdk_region_destroy( M_REGIONDATA->m_region );
        M_REGIONDATA->m_region = reg;
    }

    return TRUE;
}
void
gimp_display_shell_expose_region (GimpDisplayShell *shell,
                                  cairo_region_t   *region)
{
  GdkRegion *gdk_region;
  gint       n_rectangles;
  gint       i;

  g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
  g_return_if_fail (region != NULL);

  if (! gtk_widget_get_realized (shell->canvas))
    return;

  gdk_region = gdk_region_new ();
  n_rectangles = cairo_region_num_rectangles (region);

  for (i = 0; i < n_rectangles; i++)
    {
      cairo_rectangle_int_t rectangle;

      cairo_region_get_rectangle (region, i, &rectangle);

      gdk_region_union_with_rect (gdk_region, (GdkRectangle *) &rectangle);
    }

  gdk_window_invalidate_region (gtk_widget_get_window (shell->canvas),
                                gdk_region, TRUE);
  gdk_region_destroy (gdk_region);
}
Exemple #7
0
static void cdnewregion(cdCtxCanvas *ctxcanvas)
{
  if (ctxcanvas->new_rgn)
    gdk_region_destroy(ctxcanvas->new_rgn);

  ctxcanvas->new_rgn = gdk_region_new(); 
}
Exemple #8
0
static GdkFilterReturn 
gdk_superwin_bin_filter (GdkXEvent *gdk_xevent,
                         GdkEvent  *event,
                         gpointer   data)
{
  XEvent *xevent = (XEvent *)gdk_xevent;
  GdkSuperWin *superwin = data;
  GdkFilterReturn retval = GDK_FILTER_CONTINUE;
  GdkRegion *region = NULL;

  switch (xevent->xany.type) {
  case Expose:
    region = gdk_region_new();
    retval = GDK_FILTER_REMOVE;
    gdk_superwin_handle_expose(superwin, xevent, &region, FALSE);
    gdk_region_destroy(region);
    break;
  case KeyPress:
    if (superwin->keyprs_func)
      superwin->keyprs_func(&xevent->xkey);
    break;
  case KeyRelease:
    if (superwin->keyrel_func)
      superwin->keyrel_func(&xevent->xkey);
    break;
  default:
    break;
  }
  return retval;
}
Exemple #9
0
static gboolean
in_input_thumbnail (GtkWidget *widget, GdkEventMotion *event)
{
    g_assert (GTK_IS_TREE_VIEW (widget));

    gboolean result = FALSE;	/* Result to be returned. */

    GtkTreePath *tp = thumbnail_path (widget, event);

    if ( tp == NULL ) {
        return FALSE;		/* Pointer is not over a filled in row.  */
    }

    /* Check if we are over the input image thumbnail.  */
    GtkTreeViewColumn *itc = input_thumbnail_column (widget, event);
    GdkRectangle itnc_rect;	/* Input thumbnail cell rectangle.  */
    gtk_tree_view_get_cell_area (GTK_TREE_VIEW (widget), tp, itc, &itnc_rect);
    /* Here we depend on the fact that the input thumbnail is packed at
    the beginning of the cell horizontally, and centered in the cell
    vertically (FIXME: find a way to verify this with assertions).  */
    GdkRectangle itn_rect;	/* Input thumbnail rectangle.  */
    /* FIXME: fix this border hackery to be precise somehow.  */
    itn_rect.x = itnc_rect.x + 1;	/* There is probably a small border so +1.  */
    itn_rect.y = itnc_rect.y + 1;
    itn_rect.width = THUMB_SIZE;
    itn_rect.height = THUMB_SIZE;
    GdkRegion *itn_region = gdk_region_rectangle (&itn_rect);
    if ( gdk_region_point_in (itn_region, (int) event->x, (int) event->y) ) {
        result = TRUE;
        //    g_message ("Over input thumbnail!");
    }
    gdk_region_destroy (itn_region);

    return result;
}
Exemple #10
0
static void
cheese_flash_init (CheeseFlash *self)
{
  CheeseFlashPrivate *priv = CHEESE_FLASH_GET_PRIVATE (self);

  GtkWindow *window;

  priv->flash_timeout_tag = 0;
  priv->fade_timeout_tag  = 0;

  window = GTK_WINDOW (gtk_window_new (GTK_WINDOW_POPUP));

  /* make it so it doesn't look like a window on the desktop (+fullscreen) */
  gtk_window_set_decorated (window, FALSE);
  gtk_window_set_skip_taskbar_hint (window, TRUE);
  gtk_window_set_skip_pager_hint (window, TRUE);
  gtk_window_set_keep_above (window, TRUE);

  /* Don't take focus */
  gtk_window_set_accept_focus (window, FALSE);
  gtk_window_set_focus_on_map (window, FALSE);

  /* Don't consume input */
  gtk_widget_realize (GTK_WIDGET (window));
  GdkRegion *input_region;
  input_region = gdk_region_new ();
  gdk_window_input_shape_combine_region (gtk_widget_get_window (GTK_WIDGET (window)), input_region, 0, 0);
  gdk_region_destroy (input_region);

  g_signal_connect (G_OBJECT (window), "expose-event", G_CALLBACK (cheese_flash_window_expose_event_cb), NULL);
  priv->window = window;
}
void scenemanager_claim_polygon(scenemanager_t* pSceneManager, GdkPoint *pPoints, gint nNumPoints)
{
	// Create a GdkRegion from the given points and union it with the 'taken region'
	GdkRegion* pNewRegion = gdk_region_polygon(pPoints, nNumPoints, GDK_WINDING_RULE);
	gdk_region_union(pSceneManager->pTakenRegion, pNewRegion);
	gdk_region_destroy(pNewRegion);
}
gboolean scenemanager_can_draw_rectangle(scenemanager_t* pSceneManager, GdkRectangle* pRect, gint nFlags)
{
	//
	// 1) Enforce on-screen rules
	//
	if(nFlags & SCENEMANAGER_FLAG_FULLY_ON_SCREEN) {
		// basic rect1 contains rect2 test
		if((pRect->x) <= 0) return FALSE;
		if((pRect->y) <= 0) return FALSE;
		if((pRect->x + pRect->width) > pSceneManager->nWindowWidth) return FALSE;
		if((pRect->y + pRect->height) > pSceneManager->nWindowHeight) return FALSE;
	}
	else if(nFlags & SCENEMANAGER_FLAG_PARTLY_ON_SCREEN) {
		// basic rect intersect test
		if((pRect->x + pRect->width) <= 0) return FALSE;
		if((pRect->y + pRect->height) <= 0) return FALSE;
		if((pRect->x) > pSceneManager->nWindowWidth) return FALSE;
		if((pRect->y) > pSceneManager->nWindowHeight) return FALSE;
	}

	//
	// 2) Enforce overlap rules
	//
	GdkRegion* pNewRegion = gdk_region_rectangle(pRect);

	gdk_region_intersect(pNewRegion, pSceneManager->pTakenRegion); // sets pNewRegion to the intersection of itself and the 'taken region'
	gboolean bOK = gdk_region_empty(pNewRegion);	// it's ok to draw here if the intersection is empty
	gdk_region_destroy(pNewRegion);

	return bOK;
}
Exemple #13
0
/* Creates a new empty GdkRegion. */
int
clip_GDK_REGIONNEW(ClipMachine * ClipMachineMemory)
{
   ClipVar  *cv = _clip_spar(ClipMachineMemory, 1);

   GdkRegion *region;

   C_object *cregion;

   CHECKOPT(1, MAP_type_of_ClipVarType);

   region = gdk_region_new();

   if (region)
    {
       cregion = _register_object(ClipMachineMemory, region, GDK_TYPE_REGION, cv, NULL);
       if (cregion)
	  _clip_mclone(ClipMachineMemory, RETPTR(ClipMachineMemory), &cregion->obj);
       else
	  gdk_region_destroy(region);
    }
   return 0;
 err:
   return 1;
}
Exemple #14
0
/* static */ void
nsRegionGTK::Shutdown()
{
    if (copyRegion) {
        gdk_region_destroy(copyRegion);
        copyRegion = nsnull;
    }
}
void ChromeClient::scroll(const IntSize& delta, const IntRect& rectToScroll, const IntRect& clipRect)
{
    GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(m_webView));
    if (!window)
        return;

    m_pendingScrollInvalidations = true;

    // We cannot use gdk_window_scroll here because it is only able to
    // scroll the whole window at once, and we often need to scroll
    // portions of the window only (think frames).
    GdkRectangle area = clipRect;
    GdkRectangle moveRect;

    GdkRectangle sourceRect = area;
    sourceRect.x -= delta.width();
    sourceRect.y -= delta.height();

#ifdef GTK_API_VERSION_2
    GdkRegion* invalidRegion = gdk_region_rectangle(&area);

    if (gdk_rectangle_intersect(&area, &sourceRect, &moveRect)) {
        GdkRegion* moveRegion = gdk_region_rectangle(&moveRect);
        gdk_window_move_region(window, moveRegion, delta.width(), delta.height());
        gdk_region_offset(moveRegion, delta.width(), delta.height());
        gdk_region_subtract(invalidRegion, moveRegion);
        gdk_region_destroy(moveRegion);
    }

    gdk_window_invalidate_region(window, invalidRegion, FALSE);
    gdk_region_destroy(invalidRegion);
#else
    cairo_region_t* invalidRegion = cairo_region_create_rectangle(&area);

    if (gdk_rectangle_intersect(&area, &sourceRect, &moveRect)) {
        cairo_region_t* moveRegion = cairo_region_create_rectangle(&moveRect);
        gdk_window_move_region(window, moveRegion, delta.width(), delta.height());
        cairo_region_translate(moveRegion, delta.width(), delta.height());
        cairo_region_subtract(invalidRegion, moveRegion);
        cairo_region_destroy(moveRegion);
    }

    gdk_window_invalidate_region(window, invalidRegion, FALSE);
    cairo_region_destroy(invalidRegion);
#endif
}
Exemple #16
0
/**
 * gdk_event_free:
 * @event:  a #GdkEvent.
 * 
 * Frees a #GdkEvent, freeing or decrementing any resources associated with it.
 * Note that this function should only be called with events returned from
 * functions such as gdk_event_peek(), gdk_event_get(),
 * gdk_event_get_graphics_expose() and gdk_event_copy().
 **/
void
gdk_event_free (GdkEvent *event)
{
  g_return_if_fail (event != NULL);

  if (event->any.window)
    g_object_unref (event->any.window);
  
  switch (event->any.type)
    {
    case GDK_KEY_PRESS:
    case GDK_KEY_RELEASE:
      g_free (event->key.string);
      break;
      
    case GDK_ENTER_NOTIFY:
    case GDK_LEAVE_NOTIFY:
      if (event->crossing.subwindow != NULL)
	g_object_unref (event->crossing.subwindow);
      break;
      
    case GDK_DRAG_ENTER:
    case GDK_DRAG_LEAVE:
    case GDK_DRAG_MOTION:
    case GDK_DRAG_STATUS:
    case GDK_DROP_START:
    case GDK_DROP_FINISHED:
      g_object_unref (event->dnd.context);
      break;

    case GDK_BUTTON_PRESS:
    case GDK_BUTTON_RELEASE:
      g_free (event->button.axes);
      break;
      
    case GDK_EXPOSE:
    case GDK_DAMAGE:
      if (event->expose.region)
	gdk_region_destroy (event->expose.region);
      break;
      
    case GDK_MOTION_NOTIFY:
      g_free (event->motion.axes);
      break;
      
    case GDK_SETTING:
      g_free (event->setting.name);
      break;
      
    default:
      break;
    }

  _gdk_windowing_event_data_free (event);

  g_hash_table_remove (event_hash, event);
  g_slice_free (GdkEventPrivate, (GdkEventPrivate*) event);
}
Exemple #17
0
nsresult nsRegionGTK::Init(void)
{
    if (mRegion) {
        gdk_region_destroy(mRegion);
        mRegion = nsnull;
    }

    return NS_OK;
}
Exemple #18
0
static gboolean
about_dialog_anim_expose (GtkWidget       *widget,
                          GdkEventExpose  *event,
                          GimpAboutDialog *dialog)
{
  GdkGC *text_gc;
  gint   x, y;
  gint   width, height;

  if (! dialog->visible)
    return FALSE;

  text_gc = widget->style->text_gc[GTK_STATE_NORMAL];

  pango_layout_get_pixel_size (dialog->layout, &width, &height);

  x = (widget->allocation.width - width) / 2;
  y = (widget->allocation.height - height) / 2;

  if (dialog->textrange[1] > 0)
    {
      GdkRegion *covered_region = NULL;
      GdkRegion *rect_region;

      covered_region = gdk_pango_layout_get_clip_region (dialog->layout,
                                                         x, y,
                                                         dialog->textrange, 1);

      rect_region = gdk_region_rectangle (&event->area);

      gdk_region_intersect (covered_region, rect_region);
      gdk_region_destroy (rect_region);

      gdk_gc_set_clip_region (text_gc, covered_region);
      gdk_region_destroy (covered_region);
    }

  gdk_draw_layout (widget->window, text_gc, x, y, dialog->layout);

  gdk_gc_set_clip_region (text_gc, NULL);

  return FALSE;
}
static void
gdk_window_post_scroll (GdkWindow    *window,
			GdkRegion    *new_clip_region)
{
  GDK_NOTE (EVENTS,
	    g_print ("gdk_window_clip_changed: invalidating region: %s\n",
		     _gdk_win32_gdkregion_to_string (new_clip_region)));

  gdk_window_invalidate_region (window, new_clip_region, FALSE);
  gdk_region_destroy (new_clip_region);
}
Exemple #20
0
    virtual ~wxRegionRefData()
    {
        if (m_region)
        {
#ifdef __WXGTK3__
            cairo_region_destroy(m_region);
#else
            gdk_region_destroy( m_region );
#endif
        }
    }
Exemple #21
0
static void
clip_region_clear(DiaRenderer *object)
{
  DiaGdkRenderer *renderer = DIA_GDK_RENDERER (object);

  if (renderer->clip_region != NULL)
    gdk_region_destroy(renderer->clip_region);

  renderer->clip_region =  gdk_region_new();

  gdk_gc_set_clip_region(renderer->gc, renderer->clip_region);
}
void scenemanager_clear(scenemanager_t* pSceneManager)
{
	g_assert(pSceneManager != NULL);

	// destroy and recreate hash table (XXX: better way to clear it?)
	g_hash_table_destroy(pSceneManager->pLabelHash);
	pSceneManager->pLabelHash = g_hash_table_new(g_str_hash, g_str_equal);

	// Empty the region (XXX: better way?)
	gdk_region_destroy(pSceneManager->pTakenRegion);
	pSceneManager->pTakenRegion = gdk_region_new();
}
static void
clip_region_clear(DiaRenderer *object)
{
  DiaCairoInteractiveRenderer *renderer = DIA_CAIRO_INTERACTIVE_RENDERER (object);

  if (renderer->clip_region != NULL)
    gdk_region_destroy(renderer->clip_region);

  renderer->clip_region =  gdk_region_new();

  gdk_gc_set_clip_region(renderer->gc, renderer->clip_region);
}
Exemple #24
0
/*----------------------------------------------------------------------------*
 *                     DOM Window descriptor interface                        *
 *----------------------------------------------------------------------------*/
static void _gegueb_window_destroy(void *data)
{
	Gegueb_Window *thiz = data;
	Eina_Rectangle *r;

	gegueb_document_free(thiz->doc);
	gdk_window_destroy(thiz->win);
	gdk_region_destroy(thiz->regions);
	EINA_LIST_FREE(thiz->damages, r)
		free(r);
	g_free(thiz);
}
Exemple #25
0
static gboolean
cvw_redraw_timeout(CcViewWidget* self) {
	gdk_window_invalidate_region(GTK_WIDGET(self)->window, self->priv->dirty_region, FALSE);

	gdk_region_destroy(self->priv->dirty_region);
	self->priv->dirty_region   = NULL;

	self->priv->redraw_timeout = 0;
#ifdef DEBUG_SAVED_FRAMES
	self->priv->updates++;
#endif
	return FALSE; // we're done (for now)
}
Exemple #26
0
/* Destroys a GdkRegion. */
int
clip_GDK_REGIONDESTROY(ClipMachine * ClipMachineMemory)
{
   C_object *creg = _fetch_co_arg(ClipMachineMemory);

   CHECKCOBJ(creg, GDK_IS_REGION(creg->object));

   gdk_region_destroy(GDK_REGION(creg));

   return 0;
 err:
   return 1;
}
static void destroy_windata(WindowData* windata)
{
	if (windata->window_region != NULL)
	{
#if GTK_CHECK_VERSION (3, 0, 0)
		cairo_region_destroy(windata->window_region);
#else
		gdk_region_destroy(windata->window_region);
#endif
	}

	g_free(windata);
}
Exemple #28
0
void gtk_attractor_view_redraw(GtkWidget *widget)
{
    GdkRegion *region;
    if (!widget->window) return;

// 	gdk_window_get_size(widget->window, &W, &H);
    region = gdk_drawable_get_clip_region (widget->window);
    /* redraw the cairo canvas completely by exposing it */
    gdk_window_invalidate_region (widget->window, region, TRUE);
    gdk_window_process_updates (widget->window, TRUE);
    gdk_region_destroy (region);

}
static GdkRegion *
gdk_window_clip_changed (GdkWindow    *window,
			 GdkRectangle *old_clip,
			 GdkRectangle *new_clip)
{
  GdkWindowImplWin32 *impl;
  GdkWindowObject *obj;
  GdkRegion *old_clip_region;
  GdkRegion *new_clip_region;
  
  if (((GdkWindowObject *)window)->input_only)
    return NULL;

  obj = (GdkWindowObject *) window;
  impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);
  
  old_clip_region = gdk_region_rectangle (old_clip);
  new_clip_region = gdk_region_rectangle (new_clip);

  /* Trim invalid region of window to new clip rectangle
   */
  if (obj->update_area)
    gdk_region_intersect (obj->update_area, new_clip_region);

  /* Invalidate newly exposed portion of window
   */
  gdk_region_subtract (new_clip_region, old_clip_region);
  if (!gdk_region_empty (new_clip_region))
    gdk_window_tmp_unset_bg (window);
  else
    {
      gdk_region_destroy (new_clip_region);
      new_clip_region = NULL;
    }
  gdk_region_destroy (old_clip_region);

  return new_clip_region;
}
void GraphicsContext::drawFocusRing(const Color& color)
{
    if (paintingDisabled())
        return;

    const Vector<IntRect>& rects = focusRingRects();
    unsigned rectCount = rects.size();

    cairo_t* cr = m_data->cr;
    cairo_save(cr);
    cairo_push_group(cr);
    cairo_new_path(cr);

#if PLATFORM(GTK)
    GdkRegion* reg = gdk_region_new();
    for (unsigned i = 0; i < rectCount; i++) {
        GdkRectangle rect = rects[i];
        gdk_region_union_with_rect(reg, &rect);
    }
    gdk_cairo_region(cr, reg);
    gdk_region_destroy(reg);

    setColor(cr, color);
    cairo_set_line_width(cr, 2.0f);
    setPlatformStrokeStyle(DottedStroke);
#else
    int radius = (focusRingWidth() - 1) / 2;
    for (unsigned i = 0; i < rectCount; i++)
        addPath(Path::createRoundedRectangle(rects[i], FloatSize(radius, radius)));

    // Force the alpha to 50%.  This matches what the Mac does with outline rings.
    Color ringColor(color.red(), color.green(), color.blue(), 127);
    setColor(cr, ringColor);
    cairo_set_line_width(cr, focusRingWidth());
    setPlatformStrokeStyle(SolidStroke);
#endif

    cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
    cairo_stroke_preserve(cr);

    cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
    cairo_set_fill_rule(cr, CAIRO_FILL_RULE_WINDING);
    cairo_fill(cr);

    cairo_pop_group_to_source(cr);
    cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
    cairo_paint(cr);
    cairo_restore(cr);
}