/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* *                                                                                                                 * */
/* *                                                                                                                 * */
/* * SET CONSTANTS AND DEFAULT VARIABLE VALUES                                                                       * */
/* *                                                                                                                 * */
/* *                                                                                                                 * */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

#declare LEFT = 0;
#declare RIGHT = 1;
#declare CENTERED = 2;
#declare JUSTIFIED = 3;

#declare UNLIMITED = -1;

#declare GAP_Width = .06;
#declare SPACE_Width = .26;
#declare LineSpacing = .5;

#declare LineAlignment = LEFT;
#declare MaxMicroJustificationScale = 1;
#declare MaxAdditionalGAP_WidthPercentage = UNLIMITED;
#declare SPACE_ExpansionRate = 1.5;
#declare JustifyLastLinePercentage = 95;
#declare MinJustifiedParagraphWidth = 0;

#declare CurFontStyleIndex = 0;
#declare LastFontStyleIndex = -1;

#declare FontStyleRecord_Valid = array [100]
#declare FontStyleRecord_FontVariationNumber = array [100]
#declare FontStyleRecord_P0 = array [100]
#declare FontStyleRecord_P1 = array [100]
#declare FontStyleRecord_P2 = array [100]
#declare FontStyleRecord_P3 = array [100]
#declare FontStyleRecord_P4 = array [100]
#declare FontStyleRecord_P5 = array [100]
#declare FontStyleRecord_P6 = array [100]
#declare FontStyleRecord_P7 = array [100]
#declare FontStyleRecord_P8 = array [100]
#declare FontStyleRecord_TextColor_Outer = array [100]
#declare FontStyleRecord_TextColor_Inner = array [100]
#declare FontStyleRecord_TextColor_Back = array [100]

#for (I, 0, 99)
   #declare FontStyleRecord_Valid [I] = true;
   #declare FontStyleRecord_FontVariationNumber [I] = 0;
   #declare FontStyleRecord_P0 [I] = .08;
   #declare FontStyleRecord_P1 [I] = 0;
   #declare FontStyleRecord_P2 [I] = 999;
   #declare FontStyleRecord_P3 [I] = 999;
   #declare FontStyleRecord_P4 [I] = 999;
   #declare FontStyleRecord_P5 [I] = 999;
   #declare FontStyleRecord_P6 [I] = 999;
   #declare FontStyleRecord_P7 [I] = 999;
   #declare FontStyleRecord_P8 [I] = 999;
   #declare FontStyleRecord_TextColor_Outer [I] = texture {pigment {color <1, 1, 1>}}
   #declare FontStyleRecord_TextColor_Inner [I] = texture {pigment {color <.620, .694, .071>}}
   #declare FontStyleRecord_TextColor_Back [I] = texture {pigment {color <1, 1, 1>}}
#end //#for

#declare CurrentParagraphNumber = 0;

#declare ParagraphHistory_Width = array [1000]
#declare ParagraphHistory_Height = array [1000]

#declare ApplyTextures = true;

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* *                                                                                                                 * */
/* *                                                                                                                 * */
/* * MACROS                                                                                                          * */
/* *                                                                                                                 * */
/* *                                                                                                                 * */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

#macro InitializeVariables (NLines)

   #declare LineText = array [NLines]
   #declare LineTextObject = array [NLines]
   #declare LineNCharacters = array [NLines]
   #declare LineNSpaces = array [NLines]
   #declare LineNVisibleCharacters = array [NLines]
   #declare LineScale = array [NLines]
   #declare LineWidth = array [NLines]
   #declare ItalicOffset_Beginning = array [NLines]
   #declare LineCharacters = array [NLines] [256]
   #declare LineKerning = array [NLines] [255]
   #declare CharacterVisibilityCondition = array [NLines] [256]
   #declare CharacterItalicStatus = array [NLines] [256]
   #declare CharacterFontStyleIndex = array [NLines] [256]
   #declare CharacterInUse = array [NDefinedCharacters];

#end //#macro InitializeVariables

