001/*
002 * $Id: Font.java 4784 2011-03-15 08:33:00Z blowagie $
003 *
004 * This file is part of the iText (R) project.
005 * Copyright (c) 1998-2011 1T3XT BVBA
006 * Authors: Bruno Lowagie, Paulo Soares, et al.
007 *
008 * This program is free software; you can redistribute it and/or modify
009 * it under the terms of the GNU Affero General Public License version 3
010 * as published by the Free Software Foundation with the addition of the
011 * following permission added to Section 15 as permitted in Section 7(a):
012 * FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY 1T3XT,
013 * 1T3XT DISCLAIMS THE WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
014 *
015 * This program is distributed in the hope that it will be useful, but
016 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
017 * or FITNESS FOR A PARTICULAR PURPOSE.
018 * See the GNU Affero General Public License for more details.
019 * You should have received a copy of the GNU Affero General Public License
020 * along with this program; if not, see http://www.gnu.org/licenses or write to
021 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
022 * Boston, MA, 02110-1301 USA, or download the license from the following URL:
023 * http://itextpdf.com/terms-of-use/
024 *
025 * The interactive user interfaces in modified source and object code versions
026 * of this program must display Appropriate Legal Notices, as required under
027 * Section 5 of the GNU Affero General Public License.
028 *
029 * In accordance with Section 7(b) of the GNU Affero General Public License,
030 * a covered work must retain the producer line in every PDF that is created
031 * or manipulated using iText.
032 *
033 * You can be released from the requirements of the license by purchasing
034 * a commercial license. Buying such a license is mandatory as soon as you
035 * develop commercial activities involving the iText software without
036 * disclosing the source code of your own applications.
037 * These activities include: offering paid services to customers as an ASP,
038 * serving PDFs on the fly in a web application, shipping iText with a closed
039 * source product.
040 *
041 * For more information, please contact iText Software Corp. at this
042 * address: sales@itextpdf.com
043 */
044package com.itextpdf.text;
045
046import com.itextpdf.text.pdf.BaseFont;
047
048/**
049 * Contains all the specifications of a font: fontfamily, size, style and color.
050 * <P>
051 * Example: <BLOCKQUOTE>
052 *
053 * <PRE>
054 *
055 * Paragraph p = new Paragraph("This is a paragraph", <STRONG>new
056 * Font(FontFamily.HELVETICA, 18, Font.BOLDITALIC, new BaseColor(0, 0, 255)) </STRONG>);
057 *
058 * </PRE>
059 *
060 * </BLOCKQUOTE>
061 */
062
063public class Font implements Comparable<Font> {
064
065        /**
066         * Enum describing the font family
067         *
068         * @since 5.0.1
069         */
070        public enum FontFamily {
071                COURIER,
072                HELVETICA,
073                TIMES_ROMAN,
074                SYMBOL,
075                ZAPFDINGBATS,
076                UNDEFINED
077        }
078
079        /**
080         * FontStyle.
081         *
082         * @author Balder
083         * @since 5.0.6
084         */
085        public enum FontStyle {
086                // Created to get rid of dependency of HtmlTags
087                NORMAL("normal"), BOLD("bold"), ITALIC("italic"), OBLIQUE("oblique"), UNDERLINE(
088                                "underline"), LINETHROUGH("line-through");
089
090                private String code;
091
092                private FontStyle(final String code) {
093                        this.code = code;
094                }
095
096                /**
097                 * @return a string, the text value of this style.
098                 * @since 5.0.6
099                 */
100                public String getValue() {
101                        return code;
102                }
103
104        }
105
106        // static membervariables for the different styles
107
108        /** this is a possible style. */
109        public static final int NORMAL = 0;
110
111        /** this is a possible style. */
112        public static final int BOLD = 1;
113
114        /** this is a possible style. */
115        public static final int ITALIC = 2;
116
117        /** this is a possible style. */
118        public static final int UNDERLINE = 4;
119
120        /** this is a possible style. */
121        public static final int STRIKETHRU = 8;
122
123        /** this is a possible style. */
124        public static final int BOLDITALIC = BOLD | ITALIC;
125
126        // static membervariables
127
128        /** the value of an undefined attribute. */
129        public static final int UNDEFINED = -1;
130
131        /** the value of the default size. */
132        public static final int DEFAULTSIZE = 12;
133
134        // membervariables
135
136        /** the value of the fontfamily. */
137        private FontFamily family = FontFamily.UNDEFINED;
138
139        /** the value of the fontsize. */
140        private float size = UNDEFINED;
141
142        /** the value of the style. */
143        private int style = UNDEFINED;
144
145        /** the value of the color. */
146        private BaseColor color = null;
147
148        /** the external font */
149        private BaseFont baseFont = null;
150
151        // constructors
152
153        /**
154         * Copy constructor of a Font
155         *
156         * @param other
157         *            the font that has to be copied
158         */
159        public Font(final Font other) {
160                this.family = other.family;
161                this.size = other.size;
162                this.style = other.style;
163                this.color = other.color;
164                this.baseFont = other.baseFont;
165        }
166
167        /**
168         * Constructs a Font.
169         *
170         * @param family
171         *            the family to which this font belongs
172         * @param size
173         *            the size of this font
174         * @param style
175         *            the style of this font
176         * @param color
177         *            the <CODE>BaseColor</CODE> of this font.
178         * @since iText 5.0.1 (first parameter has been replaced with enum)
179         */
180
181        public Font(final FontFamily family, final float size, final int style, final BaseColor color) {
182                this.family = family;
183                this.size = size;
184                this.style = style;
185                this.color = color;
186        }
187
188        /**
189         * Constructs a Font.
190         *
191         * @param bf
192         *            the external font
193         * @param size
194         *            the size of this font
195         * @param style
196         *            the style of this font
197         * @param color
198         *            the <CODE>BaseColor</CODE> of this font.
199         */
200
201        public Font(final BaseFont bf, final float size, final int style, final BaseColor color) {
202                this.baseFont = bf;
203                this.size = size;
204                this.style = style;
205                this.color = color;
206        }
207
208        /**
209         * Constructs a Font.
210         *
211         * @param bf
212         *            the external font
213         * @param size
214         *            the size of this font
215         * @param style
216         *            the style of this font
217         */
218        public Font(final BaseFont bf, final float size, final int style) {
219                this(bf, size, style, null);
220        }
221
222        /**
223         * Constructs a Font.
224         *
225         * @param bf
226         *            the external font
227         * @param size
228         *            the size of this font
229         */
230        public Font(final BaseFont bf, final float size) {
231                this(bf, size, UNDEFINED, null);
232        }
233
234        /**
235         * Constructs a Font.
236         *
237         * @param bf
238         *            the external font
239         */
240        public Font(final BaseFont bf) {
241                this(bf, UNDEFINED, UNDEFINED, null);
242        }
243
244        /**
245         * Constructs a Font.
246         *
247         * @param family
248         *            the family to which this font belongs
249         * @param size
250         *            the size of this font
251         * @param style
252         *            the style of this font
253         * @since iText 5.0.1 (first parameter has been replaced with enum)
254         */
255
256        public Font(final FontFamily family, final float size, final int style) {
257                this(family, size, style, null);
258        }
259
260        /**
261         * Constructs a Font.
262         *
263         * @param family
264         *            the family to which this font belongs
265         * @param size
266         *            the size of this font
267         * @since iText 5.0.1 (first parameter has been replaced with enum)
268         */
269
270        public Font(final FontFamily family, final float size) {
271                this(family, size, UNDEFINED, null);
272        }
273
274        /**
275         * Constructs a Font.
276         *
277         * @param family
278         *            the family to which this font belongs
279         * @since iText 5.0.1 (first parameter has been replaced with enum)
280         */
281
282        public Font(final FontFamily family) {
283                this(family, UNDEFINED, UNDEFINED, null);
284        }
285
286        /**
287         * Constructs a Font.
288         */
289
290        public Font() {
291                this(FontFamily.UNDEFINED, UNDEFINED, UNDEFINED, null);
292        }
293
294        // implementation of the Comparable interface
295
296        /**
297         * Compares this <CODE>Font</CODE> with another
298         *
299         * @param font
300         *            the other <CODE>Font</CODE>
301         * @return a value
302         */
303        public int compareTo(final Font font) {
304                if (font == null) {
305                        return -1;
306                }
307                try {
308                        // FIXME using equals but equals not implemented!
309                        if (baseFont != null && !baseFont.equals(font.getBaseFont())) {
310                                return -2;
311                        }
312                        if (this.family != font.getFamily()) {
313                                return 1;
314                        }
315                        if (this.size != font.getSize()) {
316                                return 2;
317                        }
318                        if (this.style != font.getStyle()) {
319                                return 3;
320                        }
321                        if (this.color == null) {
322                                if (font.color == null) {
323                                        return 0;
324                                }
325                                return 4;
326                        }
327                        if (font.color == null) {
328                                return 4;
329                        }
330                        if (this.color.equals(font.getColor())) {
331                                return 0;
332                        }
333                        return 4;
334                } catch (ClassCastException cce) {
335                        return -3;
336                }
337        }
338
339        // FAMILY
340
341        /**
342         * Gets the family of this font.
343         *
344         * @return the value of the family
345         */
346        public FontFamily getFamily() {
347                return family;
348        }
349
350        /**
351         * Gets the familyname as a String.
352         *
353         * @return the familyname
354         */
355        public String getFamilyname() {
356                String tmp = "unknown";
357                switch (getFamily()) {
358                case COURIER:
359                        return FontFactory.COURIER;
360                case HELVETICA:
361                        return FontFactory.HELVETICA;
362                case TIMES_ROMAN:
363                        return FontFactory.TIMES_ROMAN;
364                case SYMBOL:
365                        return FontFactory.SYMBOL;
366                case ZAPFDINGBATS:
367                        return FontFactory.ZAPFDINGBATS;
368                default:
369                        if (baseFont != null) {
370                                String[][] names = baseFont.getFamilyFontName();
371                                for (String[] name : names) {
372                                        if ("0".equals(name[2])) {
373                                                return name[3];
374                                        }
375                                        if ("1033".equals(name[2])) {
376                                                tmp = name[3];
377                                        }
378                                        if ("".equals(name[2])) {
379                                                tmp = name[3];
380                                        }
381                                }
382                        }
383                }
384                return tmp;
385        }
386
387        /**
388         * Sets the family using a <CODE>String</CODE> ("Courier", "Helvetica",
389         * "Times New Roman", "Symbol" or "ZapfDingbats").
390         *
391         * @param family
392         *            A <CODE>String</CODE> representing a certain font-family.
393         */
394        public void setFamily(final String family) {
395                this.family = getFamily(family);
396        }
397
398        /**
399         * Translates a <CODE>String</CODE> -value of a certain family into the
400         * FontFamily enum that is used for this family in this class.
401         *
402         * @param family
403         *            A <CODE>String</CODE> representing a certain font-family
404         * @return the corresponding FontFamily
405         *
406         * @since 5.0.1
407         */
408        public static FontFamily getFamily(final String family) {
409                if (family.equalsIgnoreCase(FontFactory.COURIER)) {
410                        return FontFamily.COURIER;
411                }
412                if (family.equalsIgnoreCase(FontFactory.HELVETICA)) {
413                        return FontFamily.HELVETICA;
414                }
415                if (family.equalsIgnoreCase(FontFactory.TIMES_ROMAN)) {
416                        return FontFamily.TIMES_ROMAN;
417                }
418                if (family.equalsIgnoreCase(FontFactory.SYMBOL)) {
419                        return FontFamily.SYMBOL;
420                }
421                if (family.equalsIgnoreCase(FontFactory.ZAPFDINGBATS)) {
422                        return FontFamily.ZAPFDINGBATS;
423                }
424                return FontFamily.UNDEFINED;
425        }
426
427        // SIZE
428
429        /**
430         * Gets the size of this font.
431         *
432         * @return a size
433         */
434        public float getSize() {
435                return size;
436        }
437
438        /**
439         * Gets the size that can be used with the calculated <CODE>BaseFont
440         * </CODE>.
441         *
442         * @return the size that can be used with the calculated <CODE>BaseFont
443         *         </CODE>
444         */
445        public float getCalculatedSize() {
446                float s = this.size;
447                if (s == UNDEFINED) {
448                        s = DEFAULTSIZE;
449                }
450                return s;
451        }
452
453        /**
454         * Gets the leading that can be used with this font.
455         *
456         * @param linespacing
457         *            a certain linespacing
458         * @return the height of a line
459         */
460        public float getCalculatedLeading(final float linespacing) {
461                return linespacing * getCalculatedSize();
462        }
463
464        /**
465         * Sets the size.
466         *
467         * @param size
468         *            The new size of the font.
469         */
470        public void setSize(final float size) {
471                this.size = size;
472        }
473
474        // STYLE
475
476        /**
477         * Gets the style of this font.
478         *
479         * @return a size
480         */
481        public int getStyle() {
482                return style;
483        }
484
485        /**
486         * Gets the style that can be used with the calculated <CODE>BaseFont
487         * </CODE>.
488         *
489         * @return the style that can be used with the calculated <CODE>BaseFont
490         *         </CODE>
491         */
492        public int getCalculatedStyle() {
493                int style = this.style;
494                if (style == UNDEFINED) {
495                        style = NORMAL;
496                }
497                if (baseFont != null)
498                        return style;
499                if (family == FontFamily.SYMBOL || family == FontFamily.ZAPFDINGBATS)
500                        return style;
501                else
502                        return style & ~BOLDITALIC;
503        }
504
505        /**
506         * checks if this font is Bold.
507         *
508         * @return a <CODE>boolean</CODE>
509         */
510        public boolean isBold() {
511                if (style == UNDEFINED) {
512                        return false;
513                }
514                return (style & BOLD) == BOLD;
515        }
516
517        /**
518         * checks if this font is italic.
519         *
520         * @return a <CODE>boolean</CODE>
521         */
522        public boolean isItalic() {
523                if (style == UNDEFINED) {
524                        return false;
525                }
526                return (style & ITALIC) == ITALIC;
527        }
528
529        /**
530         * checks if this font is underlined.
531         *
532         * @return a <CODE>boolean</CODE>
533         */
534        public boolean isUnderlined() {
535                if (style == UNDEFINED) {
536                        return false;
537                }
538                return (style & UNDERLINE) == UNDERLINE;
539        }
540
541        /**
542         * checks if the style of this font is STRIKETHRU.
543         *
544         * @return a <CODE>boolean</CODE>
545         */
546        public boolean isStrikethru() {
547                if (style == UNDEFINED) {
548                        return false;
549                }
550                return (style & STRIKETHRU) == STRIKETHRU;
551        }
552
553        /**
554         * Sets the style.
555         *
556         * @param style
557         *            the style.
558         */
559        public void setStyle(final int style) {
560                this.style = style;
561        }
562
563        /**
564         * Sets the style using a <CODE>String</CODE> containing one or more of the
565         * following values: normal, bold, italic, oblique, underline, line-through
566         *
567         * @param style
568         *            A <CODE>String</CODE> representing a certain style.
569         */
570        public void setStyle(final String style) {
571                if (this.style == UNDEFINED)
572                        this.style = NORMAL;
573                this.style |= getStyleValue(style);
574        }
575
576        /**
577         * Translates a <CODE>String</CODE> -value of a certain style into the index
578         * value is used for this style in this class. Supported styles are in
579         * {@link FontStyle} values are checked on {@link FontStyle#getValue()}
580         *
581         * @param style
582         *            A <CODE>String</CODE>
583         * @return the corresponding value
584         */
585        public static int getStyleValue(final String style) {
586                int s = 0;
587                if (style.indexOf(FontStyle.NORMAL.getValue()) != -1) {
588                        s |= NORMAL;
589                }
590                if (style.indexOf(FontStyle.BOLD.getValue()) != -1) {
591                        s |= BOLD;
592                }
593                if (style.indexOf(FontStyle.ITALIC.getValue()) != -1) {
594                        s |= ITALIC;
595                }
596                if (style.indexOf(FontStyle.OBLIQUE.getValue()) != -1) {
597                        s |= ITALIC;
598                }
599                if (style.indexOf(FontStyle.UNDERLINE.getValue()) != -1) {
600                        s |= UNDERLINE;
601                }
602                if (style.indexOf(FontStyle.LINETHROUGH.getValue()) != -1) {
603                        s |= STRIKETHRU;
604                }
605                return s;
606        }
607
608        // COLOR
609
610        /**
611         * Gets the color of this font.
612         *
613         * @return a color
614         */
615        public BaseColor getColor() {
616                return color;
617        }
618
619        /**
620         * Sets the color.
621         *
622         * @param color
623         *            the new color of the font
624         */
625
626        public void setColor(final BaseColor color) {
627                this.color = color;
628        }
629
630        /**
631         * Sets the color.
632         *
633         * @param red
634         *            the red-value of the new color
635         * @param green
636         *            the green-value of the new color
637         * @param blue
638         *            the blue-value of the new color
639         */
640        public void setColor(final int red, final int green, final int blue) {
641                this.color = new BaseColor(red, green, blue);
642        }
643
644        // BASEFONT
645
646        /**
647         * Gets the <CODE>BaseFont</CODE> inside this object.
648         *
649         * @return the <CODE>BaseFont</CODE>
650         */
651        public BaseFont getBaseFont() {
652                return baseFont;
653        }
654
655        /**
656         * Gets the <CODE>BaseFont</CODE> this class represents. For the built-in
657         * fonts a <CODE>BaseFont</CODE> is calculated.
658         *
659         * @param specialEncoding
660         *            <CODE>true</CODE> to use the special encoding for Symbol and
661         *            ZapfDingbats, <CODE>false</CODE> to always use <CODE>Cp1252
662         *            </CODE>
663         * @return the <CODE>BaseFont</CODE> this class represents
664         */
665        public BaseFont getCalculatedBaseFont(final boolean specialEncoding) {
666                if (baseFont != null)
667                        return baseFont;
668                int style = this.style;
669                if (style == UNDEFINED) {
670                        style = NORMAL;
671                }
672                String fontName = BaseFont.HELVETICA;
673                String encoding = BaseFont.WINANSI;
674                BaseFont cfont = null;
675                switch (family) {
676                case COURIER:
677                        switch (style & BOLDITALIC) {
678                        case BOLD:
679                                fontName = BaseFont.COURIER_BOLD;
680                                break;
681                        case ITALIC:
682                                fontName = BaseFont.COURIER_OBLIQUE;
683                                break;
684                        case BOLDITALIC:
685                                fontName = BaseFont.COURIER_BOLDOBLIQUE;
686                                break;
687                        default:
688                                // case NORMAL:
689                                fontName = BaseFont.COURIER;
690                                break;
691                        }
692                        break;
693                case TIMES_ROMAN:
694                        switch (style & BOLDITALIC) {
695                        case BOLD:
696                                fontName = BaseFont.TIMES_BOLD;
697                                break;
698                        case ITALIC:
699                                fontName = BaseFont.TIMES_ITALIC;
700                                break;
701                        case BOLDITALIC:
702                                fontName = BaseFont.TIMES_BOLDITALIC;
703                                break;
704                        default:
705                        case NORMAL:
706                                fontName = BaseFont.TIMES_ROMAN;
707                                break;
708                        }
709                        break;
710                case SYMBOL:
711                        fontName = BaseFont.SYMBOL;
712                        if (specialEncoding)
713                                encoding = BaseFont.SYMBOL;
714                        break;
715                case ZAPFDINGBATS:
716                        fontName = BaseFont.ZAPFDINGBATS;
717                        if (specialEncoding)
718                                encoding = BaseFont.ZAPFDINGBATS;
719                        break;
720                default:
721                case HELVETICA:
722                        switch (style & BOLDITALIC) {
723                        case BOLD:
724                                fontName = BaseFont.HELVETICA_BOLD;
725                                break;
726                        case ITALIC:
727                                fontName = BaseFont.HELVETICA_OBLIQUE;
728                                break;
729                        case BOLDITALIC:
730                                fontName = BaseFont.HELVETICA_BOLDOBLIQUE;
731                                break;
732                        default:
733                        case NORMAL:
734                                fontName = BaseFont.HELVETICA;
735                                break;
736                        }
737                        break;
738                }
739                try {
740                        cfont = BaseFont.createFont(fontName, encoding, false);
741                } catch (Exception ee) {
742                        throw new ExceptionConverter(ee);
743                }
744                return cfont;
745        }
746
747        // Helper methods
748
749        /**
750         * Checks if the properties of this font are undefined or null.
751         * <P>
752         * If so, the standard should be used.
753         *
754         * @return a <CODE>boolean</CODE>
755         */
756        public boolean isStandardFont() {
757                return family == FontFamily.UNDEFINED && size == UNDEFINED
758                                && style == UNDEFINED && color == null && baseFont == null;
759        }
760
761        /**
762         * Replaces the attributes that are equal to <VAR>null</VAR> with the
763         * attributes of a given font.
764         *
765         * @param font
766         *            the font of a bigger element class
767         * @return a <CODE>Font</CODE>
768         */
769        public Font difference(final Font font) {
770                if (font == null)
771                        return this;
772                // size
773                float dSize = font.size;
774                if (dSize == UNDEFINED) {
775                        dSize = this.size;
776                }
777                // style
778                int dStyle = UNDEFINED;
779                int style1 = this.style;
780                int style2 = font.getStyle();
781                if (style1 != UNDEFINED || style2 != UNDEFINED) {
782                        if (style1 == UNDEFINED)
783                                style1 = 0;
784                        if (style2 == UNDEFINED)
785                                style2 = 0;
786                        dStyle = style1 | style2;
787                }
788                // color
789                BaseColor dColor = font.color;
790                if (dColor == null) {
791                        dColor = this.color;
792                }
793                // family
794                if (font.baseFont != null) {
795                        return new Font(font.baseFont, dSize, dStyle, dColor);
796                }
797                if (font.getFamily() != FontFamily.UNDEFINED) {
798                        return new Font(font.family, dSize, dStyle, dColor);
799                }
800                if (this.baseFont != null) {
801                        if (dStyle == style1) {
802                                return new Font(this.baseFont, dSize, dStyle, dColor);
803                        } else {
804                                return FontFactory.getFont(this.getFamilyname(), dSize, dStyle,
805                                                dColor);
806                        }
807                }
808                return new Font(this.family, dSize, dStyle, dColor);
809        }
810
811}