home *** CD-ROM | disk | FTP | other *** search
- //
- // font.inc v0.3
- // Semi-Intelligent text manager for POVRay
- //
- // current version available at
- // http://quark.gmi.edu/~redbeard/raytracing/POVRay-util.html
- //
- // Written by Michael D Johnson
- // mjohnson@ccm.tdsnet.com or redbeard@quark.gmi.edu
- // http://quark.gmi.edu/~redbeard
- //
- // You're free to do what you like with this... I'm hereby donating it to the
- // public domain. If you do find it useful, or do anything with or to it,
- // I would like to hear from you.
- //
- // This version supports timrom.ttf, included with POVRay
- //
- // Variables:
- //
- // fontMode Indicates what action to take:
- // -2 & -3 reserved for testing purposes
- // -1 Set LetterWidth to width of character
- // 0 Generate a text object of one character
- // 1 Determine length of string. SpaceWidth must be set
- // Note that this string as NO INTERCHARACTER SPACING.
- // That is, the characters are calculated as all run
- // together.
- // 2 Place letters of a string in an arc.
- // 3 Place the letters of two strings about a circle. The
- // top has the first message centered at 12 oclock, with
- // the letters upright. The bottom has the second
- // message, centered at 6 oclock, again with the letters
- // upright.
- // The default value is 0.
- //
- // ---------- Single character variables (modes -1 and 0)
- // Letter Letter to generate the object for or get the width of.
- // Align -1 = baseline left at origin, 0 = baseline center at origin,
- // 1 = basline right at origin
- //
- // ---------- String arrangement variables
- // SpaceWidth The width of a space character in units.
- //
- // Message Mode 1: String to create to measure the length of
- // Mode 2: String to create
- // Mode 3: Top string
- // There is no default
- //
- // Message2 Mode 3: Bottom string. No default
- //
- // StartAng Mode 2: Starting angle. Negative Z-rotation, (clockwise)
- // with 9 oclock position being 0 degrees. Default = 0
- // Mode 3: Returned angle of center of left side gap
- //
- // EndAng Mode 2: Ending angle. If EndAng < StartAng, text will be
- // backwards. Default = 180
- // Mode 3: Returned angle of center of right side gap
- //
- // Rad Modes 2 & 3: Radius of baseline of text. Default = 10
- //
- // Facing Mode 2: Bottom of letters face towards center (0) or
- // outside (1). Default = 0
- //
- // Spacing Modes 2 & 3: keep this many degrees gap between letters
- // Font will be scaled to achieve this. Defaults to 2.
- //
- // Height Modes 2 & 3: Set by the file to the maximum (?) height of
- // the letters.
- //
- // Gap Mode 3: Angle of gap between top and bottom. This gap will
- // on the left and right sides. Default = 5
- //
- // Tilt Modes 2 & 3: Incline from the plane of the arc, in degrees.
- // Angle about curve with positive curve in clockwise direction.
- // I.e., place left hand with thumb pointing clockwise about
- // curve. Fingers point in direction of positive rotation.
- //
- // Thick Modes 2 & 3: Thickness of the letters
- //
- //
- // Call with Letter set to the string value of the letter (e.g. "A") and
- // fontMode set to 0 for the text object or 1 for the LetterWidth to be
- // set. LetterWidth is set, regardless, to the width in units of the text
- // object. This value is approximate.
- //
- // When a text object is created (i.e. fontMode = 0), it is centered on the
- // X axis, the baseline of the letter is on the Y axis, and the face is in
- // the XY plane. The thickness of the object is 1.
- //
- // WARNING!
- // Using the arc/circle modes (fontModes 2 and 3) incur vast recursion.
- // This can make parsing a lengthy process. Maybe in POVRay 4.0
- // true subroutines will be introduced. Then I won't have keep re-calling
- // this file :)
- //
- // Limitations:
- // Currently only handles ASCII characters 32 - 126
- // Can only generate strings arrayed in circles and arcs
- // Doesnt know anything about kerning.
- // Cannot be simply changed for different fonts.
- // Widths are only accurate to 0.01 units.
- // Documentation is still a little lacking... but you should be able to
- // get by. :)
- //
- // Bugs:
- // I think that the returned value for StartAng and EndAng from
- // fontMode = 3 are incorrect. I'll get that figured out sooner or later
- // Sooner if someone needs it.
- //
- //
-
- #declare font_inc_Ver = "0.3"
-
- #ifndef (NOBANNER) #declare NOBANNER = 0 #end
- #if (NOBANNER = 0)
- #debug concat("---font.inc v", font_inc_Ver, ", Mode: ",
- str(fontMode, 0, 0), "---\n")
- #end
-
- // This stuff is just so the banner only appears once each time it is called
- // by an external file. Otherwise, with NOBANNER undefined or set to 0,
- // the banner would appear everytime the file recurses another level.
- #ifndef (_FI_recurse) #declare _FI_recurse = 0 #end
- #declare _FI_recurse = _FI_recurse + 1
-
- #if (_FI_recurse = 1)
- #declare _FI_oldbanner = NOBANNER
- #declare NOBANNER = 1
- #end
-
- //#declare TEST_SPACING = "~"
- //#declare TEST_PHRASE = "April 1996"
-
- #declare TIMROM_Space =
- concat(
- /* ! " # $ % & ' ( ) * + , - . / */
- "012027050043079076011030030036051016025011027",
- /* 0 1 2 3 4 5 6 7 8 9 : ; < = > ? */
- "045029045039047039044043040044011016052052052037",
- /* @ A B C D E F G H I J K L M N O */
- "097074060052069059051070071030038074059089073069",
- /* P Q R S T U V W X Y Z [ \ ] ^ _ */
- "052067068044057073072095073071059022027022047055",
- /* ` a b c d e f g h i j k l m n o */
- "018031047039048040039045050023025051023079050044",
- /* p q r s t u v w x y z { | } ~ */
- "048047035032028051049075059050042030004030053")
-
- #declare fontHeight = 0.68
-
- // This section is for calculating spacing
-
- #ifdef (TEST_SPACING) #declare fontMode = -2
- #else
- #ifdef (TEST_PHRASE) #declare fontMode = -3
- #end
- #end
-
- #ifndef (fontMode) #declare fontMode = 0 #end
-
- #switch (int(fontMode))
- #range (-3, -2)
- #include "colors.inc"
- camera
- {
- orthographic
- location <1, 0.5, -3> look_at <1, 0.5, 0>
- right x * 2 * (-1 - fontMode) up y * 1.5 * (-1 - fontMode)
- }
-
- plane
- {
- z, 1
- texture
- {
- pigment
- {
- checker
- pigment { checker color Red color Yellow translate -5 scale 0.1 }
- pigment { checker color Green color Blue translate -5 scale 0.1 }
- translate -5 scale 0.1
- }
- finish { ambient 0.8 }
- }
- }
-
- text
- {
- ttf "timrom.ttf"
- #if (fontMode = -2)
- TEST_SPACING 1, 0
- #else
- TEST_PHRASE 1, 0 scale 0.5
- #end
- texture { pigment { Black } finish { ambient 0.8 } }
- }
- #break
-
- #case (0) // Generate an aligned text object
- #ifndef (Align) #declare Align = 0 #end
- #if (Align < -1 | Align > 1)
- #error concat("Align value of ", str(Align, 0, 0),
- " illegal for font.inc. Must be -1, 0, or 1")
- #end
- #declare Align = int(Align)
-
- #declare fontMode = -1
- #include "font.inc" // Recursive call to get letter width
- #declare fontMode = 0
- text
- {
- ttf "timrom.ttf" Letter 1, 0
- translate x * LetterWidth * (-1 - Align) / 2
- }
- #break
-
- #case (1) // Determine the length of a string
- #ifndef (SpaceWidth) #declare SpaceWidth = 0.5 #end
- #declare fontMode = -1
- #declare _FI_I = 0
- #declare MessageLength = 0
-
- #while (_FI_I < strlen(Message))
- #declare Letter = substr(Message, _FI_I+1, 1)
- #if (asc(Letter) = 32)
- #declare LetterWidth = SpaceWidth
- #else
- #include "font.inc" // Recursive call to get width of letter
- #end
- #declare MessageLength = MessageLength + LetterWidth
- #declare _FI_I = _FI_I + 1
- #end
- #declare fontMode = 1
- #break
-
- #range (2, 3) // Circular arrangements
- // Circular general defaults
- #ifndef (Rad) #declare Rad = 10 #end
- #ifndef (Spacing) #declare Spacing = 2 #end
- #ifndef (Gap) #declare Gap = 5 #end
- #ifndef (Tilt) #declare Tilt = 0 #end
- #ifndef (Thick) #declare Thick = 1 #end
- #ifndef (FixHeight) #declare FixHeight = 0 #end
-
- union
- {
- #switch (int(fontMode))
- #case (2)
- // Single string defaults
- #ifndef (StartAng) #declare StartAng = 0 #end
- #ifndef (EndAng) #declare EndAng = 180 #end
- #ifndef (Facing) #declare Facing = 0 #end
-
- #declare _FI_Facing = int(Facing)
- #if ((_FI_Facing < 0) | (_FI_Facing > 1))
- #error concat("Invalid value for Facing: ", str(Facing, 0,-1),
- " in textarc.inc\n")
- #end
-
- // Calculate the message length
- #declare _FI_Len = strlen(Message)
-
- // Determine the direction to go and the amount to go.
- #declare _FI_Dir = ((EndAng < StartAng) ? -1 : 1)
- #declare _FI_Ang = abs(EndAng - StartAng)
-
- // Calculate the length of the arc
- #declare _FI_Circ = 2 * pi * Rad
- #declare _FI_ArcLen = _FI_Circ * _FI_Ang / 360
-
- // Get the length of the text in a straight line
- #declare fontMode = 1 #include "font.inc"
-
- // Find the scale for the letters. This is intended to get the
- // spacing angle correct. If FixHeight is set, base everything
- // on a provided Height value instead.
- #if (FixHeight)
- #declare _FI_Scale = Height / fontHeight
- #declare Spacing = ((360 *
- (_FI_ArcLen - _FI_Scale * MessageLength)) /
- (_FI_ArcLen * (_FI_Len - 1)))
- #else
- #declare _FI_Scale = ((_FI_ArcLen -
- (_FI_Len-1)*Spacing*_FI_ArcLen/360) /
- MessageLength)
- #end
- #declare _FI_WFact = ((_FI_Ang - Spacing * (_FI_Len - 1)) /
- MessageLength)
-
- #declare fontMode = 0 // Cause font.inc to return objects
- #declare Align = 0 // Put the center baseline at the origin
-
- #declare _FI_Rot = StartAng - 90
- #declare _FI_I = 0
- #while (_FI_I < _FI_Len)
- #declare Letter = substr(Message, _FI_I + 1, 1)
- #if (asc(Letter) != 32)
- object
- {
- #include "font.inc" // Recursive call
- scale <_FI_Scale, _FI_Scale, Thick>
- rotate <0, (_FI_Dir - 1) * 90, Facing * 180>
- rotate x * Tilt
- translate y * Rad
- #declare _FI_LetAng = _FI_WFact * LetterWidth
- rotate (z * ((_FI_Rot + _FI_LetAng / 2) * _FI_Dir *
- (-1 + Facing * 2) - 180 * Facing))
- }
- #else #declare _FI_LetAng = SpaceWidth * _FI_WFact
- #end
- #declare _FI_Rot = _FI_Rot + Spacing + _FI_LetAng
- #declare _FI_I = _FI_I + 1
- #end
- #declare Height = fontHeight * _FI_Scale
- #declare fontMode = 2
- #break
-
- #case (3)
- #ifndef (Gap) #declare Gap = 5 #end
- // Figure out sizes
- #declare _FI_message = Message
- #declare fontMode = 1
- #include "font.inc"
- #declare _FI_TopLen = MessageLength
- #declare Message = Message2
- #include "font.inc"
- #declare _FI_BotLen = MessageLength
- #declare _FI_TotLen = _FI_TopLen + _FI_BotLen
- #declare _FI_TopRat = _FI_TopLen / _FI_TotLen
- #declare _FI_BotRat = _FI_BotLen / _FI_TotLen
- #declare _FI_TotAng = 360 - Gap * 2
- #declare _FI_TopAng = _FI_TotAng * _FI_TopRat
- #declare _FI_BotAng = _FI_TotAng * _FI_BotRat
- #declare _FI_TopStart = 90 - _FI_TopAng / 2
- #declare _FI_TopEnd = _FI_TopStart + _FI_TopAng
- #declare _FI_BotStart = 90 - _FI_BotAng / 2
- #declare _FI_BotEnd = _FI_BotStart + _FI_BotAng
-
- #declare fontMode = 2
- #declare StartAng = _FI_TopStart
- #declare EndAng = _FI_TopEnd
- #declare Facing = 0
- #declare Message = _FI_message
- #include "font.inc"
-
- #declare _FI_rad = Rad
- #declare _FI_spacing = Spacing
- #declare _FI_FixHeight = FixHeight
- #declare FixHeight = 1
- #declare Rad = Rad + Height
- #declare StartAng = _FI_BotStart
- #declare EndAng = _FI_BotEnd
- #declare Facing = 1
- #declare Message = Message2
- #include "font.inc"
-
- #declare Rad = _FI_rad
- #declare Spacing = _FI_spacing
- #declare FixHeight = _FI_FixHeight
- #declare StartAng = _FI_TopStart - Gap / 2
- #declare EndAng = _FI_TopEnd + Gap / 2
-
- #declare fontMode = 3
- #break
-
- #end
- }
-
- #break
-
- #else
- #declare LetterWidth =
- val(substr(TIMROM_Space, (asc(Letter) - 33) * 3 + 1,3)) / 100
- #end
-
- #declare _FI_recurse = _FI_recurse - 1
- #if (_FI_recurse = 0)
- #declare NOBANNER = _FI_oldbanner
- #end
-