alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (PangoFonts.java)

This example Java source code file (PangoFonts.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

affinetransform, awt, chars_digits, font, fontuiresource, geometry, graphicsconfiguration, graphicsenvironment, integer, numberformatexception, object, pangofonts, plaf, string, stringtokenizer, util

The PangoFonts.java Java example source code

/*
 * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.java.swing.plaf.gtk;

import java.awt.*;
import java.awt.geom.AffineTransform;
import javax.swing.plaf.FontUIResource;
import java.util.StringTokenizer;

import sun.font.FontConfigManager;
import sun.font.FontUtilities;

/**
 * @author Shannon Hickey
 * @author Leif Samuelsson
 */
class PangoFonts {

    public static final String CHARS_DIGITS = "0123456789";

    /**
     * Calculate a default scale factor for fonts in this L&F to match
     * the reported resolution of the screen.
     * Java 2D specified a default user-space scale of 72dpi.
     * This is unlikely to correspond to that of the real screen.
     * The Xserver reports a value which may be used to adjust for this.
     * and Java 2D exposes it via a normalizing transform.
     * However many Xservers report a hard-coded 90dpi whilst others report a
     * calculated value based on possibly incorrect data.
     * That is something that must be solved at the X11 level
     * Note that in an X11 multi-screen environment, the default screen
     * is the one used by the JRE so it is safe to use it here.
     */
    private static double fontScale;

    static {
        fontScale = 1.0d;
        GraphicsEnvironment ge =
           GraphicsEnvironment.getLocalGraphicsEnvironment();

        if (!ge.isHeadless()) {
            GraphicsConfiguration gc =
                ge.getDefaultScreenDevice().getDefaultConfiguration();
            AffineTransform at = gc.getNormalizingTransform();
            fontScale = at.getScaleY();
        }
    }


    /**
     * Parses a String containing a pango font description and returns
     * a Font object.
     *
     * @param pangoName a String describing a pango font
     *                  e.g. "Sans Italic 10"
     * @return a Font object as a FontUIResource
     *         or null if no suitable font could be created.
     */
    static Font lookupFont(String pangoName) {
        String family = "";
        int style = Font.PLAIN;
        int size = 10;

        StringTokenizer tok = new StringTokenizer(pangoName);

        while (tok.hasMoreTokens()) {
            String word = tok.nextToken();

            if (word.equalsIgnoreCase("italic")) {
                style |= Font.ITALIC;
            } else if (word.equalsIgnoreCase("bold")) {
                style |= Font.BOLD;
            } else if (CHARS_DIGITS.indexOf(word.charAt(0)) != -1) {
                try {
                    size = Integer.parseInt(word);
                } catch (NumberFormatException ex) {
                }
            } else {
                if (family.length() > 0) {
                    family += " ";
                }

                family += word;
            }
        }

        /*
         * Java 2D font point sizes are in a user-space scale of 72dpi.
         * GTK allows a user to configure a "dpi" property used to scale
         * the fonts used to match a user's preference.
         * To match the font size of GTK apps we need to obtain this DPI and
         * adjust as follows:
         * Some versions of GTK use XSETTINGS if available to dynamically
         * monitor user-initiated changes in the DPI to be used by GTK
         * apps. This value is also made available as the Xft.dpi X resource.
         * This is presumably a function of the font preferences API and/or
         * the manner in which it requests the toolkit to update the default
         * for the desktop. This dual approach is probably necessary since
         * other versions of GTK - or perhaps some apps - determine the size
         * to use only at start-up from that X resource.
         * If that resource is not set then GTK scales for the DPI resolution
         * reported by the Xserver using the formula
         * DisplayHeight(dpy, screen) / DisplayHeightMM(dpy, screen) * 25.4
         * (25.4mm == 1 inch).
         * JDK tracks the Xft.dpi XSETTINGS property directly so it can
         * dynamically change font size by tracking just that value.
         * If that resource is not available use the same fall back formula
         * as GTK (see calculation for fontScale).
         *
         * GTK's default setting for Xft.dpi is 96 dpi (and it seems -1
         * apparently also can mean that "default"). However this default
         * isn't used if there's no property set. The real default in the
         * absence of a resource is the Xserver reported dpi.
         * Finally this DPI is used to calculate the nearest Java 2D font
         * 72 dpi font size.
         * There are cases in which JDK behaviour may not exactly mimic
         * GTK native app behaviour :
         * 1) When a GTK app is not able to dynamically track the changes
         * (does not use XSETTINGS), JDK will resize but other apps will
         * not. This is OK as JDK is exhibiting preferred behaviour and
         * this is probably how all later GTK apps will behave
         * 2) When a GTK app does not use XSETTINGS and for some reason
         * the XRDB property is not present. JDK will pick up XSETTINGS
         * and the GTK app will use the Xserver default. Since its
         * impossible for JDK to know that some other GTK app is not
         * using XSETTINGS its impossible to account for this and in any
         * case for it to be a problem the values would have to be different.
         * It also seems unlikely to arise except when a user explicitly
         * deletes the X resource database entry.
         * There also some other issues to be aware of for the future:
         * GTK specifies the Xft.dpi value as server-wide which when used
         * on systems with 2 distinct X screens with different physical DPI
         * the font sizes will inevitably appear different. It would have
         * been a more user-friendly design to further adjust that one
         * setting depending on the screen resolution to achieve perceived
         * equivalent sizes. If such a change were ever to be made in GTK
         * we would need to update for that.
         */
        double dsize = size;
        int dpi = 96;
        Object value =
            Toolkit.getDefaultToolkit().getDesktopProperty("gnome.Xft/DPI");
        if (value instanceof Integer) {
            dpi = ((Integer)value).intValue() / 1024;
            if (dpi == -1) {
              dpi = 96;
            }
            if (dpi < 50) { /* 50 dpi is the minimum value gnome allows */
                dpi = 50;
            }
            /* The Java rasteriser assumes pts are in a user space of
             * 72 dpi, so we need to adjust for that.
             */
            dsize = ((double)(dpi * size)/ 72.0);
        } else {
            /* If there's no property, GTK scales for the resolution
             * reported by the Xserver using the formula listed above.
             * fontScale already accounts for the 72 dpi Java 2D space.
             */
            dsize = size * fontScale;
        }

        /* Round size to nearest integer pt size */
        size = (int)(dsize + 0.5);
        if (size < 1) {
            size = 1;
        }

        String fcFamilyLC = family.toLowerCase();
        if (FontUtilities.mapFcName(fcFamilyLC) != null) {
            /* family is a Fc/Pango logical font which we need to expand. */
            Font font =  FontUtilities.getFontConfigFUIR(fcFamilyLC, style, size);
            font = font.deriveFont(style, (float)dsize);
            return new FontUIResource(font);
        } else {
            /* It's a physical font which we will create with a fallback */
            Font font = new Font(family, style, size);
            /* a roundabout way to set the font size in floating points */
            font = font.deriveFont(style, (float)dsize);
            FontUIResource fuir = new FontUIResource(font);
            return FontUtilities.getCompositeFontUIResource(fuir);
        }
    }

    /**
     * Parses a String containing a pango font description and returns
     * the (unscaled) font size as an integer.
     *
     * @param pangoName a String describing a pango font
     * @return the size of the font described by pangoName (e.g. if
     *         pangoName is "Sans Italic 10", then this method returns 10)
     */
    static int getFontSize(String pangoName) {
        int size = 10;

        StringTokenizer tok = new StringTokenizer(pangoName);
        while (tok.hasMoreTokens()) {
            String word = tok.nextToken();

            if (CHARS_DIGITS.indexOf(word.charAt(0)) != -1) {
                try {
                    size = Integer.parseInt(word);
                } catch (NumberFormatException ex) {
                }
            }
        }

        return size;
    }
}

Other Java examples (source code examples)

Here is a short list of links related to this Java PangoFonts.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.