Exemple #1
0
 def _notify_canvas_observers(self, affected_layers):
     bbox = helpers.Rect()
     for layer in affected_layers:
         layer_bbox = layer.get_bbox()
         bbox.expandToIncludeRect(layer_bbox)
     for func in self.doc.canvas_observers:
         func(*bbox)
 def get_bbox(self):
     res = helpers.Rect()
     for layer in self.layers:
         # OPTIMIZE: only visible layers...
         # careful: currently saving assumes that all layers are included
         bbox = layer.get_bbox()
         res.expandToIncludeRect(bbox)
     return res
Exemple #3
0
    def flood_fill(self,
                   x,
                   y,
                   color,
                   tolerance=0.1,
                   sample_merged=False,
                   make_new_layer=False):
        """Flood-fills a point on the current layer with a colour

        :param x: Starting point X coordinate
        :param y: Starting point Y coordinate
        :param color: The RGB color to fill connected pixels with
        :type color: tuple
        :param tolerance: How much filled pixels are permitted to vary
        :type tolerance: float [0.0, 1.0]
        :param sample_merged: Use all visible layers when sampling
        :type sample_merged: bool
        :param make_new_layer: Write output to a new layer on top
        :type make_new_layer: bool

        Filling an infinite canvas requires limits. If the frame is
        enabled, this limits the maximum size of the fill, and filling
        outside the frame is not possible.

        Otherwise, if the entire document is empty, the limits are
        dynamic.  Initially only a single tile will be filled. This can
        then form one corner for the next fill's limiting rectangle.
        This is a little quirky, but allows big areas to be filled
        rapidly as needed on blank layers.
        """
        bbox = helpers.Rect(*tuple(self.get_effective_bbox()))
        rootstack = self.layer_stack
        if not self.layer_stack.current.get_fillable():
            make_new_layer = True
        if bbox.empty():
            bbox = helpers.Rect()
            bbox.x = N * int(x // N)
            bbox.y = N * int(y // N)
            bbox.w = N
            bbox.h = N
        elif not self.frame_enabled:
            bbox.expandToIncludePoint(x, y)
        cmd = command.FloodFill(self, x, y, color, bbox, tolerance,
                                sample_merged, make_new_layer)
        self.do(cmd)
Exemple #4
0
    def load_ora(self, filename, feedback_cb=None):
        """Loads from an OpenRaster file"""
        logger.info('load_ora: %r', filename)
        t0 = time.time()
        tempdir = self._tempdir
        orazip = zipfile.ZipFile(filename)
        logger.debug('mimetype: %r', orazip.read('mimetype').strip())
        xml = orazip.read('stack.xml')
        image_elem = ET.fromstring(xml)
        root_stack_elem = image_elem.find('stack')
        image_width = max(0, int(image_elem.attrib.get('w', 0)))
        image_height = max(0, int(image_elem.attrib.get('h', 0)))
        # Resolution: false value, 0 specifically, means unspecified
        image_xres = max(0, int(image_elem.attrib.get('xres', 0)))
        image_yres = max(0, int(image_elem.attrib.get('yres', 0)))

        # Delegate loading of image data to the layers tree itself
        self.layer_stack.clear()
        self.layer_stack.load_from_openraster(orazip,
                                              root_stack_elem,
                                              tempdir,
                                              feedback_cb,
                                              x=0,
                                              y=0)
        assert len(self.layer_stack) > 0

        # Set up symmetry axes
        for path, descendent in self.layer_stack.deepenumerate():
            descendent.set_symmetry_axis(self.get_symmetry_axis())

        # Resolution information if specified
        # Before frame to benefit from its observer call
        if image_xres and image_yres:
            self._xres = image_xres
            self._yres = image_yres
        else:
            self._xres = None
            self._yres = None

        # Set the frame size to that saved in the image.
        self.update_frame(x=0,
                          y=0,
                          width=image_width,
                          height=image_height,
                          user_initiated=False)

        # Enable frame if the saved image size is something other than the
        # calculated bounding box. Goal: if the user saves an "infinite
        # canvas", it loads as an infinite canvas.
        bbox_c = helpers.Rect(x=0, y=0, w=image_width, h=image_height)
        bbox = self.get_bbox()
        frame_enab = not (bbox_c == bbox or bbox.empty() or bbox_c.empty())
        self.set_frame_enabled(frame_enab, user_initiated=False)

        orazip.close()

        logger.info('%.3fs load_ora total', time.time() - t0)
Exemple #5
0
 def _notify_canvas_observers(self, layer_bboxes):
     """Notifies the document's redraw observers"""
     warn("Layers should issue their own canvas updates",
          PendingDeprecationWarning, stacklevel=2)
     redraw_bbox = helpers.Rect()
     for layer_bbox in layer_bboxes:
         if layer_bbox.w == 0 and layer_bbox.h == 0:
             redraw_bbox = layer_bbox
             break
         else:
             redraw_bbox.expandToIncludeRect(layer_bbox)
     self.doc.canvas_area_modified(*redraw_bbox)
Exemple #6
0
    def get_bbox(self):
        """Returns the dynamic bounding box of the document.

        This is currently the union of all the bounding boxes of all of the
        layers. It disregards the user-chosen frame.

        """
        res = helpers.Rect()
        for layer in self.layers:
            # OPTIMIZE: only visible layers...
            # careful: currently saving assumes that all layers are included
            bbox = layer.get_bbox()
            res.expandToIncludeRect(bbox)
        return res
Exemple #7
0
    def get_full_redraw_bbox(self):
        """Returns the full-redraw bounding box of the document

        This is the same concept as `layer.BaseLayer.get_full_redraw_bbox()`,
        and is built up from the full-redraw bounding boxes of all layers.
        """
        res = helpers.Rect()
        for layer in self.layer_stack.deepiter():
            bbox = layer.get_full_redraw_bbox()
            if bbox.w == 0 and bbox.h == 0:  # infinite
                res = bbox
            else:
                res.expandToIncludeRect(bbox)
        return res
Exemple #8
0
        if selected_layer is not None:
            for i, layer in zip(range(len(self.layers)), self.layers):
                if layer is selected_layer:
                    self.select_layer(i)
                    break

        # Set the frame size to that saved in the image.
        self.update_frame(x=0,
                          y=0,
                          width=image_w,
                          height=image_h,
                          user_initiated=False)

        # Enable frame if the saved image size is something other than the
        # calculated bounding box. Goal: if the user saves an "infinite
        # canvas", it loads as an infinite canvas.
        bbox_c = helpers.Rect(x=0, y=0, w=image_w, h=image_h)
        bbox = self.get_bbox()
        frame_enab = not (bbox_c == bbox or bbox.empty() or bbox_c.empty())
        self.set_frame_enabled(frame_enab, user_initiated=False)

        z.close()

        # remove empty directories created by zipfile's extract()
        for root, dirs, files in os.walk(tempdir, topdown=False):
            for name in dirs:
                os.rmdir(os.path.join(root, name))
        os.rmdir(tempdir)

        logger.info('%.3fs load_ora total', time.time() - t0)
Exemple #9
0
def get_tiles_bbox(tiles):
    res = helpers.Rect()
    for tx, ty in tiles:
        res.expandToIncludeRect(helpers.Rect(N * tx, N * ty, N, N))
    return res
Exemple #10
0
 def get_bbox(self):
     rect = helpers.Rect(*self.get_bbox_c())
     return rect