#macro InitializeLine (I)

   #local TempLineCharacters = array [256]
   #local TempCharacterFontStyleIndex = array [256]

   #local LineText_Copy = LineText [I];

   #declare LineScale [I] = 1;

   #declare LineNCharacters [I] = strlen (LineText_Copy);

   #for (J, 0, LineNCharacters [I] - 1)
      #declare TempCharacterFontStyleIndex [J] = CurFontStyleIndex;
   #end //#for

   #local NeedToCheck = yes;

   #while (NeedToCheck)
      #local NeedToCheck = no;
      #for (J, 1, LineNCharacters [I])
         #local CurChar = asc (substr (LineText_Copy, J, 1));
         #if (CurChar = asc ("~"))
            #local NeedToCheck = yes;
            #local EndBracketFound = false;
            #for (K, J + 2, LineNCharacters [I])
               #local CurChar = asc (substr (LineText_Copy, K, 1));
               #if (CurChar = asc ("~"))
                  #local EndBracketFound = true;
                  #break //#for
               #end //#if
            #end //#for
            #if (EndBracketFound)
               #for (L, J + 1, K - 1)
                  #local CurChar = asc (substr (LineText_Copy, L, 1));
                  #if (CurChar < asc ("0") | CurChar > asc ("9"))
                     #error concat ("* * * Line #", str (I, 0, 0), " has a mis-formated style index. (Proper format is \"~nn~\" where \"nn\" is an integer.)")
                  #end //#if
               #end //#for
            #else
               #error concat ("* * * Line #", str (I, 0, 0), " has a mis-formated style index. (Proper format is \"~nn~\" where \"nn\" is an integer.)")
            #end //#if
            #local FontStyleIndexString = substr (LineText_Copy, J + 1, K - J - 1)
            #declare CurFontStyleIndex = val (FontStyleIndexString);
            #local StringLength = K - J - 1 + 2;
            #declare LineText_Left = substr (LineText_Copy, 1, J - 1);
            #declare LineText_Right = substr (LineText_Copy, K + 1, LineNCharacters [I] - K);
            #declare LineText_Copy = concat (LineText_Left, LineText_Right);
            #declare LineNCharacters [I] = LineNCharacters [I] - StringLength;
            #for (L, J, LineNCharacters [I])
               #declare TempCharacterFontStyleIndex [L - 1] = CurFontStyleIndex;
            #end //#for
            #break //#for
         #end //#if
      #end //#for
   #end //#while

   #for (J, 1, LineNCharacters [I] - 1)
      #local CurChar = asc (substr (LineText_Copy, J, 1));
      #local NextChar = asc (substr (LineText_Copy, J + 1, 1));
      #if (CurChar = asc ("{") & NextChar = asc (" "))
         #declare LineText_Copy = concat (substr (LineText_Copy, 1, J - 1), " {",
            substr (LineText_Copy, J + 2, LineNCharacters [I] - J - 1));
      #elseif (CurChar = asc ("}") & NextChar = asc (" "))
         #declare LineText_Copy = concat (substr (LineText_Copy, 1, J - 1), " }",
            substr (LineText_Copy, J + 2, LineNCharacters [I] - J - 1));
      #end //#if
   #end //#for

   #local CurItalicCondition = false;
   #local TempLineNCharacters = 0;

   #for (J, 0, LineNCharacters [I] - 1)
      #local CurChar = asc (substr (LineText_Copy, J + 1, 1));
      #if (CurChar = asc ("{") | CurChar = asc ("}"))
         #if (CurChar = asc ("{"))
            #local CurItalicCondition = true;
         #else
            #local CurItalicCondition = false;
         #end //#if
      #else
         #local TempLineNCharacters = TempLineNCharacters + 1;
         #local TempLineCharacters [TempLineNCharacters - 1] = CurChar;
         #declare CharacterItalicStatus [I] [TempLineNCharacters - 1] = CurItalicCondition;
         #declare CharacterFontStyleIndex [I] [TempLineNCharacters - 1] = TempCharacterFontStyleIndex [J];
      #end //#if
   #end //#for

   #declare LineNCharacters [I] = TempLineNCharacters;

   #if (LineNCharacters [I] = 0)
      #error concat ("* * * Line #", str (I, 0, 0), " evaluates to a blank line.")
   #end //#if

   #for (J, 0, LineNCharacters [I] - 1)
      #declare LineCharacters [I] [J] = ASCIIToIndex (TempLineCharacters [J]);
      #declare CharacterVisibilityCondition [I] [J] = 0;
   #end //#for

   #while (LineCharacters [I] [0] = -1)
      #local N = LineNCharacters [I];
      #if (N = 1)
         #error concat ("* * * Line #", str (I, 0, 0), " evaluates to a blank line.")
      #else
         #for (J, 0, N - 2)
            #declare LineCharacters [I] [J] = LineCharacters [I] [J + 1];
            #declare CharacterItalicStatus [I] [J] = CharacterItalicStatus [I] [J + 1];
            #declare CharacterFontStyleIndex [I] [J] = CharacterFontStyleIndex [I] [J + 1];
         #end //#for
         #declare LineNCharacters [I] = LineNCharacters [I] - 1;
      #end //#if
   #end //#while

   #while (LineCharacters [I] [LineNCharacters [I] - 1] = -1)
      #declare LineNCharacters [I] = LineNCharacters [I] - 1;
   #end //#while

   #local NeedToCheck = yes;

   #while (NeedToCheck)
      #local NeedToCheck = no;
      #if (LineNCharacters [I] > 3)
         #local N = LineNCharacters [I];
         #for (J, 1, N - 3)
            #if (LineCharacters [I] [J] = -1 & LineCharacters [I] [J + 1] = -1)
               #for (K, J + 1, N - 2)
                  #declare LineCharacters [I] [K] = LineCharacters [I] [K + 1];
                  #declare CharacterItalicStatus [I] [K] = CharacterItalicStatus [I] [K + 1];
                  #declare CharacterFontStyleIndex [I] [K] = CharacterFontStyleIndex [I] [K + 1];
               #end //#for
               #declare LineNCharacters [I] = LineNCharacters [I] - 1;
               #local NeedToCheck = yes;
               #break //#for
            #end //#if
         #end //#for
      #end //#if
   #end //#while

