1 /* 2 * Copyright (c) 2009-2010 jMonkeyEngine 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: 8 * 9 * * Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * * Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * * Neither the name of 'jMonkeyEngine' nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 package com.jme3.font; 34 35 import com.jme3.export.*; 36 import com.jme3.util.IntMap; 37 import com.jme3.util.IntMap.Entry; 38 import java.io.IOException; 39 40 public class BitmapCharacterSet implements Savable { 41 42 private int lineHeight; 43 private int base; 44 private int renderedSize; 45 private int width; 46 private int height; 47 private IntMap<IntMap<BitmapCharacter>> characters; 48 private int pageSize; 49 50 @Override 51 public void write(JmeExporter ex) throws IOException { 52 OutputCapsule oc = ex.getCapsule(this); 53 oc.write(lineHeight, "lineHeight", 0); 54 oc.write(base, "base", 0); 55 oc.write(renderedSize, "renderedSize", 0); 56 oc.write(width, "width", 0); 57 oc.write(height, "height", 0); 58 oc.write(pageSize, "pageSize", 0); 59 60 int[] styles = new int[characters.size()]; 61 int index = 0; 62 for (Entry<IntMap<BitmapCharacter>> entry : characters) { 63 int style = entry.getKey(); 64 styles[index] = style; 65 index++; 66 IntMap<BitmapCharacter> charset = entry.getValue(); 67 writeCharset(oc, style, charset); 68 } 69 oc.write(styles, "styles", null); 70 } 71 72 protected void writeCharset(OutputCapsule oc, int style, IntMap<BitmapCharacter> charset) throws IOException { 73 int size = charset.size(); 74 short[] indexes = new short[size]; 75 BitmapCharacter[] chars = new BitmapCharacter[size]; 76 int i = 0; 77 for (Entry<BitmapCharacter> chr : charset){ 78 indexes[i] = (short) chr.getKey(); 79 chars[i] = chr.getValue(); 80 i++; 81 } 82 83 oc.write(indexes, "indexes"+style, null); 84 oc.write(chars, "chars"+style, null); 85 } 86 87 @Override 88 public void read(JmeImporter im) throws IOException { 89 InputCapsule ic = im.getCapsule(this); 90 lineHeight = ic.readInt("lineHeight", 0); 91 base = ic.readInt("base", 0); 92 renderedSize = ic.readInt("renderedSize", 0); 93 width = ic.readInt("width", 0); 94 height = ic.readInt("height", 0); 95 pageSize = ic.readInt("pageSize", 0); 96 int[] styles = ic.readIntArray("styles", null); 97 98 for (int style : styles) { 99 characters.put(style, readCharset(ic, style)); 100 } 101 } 102 103 private IntMap<BitmapCharacter> readCharset(InputCapsule ic, int style) throws IOException { 104 IntMap<BitmapCharacter> charset = new IntMap<BitmapCharacter>(); 105 short[] indexes = ic.readShortArray("indexes"+style, null); 106 Savable[] chars = ic.readSavableArray("chars"+style, null); 107 108 for (int i = 0; i < indexes.length; i++){ 109 int index = indexes[i] & 0xFFFF; 110 BitmapCharacter chr = (BitmapCharacter) chars[i]; 111 charset.put(index, chr); 112 } 113 return charset; 114 } 115 116 public BitmapCharacterSet() { 117 characters = new IntMap<IntMap<BitmapCharacter>>(); 118 } 119 120 public BitmapCharacter getCharacter(int index){ 121 return getCharacter(index, 0); 122 } 123 124 public BitmapCharacter getCharacter(int index, int style){ 125 IntMap<BitmapCharacter> map = getCharacterSet(style); 126 return map.get(index); 127 } 128 129 private IntMap<BitmapCharacter> getCharacterSet(int style) { 130 if (characters.size() == 0) { 131 characters.put(style, new IntMap<BitmapCharacter>()); 132 } 133 return characters.get(style); 134 } 135 136 public void addCharacter(int index, BitmapCharacter ch){ 137 getCharacterSet(0).put(index, ch); 138 } 139 140 public int getLineHeight() { 141 return lineHeight; 142 } 143 144 public void setLineHeight(int lineHeight) { 145 this.lineHeight = lineHeight; 146 } 147 148 public int getBase() { 149 return base; 150 } 151 152 public void setBase(int base) { 153 this.base = base; 154 } 155 156 public int getRenderedSize() { 157 return renderedSize; 158 } 159 160 public void setRenderedSize(int renderedSize) { 161 this.renderedSize = renderedSize; 162 } 163 164 public int getWidth() { 165 return width; 166 } 167 168 public void setWidth(int width) { 169 this.width = width; 170 } 171 172 public int getHeight() { 173 return height; 174 } 175 176 public void setHeight(int height) { 177 this.height = height; 178 } 179 180 /** 181 * Merge two fonts. 182 * If two font have the same style, merge will fail. 183 * @param styleSet Style must be assigned to this. 184 * @author Yonghoon 185 */ 186 public void merge(BitmapCharacterSet styleSet) { 187 if (this.renderedSize != styleSet.renderedSize) { 188 throw new RuntimeException("Only support same font size"); 189 } 190 for (Entry<IntMap<BitmapCharacter>> entry : styleSet.characters) { 191 int style = entry.getKey(); 192 if (style == 0) { 193 throw new RuntimeException("Style must be set first. use setStyle(int)"); 194 } 195 IntMap<BitmapCharacter> charset = entry.getValue(); 196 this.lineHeight = Math.max(this.lineHeight, styleSet.lineHeight); 197 IntMap<BitmapCharacter> old = this.characters.put(style, charset); 198 if (old != null) { 199 throw new RuntimeException("Can't override old style"); 200 } 201 202 for (Entry<BitmapCharacter> charEntry : charset) { 203 BitmapCharacter ch = charEntry.getValue(); 204 ch.setPage(ch.getPage() + this.pageSize); 205 } 206 } 207 this.pageSize += styleSet.pageSize; 208 } 209 210 public void setStyle(int style) { 211 if (characters.size() > 1) { 212 throw new RuntimeException("Applicable only for single style font"); 213 } 214 Entry<IntMap<BitmapCharacter>> entry = characters.iterator().next(); 215 IntMap<BitmapCharacter> charset = entry.getValue(); 216 characters.remove(entry.getKey()); 217 characters.put(style, charset); 218 } 219 220 void setPageSize(int pageSize) { 221 this.pageSize = pageSize; 222 } 223 }