Creating a Simple Beveled Button

Gimp 1.1 comes with a script to create a simple button. (You can read more about Gimp's scripts in the Gimp manual or at www.script-fu.org.) Go to Xtns / Script-Fu / Buttons / Simple Beveled Button. It will put up the script's parameters dialog box. Click OK. You should see a button that says "Hello World!".

Extending the Simple Beveled Button Script

You've got to get the script to remember the font from run to run, or you'll go gaga trying to create more than one or two buttons. To do this, you've got to make a copy of the script, and rewrite it a bit. You can read more about writing Gimp scripts in the Gimp manual, and also in the Gimp Developers' FAQ.

Here are the steps to customize the script.

Copy the script in to your personal script directory

	$ cd ~/.gimp.scripts
	$ cp /usr/share/gimp/scripts/beveled-button.scm foo-button.scm.orig
	$ cp foo-button.scm.orig foo-button.scm

Edit the script to change its name

Note: for the impatient, you can skip forward and download an improved button script that has all the changes described below.

Using a text editor like pico, edit foo-button.scm as follows: Change all occurrances of 'button00' to 'button01', and "beveled button" to "beveled button #2". This should affect three lines:

(define (script-fu-button00 text
should become
(define (script-fu-button01 text
and
(script-fu-register "script-fu-button00"
		    "/Xtns/Script-Fu/Buttons/Simple beveled button"
should become
 
(script-fu-register "script-fu-button01"
		    "/Xtns/Script-Fu/Buttons/Simple beveled button #2"
Then write the file.

Test it

Test your changed script, to make sure it shows up in the menus, and does what it claims. Have Gimp refresh its scripts by clicking Xtns / Script-Fu / Refresh. Then try out your new script; click Xtns / Script-Fu / Buttons / Simple Beveled Button #2. It should work just like the original one.

(If you get any errors, stop and check the differences between your script and the original, with the command

	$ diff foo-button.scm.orig foo-button.scm
It ought to match the changes listed above.)

A Useful Change

Now let's change the script's default values. Edit the lines
		    SF-VALUE "Size" "16"
		    SF-VALUE "Foundry" "\"adobe\""
		    SF-VALUE "Family" "\"helvetica\""
to have the font size, foundry, and exact name that you chose in the section above. Save the file, and have Gimp refresh its scripts as above, then try out your new script. It should default to the right font now.

Another Useful Change

If that worked, let's make a real change to the innards of the script. Let's add a second string which isn't displayed, but which sets the width of the button. (If you're making a bunch of buttons for the left side of a web page, you probably want them all the same width, right?) All we have to do is add another variable, 'reftext', just like 'text', and use its width instead. Here are context diffs that illustrate the difference; + in the left column indicates an added line, | indicates a changed line (in which case, the section from the new file is repeated right under the section for the old file; read 'man diff' for more info).
*** foo-button.old	Sat Apr  3 12:58:16 1999
--- foo-button.scm	Sat Apr  3 13:06:48 1999
***************
*** 50,55 ****
--- 50,56 ----
  	      y2))
  
  (define (script-fu-button01 text
+ 			    reftext
  			    size
  			    foundry
  			    family
***************
*** 66,72 ****
    (let* ((old-fg-color (car (gimp-palette-get-foreground)))
  	 (old-bg-color (car (gimp-palette-get-background)))
  	 
! 	 (text-extents (gimp-text-get-extents text
  					      size
  					      PIXELS
  					      foundry
--- 67,73 ----
    (let* ((old-fg-color (car (gimp-palette-get-foreground)))
  	 (old-bg-color (car (gimp-palette-get-background)))
  	 
! 	 (text-extents (gimp-text-get-extents reftext
  					      size
  					      PIXELS
  					      foundry
***************
*** 171,176 ****
--- 172,178 ----
  		    "Apr 1999"
  		    ""
  		    SF-VALUE "Text" "\"Hello world!\""
+ 		    SF-VALUE "Reftext" "\"This is how wide it is\""
  		    SF-VALUE "Size" "16"
  		    SF-VALUE "Foundry" "\"adobe\""
  		    SF-VALUE "Family" "\"helvetica\""
Try out the new script (after doing the usual save and refresh). It should set the button to be as wide as the reference text; the other text field (cleverly named Text) is displayed at its normal width, but inside a wide button.

But wait! It's not centered!

To get the text centered in the button, we have to do a little math. Since this is the first Gimp script I've ever written, the change I made is probably longer than it has to be. Here it is:
*** foo-button.old2	Sat Apr  3 13:06:48 1999
--- foo-button.scm	Sat Apr  3 13:00:31 1999
***************
*** 67,72 ****
--- 67,81 ----
    (let* ((old-fg-color (car (gimp-palette-get-foreground)))
  	 (old-bg-color (car (gimp-palette-get-background)))
  	 
+ 	 (real-text-extents (gimp-text-get-extents text
+ 					      size
+ 					      PIXELS
+ 					      foundry
+ 					      family
+ 					      weight
+ 					      slant
+ 					      set-width
+ 					      spacing))
  	 (text-extents (gimp-text-get-extents reftext
  					      size
  					      PIXELS
***************
*** 76,81 ****
--- 85,94 ----
  					      slant
  					      set-width
  					      spacing))
+ 	 (foo-width (text-width text-extents) )
+ 	 (foo-realwidth (text-width real-text-extents) )
+ 	 (foo-diff-x (- foo-width foo-realwidth ) )
+ 	 (foo-offset-x (/ foo-diff-x 2 ) )
  
  	 (ascent (text-ascent text-extents))
  	 (descent (text-descent text-extents))
***************
*** 151,157 ****
      (let ((textl (car (gimp-text
  		       img -1 0 0 text 0 TRUE size PIXELS foundry family weight slant set-width spacing))))
        (gimp-layer-set-offsets textl
! 			      (+ bevel-width padding)
  			      (+ bevel-width padding descent)))
  
      ; Done
--- 164,170 ----
      (let ((textl (car (gimp-text
  		       img -1 0 0 text 0 TRUE size PIXELS foundry family weight slant set-width spacing))))
        (gimp-layer-set-offsets textl
! 			      (+ (+ bevel-width padding) foo-offset-x)
  			      (+ bevel-width padding descent)))
  
      ; Done

The Result

If you don't feel like making all those changes by hand, here's the complete script.

Comparison with PowerPoint

The buttons produced by PowerPoint support multiline text, can use drop-shadowed text, and don't antialias the text; at least in one recent comparison, they looked better than the ones produced by Gimp for a particular task. The stock button script that comes with Gimp could use the following improvements:

Update 7/2001

Mark Lybarger contributed a version of the button script updated for Gimp 1.2, check it out. (I haven't tried it myself.)
Dan Kegel
Last update: 11 June 1999