#end //#macro InitializeLine

#macro MarkInvisibleCharacters (I)

   #for (J, 2, LineNCharacters [I] - 1)
      #local CurChar = LineCharacters [I] [J];
      #if (CurChar != -1)
         #local PrevChar1 = LineCharacters [I] [J - 1];
         #local PrevChar2 = LineCharacters [I] [J - 2];
         #local Condition = 1;
         #if (PrevChar1 = -1)
            #local Condition = 0;
         #end //#if
         #if (J > 2)
            #local PrevChar3 = LineCharacters [I] [J - 3];
            #if (PrevChar3 != -1)
               #if (PrevChar1 = -1)
                  #local Condition = 2;
               #elseif (PrevChar2 = -1)
                  #local Condition = 3;
               #end //#if
            #end //#if
         #end //#if
         #switch (Condition)
            #case (1) //Example: "P.T"
               #local X1 = Kerning [PrevChar2] [PrevChar1] + GAP_Width + BorderCharacterWidth [PrevChar1] +
                  GAP_Width + Kerning [PrevChar1] [CurChar];
               #local X2 = Kerning [PrevChar2] [CurChar] + GAP_Width;
               #if (X2 > X1)
                  //#debug concat ("\nCondition 1:\nLine #", str (I, 0, 0), ": \n")
                  //#debug concat ("Invisible character: ", str (PrevChar1, 0, 0), "\n")
                  #declare CharacterVisibilityCondition [I] [J - 1] = 1;
               #end //#if
            #break //#case
            #case (2) //Example: "P. T"
               #local X1 = Kerning [PrevChar3] [PrevChar2] + GAP_Width + BorderCharacterWidth [PrevChar2] +
                  Kerning [PrevChar2] [CurChar] + GAP_Width + SPACE_Width;
               #local X2 = Kerning [PrevChar3] [CurChar] + GAP_Width + SPACE_Width;
               #if (X2 > X1)
                  //#debug concat ("\nCondition 2:\nLine #", str (I, 0, 0), ": \n")
                  //#debug concat ("Invisible character: ", str (PrevChar2, 0, 0), "\n")
                  #declare CharacterVisibilityCondition [I] [J - 2] = 2;
               #end //#if
            #break //#case
            #case (3) //Example: "I .T"
               #local X1 = Kerning [PrevChar3] [PrevChar1] + GAP_Width + SPACE_Width + BorderCharacterWidth [PrevChar1] +
                  GAP_Width + Kerning [PrevChar1] [CurChar];
               #local X2 = Kerning [PrevChar3] [CurChar] + GAP_Width + SPACE_Width;
               #if (X2 > X1)
                  //#debug concat ("\nCondition 3:\nLine #", str (I, 0, 0), ": \n")
                  //#debug concat ("Invisible character: ", str (PrevChar1, 0, 0), "\n")
                  #declare CharacterVisibilityCondition [I] [J - 1] = 3;
               #end //#if
            #break //#case
         #end //#switch
      #end //#if
   #end //#for

   #if (LineNCharacters [I] > 1) //See if the first character is invisible
      #local Char1 = LineCharacters [I] [0];
      #local Char2 = LineCharacters [I] [1];
      #if (Char2 != -1)
         #local X1 = BorderCharacterWidth [Char1] + GAP_Width + Kerning [Char1] [Char2];
         #if (X1 <= 0)
            //#debug concat ("\nLine #", str (I, 0, 0), ": First character is invisible\n")
            #declare CharacterVisibilityCondition [I] [0] = 3;
         #end //#if
      #end //#if
   #end //#if

   #if (LineNCharacters [I] > 1) //See if the last character is invisible
      #local Char1 = LineCharacters [I] [LineNCharacters [I] - 2];
      #local Char2 = LineCharacters [I] [LineNCharacters [I] - 1];
      #if (Char1 != -1)
         #local X1 = Kerning [Char1] [Char2] + GAP_Width + BorderCharacterWidth [Char2];
         #if (X1 <= 0)
            //#debug concat ("\nLine #", str (I, 0, 0), ": Last character is invisible\n")
            #declare CharacterVisibilityCondition [I] [LineNCharacters [I] - 1] = 1;
         #end //#if
      #end //#if
   #end //#if

