Reads the font metrics
@param rf the AFM file
@throws DocumentException the AFM file is invalid
@throws IOException the AFM file could not be read
334417
public void process(RandomAccessFileOrArray rf) throws DocumentException, IOException
    {
        String line;
        boolean isMetrics = false;
        while ((line = rf.readLine()) != null)
        {
            StringTokenizer tok = new StringTokenizer(line, " ,\n\r\t\f");
            if (!tok.hasMoreTokens())
                continue;
            String ident = tok.nextToken();
            if (ident.equals("FontName"))
                FontName = tok.nextToken("\u00ff").substring(1);
            else if (ident.equals("FullName"))
                FullName = tok.nextToken("\u00ff").substring(1);
            else if (ident.equals("FamilyName"))
                FamilyName = tok.nextToken("\u00ff").substring(1);
            else if (ident.equals("Weight"))
                Weight = tok.nextToken("\u00ff").substring(1);
            else if (ident.equals("ItalicAngle"))
                ItalicAngle = Float.parseFloat(tok.nextToken());
            else if (ident.equals("IsFixedPitch"))
                IsFixedPitch = tok.nextToken().equals("true");
            else if (ident.equals("CharacterSet"))
                CharacterSet = tok.nextToken("\u00ff").substring(1);
            else if (ident.equals("FontBBox"))
            {
                llx = (int)Float.parseFloat(tok.nextToken());
                lly = (int)Float.parseFloat(tok.nextToken());
                urx = (int)Float.parseFloat(tok.nextToken());
                ury = (int)Float.parseFloat(tok.nextToken());
            }
            else if (ident.equals("UnderlinePosition"))
                UnderlinePosition = (int)Float.parseFloat(tok.nextToken());
            else if (ident.equals("UnderlineThickness"))
                UnderlineThickness = (int)Float.parseFloat(tok.nextToken());
            else if (ident.equals("EncodingScheme"))
                EncodingScheme = tok.nextToken("\u00ff").substring(1);
            else if (ident.equals("CapHeight"))
                CapHeight = (int)Float.parseFloat(tok.nextToken());
            else if (ident.equals("XHeight"))
                XHeight = (int)Float.parseFloat(tok.nextToken());
            else if (ident.equals("Ascender"))
                Ascender = (int)Float.parseFloat(tok.nextToken());
            else if (ident.equals("Descender"))
                Descender = (int)Float.parseFloat(tok.nextToken());
            else if (ident.equals("StdHW"))
                StdHW = (int)Float.parseFloat(tok.nextToken());
            else if (ident.equals("StdVW"))
                StdVW = (int)Float.parseFloat(tok.nextToken());
            else if (ident.equals("StartCharMetrics"))
            {
                isMetrics = true;
                break;
            }
        }
        if (!isMetrics)
            throw new DocumentException("Missing StartCharMetrics in " + fileName);
        while ((line = rf.readLine()) != null)
        {
            StringTokenizer tok = new StringTokenizer(line);
            if (!tok.hasMoreTokens())
                continue;
            String ident = tok.nextToken();
            if (ident.equals("EndCharMetrics"))
            {
                isMetrics = false;
                break;
            }
            Integer C = Integer.valueOf(-1);
            Integer WX = Integer.valueOf(250);
            String N = "";
            int B[] = null;

            tok = new StringTokenizer(line, ";");
            while (tok.hasMoreTokens())
            {
                StringTokenizer tokc = new StringTokenizer(tok.nextToken());
                if (!tokc.hasMoreTokens())
                    continue;
                ident = tokc.nextToken();
                if (ident.equals("C"))
                    C = Integer.valueOf(tokc.nextToken());
                else if (ident.equals("WX"))
                    WX = Integer.valueOf((int)Float.parseFloat(tokc.nextToken()));
                else if (ident.equals("N"))
                    N = tokc.nextToken();
                else if (ident.equals("B")) {
                    B = new int[]{Integer.parseInt(tokc.nextToken()), 
                                         Integer.parseInt(tokc.nextToken()),
                                         Integer.parseInt(tokc.nextToken()),
                                         Integer.parseInt(tokc.nextToken())};
                }
            }
            Object metrics[] = new Object[]{C, WX, N, B};
            if (C.intValue() >= 0)
                CharMetrics.put(C, metrics);
            CharMetrics.put(N, metrics);
        }
        if (isMetrics)
            throw new DocumentException("Missing EndCharMetrics in " + fileName);
        if (!CharMetrics.containsKey("nonbreakingspace")) {
            Object[] space = (Object[])CharMetrics.get("space");
            if (space != null)
                CharMetrics.put("nonbreakingspace", space);
        }
        while ((line = rf.readLine()) != null)
        {
            StringTokenizer tok = new StringTokenizer(line);
            if (!tok.hasMoreTokens())
                continue;
            String ident = tok.nextToken();
            if (ident.equals("EndFontMetrics"))
                return;
            if (ident.equals("StartKernPairs"))
            {
                isMetrics = true;
                break;
            }
        }
        if (!isMetrics)
            throw new DocumentException("Missing EndFontMetrics in " + fileName);
        while ((line = rf.readLine()) != null)
        {
            StringTokenizer tok = new StringTokenizer(line);
            if (!tok.hasMoreTokens())
                continue;
            String ident = tok.nextToken();
            if (ident.equals("KPX"))
            {
                String first = tok.nextToken();
                String second = tok.nextToken();
                Integer width = Integer.valueOf((int)Float.parseFloat(tok.nextToken()));
                Object relates[] = (Object[])KernPairs.get(first);
                if (relates == null)
                    KernPairs.put(first, new Object[]{second, width});
                else
                {
                    int n = relates.length;
                    Object relates2[] = new Object[n + 2];
                    System.arraycopy(relates, 0, relates2, 0, n);
                    relates2[n] = second;
                    relates2[n + 1] = width;
                    KernPairs.put(first, relates2);
                }
            }
            else if (ident.equals("EndKernPairs"))
            {
                isMetrics = false;
                break;
            }
        }
        if (isMetrics)
            throw new DocumentException("Missing EndKernPairs in " + fileName);
        rf.close();
    }
