/*
* Copyright (C) 2006 Clam <clamisgood@gmail.com>
* Copyright (C) 2008, 2009 Quadduc <quadduc@gmail.com>
*
* This file is part of LateralGM.
* LateralGM is free software and comes with ABSOLUTELY NO WARRANTY.
* See LICENSE for details.
*/
package org.lateralgm.resources;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumMap;
import org.lateralgm.main.LGM;
import org.lateralgm.main.UpdateSource;
import org.lateralgm.main.UpdateSource.UpdateEvent;
import org.lateralgm.main.UpdateSource.UpdateTrigger;
import org.lateralgm.resources.sub.CharacterRange;
import org.lateralgm.resources.sub.CharacterRange.PCharacterRange;
import org.lateralgm.resources.sub.GlyphMetric;
import org.lateralgm.util.ActiveArrayList;
import org.lateralgm.util.PropertyMap;
public class Font extends InstantiableResource<Font,Font.PFont>
{
public enum PFont
{
FONT_NAME,SIZE,BOLD,ITALIC,ANTIALIAS,CHARSET
}
private static final EnumMap<PFont,Object> DEFS = PropertyMap.makeDefaultMap(PFont.class,"Arial",
12,false,false,3,0);
public final ActiveArrayList<CharacterRange> characterRanges = new ActiveArrayList<CharacterRange>();
public final ActiveArrayList<GlyphMetric> glyphMetrics = new ActiveArrayList<GlyphMetric>();
private final UpdateTrigger rangeUpdateTrigger = new UpdateTrigger();
public final UpdateSource rangeUpdateSource = new UpdateSource(this,rangeUpdateTrigger);
public Font()
{
this(null);
}
public Font(ResourceReference<Font> r)
{
super(r);
}
public Font makeInstance(ResourceReference<Font> r)
{
return new Font(r);
}
public GlyphMetric addGlyph()
{
GlyphMetric gm = new GlyphMetric();
glyphMetrics.add(gm);
return gm;
}
public CharacterRange addRange()
{
CharacterRange cr = new CharacterRange(this);
characterRanges.add(cr);
return cr;
}
public CharacterRange addRange(int min, int max)
{
if (min < 0 || min > max) throw new IllegalArgumentException();
CharacterRange cr = new CharacterRange(this,min,max);
characterRanges.add(cr);
return cr;
}
public void addRangesFromString(String s)
{
ArrayList<Integer> sorted = new ArrayList<Integer>();
int cp = 0;
for (int i = 0; i < s.codePointCount(0,s.length()); i++)
{
int cpa = s.codePointAt(cp);
sorted.add(cpa);
cp += Character.toChars(cpa).length;
}
Collections.sort(sorted);
int last = sorted.get(0);
CharacterRange cr = addRange(last,last);
for (Integer charint : sorted)
{
int current = charint;
if (current - last > 1) cr = addRange(current,current);
last = current;
cr.properties.put(PCharacterRange.RANGE_MAX,current);
}
}
public void addRangesFromFile(File f)
{
try
{
addRangesFromString(new String(Files.readAllBytes(f.toPath()),"UTF-8"));
}
catch (IOException e)
{
LGM.showDefaultExceptionHandler(e);
}
}
public static int makeStyle(boolean bold, boolean italic)
{
return (italic ? java.awt.Font.ITALIC : 0) | (bold ? java.awt.Font.BOLD : 0);
}
public java.awt.Font getAWTFont(int resolution)
{
int s = get(PFont.SIZE);
String fn = get(PFont.FONT_NAME);
boolean b = get(PFont.BOLD);
boolean i = get(PFont.ITALIC);
/* Java assumes 72 dpi, but we shouldn't depend on the native resolution either.
* For consistent pixel size across different systems, we should pick a common default.
* AFAIK, the default in Windows (and thus GM) is 96 dpi. */
int fontSize = (int) Math.round(s * resolution / 72.0);
return new java.awt.Font(fn,makeStyle(b,i),fontSize);
}
public java.awt.Font getAWTFont()
{
return getAWTFont(96);
}
@Override
protected PropertyMap<PFont> makePropertyMap()
{
return new PropertyMap<PFont>(PFont.class,this,DEFS);
}
@Override
protected void postCopy(Font dest)
{
super.postCopy(dest);
dest.characterRanges.clear();
for (CharacterRange cr : characterRanges)
{
CharacterRange r2 = dest.addRange();
r2.properties.putAll(cr.properties);
}
dest.glyphMetrics.clear();
for (GlyphMetric gm : glyphMetrics)
{
GlyphMetric g2 = dest.addGlyph();
g2.properties.putAll(gm.properties);
}
}
public void rangeUpdated(UpdateEvent e)
{
rangeUpdateTrigger.fire(new UpdateEvent(rangeUpdateSource,e));
}
}