Brauchen Sie noch einen Weg, um eine Schriftart zu skalieren, um ein Rechteck zu passen

StackOverflow https://stackoverflow.com/questions/876234

  •  22-08-2019
  •  | 
  •  

Frage

Ich schrieb einige Code eine Schriftart zu skalieren innerhalb (der Länge) ein Rechteck zu passen. Es beginnt bei 18 Breite und iteriert nach unten, bis sie paßt.

Das scheint schrecklich ineffizient, aber ich kann keine nicht-Looping Art und Weise zu tun, es finden. Diese Linie ist für Etiketten in einem Spielraster, die skaliert, so dass ich keine Arbeits-around-Lösung (Wrapping, abschneidet und sie hinter dem Rechteck sind alle nicht akzeptabel) sehen.

Es ist eigentlich ziemlich schnell, ich tue dies für Hunderte von Rechtecken und es ist schnell genug, um es einfach langsam, um eine Note nach unten.

Wenn niemand mit etwas besser kommt, ich werde nur aus einer Tabelle die Start Vermutung laden (so dass es viel näher als 18) und diese verwenden -. Mit Ausnahme der Lag es große Werke

public Font scaleFont(String text, Rectangle rect, Graphics g, Font pFont) {
    float nextTry=18.0f;
    Font font=pFont;

    while(x > 4) {                             
            font=g.getFont().deriveFont(nextTry);
            FontMetrics fm=g.getFontMetrics(font);
            int width=fm.stringWidth(text);
            if(width <= rect.width)
                return font;
            nextTry*=.9;            
    }
    return font;
}
War es hilfreich?

Lösung

semi-Pseudocode:

public Font scaleFont(String text, Rectangle rect, Graphics g, Font pFont) {
    float fontSize = 20.0f;
    Font font = pFont;

    font = g.getFont().deriveFont(fontSize);
    int width = g.getFontMetrics(font).stringWidth(text);
    fontSize = (rect.width / width ) * fontSize;
    return g.getFont().deriveFont(fontSize);
}

ich bin nicht sicher, warum Sie in pFont passieren, wie es nicht verwendet wird ...

Andere Tipps

Sie könnten Interpolationssuche verwenden:

public static Font scaleFont(String text, Rectangle rect, Graphics g, Font pFont) {
    float min=0.1f;
    float max=72f;
    float size=18.0f;
    Font font=pFont;

    while(max - min <= 0.1) {
        font = g.getFont().deriveFont(size);
        FontMetrics fm = g.getFontMetrics(font);
        int width = fm.stringWidth(text);
        if (width == rect.width) {
            return font;
        } else {
            if (width < rect.width) {
                min = size;
            } else {
                max = size;
            }
            size = Math.min(max, Math.max(min, size * (float)rect.width / (float)width));
        }
    }
    return font;
}

Ändern Sie alle Breite Variablen für besseres Ergebnis anstelle von int zu schweben.

public static Font scaleFontToFit(String text, int width, Graphics g, Font pFont)
{
    float fontSize = pFont.getSize();
    float fWidth = g.getFontMetrics(pFont).stringWidth(text);
    if(fWidth <= width)
        return pFont;
    fontSize = ((float)width / fWidth) * fontSize;
    return pFont.deriveFont(fontSize);
}
private Font scaleFont ( String text, Rectangle rect, Graphics gc )
{
    final float fMinimumFont = 0.1f;
    float fMaximumFont = 1000f;

    /* Use Point2d.Float to hold ( font, width of font in pixels ) pairs. */
    Point2D.Float lowerPoint = new Point2D.Float ( fMinimumFont, getWidthInPixelsOfString ( text, fMinimumFont, gc ) );
    Point2D.Float upperPoint = new Point2D.Float ( fMaximumFont, getWidthInPixelsOfString ( text, fMaximumFont, gc ) );
    Point2D.Float midPoint = new Point2D.Float ();

    for ( int i = 0; i < 50; i++ )
    {
        float middleFont = ( lowerPoint.x + upperPoint.x ) / 2;

        midPoint.setLocation ( middleFont, getWidthInPixelsOfString ( text, middleFont, gc ) );

        if ( midPoint.y >= rect.getWidth () * .95 && midPoint.y <= rect.getWidth () )
            break;
        else if ( midPoint.y < rect.getWidth () )
            lowerPoint.setLocation ( midPoint );
        else if ( midPoint.y > rect.getWidth () )
            upperPoint.setLocation ( midPoint );
    }

    fMaximumFont = midPoint.x;

    Font font = gc.getFont ().deriveFont ( fMaximumFont );

    /* Now use Point2d.Float to hold ( font, height of font in pixels ) pairs. */
    lowerPoint.setLocation ( fMinimumFont, getHeightInPixelsOfString ( text, fMinimumFont, gc ) );
    upperPoint.setLocation ( fMaximumFont, getHeightInPixelsOfString ( text, fMaximumFont, gc ) );

    if ( upperPoint.y < rect.getHeight () )
        return font;

    for ( int i = 0; i < 50; i++ )
    {
        float middleFont = ( lowerPoint.x + upperPoint.x ) / 2;

        midPoint.setLocation ( middleFont, getHeightInPixelsOfString ( text, middleFont, gc ) );

        if ( midPoint.y >= rect.getHeight () * .95 && midPoint.y <= rect.getHeight () )
            break;
        else if ( midPoint.y < rect.getHeight () )
            lowerPoint.setLocation ( midPoint );
        else if ( midPoint.y > rect.getHeight () )
            upperPoint.setLocation ( midPoint );
    }

    fMaximumFont = midPoint.x;

    font = gc.getFont ().deriveFont ( fMaximumFont );

    return font;
}


private float getWidthInPixelsOfString ( String str, float fontSize, Graphics gc )
{
    Font font = gc.getFont ().deriveFont ( fontSize );

    return getWidthInPixelsOfString ( str, font, gc );
}

private float getWidthInPixelsOfString ( String str, Font font, Graphics gc )
{
    FontMetrics fm = gc.getFontMetrics ( font );
    int nWidthInPixelsOfCurrentFont = fm.stringWidth ( str );

    return (float) nWidthInPixelsOfCurrentFont;
}


private float getHeightInPixelsOfString ( String string, float fontSize, Graphics gc )
{
    Font font = gc.getFont ().deriveFont ( fontSize );

    return getHeightInPixelsOfString ( string, font, gc );
}

private float getHeightInPixelsOfString ( String string, Font font, Graphics gc )
{
    FontMetrics metrics = gc.getFontMetrics ( font );
    int nHeightInPixelsOfCurrentFont = (int) metrics.getStringBounds ( string, gc ).getHeight () - metrics.getDescent () - metrics.getLeading ();

    return (float) nHeightInPixelsOfCurrentFont * .75f;
}

Sie können die Effizienz unter Verwendung eines binären Suchmuster verbessern - high / low mit einigen Granularität -. Entweder 1, 0,5 oder 0,25 Punkte

Zum Beispiel bei 18 erraten, zu hoch? Bewegen bis 9, zu niedrig? 13,5, zu niedrig? 15.75, zu hoch? 14!

Eine andere wäre offensichtliche Möglichkeit, den Text zu haben, auf einem Bitmap-Pre gezogen, und dann die Bitmap schrumpfen das Rechteck zu passen; aber wegen des handgearbeiteten Schriftdesigns und Hinting usw., die richtige Schriftgröße zu finden, erzeugt die am besten aussehende (wenn auch vielleicht nicht das schnellste) Ergebnis.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top