1198826
@Override
    public void filter(Document document, Map<String, String> cleaningParameters)
    {
        List<Element> fontTags = filterDescendants(document.getDocumentElement(), new String[] { TAG_FONT });
        for (Element fontTag : fontTags) {
            Element span = document.createElement(TAG_SPAN);
            moveChildren(fontTag, span);
            StringBuffer buffer = new StringBuffer();
            if (fontTag.hasAttribute(ATTRIBUTE_FONTCOLOR)) {
                buffer.append(String.format("color:%s;", fontTag.getAttribute(ATTRIBUTE_FONTCOLOR)));
            }
            if (fontTag.hasAttribute(ATTRIBUTE_FONTFACE)) {
                buffer.append(String.format("font-family:%s;", fontTag.getAttribute(ATTRIBUTE_FONTFACE)));
            }
            if (fontTag.hasAttribute(ATTRIBUTE_FONTSIZE)) {
                String fontSize = fontTag.getAttribute(ATTRIBUTE_FONTSIZE);
                String fontSizeCss = FONT_SIZE_MAP.get(fontSize);
                fontSizeCss = (fontSizeCss != null) ? fontSizeCss : fontSize;
                buffer.append(String.format("font-size:%s;", fontSizeCss));
            }
            if (fontTag.hasAttribute(ATTRIBUTE_STYLE) && fontTag.getAttribute(ATTRIBUTE_STYLE).trim().length() == 0) {
                buffer.append(fontTag.getAttribute(ATTRIBUTE_STYLE));
            }
            if (buffer.length() > 0) {
                span.setAttribute(ATTRIBUTE_STYLE, buffer.toString());
            }
            fontTag.getParentNode().insertBefore(span, fontTag);
            fontTag.getParentNode().removeChild(fontTag);
        }
    }
69291
public int rtf(XPathContext support)
  {

    int result = rtf();

    if (DTM.NULL == result)
    {
      DTM frag = support.createDocumentFragment();

      // %OPT%
      frag.appendTextChild(str());

      result = frag.getDocument();
    }

    return result;
  }
1047255
public int rtf(XPathContext support)
  {

    DTM frag = support.createDocumentFragment();

    frag.appendTextChild(str());

    return frag.getDocument();
  }
448827
public LOADSTATUS loadFont(InputStream in, String extension) throws IOException, VectorPrintException {
      // first download, then load
      File f = File.createTempFile("font.", extension);
      f.deleteOnExit();
      IOHelper.load(in, new FileOutputStream(f), ReportConstants.DEFAULTBUFFERSIZE, true);
      return loadFont(f.getPath());
   }
