blob: 09bcf5c968a4456ec6f0e7eb08a4740c47e54de7 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @author Oleg V. Khaschansky
* @version $Revision$
*
* @date: Jul 12, 2005
*/
package org.apache.harmony.awt.gl.font;
import java.awt.Font;
import java.awt.GraphicsEnvironment;
import java.util.List;
import java.util.Map;
/**
* This class chooses the default font for the given text.
* If it finds the character which current font is unable to display
* it starts the next font run and looks for the font which is able to
* display the current character. It also caches the font mappings
* (index in the array containing all fonts) for the characters,
* using that fact that scripts are mainly contiguous in the UTF-16 encoding
* and there's a high probability that the upper byte will be the same for the
* next character as for the previous. This allows to save the space used for the cache.
*/
public class FontFinder {
private static final float DEFAULT_FONT_SIZE = 12;
private static final Font fonts[] =
GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts();
private static final int NUM_BLOCKS = 256;
private static final int BLOCK_SIZE = 256;
private static final int INDEX_MASK = 0xFF;
private static final int BLOCK_SHIFT = 8;
// Maps characters into the fonts array
private static final int blocks[][] = new int[NUM_BLOCKS][];
/**
* Finds the font which is able to display the given character
* and saves the font mapping for this character
* @param c - character
* @return font
*/
static Font findFontForChar(char c) {
int blockNum = c >> BLOCK_SHIFT;
int index = c & INDEX_MASK;
if (blocks[blockNum] == null) {
blocks[blockNum] = new int[BLOCK_SIZE];
}
if (blocks[blockNum][index] == 0) {
blocks[blockNum][index] = 1;
for (int i=0; i<fonts.length; i++) {
if (fonts[i].canDisplay(c)) {
blocks[blockNum][index] = i+1;
break;
}
}
}
return getDefaultSizeFont(blocks[blockNum][index]-1);
}
/**
* Derives the default size font
* @param i - index in the array of all fonts
* @return derived font
*/
static Font getDefaultSizeFont(int i) {
if (fonts[i].getSize() != DEFAULT_FONT_SIZE) {
fonts[i] = fonts[i].deriveFont(DEFAULT_FONT_SIZE);
}
return fonts[i];
}
/**
* Assigns default fonts for the given text run.
* First three parameters are input, last three are output.
* @param text - given text
* @param runStart - start of the text run
* @param runLimit - end of the text run
* @param runStarts - starts of the resulting font runs
* @param fonts - mapping of the font run starts to the fonts
*/
static void findFonts(char text[], int runStart, int runLimit, List<Integer> runStarts,
Map<Integer, Font> fonts) {
Font prevFont = null;
Font currFont;
for (int i = runStart; i < runLimit; i++) {
currFont = findFontForChar(text[i]);
if (currFont != prevFont) {
prevFont = currFont;
Integer idx = new Integer(i);
fonts.put(idx, currFont);
if (i != runStart) {
runStarts.add(idx);
}
}
}
}
}