#end //#macro MarkInvisibleCharacters

#macro ComputeLineWidth (I)

   #declare LineNVisibleCharacters [I] = 0;
   #declare LineNSpaces [I] = 0;
   #declare LineWidth [I] = 0;

   #local LastItalicCondition = CharacterItalicStatus [I] [0];

   #for (J, 0, LineNCharacters [I] - 1)
      #local CurChar = LineCharacters [I] [J];
      #if (CharacterVisibilityCondition [I] [J] = 0)
         #declare LineNVisibleCharacters [I] = LineNVisibleCharacters [I] + 1;
         #if (CurChar = -1)
            #declare LineKerning [I] [J] = SPACE_Width;
            #declare LineWidth [I] = LineWidth [I] + SPACE_Width + GAP_Width;
            #declare LineNSpaces [I] = LineNSpaces [I] + 1;
         #else
            #declare LineWidth [I] = LineWidth [I] + BorderCharacterWidth [CurChar];
            #if (J < LineNCharacters [I] - 2) //There ARE more remaining VISIBLE characters
               #declare LineWidth [I] = LineWidth [I] + GAP_Width;
            #end //#if
            #if (J = LineNCharacters [I] - 2) //There MIGHT BE more remaining VISIBLE characters
               #if (CharacterVisibilityCondition [I] [J + 1] = 0)
                  #declare LineWidth [I] = LineWidth [I] + GAP_Width;
               #end //#if
            #end //#if
            #if (J <= LineNCharacters [I] - 2)
               #local NextCharFound = false;
               #for (K, J + 1, LineNCharacters [I] - 1)
                  #local CompChar = LineCharacters [I] [K];
                  #if (CharacterVisibilityCondition [I] [K] = 0 & CompChar != -1)
                     #local NextCharFound = true;
                     #local NextChar = LineCharacters [I] [K];
                     #break //#for
                  #end //#if
               #end //#for
               #if (NextCharFound)
                  #declare LineKerning [I] [J] = Kerning [CurChar] [NextChar];
                  #declare LineWidth [I] = LineWidth [I] + LineKerning [I] [J];
               #end //#if
            #end //#if
         #end //#if
      #end //#if
      #local CurItalicCondition = CharacterItalicStatus [I] [J];
      #if (CurItalicCondition != LastItalicCondition)
         #if (CurItalicCondition = true) //Transitioning from normal to italic
            #local PrevCharFound = false;
            #for (K, J - 1, 0, -1)
               #if (CharacterVisibilityCondition [I] [K] = 0 & LineCharacters [I] [K] != -1)
                  #local PrevCharFound = true;
                  #local PrevChar = LineCharacters [I] [K];
                  #break //#for
               #end //#if
            #end //#for
            #if (PrevCharFound)
               #declare LineKerning [I] [K] = LineKerning [I] [K] + ItalicOffset [CurChar * 2] - Kerning [PrevChar] [CurChar] + Kerning_NormalToItalic [PrevChar] [CurChar];
               #declare LineWidth [I] = LineWidth [I] + ItalicOffset [CurChar * 2] - Kerning [PrevChar] [CurChar] + Kerning_NormalToItalic [PrevChar] [CurChar];
            #end //#if
         #else //Transitioning from italic to normal
            #local PrevCharFound = false;
            #for (K, J - 1, 0, -1)
               #if (CharacterVisibilityCondition [I] [K] = 0 & LineCharacters [I] [K] != -1)
                  #local PrevCharFound = true;
                  #local PrevChar = LineCharacters [I] [K];
                  #break //#for
               #end //#if
            #end //#for
            #if (PrevCharFound)
               #declare LineKerning [I] [K] = LineKerning [I] [K] + ItalicOffset [PrevChar * 2 + 1] - Kerning [PrevChar] [CurChar] + Kerning_ItalicToNormal [PrevChar] [CurChar];
               #declare LineWidth [I] = LineWidth [I] + ItalicOffset [PrevChar * 2 + 1] - Kerning [PrevChar] [CurChar] + Kerning_ItalicToNormal [PrevChar] [CurChar];
            #end //#if
         #end //#if
         #local LastItalicCondition = CurItalicCondition;
      #end //#if
   #end //#for

   #declare ItalicOffset_Beginning [I] = 0;

   #declare ItalicOffset_End = 0;

   #if (CharacterItalicStatus [I] [0])
      #local FirstChar = LineCharacters [I] [0];
      #declare ItalicOffset_Beginning [I] = ItalicOffset [FirstChar * 2];
      #declare LineWidth [I] = LineWidth [I] + ItalicOffset_Beginning [I];
   #end //#if

   #if (CharacterItalicStatus [I] [LineNCharacters [I] - 1])
      #if (CharacterVisibilityCondition [I] [LineNCharacters [I] - 1] = 0)
         #local LastChar = LineCharacters [I] [LineNCharacters [I] - 1];
      #else
         #local LastChar = LineCharacters [I] [LineNCharacters [I] - 2];
      #end //#if
      #local ItalicOffset_End = ItalicOffset [LastChar * 2 + 1];
      #declare LineWidth [I] = LineWidth [I] + ItalicOffset_End;
   #end //#if

