File: write_scriptfu3.html

package info (click to toggle)
gimp-manual 1.0.0-5
  • links: PTS
  • area: main
  • in suites: woody
  • size: 19,112 kB
  • ctags: 11,163
  • sloc: makefile: 29; sh: 14
file content (855 lines) | stat: -rw-r--r-- 45,845 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">

<!-- Generated by fmtoweb (v. 2.9c) by Peter G. Martin -->
<HTML>
<HEAD><title>GUM v.1.0.0</title></HEAD><BODY TEXT="#000000" BGCOLOR="#FFFFFF" LINK="#0000EE" VLINK="#551A8B" ALINK="#FF0000">
<body>
<A HREF="write_scriptfu.html"><IMG ALIGN = BOTTOM SRC = "prev.gif" ALT="Previous"></A>
<A HREF="Part_nine.html"><IMG ALIGN = BOTTOM SRC = "next.gif" ALT="Next"></A>
<A HREF="index2.html"><IMG ALIGN=BOTTOM SRC = "toc.gif" ALT="TOC"></A>
<A HREF="GimpmanualIX.html"><IMG ALIGN = BOTTOM SRC = "index.gif" ALT="Index"></A>
<A HREF="webfeedback.html"><IMG ALIGN = BOTTOM SRC = "feedback.gif" ALT="Feedback"></A><P>

<center><h1>GUM v.1.0.0</h1></center>
<hr>

<A name="913089"><!-- 913089 --></A>
<P>

<A name="913090"><!-- 913090 --></A>
<P>

<A name="913094"><!-- 913094 --></A>


<A name="448435"><!-- 448435 --></A>
<H1>39&nbsp;</H1>

<A name="448436"><!-- 448436 --></A>
<H1>Mike Terry's black belt school of Script-Fu</H1>

<A name="446042"><!-- 446042 --></A>
<EM><P>A</P>uthor Mike Terry; Copyright 1998 by Mike Terry License, GDPCL.</EM><br>

<A name="446766"><!-- 446766 --></A>
<H2>The road to Script-Fu Mastery</H2>

<A name="446771"><!-- 446771 --></A>
<P>So, little grasshopper, you have found Gimp, and you want to learn of its secrets? </P>

<A name="446774"><!-- 446774 --></A>
<P>More specifically, you wish to learn of its fantastic scripting abilities, no? You are perhaps tantalized at the prospect of automating image-editing drudgery, or maybe you seek the kind precision in your work that only a well-written script can achieve... </P>

<A name="446778"><!-- 446778 --></A>
<P>Well, you have come to the right place, my friend, as <EM>Mike Terry's Black Belt School of Script-Fu</EM> can train you in the not-so-ancient art of Script-Fu. </P>

<A name="446794"><!-- 446794 --></A>
<H3>Course outline</H3>

<A name="446796"><!-- 446796 --></A>
<P>In this training course, we'll introduce you to the <EM>fundamentals</EM> of <EM>Scheme</EM> necessary to use Script-Fu, and then build a handy script which you can add to your toolbox of scripts. The script prompts the user for some text, then creates a new image sized perfectly to the text. We will then enhance the script to allow for a <EM>buffer</EM> of space around the text. </P>

<A name="446801"><!-- 446801 --></A>
<H4>Meet your instructor</H4>

<A name="446820"><!-- 446820 --></A>
<P>Let me first confess that I am currently only a yellow-belt of this art, and as such, can only take you so far. However, together, we can press on and reach new heights. If I err, omit some important detail in this training, or am just plain wrong about something, please email me so I may correct it.   Similarly, if you have tips or suggestions on how to improve your training, please forward them to me. </P>

<A name="446842"><!-- 446842 --></A>
<P>I hope you benefit from this training, and may you soon become a Master of <EM>Script-Fu</EM>! </P>

<A name="446844"><!-- 446844 --></A>
<H4>Audience</H4>

<A name="446863"><!-- 446863 --></A>
<P>These training sessions are intended for the beginning Script-Fu'er. When I heard that Gimp was scriptable, I got very excited, and wanted to dive right in. Unfortunately, the tutorials were scant and incomplete, especially if you knew no <EM>Scheme</EM> (like I didn't). After about two days of trying to force my square peg of C/C++ knowledge into the round hole of Scheme, I reckoned a tutorial from the ground-up, chock-full of demos, would do the new Script-Fu'er a lot of good. </P>

<A name="446851"><!-- 446851 --></A>
<P>Currently, then, the tutorial is really aimed at the beginner, but as I learn more, I will expand it so we can all be Script-Fu Masters! Your suggestions and complaints are welcome. </P>

<A name="446852"><!-- 446852 --></A>
<PRE><CODE>Michael Terry </CODE>
<CODE>mterry@soulfry.com </CODE>

</PRE><A name="448474"><!--448474--></A>
<H2>Lesson 1: Getting acquainted with Scheme</H2>

<A name="448475"><!-- 448475 --></A>
<H4>Let's start Scheme'ing</H4>

<A name="446887"><!-- 446887 --></A>
<P><STRONG>The first thing</STRONG> to learn is that every statement in Scheme is surrounded by <EM>parentheses</EM> - (). </P>

