Inkscape.org
Creating New Extensions Text Bounding Boxes Command Call
  1. #1
    inklinea inklinea @inklinea⛰️

    Put together something for myself on Inkscape 1.1   ( I don't use earlier versions )

    It uses a command call to create : 

    Red dashed bounding boxes for text Elements 

    Blue dashed bounding boxes for tspan Elements

    Red circles for the centre points of text Elements

    Blue circles for the centre points of tspan Elements.

     

    import inkex
    import random
    from inkex import command, Circle, Rectangle, units, styles
    
    def query_all_bbox(self):
        my_file_path = self.options.input_file
        ink = inkex.command.INKSCAPE_EXECUTABLE_NAME
        try:
            my_query = inkex.command.inkscape(my_file_path, '--query-all')
            my_query_items = my_query.split('\n')
        except:
            return
    
        my_element_list = []
        for my_query_item in my_query_items:
            my_element = my_query_item.split(',')
    
            # Reject any malformed query lines
            if len(my_element) > 4 and ('tspan' in my_element[0] or 'text' in my_element[0]):
                my_element_list.append(my_element)
    
        for element in my_element_list:
    
            my_element_object = self.svg.getElementById(element[0])
    
            if 'tspan' in element[0]:
                object_type = 'tspan'
            else:
                object_type = 'text'
    
            cl_bbox_x = float(element[1])
            cl_bbox_y = float(element[2])
            cl_bbox_width = float(element[3])
            cl_bbox_height = float(element[4])
    
            cl_bbox_center_x = (cl_bbox_x + (cl_bbox_x + cl_bbox_width)) / 2
            cl_bbox_center_y = (cl_bbox_y + (cl_bbox_y + cl_bbox_height)) / 2
    
            my_element_object.cl_bbox_x = cl_bbox_x
            my_element_object.cl_bbox_y = cl_bbox_y
            my_element_object.cl_bbox_width = cl_bbox_width
            my_element_object.cl_bbox_height = cl_bbox_height
    
            my_element_object.cl_bbox_center_x = cl_bbox_center_x
            my_element_object.cl_bbox_center_y = cl_bbox_center_y
    
            # Mark the centres and bounding boxes of elements
    
            make_outlines(self, my_element_object.cl_bbox_center_x, my_element_object.cl_bbox_center_y, my_element_object.cl_bbox_x, my_element_object.cl_bbox_y, my_element_object.cl_bbox_width, my_element_object.cl_bbox_height, object_type)
    
    
    
    
    def make_outlines(self, center_x, center_y, x, y, width, height, object_type):
    
        conversions = {
            'in': 96.0,
            'pt': 1.3333333333333333,
            'px': 1.0,
            'mm': 3.779527559055118,
            'cm': 37.79527559055118,
            'm': 3779.527559055118,
            'km': 3779527.559055118,
            'Q': 0.94488188976378,
            'pc': 16.0,
            'yd': 3456.0,
            'ft': 1152.0,
            '': 1.0,  # Default px
        }
        found_units = self.svg.unit
    
        try:
            pixel_conversion_factor = conversions[found_units]
        except:
            pixel_conversion_factor = 1
    
        my_circle = Circle()
        my_circle.style['stroke-width'] = 1
        if object_type == 'text':
            my_circle.style['fill'] = 'red'
        else:
            my_circle.style['fill'] = 'blue'
    
        my_circle.style['stroke'] = 'black'
        my_circle.radius = 2
        my_circle.center = (center_x / pixel_conversion_factor, center_y / pixel_conversion_factor)
        self.svg.get_current_layer().append(my_circle)
    
        my_rectangle = Rectangle().new(x / pixel_conversion_factor, y / pixel_conversion_factor, width / pixel_conversion_factor, height / pixel_conversion_factor)
        my_rectangle.style['stroke-width'] = 0.5
        my_rectangle.style['fill'] = 'none'
        if object_type == 'text':
            my_rectangle.style['stroke'] = 'red'
            my_rectangle.style['stroke-dasharray'] = '1,1'
        else:
            my_rectangle.style['stroke'] = 'blue'
            my_rectangle.style['stroke-dasharray'] = '1,2'
        self.svg.get_current_layer().append(my_rectangle)
    
    
    
    
    
    
    
    
    
    
    class MyFirstExtension(inkex.EffectExtension):
        def effect(self):
    
    
            query_all_bbox(self)
    
    
    if __name__ == '__main__':
        MyFirstExtension().run()
    
  2. #2
    inklinea inklinea @inklinea⛰️

    Should have pointed out. 

    It is not possible to get the bounding box of text or tspan elements from the extension system directly. You can have a hacky attempt using pango, but it's not accurate.

    The purpose of this command call is to enable the extension system to access accurate values for the placement of text by the extension :)