View Javadoc

1   /* ========================================================================
2    * JFiglet, a free open source java implementation of figlet and the
3    * figfont specification (see http://www.figlet.org)
4    * Copyright (C) 2004 Sebastien Brunot
5    *
6    * This library is free software; you can redistribute it and/or
7    * modify it under the terms of the GNU Lesser General Public
8    * License as published by the Free Software Foundation; either
9    * version 2.1 of the License, or (at your option) any later version.
10   *
11   * This library is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14   * Lesser General Public License for more details.
15   *
16   * You should have received a copy of the GNU Lesser General Public
17   * License along with this library; if not, write to the Free Software
18   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19   * ========================================================================
20   */
21  package org.gnu.jfiglet.core;
22  
23  /***
24   * Layout of a FIGFont.
25   * 
26   * @version $Id: FIGFontLayout.java,v 1.3 2004/04/27 20:09:28 sbrunot Exp $
27   *
28   * @author <a href="mailto:sebastien.brunot@club-internet.fr">
29   *  Sebastien Brunot</a>
30   * 
31   */
32  public class FIGFontLayout
33  {
34      ///////////////////////////////
35      // Constants
36      ///////////////////////////////
37  
38      /***
39       * Horizontal layout mode "Full size".
40       * Represents each FIGcharacter occupying the full width of its arrangement
41       * of sub-characters as designed.
42       */
43      public static final int HORIZONTAL_LAYOUT_MODE_FULL_SIZE = 0;
44  
45      /***
46       * Horizontal layout mode "Fitting only".
47       * Moves FIGcharacters closer together until they touch.
48       * Typographers use the term "kerning" for this phenomenon
49       * when applied to the horizontal axis, but fitting also
50       * includes this as a vertical behavior, for which there is
51       * apparently no established typographical term.
52       */
53      public static final int HORIZONTAL_LAYOUT_MODE_FITTING_ONLY = 1;
54  
55      /***
56       * Horizontal layout mode "smushing"
57       * Moves FIGcharacters one step closer after they touch, so that
58       * they partially occupy the same space.  A FIGdriver must decide
59       * what sub-character to display at each junction.  There are two
60       * ways of making these decisions: by controlled smushing or by
61       * universal smushing.
62       *
63       * Controlled smushing uses a set of "smushing rules" selected by
64       * the designer of a FIGfont.
65       * Each rule is a comparison of the two sub-characters which must
66       * be joined to yield what to display at the junction.
67       * Controlled smushing will not always allow smushing to occur,
68       * because the compared sub-characters may not correspond to any
69       * active rule.  Wherever smushing cannot occur, fitting occurs
70       * instead.
71       *
72       * Universal smushing simply overrides the sub-character from the
73       * earlier FIGcharacter with the sub-character from the later
74       * FIGcharacter.  This produces an "overlapping" effect with some
75       * FIGfonts, wherin the latter FIGcharacter may appear to be "in
76       * front".
77       *
78       * A FIGfont which does not specify any smushing rules for a
79       * particular axis indicates that universal smushing is to occur
80       * when smushing is requested.  Therefore, it is not possible for
81       * a FIGfont designer to "forbid" smushing.  However there are
82       * ways to ensure that smushing does not cause a FIGfont to be
83       * illegible when smushed.  This is especially important for
84       * smaller FIGfonts.
85       */
86      public static final int HORIZONTAL_LAYOUT_MODE_SMUSHING = 2;
87  
88      /***
89       * Vertical layout modes
90       */
91      public static final int VERTICAL_LAYOUT_MODE_FULL_SIZE = 3;
92      public static final int VERTICAL_LAYOUT_MODE_FITTING_ONLY = 4;
93      public static final int VERTICAL_LAYOUT_MODE_SMUSHING = 5;
94  
95      private static final int OLD_LAYOUT_FULL_WIDTH = -1;
96      private static final int OLD_LAYOUT_HORIZONTAL_FITTING = 0;
97  
98      private static final int FULL_LAYOUT_HORIZONTAL_FITTING = 64;
99      private static final int FULL_LAYOUT_HORIZONTAL_SMUSHING = 128;
100     private static final int FULL_LAYOUT_VERTICAL_FITTING = 8192;
101     private static final int FULL_LAYOUT_VERTICAL_SMUSHING = 16384;
102 
103     /***
104      * Smushing rules
105      */
106     private static final int SMUSHING_RULE_UNIVERSAL = 0;
107     public static final int HORIZONTAL_SMUSHING_RULE_EQUALS_CHARACTER = 1;
108     public static final int HORIZONTAL_SMUSHING_RULE_UNDERSCORE = 2;
109     public static final int HORIZONTAL_SMUSHING_RULE_HIERARCHY = 4;
110     public static final int HORIZONTAL_SMUSHING_RULE_OPPOSITE_PAIR = 8;
111     public static final int HORIZONTAL_SMUSHING_RULE_BIG_X = 16;
112     public static final int HORIZONTAL_SMUSHING_RULE_HARDBLANK = 32;
113     public static final int VERTICAL_SMUSHING_RULE_EQUALS_CHARACTER = 256;
114     public static final int VERTICAL_SMUSHING_RULE_UNDERSCORE = 512;
115     public static final int VERTICAL_SMUSHING_RULE_HIERARCHY = 1024;
116     public static final int VERTICAL_SMUSHING_RULE_HORIZONTAL_LINE = 2048;
117     public static final int VERTICAL_SMUSHING_RULE_VERTICAL_LINE = 4096;
118 
119     ///////////////////////////////
120     // Attributes
121     ///////////////////////////////
122 
123     private int horizontalMode = HORIZONTAL_LAYOUT_MODE_FITTING_ONLY;
124     private int verticalMode = VERTICAL_LAYOUT_MODE_FULL_SIZE;
125     private int horizontalSmushingModes = SMUSHING_RULE_UNIVERSAL;
126     private int verticalSmushingModes = SMUSHING_RULE_UNIVERSAL;
127 
128     ///////////////////////////////
129     // Constructors
130     ///////////////////////////////
131 
132     /***
133      * @TODO : DOCUMENT ME !
134      */
135     public FIGFontLayout(
136         int theOldLayoutSpecification,
137         Integer theFullLayoutSpecification)
138     {
139         // Verify old layout specification value
140         if ((theOldLayoutSpecification < -1)
141             || (theOldLayoutSpecification > 63))
142         {
143             throw new IllegalArgumentException("the old layout specification must be an integer between -1 and 63 included");
144         }
145 
146         // Is there a full layout specification ?
147         if (theFullLayoutSpecification != null)
148         {
149             // verify its values
150             if ((theFullLayoutSpecification.intValue() < 0)
151                 || (theFullLayoutSpecification.intValue() > 32767))
152             {
153                 throw new IllegalArgumentException("the full layout specification must be an integer between 0 and 32767 included");
154             }
155         }
156         // Define Horizontal layout
157         if (theOldLayoutSpecification == OLD_LAYOUT_FULL_WIDTH)
158         {
159             // HORIZONTAL MODE = FULL WIDTH
160             this.horizontalMode = HORIZONTAL_LAYOUT_MODE_FULL_SIZE;
161             // If full width is to be the horizontal default:
162             //   Old_Layout must be -1.
163             //   Full_Layout must NOT include code values 64 nor 128.
164             if (theFullLayoutSpecification != null)
165             {
166                 if (((theFullLayoutSpecification.intValue()
167                     & FULL_LAYOUT_HORIZONTAL_FITTING)
168                     == FULL_LAYOUT_HORIZONTAL_FITTING)
169                     || ((theFullLayoutSpecification.intValue()
170                         & FULL_LAYOUT_HORIZONTAL_SMUSHING)
171                         == FULL_LAYOUT_HORIZONTAL_SMUSHING))
172                 {
173                     throw new IllegalArgumentException("Old and full layout specifications are unconsistent");
174                 }
175             }
176         }
177         else if (
178             theOldLayoutSpecification == OLD_LAYOUT_HORIZONTAL_FITTING)
179         {
180             // The horizontal mode depends on the full layout specification
181             //If horizontal fitting (kerning) is to be default:
182             //  Old_Layout must be 0.
183             //  Full_Layout must include code value 64.
184             //  Full_Layout must NOT include code value 128.
185             // If UNIVERSAL smushing is to be the horizontal default:
186             //  Old_Layout must be 0.
187             //  Full_Layout must include code value 128.
188             //  Full_Layout must NOT include any code value under 64.
189             if (theFullLayoutSpecification != null)
190             {
191                 if (((theFullLayoutSpecification.intValue()
192                     & FULL_LAYOUT_HORIZONTAL_FITTING)
193                     == FULL_LAYOUT_HORIZONTAL_FITTING)
194                     && ((theFullLayoutSpecification.intValue()
195                         & FULL_LAYOUT_HORIZONTAL_SMUSHING)
196                         == 0))
197                 {
198                     // HORIZONTAL MODE = FITTING
199                     this.horizontalMode =
200                         HORIZONTAL_LAYOUT_MODE_FITTING_ONLY;
201                 }
202                 else if (
203                     ((theFullLayoutSpecification.intValue()
204                         & FULL_LAYOUT_HORIZONTAL_FITTING)
205                         == 0)
206                         && ((theFullLayoutSpecification.intValue()
207                             & FULL_LAYOUT_HORIZONTAL_SMUSHING)
208                             == FULL_LAYOUT_HORIZONTAL_SMUSHING))
209                 {
210                     // HORIZONTAL MODE = UNIVERSAL SMUSHING
211                     this.horizontalMode = HORIZONTAL_LAYOUT_MODE_SMUSHING;
212                 }
213                 else
214                 {
215                     throw new IllegalArgumentException("The old and full layout specifications are unconsistent");
216                 }
217             }
218             else
219             {
220                 // HORIZONTAL MODE = FITTING
221                 this.horizontalMode = HORIZONTAL_LAYOUT_MODE_FITTING_ONLY;
222             }
223         }
224         else
225         {
226             // HORIZONTAL MODE = SMUSHING
227             this.horizontalMode = HORIZONTAL_LAYOUT_MODE_SMUSHING;
228             this.horizontalSmushingModes = theOldLayoutSpecification;
229             // @TODO : verify consistency with full layout ?
230         }
231         // define vertical mode of specified by a full layout
232         if (theFullLayoutSpecification != null)
233         {
234             if ((theFullLayoutSpecification.intValue()
235                 & FULL_LAYOUT_VERTICAL_FITTING)
236                 == FULL_LAYOUT_VERTICAL_FITTING)
237             {
238                 // VERTICAL MODE = FITTING
239                 this.verticalMode = VERTICAL_LAYOUT_MODE_FITTING_ONLY;
240             }
241             else if (
242                 (theFullLayoutSpecification.intValue()
243                     & FULL_LAYOUT_VERTICAL_SMUSHING)
244                     == FULL_LAYOUT_VERTICAL_SMUSHING)
245             {
246                 // VERTICAL MODE = SMUSHING
247                 this.verticalMode = VERTICAL_LAYOUT_MODE_SMUSHING;
248                 this.verticalSmushingModes =
249                     theFullLayoutSpecification.intValue();
250             }
251         }
252     }
253 
254     ////////////////////////////////////////
255     // Accessors
256     ////////////////////////////////////////
257 
258     /***
259      * @TODO : DOCUMENT ME !
260      */
261     public int getHorizontalMode()
262     {
263         return this.horizontalMode;
264     }
265 
266     /***
267      * @TODO : DOCUMENT ME !
268      */
269     public int getVerticalMode()
270     {
271         return this.verticalMode;
272     }
273 
274     /***
275      * @TODO : DOCUMENT ME !
276      */
277     public boolean hasHorizontalSmushingRule(int theSmushingRule)
278     {
279         return (
280             (this.horizontalSmushingModes & theSmushingRule)
281                 == theSmushingRule);
282     }
283 
284     /***
285      * @TODO : DOCUMENT ME !
286      */
287     public boolean hasVerticalSmushingRule(int theSmushingRule)
288     {
289         return (
290             (this.verticalSmushingModes & theSmushingRule)
291                 == theSmushingRule);
292     }
293 
294 }