3.6. Extending The Text Box Script

3.6.1. Handling Undo Correctly

When creating a script, you want to give your users the ability to undo their actions, should they make a mistake. This is easily accomplished by calling the functions gimp-undo-push-group-start and gimp-undo-push-group-end around the code that manipulates the image. You can think of them as matched statements that let GIMP know when to start and stop recording manipulations on the image, so that those manipulations can later be undone.

If you are creating a new image entirely, it doesn't make sense to use these functions because you're not changing an existing image. However, when you are changing an existing image, you most surely want to use these functions.

Undoing a script works nearly flawlessly when using these functions.

3.6.2. Extending The Script A Little More

Now that we have a very handy-dandy script to create text boxes, let's add two features to it:

  • Currently, the image is resized to fit exactly around the text — there's no room for anything, like drop shadows or special effects (even though many scripts will automatically resize the image as necessary). Let's add a buffer around the text, and even let the user specify how much buffer to add as a percentage of the size of the resultant text.

  • This script could easily be used in other scripts that work with text. Let's extend it so that it returns the image and the layers, so other scripts can call this script and use the image and layers we create.

3.6.3. Modifying The Parameters And The Registration Function

To let the user specify the amount of buffer, we'll add a parameter to our function and the registration function:

  (define (script-fu-text-box inTest inFont inFontSize inTextColor inBufferAmount)
           ; define our local variables
           ; create a new image:
           (theImageWidth  10)
           (theImageHeight 10)
           (theImage (car
           (theText)          ;a declaration for the text
                              ;we create later

           (theBuffer)        ;added

                          "layer 1"
        ) ;end of our local variables

   [Code here]
    "script-fu-text-box"                        ;func name
    "Text Box"                                  ;menu label
    "Creates a simple text box, sized to fit\
      around the user's choice of text,\
      font, font size, and color."              ;description
    "Michael Terry"                             ;author
    "copyright 1997, Michael Terry;\
      2009, the GIMP Documentation Team"        ;copyright notice
    "October 27, 1997"                          ;date created
    ""                     ;image type that the script works on
    SF-STRING      "Text"          "Text Box"   ;a string variable
    SF-FONT        "Font"          "Charter"    ;a font variable
    SF-ADJUSTMENT  "Font size"     '(50 1 1000 1 10 0 1)
                                                ;a spin-button
    SF-COLOR       "Color"         '(0 0 0)     ;color variable
    SF-ADJUSTMENT  "Buffer amount" '(35 0 100 1 10 1 0)
                                                ;a slider
  (script-fu-menu-register "script-fu-text-box" "<Image>/Font/Create/Text")

3.6.4. Adding The New Code

We're going to add code in two places: right before we resize the image, and at the end of the script (to return the new image, the layer and the text).

After we get the text's height and width, we need to resize these values based on the buffer amount specified by the user. We won't do any error checking to make sure it's in the range of 0-100% because it's not life-threatening, and because there's no reason why the user can't enter a value like 200 as the percent of buffer to add.

        (set! theBuffer (* theImageHeight (/ inBufferAmount 100) ) )

        (set! theImageHeight (+ theImageHeight theBuffer theBuffer) )
        (set! theImageWidth  (+ theImageWidth  theBuffer theBuffer) )

All we're doing here is setting the buffer based on the height of the text, and adding it twice to both the height and width of our new image. (We add it twice to both dimensions because the buffer needs to be added to both sides of the text.)

Now that we have resized the image to allow for a buffer, we need to center the text within the image. This is done by moving it to the (x, y) coordinates of (theBuffer, theBuffer). I added this line after resizing the layer and the image:

        (gimp-layer-set-offsets theText theBuffer theBuffer)

Go ahead and save your script, and try it out after refreshing the database.

All that is left to do is return our image, the layer, and the text layer. After displaying the image, we add this line:

(list theImage theLayer theText)

This is the last line of the function, making this list available to other scripts that want to use it.

To use our new text box script in another script, we could write something like the following:

        (set! theResult (script-fu-text-box
                         "Some text"
                         "Charter" "30"
                         '(0 0 0)
        (gimp-image-flatten (car theResult))

Congratulations, you are on your way to your Black Belt of Script-Fu!