CustomFont.java
上传用户:haobig99
上传日期:2022-06-15
资源大小:369k
文件大小:11k
源码类别:

J2ME

开发平台:

Java

  1. /*
  2.  * Copyright 2008 Sun Microsystems, Inc.  All Rights Reserved.
  3.  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4.  *
  5.  * This code is free software; you can redistribute it and/or modify it
  6.  * under the terms of the GNU General Public License version 2 only, as
  7.  * published by the Free Software Foundation.  Sun designates this
  8.  * particular file as subject to the "Classpath" exception as provided
  9.  * by Sun in the LICENSE file that accompanied this code.
  10.  *
  11.  * This code is distributed in the hope that it will be useful, but WITHOUT
  12.  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13.  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14.  * version 2 for more details (a copy is included in the LICENSE file that
  15.  * accompanied this code).
  16.  *
  17.  * You should have received a copy of the GNU General Public License version
  18.  * 2 along with this work; if not, write to the Free Software Foundation,
  19.  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20.  *
  21.  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
  22.  * CA 95054 USA or visit www.sun.com if you need additional information or
  23.  * have any questions.
  24.  */
  25. package com.sun.lwuit;
  26. import java.lang.ref.WeakReference;
  27. import java.util.Hashtable;
  28. /**
  29.  * Implements a bitmap font that uses an image and sets of offsets to draw a font
  30.  * with a given character set.
  31.  *
  32.  * @author Shai Almog
  33.  */
  34. class CustomFont extends Font {
  35.     /**
  36.      * Keep two colors in cache by default to allow faster selection colors
  37.      */
  38.     private static final int COLOR_CACHE_SIZE = 20;
  39.     
  40.     private Hashtable colorCache = new Hashtable();
  41.     private String charsets;
  42.     private int color;
  43.     
  44.     // package protected for the resource editor
  45.     Image cache;
  46.     
  47.     /**
  48.      * The offset in which to cut the character from the bitmap
  49.      */
  50.     int[] cutOffsets;
  51.     /**
  52.      * The width of the character when drawing... this should not be confused with
  53.      * the number of cutOffset[o + 1] - cutOffset[o]. They are completely different
  54.      * since a character can be "wider" and "seep" into the next region. This is
  55.      * especially true with italic characters all of which "lean" outside of their 
  56.      * bounds.
  57.      */
  58.     int[] charWidth;
  59.     private int imageWidth;
  60.     private int imageHeight;
  61.     private WeakReference imageArrayRef;
  62.     
  63.     
  64.     private int[] getImageArray() {
  65.         if(imageArrayRef != null) {
  66.             int[] a = (int[])imageArrayRef.get();
  67.             if(a != null) {
  68.                 return a;
  69.             }
  70.         }
  71.         int[] a = cache.getRGBCached();
  72.         
  73.         imageArrayRef = new WeakReference(a);
  74.         return a;
  75.     }
  76.     
  77.     /**
  78.      * Creates a bitmap font with the given arguments
  79.      * 
  80.      * @param bitmap a transparency map in red and black that indicates the characters
  81.      * @param cutOffsets character offsets matching the bitmap pixels and characters in the font 
  82.      * @param charWidth The width of the character when drawing... this should not be confused with
  83.      *      the number of cutOffset[o + 1] - cutOffset[o]. They are completely different
  84.      *      since a character can be "wider" and "seep" into the next region. This is
  85.      *      especially true with italic characters all of which "lean" outside of their 
  86.      *      bounds.
  87.      * @param charsets the set of characters in the font
  88.      * @return a font object to draw bitmap fonts
  89.      */
  90.     public CustomFont(Image bitmap, int[] cutOffsets, int[] charWidth, String charsets) {
  91.         this.cutOffsets = cutOffsets;
  92.         this.charWidth = charWidth;
  93.         this.charsets = charsets;
  94.         imageWidth = bitmap.getWidth();
  95.         imageHeight = bitmap.getHeight();
  96.         int[] imageArray = new int[imageWidth * imageHeight];
  97.         
  98.         // default to black colored font
  99.         bitmap.getRGB(imageArray, 0, 0, 0, imageWidth, imageHeight);
  100.         for(int iter = 0 ; iter < imageArray.length ; iter++) {
  101.             // extract the red component from the font image
  102.             // shift the alpha 8 bits to the left
  103.             // apply the alpha to the image
  104.             imageArray[iter] = ((imageArray[iter] & 0xff0000) << 8);
  105.         }
  106.         cache = Image.createImage(imageArray, imageWidth, imageHeight);
  107.         imageArrayRef = new WeakReference(imageArray);
  108.     }
  109.     
  110.     /**
  111.      * @inheritDoc
  112.      */
  113.     public int charWidth(char ch) {
  114.         int i = charsets.indexOf(ch);
  115.         if(i < 0) {
  116.             return 0;
  117.         }
  118.         return charWidth[i];
  119.     }
  120.     /**
  121.      * @inheritDoc
  122.      */
  123.     public int getHeight() {
  124.         return imageHeight;
  125.     }
  126.     private boolean checkCacheCurrentColor(int newColor) {
  127.         Integer currentColor = new Integer(color);
  128.         Integer newColorKey = new Integer(newColor);
  129.         if(colorCache.get(currentColor) == null){
  130.             colorCache.put(currentColor, new WeakReference(cache));
  131.         }
  132.         color = newColor;
  133.         WeakReference newCache = (WeakReference)colorCache.get(newColorKey);
  134.         if(newCache != null) {
  135.             Image i = (Image)newCache.get();
  136.             if(i != null) {
  137.                 cache = i;
  138.                 if(colorCache.size() > COLOR_CACHE_SIZE) {
  139.                     // remove a random cache element
  140.                     colorCache.remove(colorCache.keys().nextElement());
  141.                 }
  142.                 return true;
  143.             }else{
  144.                 colorCache.remove(newColorKey);
  145.             }
  146.         }
  147.         if(colorCache.size() > COLOR_CACHE_SIZE) {
  148.             // remove a random cache element
  149.             colorCache.remove(colorCache.keys().nextElement());
  150.         }        
  151.         return false;
  152.     }
  153.     
  154.     private void initColor(Graphics g) {
  155.         int newColor = g.getColor();
  156.         
  157.         if(newColor != color && !checkCacheCurrentColor(newColor)) {
  158.             color = newColor & 0xffffff;
  159.             int[] imageArray = getImageArray();
  160.             for(int iter = 0 ; iter < imageArray.length ; iter++) {
  161.                 // extract the red component from the font image
  162.                 // shift the alpha 8 bits to the left
  163.                 // apply the alpha to the image
  164.                 imageArray[iter] = color | (imageArray[iter] & 0xff000000);
  165.             }
  166.             cache = Image.createImage(imageArray, imageWidth, imageHeight);
  167.         }
  168.     }
  169.     
  170.     /**
  171.      * @inheritDoc
  172.      */
  173.     void drawChar(Graphics g, char character, int x, int y) {
  174.         int clipX = g.getClipX();
  175.         int clipY = g.getClipY();
  176.         int clipWidth = g.getClipWidth();
  177.         int clipHeight = g.getClipHeight();
  178.         int i = charsets.indexOf(character);
  179.         if(i > -1) {
  180.             initColor(g);
  181.             
  182.             // draw region is flaky on some devices, use setClip instead
  183.             g.clipRect(x, y, charWidth[i], imageHeight);
  184.             g.drawImage(cache, x - cutOffsets[i], y);
  185.             //g.drawRegion(cache, cutOffsets[i], 0, charWidth[i], imageHeight, x, y);
  186.         }
  187.         // restore the clip
  188.         g.setClip(clipX, clipY, clipWidth, clipHeight);
  189.     }
  190.     /**
  191.      * @inheritDoc
  192.      */
  193.     public void addContrast(byte value) {
  194.         int[] imageArray = getImageArray();
  195.         for(int iter = 0 ; iter < imageArray.length ; iter++) {
  196.             int alpha = (imageArray[iter] >> 24) & 0xff;
  197.             if(alpha != 0) {
  198.                 alpha = Math.min(alpha + value, 255);
  199.                 imageArray[iter] = ((alpha << 24) & 0xff000000) | color;
  200.             }
  201.         }
  202.     }
  203.     /**
  204.      * Override this frequently used method for a slight performance boost...
  205.      * 
  206.      * @param g the component graphics
  207.      * @param data the chars to draw
  208.      * @param offset the offset to draw the chars 
  209.      * @param length the length of chars 
  210.      * @param x the x coordinate to draw the chars
  211.      * @param y the y coordinate to draw the chars
  212.      */
  213.     void drawChars(Graphics g, char[] data, int offset, int length, int x, int y) {
  214.         initColor(g);
  215.         int clipX = g.getClipX();
  216.         int clipY = g.getClipY();
  217.         int clipWidth = g.getClipWidth();
  218.         int clipHeight = g.getClipHeight();
  219.         if(clipY <= y + getHeight() && clipY + clipHeight >= y) {
  220.             char c;
  221.             for ( int i = 0; i < length; i++ ) {
  222.                 c = data[offset+i];
  223.                 int position = charsets.indexOf(c);
  224.                 if(position < 0) {
  225.                     continue;
  226.                 }
  227.                 // draw region is flaky on some devices, use setClip instead
  228.                 g.clipRect(x, y, charWidth[position], imageHeight);
  229.                 if(g.getClipWidth() > 0 && g.getClipHeight() > 0) {
  230.                     g.drawImage(cache, x - cutOffsets[position], y);
  231.                 }
  232.                 x += charWidth[position];
  233.                 g.setClip(clipX, clipY, clipWidth, clipHeight);
  234.             }
  235.         }
  236.     }
  237.     /**
  238.      * @inheritDoc
  239.      */
  240.     public String getCharset() {
  241.         return charsets;
  242.     }
  243.     /**
  244.      * @inheritDoc
  245.      */
  246.     public int charsWidth(char[] ch, int offset, int length){
  247.         int retVal = 0;
  248.         for(int i=0; i<length; i++){
  249.             retVal += charWidth(ch[i + offset]);
  250.         }
  251.         return retVal;
  252.     }
  253.     /**
  254.      * @inheritDoc
  255.      */
  256.     public int substringWidth(String str, int offset, int len){
  257.         return charsWidth(str.toCharArray(), offset, len);
  258.     }
  259.     /**
  260.      * @inheritDoc
  261.      */
  262.     public int stringWidth(String str){
  263.         if( str==null || str.length()==0)
  264.             return 0;
  265.         return substringWidth(str, 0, str.length());
  266.     }
  267.     /**
  268.      * @inheritDoc
  269.      */
  270.     public int getFace(){
  271.         return 0;
  272.     }
  273.     /**
  274.      * @inheritDoc
  275.      */
  276.     public int getSize(){
  277.         return 0;
  278.     }
  279.     /**
  280.      * @inheritDoc
  281.      */
  282.     public int getStyle() {
  283.         return 0;
  284.     }
  285.     
  286.     /**
  287.     * @inheritDoc
  288.     */
  289.    public boolean equals(Object o) {
  290.        if(o == this) {
  291.            return true;
  292.        }
  293.        if(o.getClass() == getClass()) {
  294.            CustomFont f = (CustomFont)o;
  295.            if(charsets.equals(f.charsets)) {
  296.                for(int iter = 0 ; iter < cutOffsets.length ; iter++) {
  297.                    if(cutOffsets[iter] != f.cutOffsets[iter]) {
  298.                        return false;
  299.                    }
  300.                }
  301.                return true;
  302.            }
  303.        }
  304.        return false;
  305.    }
  306. }