Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
e244db203This file is pinned to the selected release. Download the original to open it in your design tool.
package controlP5;
/**
* controlP5 is a processing gui library.
*
* 2006-2012 by Andreas Schlegel
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307 USA
*
* @author Andreas Schlegel (http://www.sojamo.de)
* @modified 07/30/2015
* @version 2.2.5
*
*/
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import processing.core.PApplet;
import processing.core.PFont;
import processing.core.PGraphics;
/**
* A ControlFont is a container for a PFont that can be used to customize the font of a label.
* (Designing the Font handling gave me a big headache, especially when it comes to calculating the
* dimensions of a font which are not available at all times but only at certain times. The current
* status I suppose is a good compromise and works for standard font handling cases. For any special
* cases it will be difficult to convince me to make any changes.)
*
* @example extra/ControlP5controlFont
*/
public class ControlFont {
public static boolean DEBUG = false;
/**
* set the RENDER_2X variable to true to double render text, this makes the font look bolder
* especially in OpenGL mode. use: ControlFont.RENDER_2X = true;
*/
public static boolean RENDER_2X;
/**
* renders a PFont twice for better and sharper readability
*/
public static void sharp( ) {
RENDER_2X = true;
}
/**
* sets the rendering of a PFont back to normal and single rendering.
*/
public static void normal( ) {
RENDER_2X = false;
}
PFont pfont;
List< String > txt;
String s = "";
private int top;
private int bottom;
private int center;
private int height;
private int width;
private int baseline = 0;
private int _myTextHeight = 1;
private int[] offset = new int[ 2 ];
private int size;
public ControlFont( PFont theFont ) {
this( theFont , checkFontSize( theFont ) );
}
public ControlFont( PFont theFont , int theFontSize ) {
this( theFont , theFontSize , theFontSize + 2 );
}
public ControlFont( PFont theFont , int theFontSize , int theLineHeight ) {
pfont = theFont;
size = theFontSize;
txt = new ArrayList< String >( );
}
static private int checkFontSize( PFont theFont ) {
try {
// was: return theFont.getFont().getSize(); but disappeared with p5 2.0b1
return theFont.getSize( );
} catch ( NullPointerException e ) {
System.out.println( "ControlP5: could not find font-size details for font " + theFont.getName( ) + ", use constructor ControlFont(PFont theFont, int theFontSize) to specify the font size." );
return 10;
}
}
public void init( Label theLabel ) {
// when the font changes, init is called.
// width and height should be adjusted to the updated font here,
// but we need PApplet here to determine the width of the label.
// unfortunately we dont have access to PApplet here, so a change
// might result in a 1-frame-flickr but doesnt necessarily need
// to happen.
}
public void setSize( int theSize ) {
size = theSize;
}
public int getSize( ) {
/* quickfix http://code.google.com/p/controlp5/issues/detail?id=46 first check the pfont
* size then default back to size */
return size;
}
public int getOffset( int theIndex ) {
return offset[ theIndex ];
}
public int getTextHeight( ) {
return _myTextHeight;
}
public int getWidth( ) {
return width;
}
public int getHeight( ) {
return height;
}
public int getCenter( ) {
return center;
}
public int getTop( ) {
return top;
}
public int getBottom( ) {
return bottom;
}
public int getBaseline( ) {
return baseline;
}
public PFont getFont( ) {
return pfont;
}
public void adjust( PGraphics theGraphics , Label theLabel ) {
if ( theLabel.isChanged( ) ) {
theGraphics.textFont( pfont , size );
// the origin of a PFont Label is top left corner, therefore
// the following the following measures have to be calculated
// when a font is changed. we have to do that here since PApplet
// is required to calculate a font's ascent and descent value.
// values are calculated based on the baseline (which is 0),
// therefore center and top are negative values.
// to order to sync the line height with the height of the font,
// the value of lineHeightOffset carries this offset value.
// This becomes necessary when working with multiple lines.
top = -( int ) theGraphics.textAscent( );
bottom = ( int ) theGraphics.textDescent( );
center = -( int ) ( ( -top - bottom ) / 2 );
height = theLabel.isMultiline( ) ? theLabel.getHeight( ) : ( int ) ( theGraphics.textAscent( ) + theGraphics.textDescent( ) );
width = theLabel.isMultiline( ) ? theLabel.getWidth( ) : ( int ) theGraphics.textWidth( theLabel.getTextFormatted( ) );
if ( theLabel.isMultiline( ) ) {
calculateHeight( theGraphics , theLabel );
}
theLabel.setChanged( false );
}
}
private void calculateHeight( PGraphics theGraphics , Label theLabel ) {
txt.clear( );
String myString = theLabel.getTextFormatted( );
List< String > paragraphs = Arrays.asList( myString.split( "\n" ) );
// does not recognize linebreaks at the end of theString.
myString = "";
for ( String p : paragraphs ) {
List< String > words = Arrays.asList( p.split( "\\s" ) );
for ( String w : words ) {
if ( theGraphics.textWidth( myString + w ) < width ) {
myString += w + " ";
} else {
txt.add( myString.substring( 0 , PApplet.max( 0 , myString.length( ) - 1 ) ) );
myString = w + " ";
}
}
txt.add( myString.substring( 0 , myString.length( ) - 1 ) );
myString = "";
}
if ( theLabel.getHeight( ) % theLabel.getLineHeight( ) != 0 ) {
txt.add( "" );
}
_myTextHeight = ( PApplet.round( txt.size( ) * theLabel.getLineHeight( ) ) );
int maxLineNum = PApplet.round( theLabel.getHeight( ) / theLabel.getLineHeight( ) );
int offset = ( int ) ( PApplet.max( 0 , txt.size( ) - maxLineNum ) * ( PApplet.abs( theLabel.getOffsetYratio( ) ) ) );
int lim = PApplet.min( txt.size( ) , maxLineNum );
s = "";
for ( int i = 0 ; i < lim ; i++ ) {
s += txt.get( i + offset ) + "\n";
}
}
public int getOverflow( ) {
return ( _myTextHeight - height );
}
public void draw( ControlP5 c , Label theLabel ) {
draw( c.pg , theLabel );
}
public void draw( PGraphics theGraphics , Label theLabel ) {
PFont loadedFont = theGraphics.textFont;
float loadedSize = theGraphics.textSize;
if ( loadedFont == null ) {
theGraphics.textSize( loadedSize ); // forces default font
loadedFont = theGraphics.textFont;
}
int loadedAlign = theGraphics.textAlign;
theGraphics.textFont( pfont , size );
theGraphics.textAlign( theLabel.textAlign );
theGraphics.fill( theLabel.getColor( ) );
if ( theLabel.isMultiline( ) ) {
theGraphics.fill( theLabel.getColor( ) );
theGraphics.textLeading( theLabel.getLineHeight( ) );
theGraphics.text( s , 0 , 0 , theLabel.getWidth( ) , theLabel.getHeight( ) );
} else {
theGraphics.translate( 0 , -top + 1 );
debug( theGraphics , theLabel );
theGraphics.fill( theLabel.getColor( ) );
theGraphics.textLeading( theLabel.getLineHeight( ) );
theGraphics.text( theLabel.getTextFormatted( ) , 0 , 0 );
if ( RENDER_2X ) {
theGraphics.text( theLabel.getTextFormatted( ) , 0 , 0 );
}
}
theGraphics.textFont( loadedFont , loadedSize );
theGraphics.textAlign( loadedAlign );
}
private void debug( PGraphics theGraphics , Label theLabel ) {
if ( DEBUG ) {
theGraphics.stroke( 0 , 255 , 0 ); // BASELINE
theGraphics.line( 0 , getBaseline( ) , theGraphics.textWidth( theLabel.getText( ) ) , getBaseline( ) );
theGraphics.stroke( 0 , 0 , 255 ); // TOP
theGraphics.line( 0 , getTop( ) , theGraphics.textWidth( theLabel.getText( ) ) , getTop( ) );
theGraphics.stroke( 255 , 255 , 0 ); // BOTTOM
theGraphics.line( 0 , getBottom( ) , theGraphics.textWidth( theLabel.getText( ) ) , getBottom( ) );
theGraphics.stroke( 255 , 0 , 0 ); // CENTER
theGraphics.line( 0 , getCenter( ) , theGraphics.textWidth( theLabel.getText( ) ) , getCenter( ) );
theGraphics.stroke( 255 , 128 , 0 ); // CENTER_CAPS
theGraphics.line( 0 , getTop( ) / 2 , theGraphics.textWidth( theLabel.getText( ) ) , getTop( ) / 2 );
theGraphics.noStroke( );
}
}
public static int getWidthFor( String theText , Label theLabel , PGraphics theGraphics ) {
theGraphics.textFont( theLabel.getFont( ).pfont , theLabel.getFont( ).size );
return ( int ) theGraphics.textWidth( theText );
}
}
// textorize, a Ruby-based font rasterizer command line utility for Mac OS X
// http://textorize.org/