811589
private function readFont()
    {
        $length = self::getInt2d($this->data, $this->pos + 2);
        $recordData = $this->readRecordData($this->data, $this->pos + 4, $length);

        // move stream pointer to next record
        $this->pos += 4 + $length;

        if (!$this->readDataOnly) {
            $objFont = new PHPExcel_Style_Font();

            // offset: 0; size: 2; height of the font (in twips = 1/20 of a point)
            $size = self::getInt2d($recordData, 0);
            $objFont->setSize($size / 20);

            // offset: 2; size: 2; option flags
            // bit: 0; mask 0x0001; bold (redundant in BIFF5-BIFF8)
            // bit: 1; mask 0x0002; italic
            $isItalic = (0x0002 & self::getInt2d($recordData, 2)) >> 1;
            if ($isItalic) {
                $objFont->setItalic(true);
            }

            // bit: 2; mask 0x0004; underlined (redundant in BIFF5-BIFF8)
            // bit: 3; mask 0x0008; strike
            $isStrike = (0x0008 & self::getInt2d($recordData, 2)) >> 3;
            if ($isStrike) {
                $objFont->setStrikethrough(true);
            }

            // offset: 4; size: 2; colour index
            $colorIndex = self::getInt2d($recordData, 4);
            $objFont->colorIndex = $colorIndex;

            // offset: 6; size: 2; font weight
            $weight = self::getInt2d($recordData, 6);
            switch ($weight) {
                case 0x02BC:
                    $objFont->setBold(true);
                    break;
            }

            // offset: 8; size: 2; escapement type
            $escapement = self::getInt2d($recordData, 8);
            switch ($escapement) {
                case 0x0001:
                    $objFont->setSuperScript(true);
                    break;
                case 0x0002:
                    $objFont->setSubScript(true);
                    break;
            }

            // offset: 10; size: 1; underline type
            $underlineType = ord($recordData{10});
            switch ($underlineType) {
                case 0x00:
                    break; // no underline
                case 0x01:
                    $objFont->setUnderline(PHPExcel_Style_Font::UNDERLINE_SINGLE);
                    break;
                case 0x02:
                    $objFont->setUnderline(PHPExcel_Style_Font::UNDERLINE_DOUBLE);
                    break;
                case 0x21:
                    $objFont->setUnderline(PHPExcel_Style_Font::UNDERLINE_SINGLEACCOUNTING);
                    break;
                case 0x22:
                    $objFont->setUnderline(PHPExcel_Style_Font::UNDERLINE_DOUBLEACCOUNTING);
                    break;
            }

            // offset: 11; size: 1; font family
            // offset: 12; size: 1; character set
            // offset: 13; size: 1; not used
            // offset: 14; size: var; font name
            if ($this->version == self::XLS_BIFF8) {
                $string = self::readUnicodeStringShort(substr($recordData, 14));
            } else {
                $string = $this->readByteStringShort(substr($recordData, 14));
            }
            $objFont->setName($string['value']);

            $this->objFonts[] = $objFont;
        }
    }
