Search code examples
gimpgimpfu

Add a line feed to a python gimp 2.8.4 script


I have a Python Gimp script that works well, but have one issue:

When I need to place multiple lines on an image, I have to create two separate text layers.

             #Sample of text parameter xml file
        <txtLyrs>
        <extra_txtLyr>
        <extra_txtLyr txtLyrName="lblLayer6" LyrFontColor="WHITE" \
        LyrFontName="Interstate-Bold Bold" LyrFontSize="15.0" txtLyrString=\
        "Some Text" txtX="460" txtY="331" txtlyr_height="17" txtlyr_width="73" index="71" />
        <extra_txtLyr txtLyrName="lblLayer5" LyrFontColor="WHITE" \
        LyrFontName="Interstate-Bold Bold" LyrFontSize="8.0" txtLyrString=\
        "Some Text [10][13] Really Long Text" txtX="676" txtY="144" txtlyr_height="9"\
         txtlyr_width="95" index="70" />
        <extra_txtLyr txtLyrName="lblLayer4" LyrFontColor="WHITE" \
        LyrFontName="Interstate-Bold Bold" LyrFontSize="8.0" txtLyrString=\
        "Some Text" txtX="676" txtY="130" txtlyr_height="9" txtlyr_width="125" index="69" />
        <extra_txtLyr txtLyrName="lblLayer3" LyrFontColor="WHITE" \
        LyrFontName="Interstate-Bold Bold" LyrFontSize="15.0" txtLyrString=\
        "Some Text" txtX="678" txtY="331" txtlyr_height="17" txtlyr_width="72" index="68" />
        </extra_txtLyrs>
        </txtLyrs>

        #Constants removed to make smaller block

        #Helper function to read parameters from xml file
        def get_extratxt_btn_params( active_name ): 

            active_dgm = active_name
            extraTxtLayers = xmldoc.getElementsByTagName("txtLyrs")[0]

            if active_dgm:
                siteTxtLayers = xmldoc.getElementsByTagName("extra_txtLyr")[0]
                extraButtonTxtLayers = siteTxtLayers.getElementsByTagName("extra_txtLyr")
            else:
                siteTxtLayers = xmldoc.getElementsByTagName("other_txtLyr")[0]
                extraButtonTxtLayers = siteTxtLayers.getElementsByTagName("other_txtLyr")

            extraTxtParms = {}
            for lyrParm in extraButtonTxtLayers:
                lyrParams = [ lyrParm.getAttribute("txtLyrName"), \
                lyrParm.getAttribute("LyrFontName"), \
                lyrParm.getAttribute("LyrFontSize"), lyrParm.getAttribute("txtLyrString"), \
                lyrParm.getAttribute("LyrFontColor"), lyrParm.getAttribute("txtlyr_height"), \
                lyrParm.getAttribute("txtlyr_width"), lyrParm.getAttribute("txtX"), \
                lyrParm.getAttribute("txtY")]
                extraTxtParms [lyrParm.getAttribute("index")] = lyrParams
            return extraTxtParms

         ##**function called by GIMP to create text layers from xml file

        def dgm_extratxtlyr_create(image, drawable, title_color, inactive_color, active_color, \
        alarm_color, normal_color, active_diagram):

        txtlyrdict = get_extratxt_params( active_diagram )

        d_sorted_by_value = OrderedDict(sorted(txtlyrdict.items(), key=lambda x: x[1]))

        for k, txtlyr in d_sorted_by_value.items():
            #Assign Layer Text
            txtlayerName = txtlyr[3]
            #Assign Layer Font Name
            font_name = txtlyr[1]
            #Assign Font Size 
            font_size = txtlyr[2]

            #Assign Text color RGB values for colors are predefined constants because 
            #tuples don't pass correctly from xml

            if txtlyr[4] == "RED":
                textcolor = alarm_color
            elif txtlyr[4] == "WHITE":
                textcolor = inactive_color
            elif txtlyr[4] == "GREEN":
                textcolor = normal_color
            elif txtlyr[4] == "BLACK":
                textcolor = active_color

            #Assign Text X Coordinate
            xloc = txtlyr[7]
            #Assign Text Y Coordinate
            yloc = txtlyr[8]
            #Create the new text layer
            temp_layer = pdb.gimp_text_layer_new(image, txtlayerName, font_name, font_size, 0)
            #Add it to the image
            pdb.gimp_image_add_layer(image,temp_layer,-1)
            #Change the color of the text
            pdb.gimp_text_layer_set_color(temp_layer,textcolor)
            #Move the text to the proper location
            pdb.gimp_layer_translate(temp_layer, xloc, yloc)
            #Set the text justification
            pdb.gimp_text_layer_set_justification(temp_layer, 0)

How can I tell GIMP to add line feeds to the text layers, when I know they are too long?


Solution

  • Just add "new line" characters in your text string, before calling pdb.gimp_text_layer_new, as appropriate.

    Btw, the variable you are naming "txtlayerName" (considerations about variable naming style apart) is the actual Text Content of the layer - not just the layer name. It happens that GIMP's usually name text layers by its contents by default - the parameter taken by gimp_text_layer_add_new is the actual text content on the image. You could also consider using the more complete call : "pdb.gimp_text_fontname` instead- which already adds the layer to the image, at the offset you want.

    As for inserting the new lines using Python code, it is as simple as using the powerful langage syntax and methods for string manipulation to do that. For example, prior to creating the layer, you could do a lot of things.

    This snippet replaces spaces by new lines if the layer is more than 12 characters long, and cut arbitrarily at each 6 chars if there are no spaces. It is naive, but you can get the idea and fashion your code:

    if len(txtlayerName) > 12:
       if " " in txtlayerName:
           txtlayerName = txtlayerName.replace(" ", "\n")
       else:
           textlayerName = "\n".join(txtlayerName[i:i+6] for i in range(0, len(txtlayerName), 6))
    

    This snippet allows for longer lines, assumiong there are several words in each line - let's suppose you want a max-width of 80 chars, and there are several white-space separated words in the text:

    textwidth = 80
    result = []
    txtline = []
    index = 0
    for word in textlayerName.split():
        if index + len(word) <  textwidth:
            txtline.append(word)
            index += len(word)
        else:
            result.append(" ".join(txtline))
            txtline = [word]
            index = len(word)
    
    textlayerName = "\n".join(result)