def rectangle_stroke_region(rect: Optional[Rect2[float]], width: float) -> cairo.Region: if rect is None: return cairo.Region() left_side = cairo.RectangleInt( int(math.floor(rect.x0 - width - 1)), int(math.floor(rect.y0 - width - 1)), int(math.ceil(2 * width + 2)), int(math.ceil(rect.h + 2 * width + 2)), ) right_side = cairo.RectangleInt( int(math.floor(rect.x1 - width - 1)), int(math.floor(rect.y0 - width - 1)), int(math.ceil(2 * width + 2)), int(math.ceil(rect.h + 2 * width + 2)), ) top_side = cairo.RectangleInt( int(math.floor(rect.x0 - width - 1)), int(math.floor(rect.y0 - width - 1)), int(math.ceil(rect.w + 2 * width + 2)), int(math.ceil(2 * width + 2)), ) bottom_side = cairo.RectangleInt( int(math.floor(rect.x0 - width - 1)), int(math.floor(rect.y1 - width - 1)), int(math.ceil(rect.w + 2 * width + 2)), int(math.ceil(2 * width + 2)), ) return cairo.Region([left_side, right_side, top_side, bottom_side])
def test_region_cmp_hash(): region = cairo.Region() other = cairo.Region() differ = cairo.Region(cairo.RectangleInt(0, 0, 10, 10)) with pytest.raises(TypeError): hash(region) assert region == region assert region == other assert not region != other assert region != differ with pytest.raises(TypeError): region < region with pytest.raises(TypeError): region > region rect = cairo.RectangleInt(1, 2, 10, 13) same = cairo.RectangleInt(1, 2, 10, 13) other = cairo.RectangleInt(2, 2, 10, 13) with pytest.raises(TypeError): hash(rect) assert rect == same assert rect != other with pytest.raises(TypeError): rect < same with pytest.raises(TypeError): rect > same
def test_region(): with pytest.raises(TypeError): cairo.Region(object()) with pytest.raises(TypeError): cairo.Region(object(), object()) with pytest.raises(TypeError): cairo.Region([object()])
def draw(self): self.painted = True if self.rgba_support or self.width < 4 or self.height < 4: return outer = cairo.Region(cairo.RectangleInt(0, 0, self.width, self.height)) inner = cairo.Region( cairo.RectangleInt(2, 2, self.width - 4, self.height - 4)) outer.subtract(inner) self.shape_combine_region(outer)
def circle_region(x: float, y: float, radius: float): radius = math.fabs(radius) if radius == 0.0: return cairo.Region() return cairo.Region( cairo.RectangleInt( x=int(math.floor(x - radius)), y=int(math.floor(y - radius)), width=int(math.ceil(2 * radius)), height=int(math.ceil(2 * radius)), ))
def test_region_contains_rectangle(): rect = cairo.RectangleInt(1, 2, 10, 13) region = cairo.Region() assert region.contains_rectangle(rect) == cairo.RegionOverlap.OUT assert isinstance(region.contains_rectangle(rect), cairo.RegionOverlap) with pytest.raises(TypeError): region.contains_rectangle(object())
def test_contains_point(): rect = cairo.RectangleInt(0, 0, 10, 10) r = cairo.Region(rect) assert r.contains_point(0, 0) assert not r.contains_point(0, 20) with pytest.raises(TypeError): r.contains_point(0, object())
def _artist_invalidated(self, artist: Artist, region: Optional[cairo.Region]) -> None: if region is None: self.invalidate() return if self._last_draw_transform is None: self.invalidate() return xx, xy, yx, yy, x0, y0 = self._last_draw_transform if yx or xy: # XXX: Calculating invalidated region for skew/rotations not implemented. self.invalidate() return region = cairo.Region([ cairo.RectangleInt( math.floor(x0 + xx * rect.x), math.floor(y0 + yy * rect.y), math.ceil(xx * rect.width), math.ceil(yy * rect.height), ) for rect in map(region.get_rectangle, range(region.num_rectangles())) ]) self.invalidate(region)
def _draw_lens(self, x: int, y: int): """ Calculate what image data to put in the lens and update the cursor with it; <x> and <y> are the positions of the cursor within the main window layout area """ if self.__window.images[0].get_storage_type() not in (Gtk.ImageType.PIXBUF, Gtk.ImageType.ANIMATION): return rectangle = self._calculate_lens_rect(x, y, config['LENS_SIZE'], config['LENS_SIZE']) rectangle_alt = [rectangle.x, rectangle.y, rectangle.width, rectangle.height] pixbuf = self._get_lens_pixbuf(x, y) draw_region = cairo.Region(rectangle=rectangle) window = self.__window.get_main_layout().get_bin_window() window.end_draw_frame(window.begin_draw_frame(draw_region)) self._clear_lens(rectangle_alt) cr = window.cairo_create() surface = Gdk.cairo_surface_create_from_pixbuf(pixbuf, 0, window) cr.set_source_surface(surface, rectangle.x, rectangle.y) cr.paint() window.end_paint() self.__last_lens_rect = rectangle_alt
def _draw_lens(self, x: int, y: int): """ Calculate what image data to put in the lens and update the cursor with it; <x> and <y> are the positions of the cursor within the main window layout area """ rectangle = self._calculate_lens_rect(x, y, config['LENS_SIZE'], config['LENS_SIZE']) pixbuf = self._get_lens_pixbuf(x, y) draw_region = cairo.Region(rectangle=rectangle) window = self.__window.main_layout.get_window() frame = window.begin_draw_frame(draw_region) self._clear_lens(rectangle) cr = Gdk.DrawingContext.get_cairo_context(frame) surface = Gdk.cairo_surface_create_from_pixbuf(pixbuf, 0, window) cr.set_source_surface(surface, rectangle.x, rectangle.y) cr.paint() window.end_paint() window.end_draw_frame(frame) self.__last_lens_rect = rectangle
def toggle_pass_through(self): if not self.pass_through: self.input_shape_combine_region(cairo.Region()) self.pass_through = True else: self.input_shape_combine_region(None) self.pass_through = False self.queue_draw()
def test_subtract(): rect = cairo.RectangleInt(0, 0, 10, 10) r = cairo.Region(rect) r.subtract(r) with pytest.raises(TypeError): r.subtract(object()) with pytest.raises(TypeError): r.subtract()
def test_equal(): rect = cairo.RectangleInt(0, 0, 10, 10) r = cairo.Region(rect) assert r.equal(r) with pytest.raises(TypeError): r.equal(object()) with pytest.raises(TypeError): r.equal()
def cairo_region_create_from_surface(surface, mask_accuracy): rect = cairo.RectangleInt() extents = _cairo_surface_extents(surface) if extents != False: if surface.get_content() == cairo.CONTENT_COLOR: return cairo.Region(extents) if type( surface ) != cairo.ImageSurface or surface.get_format != cairo.FORMAT_A1: image = cairo.ImageSurface(cairo.FORMAT_A1, extents.width, extents.height) cr = cairo.Context(image) cr.set_source_surface(surface, -extents.x, -extents.y) cr.paint() else: image = surface image.flush() data = image.get_data() stride = image.get_stride() region = cairo.Region() for y in range(0, extents.height, mask_accuracy): for x in range(0, extents.width, mask_accuracy): x0 = x while x < extents.width: if sys.byteorder == 'little': if ((data[y * stride + x // 8] >> (x % 8)) & 1) == 0: break if sys.byteorder == 'big': if ((data[y * stride + x // 8] >> (7 - (x % 8))) & 1) == 0: break x += mask_accuracy if x > x0: rect.x = x0 rect.width = x - x0 rect.y = y rect.height = mask_accuracy region.union(rect) region.translate(extents.x, extents.y) return region
def test_xor(): rect = cairo.RectangleInt(0, 0, 10, 10) r = cairo.Region(rect) r.xor(r) r.xor(rect) with pytest.raises(TypeError): r.xor(object()) with pytest.raises(TypeError): r.xor()
def _invalidate(self) -> None: xc = self._xc yc = self._yc radius = self._radius radius_scale = self._last_drawn_radius_scale inv_region = self._last_drawn_region or cairo.Region() inv_region.union(circle_region(xc, yc, radius_scale * radius)) self.invalidate(inv_region)
def _invalidate(self) -> None: extents = self._extents stroke_width = self._stroke_width stroke_scale = self._last_drawn_stroke_scale inv_region = self._last_drawn_region or cairo.Region() inv_region.union( rectangle_stroke_region(extents, stroke_width * stroke_scale)) self.invalidate(inv_region)
def test_get_rectangle(): rect = cairo.RectangleInt(0, 0, 10, 10) r = cairo.Region(rect) with pytest.raises(ValueError): r.get_rectangle(-1) with pytest.raises(ValueError): r.get_rectangle(1) assert r.get_rectangle(0) == rect with pytest.raises(TypeError): r.get_rectangle(object())
def on_configure(self, *_): window_x, window_y = self.get_position() window_width, window_height = self.get_size() # set event mask for click-through self.input_shape_combine_region( cairo.Region(cairo.RectangleInt(0, 0, 0, 0))) # set some proportional inner padding self.label.set_padding(window_width // 100, 0) self.update_font()
def __init__(self, title='veil'): super(Veil, self).__init__() self.brush_id = 0 self.brushes = [ PolygonBrush(), FilledRectangleBrush(), LineBrush(), FreehandBrush(), CircleBrush() ] self.active_tool = self.brushes[0] self.images = [] self.connect("destroy", Gtk.main_quit) self.set_title(title) self.screen = self.get_screen() # type: GdkX11.X11Screen s = Gdk.Screen.get_default() self.width = s.get_width() self.height = s.get_height() #self.set_size_request(s.get_width(), s.get_height()) # unresizeable self.fullscreen() # toggles, user-controlled vars self.pass_through = False self.hidden = False self.grid = False self.glow = 0 self.rgbtheme = [0, 1, 0] self.rgbatheme = [0, 1, 0, 0.1] visual = self.screen.get_rgba_visual() if visual and self.screen.is_composited(): self.set_visual(visual) if self.pass_through: self.input_shape_combine_region(cairo.Region()) self.set_decorated(False) self.set_app_paintable(True) self.set_keep_above(True) self.connect('draw', self.veil_update) self.connect('button-press-event', self.mouse_press) self.connect('motion-notify-event', self.mouse_move) self.connect('button-release-event', self.mouse_release) self.connect('key-press-event', self.key_press) self.connect('key-release-event', self.key_release) self.set_events(self.get_events() | Gdk.EventMask.BUTTON_PRESS_MASK | Gdk.EventMask.POINTER_MOTION_MASK | Gdk.EventMask.BUTTON_RELEASE_MASK | Gdk.EventMask.KEY_PRESS_MASK | Gdk.EventMask.KEY_RELEASE_MASK) self.show()
def test_intersect(): rect = cairo.RectangleInt(0, 0, 10, 10) r = cairo.Region(rect) r.intersect(r) r.intersect(rect) with pytest.raises(TypeError): r.intersect(object()) with pytest.raises(TypeError): r.intersect() assert r.__eq__(object()) == NotImplemented assert rect.__eq__(object()) == NotImplemented
def region(self): # TODO x1 = int(self.left()) x2 = int(self.right()) y1 = int(self.top()) y2 = int(self.bottom()) w = int(self.w) h = int(self.h) r = cairo.Region(cairo.RectangleInt(x=x1, y=y1, width=1, height=h)) r.union(cairo.RectangleInt(x=x1, y=y1, width=w, height=1)) r.union(cairo.RectangleInt(x=x2, y=y1, width=1, height=h)) r.union(cairo.RectangleInt(x=x1, y=y2, width=w, height=1)) return r
def get_mask(self): w, h = self.get_size() region = cairo.Region(cairo.RectangleInt(width=0, height=0)) for i in list(self.ui.actions.keys()): r = i.region() if r: region.union(r) else: logger.warning("warning: no region for " + str(i)) p = self.root.get_pointer() self.cut_pointer(region, p.x, p.y) return region
def show(self): """Show this mouse indicator and ignore awaiting fade away request.""" if self.timeout_timer and self.shown: # There is a fade away request, ignore it if (GLib.main_context_default().find_source_by_id( self.timeout_timer) and not GLib.main_context_default().find_source_by_id( self.timeout_timer).is_destroyed()): GLib.source_remove(self.timeout_timer) self.timeout_timer = None # This method only is called when mouse is pressed, so there will be a # release and fade_away call, no need to set up another timer. super(ShapedWindow, self).show() # Fix click-through self.input_shape_combine_region(cairo.Region())
def extents(self, extents: Optional[Rect2[float]]) -> None: self._extents = extents inv_region = self._last_drawn_region if extents: to_draw = cairo.Region( cairo.RectangleInt(int(extents.x - 1), int(extents.y - 1), int(extents.w + 2), int(extents.h + 2))) if inv_region is not None: inv_region.union(to_draw) else: inv_region = to_draw if inv_region is not None: self.invalidate(inv_region)
def reload(self): '''重新设定属性, 然后重绘''' if self.app.conf['osd-locked']: self.toolbar.hide() try: region = cairo.Region() except AttributeError: print('cairo.Region is missing, a patch is required:', 'http://bugs.debian.org/688079') logger.error(traceback.format_exc()) return self.input_shape_combine_region(region) else: self.toolbar.show_all() self.app.conf['osd-toolbar-y'] = self.toolbar.get_allocated_height( ) self.auto_hide_toolbar() self.input_shape_combine_region(None) self.move(self.app.conf['osd-x'], self.app.conf['osd-y'])
def draw(self, cr: cairo.Context) -> None: polyline = self._polyline stroke_width = self._stroke_width stroke_color = self._stroke_color if polyline is None or len(polyline) == 0: self._last_drawn_region = None return if self._path_cache is not None: cr.append_path(self._path_cache) else: self._show_polyline(cr, polyline) self._path_cache = cr.copy_path() extents = Rect2(cr.path_extents()) dx = 1 / cr.get_matrix().xx dy = 1 / cr.get_matrix().yy cr.save() if self._scale_strokes: stroke_scale = max(dx, dy) cr.identity_matrix() else: stroke_scale = 1.0 cr.set_line_width(stroke_width) cr.set_source_rgba(*stroke_color) cr.stroke() cr.restore() extents = expand_rect(extents, max(stroke_width * stroke_scale, dx, dy)) self._last_drawn_region = cairo.Region( cairo.RectangleInt( int(math.floor(extents.x)), int(math.floor(extents.y)), int(math.ceil(extents.w)), int(math.ceil(extents.h)), ))
def cb_draw(self, widget, cr): cr.set_source_rgba(0.0, 0.0, 0.0, 0.0) cr.set_operator(cairo.OPERATOR_SOURCE) cr.paint() surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, self.w, self.h) surface_ctx = cairo.Context(surface) surface_ctx.set_source_rgba(1.0, 1.0, 1.0, 0.0) surface_ctx.set_operator(cairo.OPERATOR_SOURCE) surface_ctx.paint() rect = cairo.RectangleInt(0, 0, 1, 1) reg = cairo.Region(rect) if (not reg.is_empty()): widget.input_shape_combine_region(None) widget.input_shape_combine_region(reg) cr.move_to(0, 0) cr.set_source_rgba(1.0, 0.0, 0.0, 0.8) cr.set_line_width(2.0) # # Seriously? # The thing is, windows cannot overlap Panel or Launcher. # Ugly code taking care of this overlapping is below. # if self.y > self.panel_height - 1: cr.line_to(self.w, 0) else: cr.move_to(self.w, 0) if self.x + self.w < HW.screens[self.screen.get_number()]['width']: cr.line_to(self.w, self.h) else: cr.move_to(self.w, self.h) if self.y + self.h < HW.screens[self.screen.get_number()]['height']: cr.line_to(0, self.h) else: cr.move_to(0, self.h) if self.x > self.launcher_width: cr.line_to(0, 0) cr.stroke() cr.set_operator(cairo.OPERATOR_OVER)
def draw(self, cr: cairo.Context) -> None: if self._extents is None or self._surface is None: return extents = self._extents surface = self._surface matrix = cairo.Matrix() matrix.scale(surface.get_width() / extents.w, surface.get_height() / extents.h) matrix.translate(-extents.x, -extents.y) pattern = cairo.SurfacePattern(surface) pattern.set_filter(cairo.Filter.FAST) pattern.set_matrix(matrix) cr.set_source(pattern) cr.paint() self._last_drawn_region = cairo.Region( cairo.RectangleInt(int(extents.x - 1), int(extents.y - 1), int(extents.w + 2), int(extents.h + 2)))
def on_draw(self, *args): # FIXME: This is running constantly, I only want it to run once after window is initialised # Tell the window manager to fullscreen this window # FIXME [1]: Before this self.fullscreen() # Tell the window manager to keep this window on every workspace self.stick() # Tell the window manager to keep this window on top self.set_keep_above(True) # I'm not sure whether the WM or X11 handles this, but make the window not accept focus self.set_accept_focus(False) # Tell the Window manager not to show it in the alt-tab menu or taskbar self.set_skip_taskbar_hint(True) # FIXME: This just don't seem to work self.set_skip_pager_hint(True) # Tell the compositor that mouse clicks anywhere on the window go through to what's behind it # NOTE: This can't be done before the window has been created # NOTE: Is there any problem with this happening before the window has been sized? self.input_shape_combine_region(cairo.Region(cairo.RectangleInt(0, 0, 1, 1))) self.hide() # DEBUGGING: Minimize the window because it's all broken at the moment anyway