subtypeidKGScriptParserduration@^ framebaseencodingparms inputFormat inputCountpublicurltitlewww.fxscript.orguitype typedefaultstringvalue theinputtextTextstib's better text 1.4b textheightvarname character fontnamefont  Lucida Grande"etViewstr fontstylestyleuiinfolabelsPlainBoldItalic Bold/Italicmin?€max@€?€?€ fontcolour font colourÿÿÿÿÿÿÿÿfontsizesize01DzBBrampB poomargins (% of screen size) <centrehorizontallyllycentre H (mirror left)01centreverticallycentre V (mirror top)01 leftmargin left margin01BÈApAp rightmargin right margin01BÈBªBª topmargintop01BÈApAp bottommarginbottom01BÈBªBª drawmarginsdraw margins on screen01spud paragraph U fontalign alignment(*LeftCenterRight0?€1@@@@ fonttracktracking0ÃH1CH?€?€8B  lineleadingleading0ÂÈ1BÈA A aspectaspect0<#× 1@ ?€?€spack Transitions j visiblelinesnumber of visible paragraphs01A A A transitionstyletransition style(*fadetype-onslidestretch0?€1@€?€?€easeinease in0<#× 1A ?€?€8BH maxstretchh max H Stretch01C–?€?€8BÆ maxstretchv max V Stretch01C–?€?€8BÆbluronblur transitions01maxblurhMax Horizontal Blur01BÈA A 8BHmaxblurvMax Vertical Blur01BÈA A 8BHprivatestaticsscripte·// Stib's text list maker - gives you better text composition tools than the generic text editor with FCP // Copyright © 2002-3 stephen dixon generator "better text 1.4b", 120; group "stib's generators"; //ProducesAlpha AlphaType(kAlpha); fullFrame; //-------------------------------------------------------------inputs----------------------------------------- input url, "www.fxscript.org", Label, "string" input theinputText, "Text", text, "stib's better text 1.4b" textheight 5; input varName, "character", Label, "" input fontname, "font", FontList, "", "str"; input fontstyle, "style", popup, 1, "Plain", "Bold", "Italic", "Bold/Italic"; input fontcolour, "font colour", color, 255, 255, 255, 255; input fontsize, "size", slider, 36, 0, 1000 ramp 80; input poo, "margins (% of screen size)", Label, "" input CentreHorizontallylly, "centre H (mirror left)", checkbox, true input CentreVertically, "centre V (mirror top)", checkbox, true; input leftMargin, "left margin", slider, 15, 0, 100 ; input RightMargin, "right margin", slider, 85, 0, 100 ; input TopMargin, "top", slider, 15, 0, 100; input BottomMargin, "bottom", slider, 85, 0, 100; input drawMargins, "draw margins on screen", CheckBox, false input spud, "paragraph", Label, "" input fontalign, "alignment", popup, 2, "Left", "Center", "Right"; input fonttrack, "tracking", slider, 1, -200, 200 ramp 80; input lineleading, "leading", slider, 20, -100, 100 ; input aspect, "aspect", slider, 1, 0.01, 5; input Spack, "Transitions", Label, "" input visiblelines, "number of visible paragraphs", slider, 20, 0, 20; input transitionstyle, "transition style", Popup, 1, "fade","type-on", "slide", "stretch"; input EaseIn, "ease in", slider, 1, 0.01, 10 ramp 50; input MaxStretchH, "max H Stretch", slider, 1 , 0, 300 ramp 99; input MaxStretchV, "max V Stretch", slider, 1 , 0, 300 ramp 99; input BlurOn, "blur transitions", checkbox, false input maxBlurH, "Max Horizontal Blur", slider, 10, 0, 100 ramp 50; input maxBlurV, "Max Vertical Blur", slider, 10, 0, 100 ramp 50; //-------------------------------------------------------------start code----------------------------------------- code exposedbackground=1; resetText; SetPixelFormat(dest, kFormatYUV219) string StringToMeasure, thecurrentParagraph, lastline , outString, LineReturn, nextword, thecurrentline, CurrentLetter, hyphenatedword, truncateddisplayline, spacer, colourstring; string debugstring; //for debugging float NumberOfParagraphs, numberoflinesinParagraph, totalcharsinparagraph, longestParagraph; float counter, LineCounter, charcounter; float wordstart, wordendmarker, currentlinelength, minimumHyphenatedWord; float numberofvisiblechars, lineVisibility; float needToWrap, keepgoing,incrementdirection, incrementSize, transitionLine; // booleans float leading, currentlinewidth, nextwordwidth, textlength, lineheight, Truetextorigin, i float slideOnOffset; float TotalTextHeight, wrapwidth , paragraphVerticalSpacing, lastlinewidth, CurrentLetterASCII, colourval[4],colourcount, newcolourval[3],digitcount,ascent,descent; point p, framesize, textorigin; point blurriness; color opacity; if transitionstyle == 4 point textRect[4] point DestRect[4] end if; //------------------------------------------------------format text etc etc etc------------------------------------- fontcolour.a = 255; channelFill(dest, 0, 0, 0, 0); colourval[0] = fontcolour.r colourval[1] = fontcolour.g; colourval[2] = fontcolour.b; colourval[3] = fontcolour.a dimensionsof(dest, framesize.x, framesize.y); image temp[framesize.x][framesize.y]; channelFill(temp, 0, 0, 0, 0); if BlurOn | transitionstyle == 4 image blurTemp[framesize.x][framesize.y]; channelFill(blurTemp, 0, 0, 0, 0); end if; fontsize *= (framesize.x / 720) leftmargin = framesize.x * (leftmargin-50)/100); //I really hate the way coordinates start in the centre of screen for FXScript if CentreHorizontallylly then RightMargin= 0 - leftMargin; else RightMargin = framesize.x * (RightMargin-50)/100); end if; if leftmargin >= rightmargin then rightmargin = leftmargin end if TopMargin = framesize.y * (TopMargin-50)/100); if CentreVertically then BottomMargin = 0 - TopMargin else BottomMargin = framesize.y * (BottomMargin-50)/100); end if; if topmargin >= bottommargin then bottommargin = topmargin end if wrapwidth = rightmargin- leftmargin; setTextFont(fontname); setTextSize(fontsize); // we will set different justification for the text type on effect if fontalign == 1 // left setTextjustify(kleftjustify); textorigin.x = Leftmargin; else if fontalign == 3 // right setTextjustify(krightjustify); textorigin.x = RightMargin; else // center setTextjustify(kcenterjustify); textorigin.x = (rightmargin + leftmargin)/2 end if; Truetextorigin = textorigin.x ASCIIToString(13, LineReturn); //line return constant //------------------------------------------------------draw margins and centre cross for lining up-------------------------------- if drawMargins point debugline[2],RHyphen[2], Lmargin[2], Rmargin[2]; Lmargin[0] = {LeftMargin,TopMargin}; //pretty self explanatorah Lmargin[1] = {LeftMargin, BottomMargin}; Rmargin[0] = {RightMargin, TopMargin}; Rmargin[1] = {RightMargin, BottomMargin}; debugline[0] = {-20,0} debugline[1] = {20,0} line(debugline[0],debugline[1],Dest, kRed, 2) debugline[0] = {0,-20} debugline[1] = {0,20} line(debugline[0],debugline[1],Dest, kRed, 2) // draws a centre cross - was used for debugging but it was useful so I left it in.. Line(Lmargin[0] , Lmargin[1], Dest, kRed, 2); Line(Rmargin[0], Rmargin[1], Dest, kRed, 2); Line(Lmargin[0] , Rmargin[0], Dest, kRed, 2); Line(Lmargin[1], Rmargin[1], Dest, kRed, 2 ); Line(RHyphen[0] , RHyphen[1], Dest, kBlue, 1); end if; //------------------------------------------------------here comes the real hoo hah----------------------------------------- TotalTextHeight = 0; NumberOfParagraphs = CountTextLines(theInputText); // count the lines so we can break up the text into paragraphs string outputParagraph[NumberOfParagraphs] // create an array of strings, one for each paragraph float paragraphsizes[NumberOfParagraphs] // an array of sizes for each paragraph float paragraphstyle[NumberOfParagraphs] //style for each paragraph float paragraphAscent[NumberOfParagraphs] float paragraphDescent[NumberOfParagraphs] float paragraphleading[NumberOfParagraphs] //ascent and descent & leading for each paragraph color paragraphfontcolour[NumberOfParagraphs] //------------------------------------------------------wrap the text in each paragraph------------------------------------- for counter = 0 to NumberOfParagraphs-1; // now do the text wrapping for each paragraph, one by one GetTextLine(theInputText, counter,thecurrentParagraph); //theinputtext is the string we will wrap, wordendmarker = 0; // initialise all our variables, flushing any from the last paragraph outString = ""; nextword = ""; lastline = "" thecurrentline = ""; currentlinewidth = 0; spacer = ""; // we don't need a space at the start of the line, but after the first word we change this to " " numberoflinesinParagraph = 1; textlength = length(thecurrentParagraph); paragraphsizes[counter] = fontsize; paragraphstyle[counter] =fontstyle; paragraphfontcolour[counter] = fontcolour; incrementsize = 0; //--------------------------------------------------parse any tags at the start of the line------------------------------ CharsOf(thecurrentParagraph, wordendmarker, wordendmarker+1, CurrentLetter); if CurrentLetter == "<"; // we found a tag, so let's deal with it repeat while (CurrentLetter != ">" & (wordendmarker < textlength)) //untill we get to the end of a tag or run out of words - stops endless loops if the user puts a < on its own before a LR //this has the advantage that a blank line can be forced by putting a < character on its own on a line wordendmarker +=1; CharsOf(thecurrentParagraph, wordendmarker, wordendmarker+1, CurrentLetter); if (CurrentLetter == "+" | CurrentLetter == "-" | currentLetter =="=") if Currentletter == "+" then incrementdirection = 1 else if Currentletter == "-" then incrementdirection = -1 else incrementDirection = 0 end if; wordendmarker +=1; CharsOf(thecurrentParagraph, wordendmarker, wordendmarker+1, CurrentLetter); repeat while (AsciiOf(currentletter,0) >= 48) && (AsciiOf(currentletter,0) <= 57) incrementsize = 10*incrementsize + StringToNum(currentletter) wordendmarker +=1; CharsOf(thecurrentParagraph, wordendmarker, wordendmarker+1, CurrentLetter); end repeat; if incrementdirection !=0 paragraphsizes[counter] += incrementsize * incrementdirection * (framesize.x / 720) if paragraphsizes[counter] < 1 paragraphsizes[counter] = 1 end if else paragraphsizes[counter] = incrementsize * (framesize.x / 720) end if end if; if (currentletter == "P") paragraphstyle[counter] = 1 setTextstyle(kplain) wordendmarker +=1; CharsOf(thecurrentParagraph, wordendmarker, wordendmarker+1, CurrentLetter); end if; if (currentletter =="B") paragraphstyle[counter] = 2 setTextstyle(kbold) wordendmarker +=1; CharsOf(thecurrentParagraph, wordendmarker, wordendmarker+1, CurrentLetter); if (currentletter =="I") paragraphstyle[counter] = 4 setTextstyle(kbolditalic) wordendmarker +=1; CharsOf(thecurrentParagraph, wordendmarker, wordendmarker+1, CurrentLetter); end if; else if (currentletter =="I") paragraphstyle[counter] = 3; setTextstyle(kitalic) wordendmarker +=1; CharsOf(thecurrentParagraph, wordendmarker, wordendmarker+1, CurrentLetter); else if (currentletter =="C") newcolourval*= 0; colourcount =0; digitcount =0; wordendmarker +=1; CharsOf(thecurrentParagraph, wordendmarker, wordendmarker+1, CurrentLetter); repeat while (((AsciiOf(currentletter,0) >= 48) and (AsciiOf(currentletter,0) <= 57) or (currentletter == ",")) and (colourcount<4)) repeat while (AsciiOf(currentletter,0) >= 48) and (AsciiOf(currentletter,0) <= 57) digitcount +=1 CharsOf(thecurrentParagraph, wordendmarker, wordendmarker+digitcount, colourstring); CharsOf(thecurrentParagraph, wordendmarker+digitcount , wordendmarker+digitcount+1, CurrentLetter); end repeat; wordendmarker += digitcount; if digitcount != 0; colourval[colourcount] = stringtonum(colourstring) end if if currentletter =="," colourcount += 1; digitcount = 0; wordendmarker +=1; CharsOf(thecurrentParagraph, wordendmarker, wordendmarker+1, CurrentLetter); end if end repeat wordendmarker -=1; CharsOf(thecurrentParagraph, wordendmarker, wordendmarker+1, CurrentLetter); paragraphfontcolour[counter].r = colourval[0]; paragraphfontcolour[counter].g = colourval[1]; paragraphfontcolour[counter].b = colourval[2]; paragraphfontcolour[counter].a = colourval[3]; end if; end repeat wordendmarker +=1; CharsOf(thecurrentParagraph, wordendmarker, wordendmarker+1, CurrentLetter); end if; //--------------------------------------------------------------the wrapping loop------------------------ repeat while (wordendmarker < textlength); wordStart = wordendmarker; //we start looking where we stopped last time keepgoing = true; //-----------------------------------------------------------search for the next space------------ Repeat while keepgoing if (wordendmarker <= textlength-1) then // only while we haven't run out of text to search CurrentLetterASCII = ASCIIOf(thecurrentParagraph, wordendmarker) ; if CurrentLetterASCII == 32; //32 is ascii for space, Other characters could be added here if you look up the ascii, like a hyphen.. repeat while (ASCIIOf(thecurrentParagraph, wordendmarker+1)==32) wordendmarker += 1; //double spaces cause problems, so this sucks em up end repeat keepgoing = false; //we found a space, so stop this loop else CharsOf(thecurrentParagraph, wordstart, wordendmarker+1, nextword); //we add the letter to the new word if it is not a space keepgoing = true; //and continue searching for a space end if; wordendmarker += 1; //move our marker along one letter. else keepgoing = false; //if we're at the end of the string, do nothing more. this will be handled next time we come round the wrapping loop end if; end repeat; //-----------------------------------------------------------end of the search for spaces loop------- thecurrentline = thecurrentline + spacer + nextword; // append this word to the current line, with a space after it spacer = " " // the first word in a line won't ned a space, the next word will setTextSize(paragraphsizes[counter]); measurestring(nextword, fonttrack*paragraphsizes[counter]/18, nextwordwidth , lineheight, paragraphascent[counter], paragraphdescent[counter], aspectof(dest)*aspect); currentlinewidth = currentlinewidth + paragraphsizes[counter]/6 + nextwordwidth; //add the width of the current word & a space - this should be faster than adding the word to the line and measuring it. needtowrap = (currentlinewidth > wrapwidth) // check the current line to see if it is outside the margins.. //--------------------------------------------------------------------deal with lines that are longer than the margins----------------------- if needtowrap then outString = outString + linereturn + lastline; // if the current word goes outside the margins then add a line break & the last line that was within the margins to our output string numberoflinesinParagraph += 1; //this is used to determine the paragraph vertical spacing thecurrentline = nextword; // start a new line that includes only the word that went outside the margins from the previous line currentlinewidth = nextwordwidth; // don't need to measure the word again end if; lastline = thecurrentline; // move currentline to lastline. lastline should always hold a line that is smaller than the margins. end repeat; //--------------------------------------------------------------------end of the text wrapping loop----------------------- outputParagraph[counter] = outstring +linereturn + thecurrentline; //the remainder of the last line we were looking at has to be added to the end of the wrapped lines when we get to the end of the paragraph //--------------------------------------------------------------------now we measure the lines for vertical disribution--------------------------- Paragraphleading[counter] = paragraphsizes[counter]*(lineleading/100); TotalTextHeight += (numberoflinesinParagraph* paragraphAscent[counter])+((numberoflinesinParagraph -1)*paragraphleading[counter]); if longestParagraph < numberoflinesinParagraph then longestParagraph = numberoflinesinParagraph end if next; //------------------------------------------------------set the spacing for paragraphs------------------------------------- if numberofParagraphs ==1 // if there is only one paragraph then centre it between top & bottom margins - also avoids divide by zero error textorigin.y = (bottommargin + topmargin)/2 - totaltextheight/2 + paragraphAscent[0]/2 + paragraphdescent[0] //took me a bit of trial and error to get that formula right. It is right isn't it? paragraphVerticalSpacing = 0; else textorigin.y = topmargin+(paragraphAscent[0]/2 + paragraphdescent[0]); // paragraphVerticalSpacing = (bottommargin-topmargin - TotalTextHeight)/(NumberOfParagraphs-1) //ditto with the trial and error for these two previous lines. //if paragraphVerticalSpacing < 0 then // these commented out lines stop paragraphs growing into each other, but send them off the bottom of the screen when they get too large // paragraphVerticalSpacing = 0; // I can't decide which behaviour is better //end if; end if; //------------------------------------------------------draw the paragraphs-------------------------------------------------- string thecurrentdisplayline[longestParagraph] //set up an array for each line of the paragraph point baseline[2]; //####################################for debugging#################################### for counter = 0 to NumberOfParagraphs-1 // this is the loop that draws the paragraphs in outputParagraph one by one lineVisibility = 1; fontcolour = paragraphfontcolour[counter] setTextSize(paragraphsizes[counter]); leading = paragraphsizes[counter]*(1+lineleading/100) if paragraphstyle[counter] == 4 // bold & italic setTextstyle(kbolditalic); else if paragraphstyle[counter] == 3 // italic setTextstyle(kitalic); else if paragraphstyle[counter] == 2 // bold setTextstyle(kbold); else // plain setTextstyle(kplain); end if; if (counter + 1 > visiblelines ) // if this line is the next one to become visible if visiblelines != Integer(visiblelines) then // if a non integral number of lines are visible, we need the hoo ha below transitionLine = true; if visiblelines < Integer(visiblelines ) then // visible lines > x + 0.5 where x is integer, ie more than half way there, so the integer function is rounding up lineVisibility = (Integer(visiblelines)-visiblelines); //for our transition effects else lineVisibility = (visiblelines- Integer(visiblelines)); //for type on end if; // did I just reinvent the wheel? Tell me there's a better way to do that.. end if; end if; if counter < visibleLines // is it this paragraph's time to show yet? numberoflinesinParagraph = CountTextLines(outputParagraph[counter])-1; //count the lines in each paragraph - why the -1? I dunno totalcharsinparagraph = 0; for LineCounter = 0 to numberoflinesinParagraph-1; GetTextLine(outputParagraph[counter], LineCounter+1, thecurrentdisplayline[LineCounter]); //put our line into the array of lines. We do this as a separate loop because if we're using the type-on method if transitionstyle == 2 // then we first need to know how many characters there are in the whole paragraph totalcharsinparagraph += Length(thecurrentdisplayline[LineCounter]) end if; next if EaseIn != 1 lineVisibility = Power(lineVisibility, 1/EaseIn); end if; //--------------------------------------start of the write each line in the paragraph loop-------------------------------------------- for LineCounter = 0 to numberoflinesinParagraph-1; //write each line in the paragraph one by one currentlinelength = Length(thecurrentdisplayline[LineCounter]) if BlurOn channelFill(temp, 0, 0, 0, 0); channelFill(blurTemp, 0, 0, 0, 0); end if; //--------------------------------------type on effect-------------------------------------------- if transitionstyle == 2 numberofvisiblechars = integer(totalcharsinparagraph * lineVisibility ) fontcolour.a = paragraphfontcolour[counter].a //we don't need to fade the letters so alpha stays as it is set //to get the text to type on we have to do faux justification if fontalign == 3 // right setTextjustify(kleftjustify); measurestring(thecurrentdisplayline[LineCounter], fonttrack*fontsize/18, currentlinewidth , lineheight, ascent, descent, aspectof(dest)*aspect); textorigin.x = Truetextorigin - currentlinewidth; else if fontalign == 2 // center setTextjustify(kleftjustify); measurestring(thecurrentdisplayline[LineCounter], fonttrack*fontsize/18, currentlinewidth , lineheight, ascent, descent, aspectof(dest)*aspect); textorigin.x = Truetextorigin - currentlinewidth /2 end if; if currentlinelength > numberofvisiblechars then //if the current line has more characters in it than we want to show right now.. CharsOf(thecurrentdisplayline[LineCounter], 0, numberofvisiblechars, truncateddisplayline) thecurrentdisplayline[LineCounter] = truncateddisplayline //..then truncate it numberofvisiblechars = 0; // obviously we won't be showing any more text after this else numberofvisiblechars -= currentlinelength //..otherwise start on the next line, taking away the letters we are showing now end if; //--------------------------------------slide on effect--------------------------------------- else if transitionstyle == 3 slideonOffset = lineVisibility; if fontalign ==3 //right - slide on from LHS of screen textorigin.x = Truetextorigin - ((1-slideonOffset) * (framesize.x/2+Truetextorigin)); else if fontalign ==2 //centre -slide on from the RHS of screen measurestring(thecurrentdisplayline[LineCounter], fonttrack*fontsize/18, currentlinewidth , lineheight, ascent, descent, aspectof(dest)*aspect); textorigin.x = Truetextorigin + ((1-slideonOffset) * ((framesize.x/2)-Truetextorigin + currentlinewidth/2)); else if fontalign ==1 //left textorigin.x = Truetextorigin + ((1-slideonOffset) * (framesize.x/2-Truetextorigin)); end if; fontcolour.a = paragraphfontcolour[counter].a; //else if transitionstyle == 4 // measurestring(thecurrentdisplayline[LineCounter], fonttrack*fontsize/18, currentlinewidth , lineheight, ascent, descent, aspectof(dest)*aspect); else //--------------------------------------default fade on effect--------------------------------------- if transitionLine fontcolour.a =paragraphfontcolour[counter].a * lineVisibility //this line is in transition, so fade it appropriately else fontcolour.a =paragraphfontcolour[counter].a end if; end if; //--------------------------------------the actual text writing hoo hah---------------------------- if drawmargins baseline[0] = {leftmargin,textorigin.y} //draws the baseline for the text, once again I added it for debugging but it proved useful baseline[1] = {rightmargin,textorigin.y} Line(baseline[0] , baseline[1], Dest, kgreen, 2); end if; if transitionstyle == 4 && transitionLine measurestring(thecurrentdisplayline[LineCounter], fonttrack*fontsize/18, currentlinewidth , lineheight, ascent, descent, aspectof(dest)*aspect); textRect[0] = {textorigin.x- currentlinewidth/2, textorigin.y+lineheight/2}; textRect[1] = {textorigin.x+ currentlinewidth/2, textorigin.y+lineheight/2}; textRect[2] = {textorigin.x+ currentlinewidth/2, textorigin.y-lineheight/2}; textRect[3] = {textorigin.x- currentlinewidth/2, textorigin.y-lineheight/2}; DestRect[0] = {textorigin.x- currentlinewidth* (1-lineVisibility)*MaxStretchH, textorigin.y + lineheight * (1-lineVisibility) * MaxStretchV} DestRect[1] = {textorigin.x+ currentlinewidth * (1-lineVisibility)*MaxStretchH, textorigin.y + lineheight * (1-lineVisibility) * MaxStretchV} DestRect[2] = {textorigin.x+ currentlinewidth * (1-lineVisibility)*MaxStretchH, textorigin.y - lineheight * (1-lineVisibility) * MaxStretchV} DestRect[3] = {textorigin.x- currentlinewidth * (1-lineVisibility)*MaxStretchH, textorigin.y - lineheight * (1-lineVisibility) * MaxStretchV} DrawString(thecurrentdisplayline[LineCounter], textorigin.x, textorigin.y, fonttrack*fontsize/18, temp, fontcolour, aspectof(dest)*aspect); //write the text into a temporary buffer BlitRect(temp, textRect, BlurTemp, destRect) if !BlurOn dest += BlurTemp end if end if if blurOn && transitionstyle != 2 && transitionLine//blur on doesn't work with type on blurriness.x = MaxBlurH*(1-lineVisibility) blurriness.y = MaxBlurV*(1-lineVisibility) if transitionstyle != 4 //if it's a stretch on transitionwe've already written the text DrawString(thecurrentdisplayline[LineCounter], textorigin.x, textorigin.y, fonttrack*fontsize/18, blurTemp, fontcolour, aspectof(dest)*aspect); //write the text into a temporary buffer end if; MotionBlur(blurTemp, temp, MaxBlurH, MaxBlurV, (MaxBlurH+MaxBlurV)/2) //blur the contents of the buffer into another buffer //use motion blur to allow for differnt H&V values dest += temp //add the blurred image to the previously written paragraphs, etc in dest else if transitionstyle !=4 | !transitionLine DrawString(thecurrentdisplayline[LineCounter], textorigin.x, textorigin.y, fonttrack*fontsize/18, dest, fontcolour, aspectof(dest)*aspect); //the line that actually draws the text on screen. end if; if LineCounter < numberoflinesinParagraph-1 offset(textorigin, 0, paragraphAscent[counter]+paragraphleading[counter]); //carriage return: move the origin down one line end if next; if counter < numberofparagraphs-1 offset(textorigin, 0, paragraphVerticalSpacing+paragraphAscent[counter+1]); // move to the origin of the next paragraph end if end if next; // next paragraph //----------------------------------------------------------------------------------------------------------------------------------------- //NumToString(totaltextheight, debugstring, kplain) // <-- my debugging lines - put your variable in the brackets to see it on the screen //DrawString(debugstring, 0, 0, 10, dest, kblue, aspectof(dest)*aspect)//<--move these lines to wherever you need them namebetter text 1.4bscriptidgroupstib's generators alphatype fullframeencoded