<A name="446890"><!-- 446890 --></A>
<P><STRONG>The second thing</STRONG> you need to know is that the <EM>function</EM> is always the <EM>first item</EM> in the parent and the rest of the items are <EM>parameters</EM> to the function. (However, not everything enclosed in parentheses is a function - they can also be items in a list, but we'll get to that later). </P>

<A name="446895"><!-- 446895 --></A>
<P><STRONG>The third thing</STRONG> to understand is that <EM>mathematical operators </EM>are also considered <EM>functions</EM>, and thus are listed first when writing mathematical expressions. If you're familiar with <EM>post-fix notation</EM>, or own a calculator that uses<EM> Reverse Polish Notation</EM> (such as most HP calculators), you should have no problem adapting to formulating expressions in Scheme. </P>

<A name="446901"><!-- 446901 --></A>
<P>Now, young grasshopper, let's practice what we have just learned. Start up Gimp, if you have not already done so, and choose <CODE>Xtns-&gt;Script-Fu-&gt;Console</CODE>. This will start up the <EM>Script-Fu Console</EM> window, which allows us to work interactively in Scheme. <BR><IMG SRC="write_scriptfu3-image-1.jpeg" ALT="Extracted pic [1]">
</P>

<A name="446928"><!-- 446928 --></A>
<P> <BR><IMG SRC="write_scriptfu3-image-2.jpeg" ALT="Extracted pic [2]">
In a matter of moments, the<EM> Script-Fu Console</EM> will appear:</P>

<A name="446931"><!-- 446931 --></A>
<P>At the bottom of this window is an entry-field entitled <EM>current command</EM>.  Here, we can test out simple Scheme commands interactively.</P>

<A name="446936"><!-- 446936 --></A>
<P> Let's start out easy, and add some numbers. </P>

<A name="446942"><!-- 446942 --></A>
<PRE>(+ 3 5)
</PRE><P>Typing this in and hitting <EM>Return</EM> yields the expected answer of <EM>8</EM> in the center window. </P>

<A name="446992"><!-- 446992 --></A>
<P>Now what if we wanted to add more than one number? The <EM>+</EM> function can take 2 or more arguments, so this is not a problem: </P>

<A name="446999"><!-- 446999 --></A>
<PRE>(+ 3 5 6)
</PRE><P>This also yields the expected answer of <EM>14</EM>. </P>

<A name="447006"><!-- 447006 --></A>
<P>So far, so good - we type in a Scheme statement and it's executed immediately in the Script-Fu Console window. Now for a word of caution... </P>

<A name="447013"><!-- 447013 --></A>
<H4>Watch out for extra parens.</H4>

<A name="447018"><!-- 447018 --></A>
<P>If you're like me, you're used to being able to use extra parentheses whenever you want to - like when you're typing a complex mathematical equation and you want to separate the parts by parentheses to make it clearer when you read it. In <EM>Scheme</EM>, you have to be careful and not insert these extra parentheses incorrectly. For example, say we wanted to add 3 to the result of adding 5 and 6 together: </P>

<A name="447038"><!-- 447038 --></A>
<PRE>3 + (5 + 6) = ?
</PRE><P>You might be tempted to translate that into the following Scheme statement:</P>

<A name="447042"><!-- 447042 --></A>
<PRE>(+ 3 (5 6) )
</PRE><P>However, this is <EM>incorrect</EM> - remember, every statement in Scheme <EM>starts</EM> and <EM>ends</EM> with parens, so the Scheme interpreter will think that you're trying to call a function named <EM>5</EM> in the second group of parens, rather than summing those numbers before adding them to 3. </P>

<A name="447071"><!-- 447071 --></A>
<P>The correct way to write the above statement would be: </P>

<A name="447072"><!-- 447072 --></A>
<PRE>(+ 3 (+ 5 6) )
</PRE><P>Practice a bit with simple mathematical equations in the Script-Fu Console until you're totally comfortable with these initial concepts.</P>

<A name="447068"><!-- 447068 --></A>
<H2>Lesson 2: Of Variables and Functions...</H2>

<A name="447075"><!-- 447075 --></A>
<P>So, my student, you are curious and want to know about variables and functions? Such vigor in your training - I like it. </P>

<A name="447078"><!-- 447078 --></A>
<H4> Variables</H4>

<A name="447092"><!-- 447092 --></A>
<P>Now that we know that every Scheme statement is enclosed in parentheses, and that the function is listed first, we need to know how to create and use variables, and create and use functions. We'll start with the variables. </P>

<A name="447097"><!-- 447097 --></A>
<H4> Declaring global variables with "set!"</H4>

<A name="447095"><!-- 447095 --></A>
<P>Variables can have either <EM>local</EM> or <EM>global</EM> scope. To declare a global variable, use the <EM>set!</EM> function: </P>

<A name="447224"><!-- 447224 --></A>
<PRE>(set! myVar 5)
</PRE><P>Now you can use <CODE>myVar</CODE> as you'd expect: </P>

<A name="447227"><!-- 447227 --></A>
<PRE>(+ myVar 8)
</PRE><P>Go ahead and try declaring and using a variable in the Script-Fu Console. </P>

<A name="447110"><!-- 447110 --></A>
<H4> Declaring local variables with "let"</H4>

<A name="447112"><!-- 447112 --></A>
<P>Variables can also have <EM>local</EM> scope. This is achieved by using the <EM>let</EM> statement: </P>

<A name="447114"><!-- 447114 --></A>
<PRE>(let ( (x 5) (y 6) ) (...) )
</PRE><P>You'll probably notice an abundance of parens here - all I can say is, get used to it. </P>

<A name="447118"><!-- 447118 --></A>
<P>In the let statement, after the <EM>let</EM> keyword, we have a list of initialized values. We haven't gotten into lists yet, but the syntax shouldn't be too hard to grasp - we open a parens to contain all the variable declarations, then we enclose each variable declaration in its own set of parens. </P>

<A name="447126"><!-- 447126 --></A>
<P>After all the variable declarations, we can then start using our local variables, up until the final closing parens (the statements would go where the ellipsis (...) is). </P>

<A name="447131"><!-- 447131 --></A>
<P>The variables declared within the let statement have scope only within the enclosing parens. An example will help clarify this. </P>

<A name="447136"><!-- 447136 --></A>
<PRE>(<CODE>let</CODE>
<CODE>(</CODE>
<CODE>(x 5)</CODE>
<CODE>(y 6)</CODE>
<CODE>)</CODE>
<CODE>(+ x y)</CODE>
<A name="447149"><!--447149--></A>
)
</PRE><P>As you might expect, this produces the answer of <EM>11</EM> when used within a script. However, if we were to follow this with the following statement: </P>

<A name="447167"><!-- 447167 --></A>
<PRE>(* x y)
</PRE><P>we'd get an error because x and y are now<EM> out of scope</EM> - they only are <EM>usable</EM> within the<EM> let</EM> statement in which they're declared. </P>

<A name="447175"><!-- 447175 --></A>
<H4>White space</H4>

<A name="447172"><!-- 447172 --></A>
<P> If you notice above, the <EM>let</EM> statement is written across <EM>multiple lines</EM> - this is not a problem, as white space can be liberally applied to help clarify and organize the code within a script. (However, if you're working in Script-Fu's Console window, you'll need to enter everything on one line.) </P>

<A name="447180"><!-- 447180 --></A>
<H4> Assigning a new value to a variable</H4>

<A name="447186"><!-- 447186 --></A>
<P>Once you've initialized a variable, you'll more than likely need to change its value later on in the script. Use the <EM>set! </EM>statement for both local and global variables to change the variable's value: </P>

<A name="447191"><!-- 447191 --></A>
<PRE>(set! gCount 15)
(let ( (theNum 10) ) (set! theNum (+ gCount theNum) ) (set! gCount theNum) )
(* gCount gCount)
</PRE><P>Try to guess what the above statements will do, then go ahead and enter them in the Script-Fu Console window. </P>

<A name="447212"><!-- 447212 --></A>
<H4> Functions</H4>

<A name="447214"><!-- 447214 --></A>
<P>Now that you've got the hang of variables, let's get to work with some <EM>functions</EM>. </P>

<A name="447218"><!-- 447218 --></A>
<P>You declare a function with the following syntax: </P>

<A name="447220"><!-- 447220 --></A>
<PRE>define (TheFunctionName param1 param2) (...) (...) )
</PRE><P>where <CODE>TheFunctionName </CODE>is the function's name, and any and all param names follow it. Notice that the parameter's don't have any <EM>types</EM> - Scheme is a type-less language. </P>

<A name="447217"><!-- 447217 --></A>
<P>The <EM>(...)</EM> characters represent the function's <EM>code</EM>. Thus, to find the square of a number, we could write the following function: </P>

<A name="447242"><!-- 447242 --></A>
<PRE>(define (square inNumber) (* inNumber inNumber) )
</PRE><P>If you type this into Script-Fu's Console window, you'll get a message about <EM>Closure</EM>, then you'll be ready to use the function: </P>

<A name="447249"><!-- 447249 --></A>
<PRE>(square 5)
</PRE><P>Typing this in will yield the expected result. </P>

<A name="447253"><!-- 447253 --></A>
<P>But how do you know what will be returned? Basically, the result of the last statement executed within the function is the result it returns. </P>

<A name="447256"><!-- 447256 --></A>
<H2> Lesson 3: '(Lists Lists and More Lists)</H2>

<A name="447261"><!-- 447261 --></A>
<P>We've trained you in variables and functions, young Script-Fu'er, and now we must enter the murky swamps of Scheme's <EM>lists</EM>. Are you ready for the challenge? </P>

<A name="447264"><!-- 447264 --></A>
<H4> Defining a list</H4>

<A name="447268"><!-- 447268 --></A>
<P>Before we talk more about lists, it is necessary that you know the difference between <EM>atomic values </EM>and <EM>lists</EM>. </P>

<A name="447271"><!-- 447271 --></A>
<P>You've already seen <EM>atomic values</EM> when we initialized variables in the previous lesson. An atomic value is<EM> a single value</EM>. So, for example, we can assign the variable <EM>x</EM> the single value of <EM>8</EM> in the following statement: </P>

<A name="447272"><!-- 447272 --></A>
<PRE>(set! x 8)
</PRE><P>Try typing both statements into the Script-Fu Console and notice how it replies. When you type the first statement in, it simply replies with the result: </P>

<A name="447288"><!-- 447288 --></A>
<PRE>8
</PRE><P>However, when you type in the other statement, it replies with the following result:</P>

<A name="447292"><!-- 447292 --></A>
<PRE>(1 3 5)
</PRE><P>When it replies with the value <EM>8 </EM>it is informing you that <EM>x</EM> contains the atomic value <EM>8</EM>. However, when it replies with (1 3 5), it is then informing you that<EM> x</EM> no longer contains a single value, but a list of values. Notice that there are no<EM> commas</EM> in our declaration or assignment of the list, nor in the printed result. </P>

<A name="447299"><!-- 447299 --></A>
<P>The syntax to define a list is: </P>

<A name="447308"><!-- 447308 --></A>
<PRE>'(a b c)
</PRE><P>where a, b, and c are <EM>literals</EM>. We use the <EM>apostrophe</EM> (') to indicate that what follows in the parentheses is a list of literal values, rather than a function. </P>

<A name="447319"><!-- 447319 --></A>
<P>An empty list can be defined as such: </P>

<A name="447313"><!-- 447313 --></A>
<PRE><CODE>'()</CODE>
</PRE><P>or simply: </P>

<A name="447327"><!-- 447327 --></A>
<PRE><CODE>()</CODE>
</PRE><P>Lists can contain atomic values, as well as other lists: </P>

<A name="447330"><!-- 447330 --></A>
<PRE>(set! x '("The GIMP" (1 2 3) ("is" ("great" ()) ) ) )
</PRE><A name="447332"><!--447332--></A>
<P>Notice that after the first apostrophe, we no longer need to use an apostrophe when defining the inner lists. Go ahead and copy the statement into the Script-Fu Console and see what it returns. </P>

<A name="447335"><!-- 447335 --></A>
<P>You should notice that the result returned is not a list of single, atomic values - rather, it is a list of a literal ("The GIMP"), a list of the values (1 2 3), etc. </P>

<A name="447341"><!-- 447341 --></A>
<H4> Concatenating variables to lists</H4>

<A name="447345"><!-- 447345 --></A>
<P>To <EM>concatenate</EM> variables to a list, use the <EM>cons</EM> function: </P>

<A name="447336"><!-- 447336 --></A>
<PRE>(cons x (cons y () ) )
</PRE><P>This concatenates the empty list to the variable <EM>y</EM>, then concatenates that list to the variable <EM>x</EM>.</P>

<A name="447350"><!-- 447350 --></A>
<H4>Accessing values in a list</H4>

<A name="447352"><!-- 447352 --></A>
<P> To access the values in a list, we use the functions <EM>car</EM> and <EM>cdr</EM>, which return the first element of the list, and the rest of the list, respectively. </P>

<A name="447355"><!-- 447355 --></A>
<H4>car</H4>

<A name="447359"><!-- 447359 --></A>
<P><EM>car</EM> returns the <EM>first element</EM> of the <EM>list</EM> (also known as the <EM>head</EM> of the list). The list needs to be non-null. Thus, the following returns the first element of the list: </P>

<A name="447364"><!-- 447364 --></A>
<PRE>(car '("first" 2 "third"))
</PRE><P>(which returns:) </P>

<A name="447371"><!-- 447371 --></A>
<PRE>"first"
</PRE><H4>cdr</H4>

<A name="447375"><!-- 447375 --></A>
<P><EM>cdr</EM> returns the<EM> rest of the list </EM>after the first element (also known as the <EM>tail</EM> of the list). If there is only one element in the list, it returns an empty list. </P>

<A name="447380"><!-- 447380 --></A>
<PRE>(cdr '("first" 2 "third"))
</PRE><P>returns: </P>

<A name="447384"><!-- 447384 --></A>
<PRE>(2 "third")
</PRE><P>while the following: </P>

<A name="447388"><!-- 447388 --></A>
<PRE>(cdr '("one and only"))
</PRE><P>returns: </P>

<A name="447392"><!-- 447392 --></A>
<PRE>()
</PRE><A name="447394"><!--447394--></A>
<H4>Accessing other elements a list</H4>

<A name="447397"><!-- 447397 --></A>
<P>OK, great, we can get the first element in a list, as well as the rest of the list, but how do we access the second, third, or other elements of a list? Well, there exist several <EM>convenience</EM> functions to access, for example, the head of the head of the tail of a list (<EM>caadr</EM>), the tail of the tail of a list (<EM>cddr</EM>), etc. </P>

<A name="447408"><!-- 447408 --></A>
<P>The basic naming convention is easy - the <EM>a</EM>'s and<EM> d</EM>'s represent the <EM>heads</EM> and <EM>tails</EM> of lists, so </P>

<A name="447418"><!-- 447418 --></A>
<PRE>(car (cdr (car x) ) )
</PRE><P>could be written as: </P>

<A name="447422"><!-- 447422 --></A>
<PRE>(cadar x)
</PRE><P>To view a full list of the list functions, refer to the <EM>SIOD</EM> home page (or appendix D) which lists the available functions for the version of Scheme used by Script-Fu. </P>

<A name="447427"><!-- 447427 --></A>
<P>To get some practice with list accessing functions, try typing in the following and using different variations of car and cdr to access the different elements of the list: </P>

<A name="447428"><!-- 447428 --></A>
<PRE>(set! x '( (1 2 (3 4 5) 6) 7 8 (9 10) ) )
</PRE><P>Try accessing the number <EM>3 </EM>in the list using only two function calls. If you can do that, you're on your way to becoming a Script-Fu Master! </P>

<A name="447441"><!-- 447441 --></A>
<H2>Lesson 4: Your First Script-Fu Script</H2>

<A name="447444"><!-- 447444 --></A>
<P>Do you not need to stop and catch your breath, little grasshopper? No? Well then, let's proceed with the 4th lesson in your training - your first Script-Fu Script. </P>

<A name="447482"><!-- 447482 --></A>
<H4>Creating a text box script</H4>

<A name="447451"><!-- 447451 --></A>
<P>One of the most common operations I perform in Gimp is creating a box with some text in it for a web page, a logo, or whatever. However, you never quite know how big to make the initial image when you start out - you don't know how much space the text will fill with the font and font size you want. </P>

<A name="447456"><!-- 447456 --></A>
<P>The Script-Fu Master (and student) will quickly realize that this problem can easily be solved and automated with Script-Fu. </P>

<A name="447466"><!-- 447466 --></A>
<P>We will therefore create a script, called <EM>Text Box</EM>, which creates an image correctly sized to fit snug around a line of text the user inputs. We'll also let the user choose the <EM>font</EM>, <EM>font size</EM>, and <EM>text color</EM>. </P>

<A name="447473"><!-- 447473 --></A>
<H3> Getting started</H3>

<A name="447487"><!-- 447487 --></A>
<H4>Editing and storing your scripts</H4>

<A name="447457"><!-- 447457 --></A>
<P>Up until now, we've been working in the <EM>Script-Fu Console</EM>. Now, however, we're going to switch to editing script text files. </P>

<A name="447491"><!-- 447491 --></A>
<P>Where you place your scripts is a matter of preference - if you have access to Gimp's default script directory, you can place your scripts there. However, I prefer keeping my own personal scripts in my own script directory, to keep them separate from the<EM> factory-installed </EM>scripts. </P>

<A name="447492"><!-- 447492 --></A>
<P>I copied the script to<CODE> ~/.gimp/scripts</CODE> which is the my personal script directory (made by Gimp when it was installed).</P>

<A name="449082"><!-- 449082 --></A>
<P>Now, whenever Gimp starts up, or I refresh the Script-Fu database (<CODE>Xtns-&gt;Script-Fu-&gt;Refresh</CODE>), it will add my personal scripts to the procedural database. </P>

<A name="447514"><!-- 447514 --></A>
<H4> The bare essentials</H4>

<A name="447518"><!-- 447518 --></A>
<P>Every Script-Fu script defines at least one <EM>function</EM>, which is the script's main function. This is where you do the work. </P>

<A name="447521"><!-- 447521 --></A>
<P>Every script must also <EM>register</EM> with the <EM>procedural database</EM>, so you can access it within Gimp. </P>

<A name="447526"><!-- 447526 --></A>
<P>We'll define the main function first: </P>

<A name="447527"><!-- 447527 --></A>
<PRE>(define (script-fu-text-box inText inFont inFontSize inTextColor))
</PRE><P>Here we've defined a new function called <EM>script-fu-text-box </EM>which takes four parameters, which will later correspond to some text, a <EM>font</EM>, the font <EM>size</EM>, and the text's <EM>color</EM>. The function is currently empty and thus does nothing. So far, so good - nothing new, nothing fancy. </P>

<A name="447533"><!-- 447533 --></A>
<H4>Naming conventions</H4>

<A name="447539"><!-- 447539 --></A>
<P>Scheme's naming conventions seem to prefer <EM>lowercase</EM> letters with <EM>hyphens</EM>, which I've followed in the naming of the function. However, I've departed from the convention with the parameters - I like more descriptive names for my parameters and variables, and thus add the<EM> in </EM>prefix to the parameters so I can quickly see that they're values passed into the script, rather than created within it. I use the prefix <EM>the</EM> for variables defined within the script. </P>

<A name="447546"><!-- 447546 --></A>
<P> It's Gimp convention to name your script functions <EM>script-fu-abc</EM>, because then when they're listed in the procedural database, they'll all show up under<EM> script-fu </EM>when you're listing the functions. This also helps distinguish them from plug-ins when listed. </P>

<A name="447560"><!-- 447560 --></A>
<H4>Registering the function</H4>

<A name="447566"><!-- 447566 --></A>
<P>Now, let's <EM>register</EM> the function with Gimp - when  Gimp reads in a script, it will search for this function and use it to register the script with the procedural database. These lines of code come after the function definition listed above. </P>

<A name="447574"><!-- 447574 --></A>
<PRE>(script-fu-register
&nbsp;&nbsp;&nbsp;"script-fu-text-box"
&nbsp;&nbsp;&nbsp;"&lt;Toolbox&gt;/Xtns/Script-Fu/Text/Text Box"
<A name="447647"><!--447647--></A>
&nbsp;&nbsp;&nbsp;"Creates a simple text box, sized to fit around the user's choice of text, font, font size, and color."
&nbsp;&nbsp;&nbsp;"Michael Terry"
&nbsp;&nbsp;&nbsp;"copyright 1997, Michael Terry"
&nbsp;&nbsp;&nbsp;"October 27, 1997"
&nbsp;&nbsp;&nbsp;""
&nbsp;&nbsp;&nbsp;SF-VALUE "Text:"       "\"Text Box\""
&nbsp;&nbsp;&nbsp;SF-VALUE "Font:"       "\"Charter\""
&nbsp;&nbsp;&nbsp;SF-VALUE "Font size:"  "45"
&nbsp;&nbsp;&nbsp;SF-COLOR "Color:"      '(0 0 0)
)
</PRE><P>If you save these functions in a text file with a .<EM>scm</EM> suffix in your script directory, then choose <CODE> Xtns-&gt;Script-Fu-&gt;Refresh</CODE>, this new script will appear as <CODE>Xtns-&gt;Script-Fu-&gt;Text-&gt;Text Box</CODE>: <BR><IMG SRC="write_scriptfu3-image-3.jpeg" ALT="Extracted pic [3]">
</P>

<A name="447673"><!-- 447673 --></A>
<P>If you <EM>invoke</EM> this new script, it won't do anything, of course, but you can view the <EM>prompts</EM> you created when registering the script (more information about what we did is covered next). <BR><IMG SRC="write_scriptfu3-image-4.jpeg" ALT="Extracted pic [4]">
</P>

<A name="447684"><!-- 447684 --></A>
<P>Finally, if you invoke the <EM>DB Browser </EM>(the procedural database browser - <CODE>Xtns-&gt;DB Browser</CODE>), you'll notice that our script now appears in the database: <BR><IMG SRC="write_scriptfu3-image-5.jpeg" ALT="Extracted pic [5]">
</P>

<A name="447687"><!-- 447687 --></A>
<H4>Steps for registering the script</H4>

<A name="447696"><!-- 447696 --></A>
<P>To register our script with Gimp, we call the function <EM>script-fu-register</EM>, fill in the 7 required parameters, and add our scripts' own parameters, along with a description and default value for each parameter. </P>

<A name="447701"><!-- 447701 --></A>
<H4>The required parameters</H4>

<A name="447703"><!-- 447703 --></A>

<UL>
<!--L1Bullet--><LI>The <EM>name</EM> of the function we defined above. This is the function called when our script is invoked (i.e., the entry-point into our script). This is necessary because we may define additional functions within the same file, and Gimp needs to know which of these functions to call.In our example, we only defined one function, <EM>text-box</EM>, which we registered. <!--L1Bullet--></LI>

<A name="447718"><!-- 447718 --></A>
<!--L1Bullet--><LI>The <EM>location</EM> in the menu where the script will be inserted. The exact location of the script is specified like a <EM>path</EM> in Unix, with the root of the path being either <EM>&lt;Toolbox&gt; </EM>or <EM>&lt;Image&gt;</EM>. If your script does not operate on an existing image (and thus creates a new image, like our Text Box script will), you'll want to insert it in the <EM>&lt;Toolbox&gt;</EM> menu - this is the menu in Gimp's <EM>main window</EM> (where all the <EM>tools</EM> are located - the selection tools, magnifying glass, etc.). If your script is intended to work on an image being <EM>edited</EM>, you'll want to insert it in the <EM>&lt;Image&gt;</EM> menu - this menu appears when your <CODE>right-click </CODE>on an open image. The rest of the <EM>path</EM> to the menu lists menus and sub-menus. Thus, we registered our <EM>Text Box </EM>script in the <EM>Text</EM> menu of the <EM>Script-Fu</EM> menu of the <EM>Xtns</EM> menu of the <EM>Toolbox</EM> (<CODE>Toolbox-&gt;Xtns-&gt;Script-Fu-&gt;Text-&gt;Text Box</CODE>). If you notice, the <EM>Text</EM> sub-menu in the <EM>Script-Fu</EM> menu wasn't there when we began - Gimp automatically creates any menus not already existing. <!--L1Bullet--></LI>

<A name="447740"><!-- 447740 --></A>
<!--L1Bullet--><LI>A <EM>description</EM> of your script. I'm not quite sure where this is displayed. <!--L1Bullet--></LI>

<A name="447726"><!-- 447726 --></A>
<!--L1Bullet--><LI>Your <EM>name</EM> (the author of the script). <!--L1Bullet--></LI>

<A name="447763"><!-- 447763 --></A>
<!--L1Bullet--><LI><EM>Copyright</EM> information. <!--L1Bullet--></LI>

<A name="447765"><!-- 447765 --></A>
<!--L1Bullet--><LI>The <EM>date</EM> the script was made, or the last <EM>revision</EM> of the script. <!--L1Bullet--></LI>

<A name="447767"><!-- 447767 --></A>
<!--L1Bullet--><LI>The <EM>types</EM> of images the script works on. This may be any of the types: RGB, RGBA, GRAY, GRAYA, INDEXED, INDEXEDA, or it may be none at all - in our case, we're creating an image, and thus don't need to define the type of image on which we work. <!--L1Bullet--></LI>

<A name="447779"><!-- 447779 --></A>

</UL>
<P>

<A name="447781"><!-- 447781 --></A>
<H4>Registering the script's parameters</H4>

<A name="447707"><!-- 447707 --></A>
<P>Once we have <EM>listed</EM> the required <EM>parameters</EM>, we then need to list the parameters which correspond to the parameters our script needs. When we list these params, we give <EM>hints</EM> as to what their types are - this is for the dialog box which pops up when the user selects our script. We also provide a <EM>default</EM> value. </P>

<A name="447785"><!-- 447785 --></A>
<P>This section of the registration process has the following format: </P>

<A name="447795"><!-- 447795 --></A>
<PRE>Param-type "Prompt text" "default value"
</PRE><P>The different parameter types, plus examples, are listed below: </P>
<P>
<!-- Table extracted from write_scriptfu3 : 1 (ID:9) -->
<TABLE>

<!------------------------ Row 0 ------------------------>
<TR>

<!---------- Col 1 ---------->
<TH>
<A name="447879"><!-- 447879 --></A>
<STRONG>Param type</STRONG></TH>

<!---------- Col 2 ---------->
<TH>
<A name="447881"><!-- 447881 --></A>
<STRONG>Description</STRONG></TH>

<!---------- Col 3 ---------->
<TH>
<A name="447883"><!-- 447883 --></A>
<STRONG>Examples</STRONG></TH>

</TR>

<!------------------------ Row 1 ------------------------>
<TR>

<!---------- Col 1 ---------->
<TD>
<A name="447885"><!-- 447885 --></A>
<P>SF-VALUE</P></TD>

<!---------- Col 2 ---------->
<TD>
<A name="447887"><!-- 447887 --></A>
<P>Accepts numbers and strings.Note that quotes must be escaped for default text</P></TD>

<!---------- Col 3 ---------->
<TD>
<A name="447889"><!-- 447889 --></A>
<P>SF-VALUE "Text:" "\"Some text\""</P>
<A name="447927"><!-- 447927 --></A>
<P>SF-VALUE  "A number:" "34"</P></TD>

</TR>

<!------------------------ Row 2 ------------------------>
<TR>

<!---------- Col 1 ---------->
<TD>
<A name="447891"><!-- 447891 --></A>
<P>SF-COLOR</P></TD>

<!---------- Col 2 ---------->
<TD>
<A name="447893"><!-- 447893 --></A>
<P>Indicates that a color is requested in this parameter</P></TD>

<!---------- Col 3 ---------->
<TD>
<A name="447895"><!-- 447895 --></A>
<P>SF-COLOR "Color:" '(0 0 0)</P></TD>

</TR>

<!------------------------ Row 3 ------------------------>
<TR>

<!---------- Col 1 ---------->
<TD>
<A name="447897"><!-- 447897 --></A>
<P>SF-TOGGLE</P></TD>

<!---------- Col 2 ---------->
<TD>
<A name="447899"><!-- 447899 --></A>
<P>A checkbox is displayed, to get boolean value</P></TD>

<!---------- Col 3 ---------->
<TD>
<A name="447901"><!-- 447901 --></A>
<P>SF-TOGGLE "Resize?" TRUE</P></TD>

</TR>

<!------------------------ Row 4 ------------------------>
<TR>

<!---------- Col 1 ---------->
<TD>
<A name="447903"><!-- 447903 --></A>
<P>SF-IMAGE</P></TD>

<!---------- Col 2 ---------->
<TD>
<A name="447905"><!-- 447905 --></A>
<P>If your script operates on an open image, this should be the first parameter after the required parameters. The GIMP will pass n a reference to the image in this parameter.</P></TD>

<!---------- Col 3 ---------->
<TD>
<A name="447907"><!-- 447907 --></A>
<P>SF-IMAGE "The image" 0</P></TD>

</TR>

<!------------------------ Row 5 ------------------------>
<TR>

<!---------- Col 1 ---------->
<TD>
<A name="447935"><!-- 447935 --></A>
<P>SF-DRAWABLE</P></TD>

<!---------- Col 2 ---------->
<TD>
<A name="447956"><!-- 447956 --></A>
<P>If your script operates on an open image, this should be the second parameter after the SF-IMAGE param. It refers to the active layer. The GIMP will pass in a reference to the active layer in this param.</P></TD>

<!---------- Col 3 ---------->
<TD>
<A name="447913"><!-- 447913 --></A>
<P>SF-DRAWABLE "The layer" 0</P></TD>

</TR>
</TABLE>
<P>

<A name="447968"><!-- 447968 --></A>
<P>Now, young student, this was a lot of information, so take a break.</P>

<A name="447970"><!-- 447970 --></A>
<H2>Lesson 5: Giving our script some guts</H2>

<A name="447973"><!-- 447973 --></A>
<P>You show great dedication to your studies, my student. Let us thus continue with your training and add some functionality to our script. </P>

<A name="447976"><!-- 447976 --></A>
<H3> Creating a new image</H3>

<A name="447980"><!-- 447980 --></A>
<P>In the previous lesson, we created an empty function and registered it with Gimp. In this lesson, we want to provide <EM>functionality</EM> to our script - we want to create a new image, add the user's text to it, and resize the image to fit the text exactly. </P>

<A name="447988"><!-- 447988 --></A>
<P>Once you know how to <EM>set variables</EM>, <EM>define functions</EM>, and access list members, the rest is all downhill - all you need to do is familiarize yourself with the functions available in Gimp's procedural database and call those functions directly. So fire up the DB Browser and let's get cookin'! </P>

<A name="447999"><!-- 447999 --></A>
<P>Let's begin by making a new image. We'll create a new variable, <EM>theImage</EM>, set to the result of calling Gimp's built-in function <CODE>gimp-image-new</CODE>: <BR><IMG SRC="write_scriptfu3-image-6.jpeg" ALT="Extracted pic [6]">
</P>

<A name="448014"><!-- 448014 --></A>
<P>As you can see from the <EM>DB Browser</EM>, the function <CODE>gimp-image-new</CODE> takes three parameters - the image's <EM>width</EM>, <EM>height</EM>, and the <EM>type</EM> of image. Since we'll later <EM>resize</EM> the image to fit the text, we'll make a 10x10 RGB image. We'll store the image's width and sizes in some variables, too, as we'll refer to and manipulate them later in the script: </P>

<A name="448025"><!-- 448025 --></A>
<PRE>(define (script-fu-text-box inText in(set! theImageWidth 10)
&nbsp;&nbsp;&nbsp;(set! theImageHeight 10)
&nbsp;&nbsp;&nbsp;(set! theImage (car (gimp-image-new theImageWidth theImageHeight RGB) ) )
&nbsp;&nbsp;&nbsp; )Font inFontSize inTextColor)
)
</PRE><P>You should notice that we used the value <EM>RGB</EM> to specify that the image is an RGB image. We could have also used <EM>0</EM>, but <EM>RGB</EM> is more descriptive when we glance at the code. </P>

<A name="448044"><!-- 448044 --></A>
<P>You should also notice that we took the <EM>head</EM> of the result of the function call - this may seem strange, because the database explicitly tells us that it returns only one value - the ID of the newly created image. However, all Gimp functions return a list, even if there is only one element in the list, so we need to get the head of the list. </P>

<A name="448045"><!-- 448045 --></A>
<H4>Adding a new layer to the image</H4>

<A name="448060"><!-- 448060 --></A>
<P>Now that we have an image, we need to add a layer to it. We'll call the <CODE>gimp-layer-new</CODE> function to create the layer, passing in the ID of the image we just created. (From now on, instead of listing the complete function, we'll only list the lines we're adding to it.) </P>

<A name="448068"><!-- 448068 --></A>
<PRE>(set! theLayer (car (gimp-layer-new theImage theImageWidth theImageHeight RGB_IMAGE "layer 1" 100 NORMAL) ) )
</PRE><P>Once we have the new layer, we need to <EM>add</EM> it to the image: </P>

<A name="448072"><!-- 448072 --></A>
<PRE>(gimp-image-add-layer theImage theLayer 0)
</PRE><P>Now just for fun, let's see the fruit of our labors up until this point, and add this line to show the new, empty, image: </P>

<A name="448076"><!-- 448076 --></A>
<PRE>(gimp-display-new theImage)
</PRE><P>Save your work, select <CODE>Xtns-&gt;Script-Fu-&gt;Refresh</CODE>, run the script, and a new image should pop up. It will probably contain garbage (random colors), because we haven't erased it. We'll get to that in a second.</P>

<A name="448083"><!-- 448083 --></A>
<H4> Adding the text</H4>

<A name="448085"><!-- 448085 --></A>
<P>Go ahead and <EM>remove</EM> the line to display the image (or comment it out with a <EM>;</EM> as the first character of the line). </P>

<A name="448091"><!-- 448091 --></A>
<P>Before we add text to the image, we need to set the <EM>background</EM> and <EM>foreground</EM> colors so that the text appears in the color the user specified. We'll use the <CODE>gimp-palette-set-back/foreground</CODE> functions: </P>

<A name="448088"><!-- 448088 --></A>
<PRE>(gimp-palette-set-background '(255 255 255) )
(gimp-palette-set-foreground inTextColor)
</PRE><P>With the colors properly set, let's now clean out the garbage currently in the image. We'll select everything in the image, and call <EM>clear</EM>: </P>

<A name="448104"><!-- 448104 --></A>
<PRE>(gimp-selection-all theImage)
(gimp-edit-clear theImage theLayer)
(gimp-selection-none theImage)
</PRE><P>With the image cleared, we're ready to add some <EM>text</EM>: </P>

<A name="448112"><!-- 448112 --></A>
<PRE>(set! theText (car (gimp-text theImage theLayer 0 0 inText 0 TRUE inFontSize PIXELS "*" inFont "*" "*" "*" "*")))
</PRE><P>While a long function call, it's fairly straight-forward if you go over the parameters while looking at the function's entry in the DB Browser. Basically, we're creating a new text layer and assigning it to the variable <EM>theText</EM>. </P>

<A name="448122"><!-- 448122 --></A>
<P>Now that we have the text, we can grab its <EM>width</EM> and <EM>height</EM> and resize the image and the image's layer to the text's size: </P>

<A name="448114"><!-- 448114 --></A>
<PRE>(set! theImageWidth  (car (gimp-drawable-width theText) ) )
(set! theImageHeight (car (gimp-drawable-height theText) ) )
<A name="448129"><!--448129--></A>
(gimp-image-resize theImage theImageWidth theImageHeight 0 0)
(gimp-layer-resize theLayer theImageWidth theImageHeight 0 0)
</PRE><P>If you're like me, you're probably wondering what a <EM>drawable</EM> is when compared to a layer - A drawable is the <EM>paintable</EM> area in an image, like a <EM>layer</EM>, a <EM>background</EM>, or a <EM>selection </EM>(floating or in a layer).</P>

<A name="448138"><!-- 448138 --></A>
<P>With the image ready to go, we can now re-add our <EM>display</EM> line: </P>

<A name="448140"><!-- 448140 --></A>
<PRE>(gimp-display-new theImage)
</PRE><P>Save your work, refresh the database, and give your first script a run! You should get something like the following: <BR><IMG SRC="write_scriptfu3-image-7.jpeg" ALT="Extracted pic [7]">
</P>

<A name="448147"><!-- 448147 --></A>
<H4>Clearing the "dirty" flag</H4>

<A name="448149"><!-- 448149 --></A>
<P>If you try and close the image created without first <EM>saving</EM> the file, Gimp will ask you if you want to save your work before you close the image. It asks this because the image is marked as <EM>dirty</EM>, or unsaved. In the case of our script, this is a nuisance for the times when we simply give it a test run and don't add or change anything in the resulting image - that is, our work is easily reproducible in such a simple script, so it makes sense to get rid of this <EM>dirty</EM> flag. </P>

<A name="448171"><!-- 448171 --></A>
<P>To do this, we can clear the dirty flag after displaying the image: </P>

<A name="448173"><!-- 448173 --></A>
<PRE>(gimp-image-clean-all theImage)
</PRE><P>This will dirty count to 0, making it appear to be a "clean" image. </P>

<A name="448177"><!-- 448177 --></A>
<P>Whether to add this line or not is a matter of personal taste - I use it in scripts that produce new images, where the results are trivial, as in this case. If your script is very complicated, or if it works on an existing image, you will probably not want to use this function. </P>

<A name="448181"><!-- 448181 --></A>
<H4> Enabling and Disabling undo</H4>

<A name="448187"><!-- 448187 --></A>
<P>If your script works on an image, you'll probably want to call <CODE>gimp-image-disable-undo</CODE> at the beginning of the script, and <CODE>gimp-image-enable-undo</CODE> at the end of the script - these functions turn <EM>undo-recording</EM> off and on, respectively. If you are writing a complex script, a user will not want to have to hit undo a million times after invoking your script, to undo all the actions your script took to do its job.</P>

<A name="448192"><!-- 448192 --></A>
<H3>       Lesson 6: Extending the Text Box Script</H3>

<A name="448201"><!-- 448201 --></A>
<P>Your will and determination are unstoppable, my eager student. So let us continue your training. </P>

<A name="448203"><!-- 448203 --></A>
<H4>The game plan</H4>

<A name="448205"><!-- 448205 --></A>
<P>Now that we have a very handy-dandy script to create text boxes, let's add two features to it: </P>

<A name="448207"><!-- 448207 --></A>

<UL>
<!--L1Bullet--><LI>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 <EM>buffer</EM> around the text, and even let the user specify how much buffer to add as a percentage of the size of the resultant text.<!--L1Bullet--></LI>

<A name="448215"><!-- 448215 --></A>
<!--L1Bullet--><LI>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 that other scripts can call this script and use the image and layers we create.<!--L1Bullet--></LI>

<A name="448223"><!-- 448223 --></A>

</UL>
<H4>Modifying the parameters and the registration function</H4>

<A name="448225"><!-- 448225 --></A>
<P>To let the user specify the amount of buffer, we'll add a parameter to our function and the registration function: </P>

<A name="448227"><!-- 448227 --></A>
<PRE>(define (script-fu-text-box inText inFont inFontSize inTextColor inBufferAmount)
...
)
(script-fu-register
&nbsp;&nbsp;&nbsp;"script-fu-text-box"
&nbsp;&nbsp;&nbsp;"&lt;Toolbox&gt;/Xtns/Script-Fu/Text/Text Box"
&nbsp;&nbsp;&nbsp;"Creates a simple text box, sized to fit around the user's choice of text, font, font size, and color."
&nbsp;&nbsp;&nbsp;"Michael Terry"
&nbsp;&nbsp;&nbsp;"copyright 1997, Michael Terry"
&nbsp;&nbsp;&nbsp;"October 27, 1997"
&nbsp;&nbsp;&nbsp;""
&nbsp;&nbsp;&nbsp;SF-VALUE "Text:"       "\"Text Box\""
&nbsp;&nbsp;&nbsp;SF-VALUE "Font:"       "\"Charter\""
&nbsp;&nbsp;&nbsp;SF-VALUE "Font size:"  "45"
&nbsp;&nbsp;&nbsp;SF-COLOR "Color:"      '(0 0 0)
&nbsp;&nbsp;&nbsp;SF-VALUE "Buffer amount (0 - 100% height of text):" "35"
)
<A name="448328"><!--448328--></A>

</PRE><H4>Adding the new code</H4>

<A name="448331"><!-- 448331 --></A>
<P>We're going to add <EM>code</EM> in two places - right before we <EM>resize</EM> the image, and at the <EM>end</EM> of the script (to return the new image, the layer, and the text). </P>

<A name="448334"><!-- 448334 --></A>
<P>After we get the text's height and width, we need to <EM>resize</EM> 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. </P>

<A name="448335"><!-- 448335 --></A>
<PRE>(set! theBuffer (* theImageHeight (/ inBufferAmount 100) ) )
(set! theImageHeight (+ theImageHeight theBuffer theBuffer) )
(set! theImageWidth  (+ theImageWidth theBuffer theBuffer) )
</PRE><P>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.) </P>

<A name="448355"><!-- 448355 --></A>
<P>Now that we have resized the image to allow for a buffer, we need to <EM>center</EM> the text within the image. This is done by moving it to the (<EM>x, y</EM>) coordinates of (<CODE>theBuffer, theBuffer</CODE>).   I added this line after resizing the layer and the image: </P>

<A name="448356"><!-- 448356 --></A>
<PRE>(gimp-layer-set-offsets theText theBuffer theBuffer)
</PRE><P>Go ahead and save your script, and try it out after refreshing the database. You should now get a window like the following:<BR><IMG SRC="write_scriptfu3-image-8.jpeg" ALT="Extracted pic [8]">
</P>

<A name="448366"><!-- 448366 --></A>
<P>All that is left to do is to return our image, the layer, and the text layer. After displaying the image, we add this line: </P>

<A name="448375"><!-- 448375 --></A>
<PRE>(cons theImage (cons theLayer (cons theText () ) ) )
</PRE><P>We use the function <EM>cons</EM> to create a list of values. This is the last line of the function, making this list available to other scripts that want to use it.</P>

<A name="448382"><!-- 448382 --></A>
<P>To use our new text box script in another script, we could write something like the following: </P>

<A name="448384"><!-- 448384 --></A>
<PRE>(set! theResult (script-fu-text-box "Some text" "Charter" "30" '(0 0 0) "35") )
<A name="448386"><!--448386--></A>
(gimp-image-flatten (car theResult) )
</PRE><P>Congratulations, my student, you are on your way to your Black Belt of Script-Fu! </P>

<A name="448395"><!-- 448395 --></A>
<P>

<P><HR>

<EM>Generated by <STRONG>fmtoweb (v. 2.9c)</STRONG> written by Peter G. Martin <a href="mailto:peterm@zeta.org.au">&lt;peterm@zeta.org.au&gt;</a> Last modified: 20 May 1998</EM><P>
<A HREF="write_scriptfu.html"><IMG ALIGN = BOTTOM SRC = "prev.gif" ALT="Previous"></A>
<A HREF="Part_nine.html"><IMG ALIGN = BOTTOM SRC = "next.gif" ALT="Next"></A>
<A HREF="index2.html"><IMG ALIGN=BOTTOM SRC = "toc.gif" ALT="TOC"></A>
<A HREF="GimpmanualIX.html"><IMG ALIGN = BOTTOM SRC = "index.gif" ALT="Index"></A>
<A HREF="webfeedback.html"><IMG ALIGN = BOTTOM SRC = "feedback.gif" ALT="Feedback"></A><P>

</BODY>
</HTML>