#end //#macro ComputeLineWidth

#macro CreateLine (I, MaxLineWidth, TextScale)

   #if (MaxAdditionalGAP_WidthPercentage != UNLIMITED)
      #local MaxGapPadding = GAP_Width * MaxAdditionalGAP_WidthPercentage / 100; //Padding is in addition to GAP_Width
   #end //#if

   #local GapPadding = 0;
   #local SpacePadding = 0;

   #if (LineAlignment = JUSTIFIED)
      #if (MaxMicroJustificationScale < 1 & MaxMicroJustificationScale != -1)
         #declare MaxMicroJustificationScale = 1;
      #end //#if
      #declare LineScale [I] = ParagraphWidth / LineWidth [I];
      #if (MaxMicroJustificationScale != UNLIMITED)
         #if (LineScale [I] > MaxMicroJustificationScale)
             #declare LineScale [I] = MaxMicroJustificationScale;
         #end //#if
      #end //#if
      #if (MaxMicroJustificationScale != 1)
         #declare LastFontStyleIndex = -1;
      #end //#if
   #end //#if

   #if (LineAlignment = JUSTIFIED & LineNVisibleCharacters [I] > 1)
      #if (I < NLines - 1 | NLines = 1 | MaxMicroJustificationScale != 1 | (LineWidth [I] * LineScale [I] / MaxLineWidth * 100 >= JustifyLastLinePercentage))
         #local ExtraWidth = MaxLineWidth - LineWidth [I] * LineScale [I];
         #local P1 = GAP_Width * LineScale [I] * (LineNVisibleCharacters [I] - 1);
         #local P2 = SPACE_Width * LineScale [I] * SPACE_ExpansionRate * LineNSpaces [I];
         #if (P1 + P2 > 0)
            #local WidthGrowthFactor = ExtraWidth / (P1 + P2);
         #else
            #local WidthGrowthFactor = 0;
         #end //#if
         #local GapPadding = GAP_Width * WidthGrowthFactor;
         #local SpacePadding = SPACE_Width * WidthGrowthFactor * SPACE_ExpansionRate;
         #if (MaxAdditionalGAP_WidthPercentage != UNLIMITED)
            #if (GapPadding > MaxGapPadding & LineNSpaces [I] > 0)
               #local GapPadding = MaxGapPadding;
               #local SpacePadding = (ExtraWidth / LineScale [I] - (LineNVisibleCharacters [I] - 1) * GapPadding) / LineNSpaces [I];
            #end //#if
         #end //#if
      #end //#if
   #end //#if

   #local CurGap = GAP_Width + GapPadding;
   #local CurSpace = SPACE_Width + SpacePadding;

   #declare LineTextObject [I] = object {
      #local CurX = ItalicOffset_Beginning [I];
      #if (LineNCharacters [I] > 1)
         union {
            #for (J, 0, LineNCharacters [I] - 1)
               #if (J = 0 & CharacterVisibilityCondition [I] [0] != 0) //First character is invisible
                  #local CurChar = LineCharacters [I] [0];
                  #declare CurFontStyleIndex = CharacterFontStyleIndex [I] [0];
                  #if (CurFontStyleIndex != LastFontStyleIndex)
                     Stylize (CurFontStyleIndex, TextScale * LineScale [I])
                     #declare LastFontStyleIndex = CurFontStyleIndex;
                  #end //#if
                  object {
                     BorderCharacter [CurChar]
                     translate CurX * x
                     #if (CharacterItalicStatus [I] [0])
                        Italicize ()
                     #end //#if
                  } //object
                  #local NextChar = LineCharacters [I] [1];
                  #local CurX = CurX + BorderCharacterWidth [CurChar] + Kerning [CurChar] [NextChar] + CurGap;
                  #if (CurX < ItalicOffset_Beginning [I])
                     #local CurX = ItalicOffset_Beginning [I];
                  #end //#if
               #end //#if
               #if (CharacterVisibilityCondition [I] [J] = 0)
                  #local CurChar = LineCharacters [I] [J];
                  #local LastX = CurX;
                  #if (CurChar = -1)
                     #local CurX = CurX + LineKerning [I] [J] + CurGap + SpacePadding;
                  #else
                     #declare CurFontStyleIndex = CharacterFontStyleIndex [I] [J];
                     #if (CurFontStyleIndex != LastFontStyleIndex)
                        Stylize (CurFontStyleIndex, TextScale * LineScale [I])
                        #declare LastFontStyleIndex = CurFontStyleIndex;
                     #end //#if
                     object {
                        BorderCharacter [CurChar]
                        translate CurX * x
                        #if (CharacterItalicStatus [I] [J])
                           Italicize ()
                        #end //#if
                     } //object
                     #if (J <= LineNCharacters [I] - 2)
                        #if (J < LineNCharacters [I] - 2 | CharacterVisibilityCondition [I] [LineNCharacters [I] - 1] = 0)
                           #local CurX = CurX + BorderCharacterWidth [CurChar] + LineKerning [I] [J] + CurGap;
                        #end //#if
                     #end //#if
                  #end //#if
                  #if (J < LineNCharacters [I] - 1)
                     #local NextLVC = CharacterVisibilityCondition [I] [J + 1];
                     #if (NextLVC != 0)
                        #local NextChar = LineCharacters [I] [J + 1];
                        #if (CurChar = -1)
                           #local TempX = LastX + CurSpace + CurGap;
                        #else
                           #local TempX = LastX + BorderCharacterWidth [CurChar] + Kerning [CurChar] [NextChar] + CurGap;
                        #end //#if
                        #declare CurFontStyleIndex = CharacterFontStyleIndex [I] [J + 1];
                        #if (CurFontStyleIndex != LastFontStyleIndex)
                           Stylize (CurFontStyleIndex, TextScale * LineScale [I])
                           #declare LastFontStyleIndex = CurFontStyleIndex;
                        #end //#if
                        object {
                           BorderCharacter [NextChar]
                           translate TempX * x
                           #if (CharacterItalicStatus [I] [J + 1])
                              Italicize ()
                           #end //#if
                        } //object
                     #end //#if
                  #end //#if
               #end //#if
            #end //#for
         } //union
      #else
         #local CurChar = LineCharacters [I] [0];
         #declare CurFontStyleIndex = CharacterFontStyleIndex [I] [0];
         #if (CurFontStyleIndex != LastFontStyleIndex)
            Stylize (CurFontStyleIndex, TextScale * LineScale [I])
            #declare LastFontStyleIndex = CurFontStyleIndex;
         #end //#if
         object {
            BorderCharacter [CurChar]
            translate CurX * x
            #if (CharacterItalicStatus [I] [0])
               Italicize ()
            #end //#if
         } //object
      #end //#if
   } //object