177927
private void go(Reader r) throws IOException {
        BufferedReader reader;
        if (r instanceof BufferedReader)
            reader = (BufferedReader)r;
        else
            reader = new BufferedReader(r);
        doc.startDocument();
        while(true) {
			// read a new character
			if (previousCharacter == -1) {
				character = reader.read();
			}
			// or re-examine the previous character
			else {
				character = previousCharacter;
				previousCharacter = -1;
			}
			
			// the end of the file was reached
			if (character == -1) {
				if (html) {
					if (html && state == TEXT)
						flush();
					doc.endDocument();
				} else {
					throwException("Missing end tag");
				}
				return;
			}
            
			// dealing with  \n and \r
			if (character == '\n' && eol) {
				eol = false;
				continue;
			} else if (eol) {
				eol = false;
			} else if (character == '\n') {
				lines++;
				columns = 0;
			} else if (character == '\r') {
				eol = true;
				character = '\n';
				lines++;
				columns = 0;
			} else {
				columns++;
			}
            
			switch(state) {
            // we are in an unknown state before there's actual content
			case UNKNOWN:
                if(character == '<') {
                    saveState(TEXT);
                    state = TAG_ENCOUNTERED;
                }
                break;
            // we can encounter any content
			case TEXT:
                if(character == '<') {
                    flush();
                    saveState(state);
                    state = TAG_ENCOUNTERED;
                } else if(character == '&') {
                    saveState(state);
                    entity.setLength(0);
                    state = ENTITY;
                    nowhite = true;
                } else if (Character.isWhitespace((char)character)) {
                	if (nowhite)
                		text.append((char)character);
                	nowhite = false;
                } else {
                    text.append((char)character);
                    nowhite = true;
                }
                break;
            // we have just seen a < and are wondering what we are looking at
            // <foo>, </foo>, <!-- ... --->, etc.
			case TAG_ENCOUNTERED:
                initTag();
                if(character == '/') {
                    state = IN_CLOSETAG;
                } else if (character == '?') {
                    restoreState();
                    state = PI;
                } else {
                    text.append((char)character);
                    state = EXAMIN_TAG;
                }
                break;
            // we are processing something like this <foo ... >.
            // It could still be a <!-- ... --> or something.
			case EXAMIN_TAG:
                if(character == '>') {
                    doTag();
                    processTag(true);
                    initTag();
                    state = restoreState();
                } else if(character == '/') {
                    state = SINGLE_TAG;
                } else if(character == '-' && text.toString().equals("!-")) {
                    flush();
                    state = COMMENT;
                } else if(character == '[' && text.toString().equals("![CDATA")) {
                    flush();
                    state = CDATA;
                } else if(character == 'E' && text.toString().equals("!DOCTYP")) {
                    flush();
                    state = PI;
                } else if(Character.isWhitespace((char)character)) {
                    doTag();
                    state = TAG_EXAMINED;
                } else {
                    text.append((char)character);
                }
                break;
            // we know the name of the tag now.
			case TAG_EXAMINED:
                if(character == '>') {
                    processTag(true);
                    initTag();
                    state = restoreState();
                } else if(character == '/') {
                    state = SINGLE_TAG;
                } else if(Character.isWhitespace((char)character)) {
                    // empty
                } else {
                    text.append((char)character);
                    state = ATTRIBUTE_KEY;
                }
                break;
                
                // we are processing a closing tag: e.g. </foo>
			case IN_CLOSETAG:
                if(character == '>') {
                    doTag();
                    processTag(false);
                    if(!html && nested==0) return;
                    state = restoreState();
                } else {
                    if (!Character.isWhitespace((char)character))
                        text.append((char)character);
                }
                break;
                
            // we have just seen something like this: <foo a="b"/
            // and are looking for the final >.
			case SINGLE_TAG:
                if(character != '>')
                    throwException("Expected > for tag: <"+tag+"/>");
				doTag();
                processTag(true);
                processTag(false);
                initTag();
                if(!html && nested==0) {
                    doc.endDocument();
                    return;
                }
                state = restoreState();
                break;
                
            // we are processing CDATA
			case CDATA:
                if(character == '>'
                && text.toString().endsWith("]]")) {
                    text.setLength(text.length()-2);
                    flush();
                    state = restoreState();
                } else
                    text.append((char)character);
                break;
                
            // we are processing a comment.  We are inside
            // the <!-- .... --> looking for the -->.
			case COMMENT:
                if(character == '>'
                && text.toString().endsWith("--")) {
                    text.setLength(text.length() - 2);
                    flush();
                    state = restoreState();
                } else
                    text.append((char)character);
                break;
                
            // We are inside one of these <? ... ?> or one of these <!DOCTYPE ... >
			case PI:
                if(character == '>') {
                    state = restoreState();
                    if(state == TEXT) state = UNKNOWN;
                }
                break;
                
            // we are processing an entity, e.g. &lt;, &#187;, etc.
			case ENTITY:
                if(character == ';') {
                    state = restoreState();
                    String cent = entity.toString();
                    entity.setLength(0);
                    char ce = EntitiesToUnicode.decodeEntity(cent);
                    if (ce == '\0')
                    	text.append('&').append(cent).append(';');
                    else
                    	text.append(ce);
                } else if ((character != '#' && (character < '0' || character > '9') && (character < 'a' || character > 'z')
                    && (character < 'A' || character > 'Z')) || entity.length() >= 7) {
                    state = restoreState();
                    previousCharacter = character;
                    text.append('&').append(entity.toString());
                    entity.setLength(0);
                }
                else {
                    entity.append((char)character);
                }
                break;
            // We are processing the quoted right-hand side of an element's attribute.
			case QUOTE:
                if (html && quoteCharacter == ' ' && character == '>') {
                    flush();
                    processTag(true);
                    initTag();
                    state = restoreState();
                }
                else if (html && quoteCharacter == ' ' && Character.isWhitespace((char)character)) {
                	flush();
                    state = TAG_EXAMINED;
                }
                else if (html && quoteCharacter == ' ') {
                    text.append((char)character);
                }
                else if(character == quoteCharacter) {
                	flush();
                    state = TAG_EXAMINED;
                } else if(" \r\n\u0009".indexOf(character)>=0) {
                    text.append(' ');
                } else if(character == '&') {
                    saveState(state);
                    state = ENTITY;
                    entity.setLength(0);
                } else {
                    text.append((char)character);
                }
                break;
                
			case ATTRIBUTE_KEY:
                if(Character.isWhitespace((char)character)) {
                    flush();
                    state = ATTRIBUTE_EQUAL;
                } else if(character == '=') {
                	flush();
                    state = ATTRIBUTE_VALUE;
                } else if (html && character == '>') {
                    text.setLength(0);
                    processTag(true);
                    initTag();
                    state = restoreState();
                } else {
                    text.append((char)character);
                }
                break;
                
			case ATTRIBUTE_EQUAL:
                if(character == '=') {
                    state = ATTRIBUTE_VALUE;
                } else if(Character.isWhitespace((char)character)) {
                    // empty
                } else if (html && character == '>') {
                    text.setLength(0);
                    processTag(true);
                    initTag();
                    state = restoreState();
                } else if (html && character == '/') {
                    flush();
                    state = SINGLE_TAG;
                } else if (html) {
                    flush();
                    text.append((char)character);
                    state = ATTRIBUTE_KEY;
                } else {
                    throwException("Error in attribute processing.");
                }
                break;
                
			case ATTRIBUTE_VALUE:
                if(character == '"' || character == '\'') {
                    quoteCharacter = character;
                    state = QUOTE;
                } else if(Character.isWhitespace((char)character)) {
                    // empty
                } else if (html && character == '>') {
                    flush();
                    processTag(true);
                    initTag();
                    state = restoreState();
                } else if (html) {
                    text.append((char)character);
                    quoteCharacter = ' ';
                    state = QUOTE;
                } else {
                    throwException("Error in attribute processing");
                }
                break;
            }
        }
    }
