// Copyright 2001-2003, FreeHEP.
package org.freehep.graphicsio.pdf;

import java.awt.Font;
import java.awt.font.FontRenderContext;
import java.io.IOException;
import java.util.*;

import org.freehep.graphicsio.FontConstants;
import org.freehep.graphicsio.font.FontIncluder;
import org.freehep.graphicsio.font.FontTable;
import org.freehep.graphicsio.font.encoding.Lookup;
import org.freehep.graphicsio.font.encoding.CharTable;

/**
 *  A table to remember which fonts were used while writing a pdf document.
 *  Entries to resource dictionaries and embedding of fonts can be done
 *  when the drawing is finished by calling <tt>addAll()</tt>.
 *  @author Simon Fischer
 *  @version $Id: PDFFontTable.java,v 1.3 2005/12/16 01:59:24 orrisroot Exp $
 */
public class PDFFontTable extends FontTable {

    private int currentFontIndex = 1;
    private PDFWriter pdf;
    private PDFRedundanceTracker tracker;

    public PDFFontTable(PDFWriter pdf) {
        super();
        this.pdf = pdf;
        this.tracker = new PDFRedundanceTracker(pdf);
    }


    /** Adds all fonts to a dictionary named "FontList". */
    public int addFontDictionary() throws IOException {
        Collection fonts = getEntries();
        if (fonts.size() > 0) {
            PDFDictionary fontList = pdf.openDictionary("FontList");
            for (Iterator i = fonts.iterator(); i.hasNext(); ) {
                Entry e = (Entry)i.next();
                fontList.entry(e.getReference(), pdf.ref(e.getReference()));
            }
            pdf.close(fontList);
        }
        return fonts.size();
    }

    /** Embeds all not yet embedded fonts to the file. */
    public void embedAll(FontRenderContext context, boolean embed, String embedAs) throws IOException {
        Collection col = getEntries();
        Iterator i = col.iterator();
        while (i.hasNext()) {
            Entry e = (Entry)i.next();
            boolean _embed = embed;
            if (!e.isWritten()) {
                e.setWritten(true);

                FontIncluder fontIncluder = null;
                if (PDFFontIncluder.isStandardFont(e.getFont())) {
                    _embed = false;
                }

                if (_embed) {
                    if (embedAs.equals(FontConstants.EMBED_FONTS_TYPE3)) {
                        fontIncluder = new PDFFontEmbedderType3(context,
                                        pdf,
                                        e.getReference(),
                                        tracker);
                    } else if (embedAs.equals(FontConstants.EMBED_FONTS_TYPE1)) {
                        fontIncluder = PDFFontEmbedderType1.create(context,
                                           pdf,
                                           e.getReference(),
                                           tracker);
                    } else {
                        System.out.println("PDFFontTable: invalid value for embedAs: "+embedAs);
                    }
                } else {
                    fontIncluder = new PDFFontIncluder(context,
                                           pdf,
                                           e.getReference(),
                                           tracker);
                }
                fontIncluder.includeFont(e.getFont(), e.getEncoding(), e.getReference());
            }
        }
        tracker.writeAll();
    }

    public CharTable getEncodingTable() {
        return Lookup.getInstance().getTable("PDFLatin");
    }

    public void firstRequest(Entry e, boolean embed, String embedAs) {
    }

    private static final Properties replaceFonts = new Properties();
    static {
        replaceFonts.setProperty("Dialog",      "Helvetica");
        replaceFonts.setProperty("DialogInput", "Helvetica");
        replaceFonts.setProperty("Serif",       "TimesRoman");
        replaceFonts.setProperty("SansSerif",   "Helvetica");
        replaceFonts.setProperty("Monospaced",  "Courier");
    }

    protected Font substituteFont(Font font) {
        String fontName = replaceFonts.getProperty(font.getName(), null);
        if (fontName != null) {
            Font newFont = new Font(fontName, font.getStyle(), font.getSize());
            font = newFont.deriveFont(font.getSize2D());
        }
        return font;
    }

    /** Creates the reference by numbering them.
     *  @return "F"+currentFontIndex */
    protected String createFontReference(Font f) {
        return "F"+(currentFontIndex++);
    }
}