#end //#macro CreateLine

#macro CreateParagraph (NLines, TextScale, UseActualParagraphHeight)

   #declare ParagraphWidth = 0;
   #declare ParagraphHeight = 0;

   #for (I, 0, NDefinedCharacters - 1)
      #declare CharacterInUse [I] = false;
   #end //#for

   #for (I, 0, NLines - 1)
      InitializeLine (I)
      #for (J, 0, LineNCharacters [I] - 1)
         #if (LineCharacters [I] [J] != -1)
            #declare CharacterInUse [LineCharacters [I] [J]] = true;
         #end //#if
      #end //#for
   #end //#for

   #declare CurFontStyleIndex = CharacterFontStyleIndex [0] [0];

   Stylize (CurFontStyleIndex, TextScale)

   #declare LastFontStyleIndex = CurFontStyleIndex;

   #for (I, 0, NLines - 1)
      MarkInvisibleCharacters (I)
      ComputeLineWidth (I)
      #declare ParagraphWidth = max (ParagraphWidth, LineWidth [I]);
   #end //#for

   #if (LineAlignment = JUSTIFIED)
      #declare ParagraphWidth = max (ParagraphWidth, MinJustifiedParagraphWidth / TextScale);
   #end //#if

   #for (I, 0, NLines - 1)
      CreateLine (I, ParagraphWidth, TextScale)
   #end //#for

   #declare Paragraph = object {
      #local CurY = 0;
      #if (NLines > 1)
         union {
            #for (I, NLines - 1, 0, -1)
               #switch (LineAlignment)
                  #case (LEFT)
                     #local XOffset = 0;
                  #break //#case
                  #case (RIGHT)
                     #local XOffset = ParagraphWidth * TextScale - LineWidth [I] * TextScale;
                  #break //#case
                  #case (CENTERED)
                     #local XOffset = ParagraphWidth / 2 * TextScale - LineWidth [I] / 2 * TextScale;
                  #break //#case
                  #case (JUSTIFIED)
                     #local XOffset = 0;
                  #break //#case
               #end //#switch
               object {
                  LineTextObject [I]
                  scale <TextScale * LineScale [I], TextScale * LineScale [I], 1>
                  translate <XOffset, CurY, 0>
               } //object
               #if (I > 0)
                  #local CurY = CurY + Height_Upper * TextScale * LineScale [I] + LineSpacing;
               #end //#if
            #end //#for
         } //union
      #else
         LineTextObject [0]
         scale <TextScale * LineScale [0], TextScale * LineScale [0], 1>
      #end //#if
      #declare ParagraphWidth = ParagraphWidth * TextScale;
      #declare ParagraphHeight = CurY + Height_Upper * TextScale * LineScale [0];
      translate -ParagraphHeight * y
   } //object

   #if (UseActualParagraphHeight)
      #declare FirstLineHeight_Top = -999;
      #for (I, 0, LineNCharacters [0] - 1)
         #local CurChar = LineCharacters [0] [I];
         #if (CurChar != -1)
            #local CurHeight = BorderCharacterHeight_Top [CurChar];
            #if (CurHeight > FirstLineHeight_Top)
               #declare FirstLineHeight_Top = CurHeight;
            #end //#if
         #end //#if
      #end //#for
      #declare ParagraphYOffset = (Height_Upper - FirstLineHeight_Top) * TextScale * LineScale [0];
      #declare ParagraphHeight = ParagraphHeight - ParagraphYOffset;
      #declare LastLineHeight_Bottom = 999;
      #for (I, 0, LineNCharacters [NLines - 1] - 1)
         #local CurChar = LineCharacters [NLines - 1] [I];
         #if (CurChar != -1)
            #local CurHeight = BorderCharacterHeight_Bottom [CurChar];
            #if (CurHeight < LastLineHeight_Bottom)
               #declare LastLineHeight_Bottom = CurHeight;
            #end //#if
         #end //#if
      #end //#for
      #declare ParagraphHeight = ParagraphHeight - LastLineHeight_Bottom * TextScale * LineScale [NLines - 1];
      #declare Paragraph = object {Paragraph translate ParagraphYOffset * y}
   #end //#if

   #declare ParagraphHistory_Width [CurrentParagraphNumber] = ParagraphWidth;
   #declare ParagraphHistory_Height [CurrentParagraphNumber] = ParagraphHeight;

   #declare CurrentParagraphNumber = CurrentParagraphNumber + 1;

   #if (LineAlignment = JUSTIFIED & MaxMicroJustificationScale != 1)
      #declare FontStyleRecord_Valid [CurFontStyleIndex] = false;
   #end //#if

   #declare SumOfAllScales = 0;

   #for (I, 0, NLines - 1)
      #declare SumOfAllScales = SumOfAllScales + LineScale [I];
   #end //#for

#end //#macro CreateParagraph

#macro SetFontStyle (I, FontVariationNumber, P0, P1, P2, P3, P4, P5, P6, P7, P8, TextColor_Outer, TextColor_Inner, TextColor_Back)

   #declare FontStyleRecord_Valid [I] = false;
   #declare FontStyleRecord_FontVariationNumber [I] = FontVariationNumber;
   #declare FontStyleRecord_P0 [I] = P0;
   #declare FontStyleRecord_P1 [I] = P1;
   #declare FontStyleRecord_P2 [I] = P2;
   #declare FontStyleRecord_P3 [I] = P3;
   #declare FontStyleRecord_P4 [I] = P4;
   #declare FontStyleRecord_P5 [I] = P5;
   #declare FontStyleRecord_P6 [I] = P6;
   #declare FontStyleRecord_P7 [I] = P7;
   #declare FontStyleRecord_P8 [I] = P8;
   #declare FontStyleRecord_TextColor_Outer [I] = texture {TextColor_Outer}
   #declare FontStyleRecord_TextColor_Inner [I] = texture {TextColor_Inner}
   #declare FontStyleRecord_TextColor_Back [I] = texture {TextColor_Back}

#end //#macro SetFontStyle