863246
public static BufferedImage read (File file)
        throws IOException
    {
        RandomAccessFile raf = new RandomAccessFile(file, "r");
        FileChannel fchan = raf.getChannel();

        try {
            MappedByteBuffer mbuf = fchan.map(FileChannel.MapMode.READ_ONLY, 0, file.length());
            return read(mbuf);
        } finally {
            fchan.close();
            raf.close();
        }
    }
897442
private void readCRLF() throws IOException {
        int cr = in.read();
        int lf = in.read();
        if ((cr != '\r') || (lf != '\n')) {
            throw new IOException(
                "CRLF expected at end of chunk: " + cr + "/" + lf);
        }
    }
503381
private void readTag(RandomAccessInputStream raf) throws FileNotFoundException, IOException
	{
		raf.seek(raf.length() - TAG_SIZE);
		byte[] buf = new byte[TAG_SIZE];
		raf.read(buf, 0, TAG_SIZE);
		String tag = new String(buf, 0, TAG_SIZE, ENC_TYPE);
		int start = TAG_START.length();
		title = tag.substring(start, start += TITLE_SIZE);
		artist = tag.substring(start, start += ARTIST_SIZE);
		album = tag.substring(start, start += ALBUM_SIZE);
		year = tag.substring(start, start += YEAR_SIZE);
		comment = tag.substring(start, start += COMMENT_SIZE);
		track = (int) tag.charAt(TRACK_LOCATION);
		genre = (int) tag.charAt(GENRE_LOCATION);
	}
1217238
public void setRtfDocument(RtfDocument doc) {
        this.document = doc;
        if(document != null) {
            this.fontNumber = document.getDocumentHeader().getFontNumber(this);
        }
        if(this.color != null) {
            this.color.setRtfDocument(this.document);
        }
    }
360015
@Override
    public void readFragmentFrom(MwsReader r) {
        payment = r.read("Payment", Money.class);
        paymentMethod = r.read("PaymentMethod", String.class);
    }
175233
private static void processFontDirectory(File dir, ArrayList fonts) {
		if (!dir.exists()) {
			return;
		}
		if (processed.contains(dir)) {
			return;
		}
		processed.add(dir);
		
		File[] sources = dir.listFiles();
		if (sources == null) {
			return;
		}
		
		for (int j=0;j<sources.length;j++) {
			File source = sources[j];
		
			if (source.getName().equals(".")) {
				continue;
			}
			if (source.getName().equals("..")) {
				continue;
			}
			if (source.isDirectory()) {
				processFontDirectory(source, fonts);
				continue;
			}
			if (source.getName().toLowerCase().endsWith(".ttf")) {
				try {
					if (statusListener != null) {
						statusListener.updateStatus("Processing "+source.getName());
					}
					FontData data = new FontData(new FileInputStream(source), 1);
					fonts.add(data);
					
					String famName = data.getFamilyName();
					if (!families.contains(famName)) {
						families.add(famName);
					}
					
					boolean bo = data.getJavaFont().isBold();
					boolean it = data.getJavaFont().isItalic();
					
					if ((bo) && (it)) {
						bolditalic.put(famName, data);
					} else if (bo) {
						bold.put(famName, data);
					} else if (it) {
						italic.put(famName, data);
					} else {
						plain.put(famName, data);
					}
				} catch (Exception e) {
					if (DEBUG) {
						System.err.println("Unable to process: "+source.getAbsolutePath()+" ("+e.getClass()+": "+e.getMessage()+")");
					}
					if (statusListener != null) {
						statusListener.updateStatus("Unable to process: "+source.getName());
					}
				}
			}
		}	
	}
809931
@SuppressWarnings("unused")
	private ByteBuffer readBuffer(final RandomAccessFile raf) throws IOException {
		final int startPos = getCheckBytesFrom();
		if (startPos > raf.length()) {
			return null;
		}
		raf.seek(startPos);
		ByteBuffer buf;
		switch (getType()) {
		case MagicMimeEntry.STRING_TYPE: {
			int len = 0;
			// Lets check if its a between test
			final int index = this.typeStr.indexOf(">");
			if (index != -1) {
				len = Integer.parseInt(this.typeStr.substring(index + 1, this.typeStr.length() - 1));
				this.isBetween = true;
			} else {
				len = getContent().length();
			}
			buf = ByteBuffer.allocate(len + 1);
			raf.read(buf.array(), 0, len);
			break;
		}

		case MagicMimeEntry.SHORT_TYPE:
		case MagicMimeEntry.LESHORT_TYPE:
		case MagicMimeEntry.BESHORT_TYPE: {
			buf = ByteBuffer.allocate(2);
			raf.read(buf.array(), 0, 2);
			break;
		}

		case MagicMimeEntry.LELONG_TYPE:
		case MagicMimeEntry.BELONG_TYPE: {
			buf = ByteBuffer.allocate(4);
			raf.read(buf.array(), 0, 4);
			break;
		}

		case MagicMimeEntry.BYTE_TYPE: {
			buf = ByteBuffer.allocate(1);
			raf.read(buf.array(), 0, 1);
		}

		default: {
			buf = null;
			break;
		}
		}
		return buf;
	}
1226728
public static void readFrom(File file, ByteBuffer buffer) throws IOException {
        try (RandomAccessFile raf = new RandomAccessFile(file, "r")) {
            FileChannel channel = raf.getChannel();
            long needed = raf.length();

            while (needed > 0 && buffer.hasRemaining())
                needed = needed - channel.read(buffer);
        }
    }
1193514
public void addFont(Font font) {
        if (font.getBaseFont() != null) {
            fonts.add(font);
            return;
        }
        BaseFont bf = font.getCalculatedBaseFont(true);
        Font f2 = new Font(bf, font.getSize(), font.getCalculatedStyle(), font.getColor());
        fonts.add(f2);
    }
1053627
public int getFontNumber(RtfFont font) {
        if(font instanceof RtfParagraphStyle) {
            font = new RtfFont(this.document, font);
        }
        int fontIndex = -1;
        for(int i = 0; i < fontList.size(); i++) {
            if(fontList.get(i).equals(font)) {
                fontIndex = i;
            }
        }
        if(fontIndex == -1) {
            fontIndex = fontList.size();
            fontList.add(font);
        }
        return fontIndex;
    }