/******************************************************************************* * Copyright (c) 2007, 2014 Innoopract Informationssysteme GmbH and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Innoopract Informationssysteme GmbH - initial API and implementation * EclipseSource - ongoing development ******************************************************************************/ package org.eclipse.rap.rwt.internal.textsize; import org.eclipse.rap.rwt.internal.service.ContextProvider; import org.eclipse.rap.rwt.internal.service.ServiceStore; import org.eclipse.rap.rwt.internal.util.EncodingUtil; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.FontData; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.internal.graphics.FontUtil; public class TextSizeUtil { static final int STRING_EXTENT = 0; static final int TEXT_EXTENT = 1; static final int MARKUP_EXTENT = 2; public static Point stringExtent( Font font, String string, boolean markup ) { if( markup ) { return determineTextSize( font, string, SWT.DEFAULT, MARKUP_EXTENT ); } return stringExtent( font, string ); } public static Point stringExtent( Font font, String string ) { if( isEmptyString( string ) ) { return createSizeForEmptyString( font ); } return determineTextSize( font, string, SWT.DEFAULT, STRING_EXTENT ); } public static Point textExtent( Font font, String text, int wrapWidth, boolean markup ) { if( markup ) { return determineTextSize( font, text, wrapWidth, MARKUP_EXTENT ); } return textExtent( font, text, wrapWidth ); } public static Point textExtent( Font font, String text, int wrapWidth ) { return determineTextSize( font, text, wrapWidth, TEXT_EXTENT ); } public static int getCharHeight( Font font ) { int result; if( containsProbeResult( font ) ) { result = lookupCharHeight( font ); } else { result = estimateCharHeight( font ); addProbeToMeasure( font ); } return result; } public static float getAvgCharWidth( Font font ) { float result; if( containsProbeResult( font ) ) { result = lookupAvgCharWidth( font ); } else { result = estimateAvgCharWidth( font ); addProbeToMeasure( font ); } return result; } public static boolean isTemporaryResize() { ServiceStore serviceStore = ContextProvider.getServiceStore(); Object attribute = serviceStore.getAttribute( TextSizeRecalculation.TEMPORARY_RESIZE ); return Boolean.TRUE.equals( attribute ); } ////////////////// // Helping methods private static Point createSizeForEmptyString( Font font ) { return new Point( 0, getCharHeight( font ) ); } private static boolean isEmptyString( String string ) { return string.length() == 0; } private static Point determineTextSize( Font font, String string, int wrapWidth, int mode ) { int normalizedWrapWidth = normalizeWrapWidth( wrapWidth ); Point result = lookup( font, string, normalizedWrapWidth, mode ); if( result == null ) { result = estimate( font, string, normalizedWrapWidth, mode ); if( !isTemporaryResize() ) { addItemToMeasure( font, string, normalizedWrapWidth, mode ); } } // TODO [rst] Still returns wrong result for texts that contain only // whitespace (and possibly more that one line) if( isHeightZero( result ) ) { result = adjustHeightForWhitespaceTexts( font, result ); } return result; } private static int normalizeWrapWidth( int wrapWidth ) { return wrapWidth <= 0 ? SWT.DEFAULT : wrapWidth; } private static boolean isHeightZero( Point result ) { return result.y == 0; } private static Point lookup( Font font, String string, int wrapWidth, int mode ) { String measurementString = createMeasurementString( string, mode ); FontData fontData = FontUtil.getData( font ); return TextSizeStorageUtil.lookup( fontData, measurementString, wrapWidth, mode ); } private static Point estimate( Font font, String string, int wrapWidth, int mode ) { Point result; switch( mode ) { case STRING_EXTENT: { result = TextSizeEstimation.stringExtent( font, string ); } break; case TEXT_EXTENT: { result = TextSizeEstimation.textExtent( font, string, wrapWidth ); } break; case MARKUP_EXTENT: { result = TextSizeEstimation.markupExtent( font, string, wrapWidth ); } break; default: { throw new IllegalStateException( "Unknown estimation mode." ); } } return result; } private static void addItemToMeasure( Font font, String string, int wrapWidth, int mode ) { String measurementString = createMeasurementString( string, mode ); MeasurementUtil.addItemToMeasure( measurementString, font, wrapWidth, mode ); } private static String createMeasurementString( String string, int mode ) { return mode == STRING_EXTENT ? EncodingUtil.replaceNewLines( string, " " ) : string; } private static Point adjustHeightForWhitespaceTexts( Font font, Point result ) { return new Point( result.x, getCharHeight( font ) ); } private static void addProbeToMeasure( Font font ) { MeasurementUtil.getMeasurementOperator().addProbeToMeasure( FontUtil.getData( font ) ); } private static int estimateCharHeight( Font font ) { return TextSizeEstimation.getCharHeight( font ); } private static int lookupCharHeight( Font font ) { return getProbeResult( font ).getSize().y; } private static boolean containsProbeResult( Font font ) { return ProbeResultStore.getInstance().containsProbeResult( FontUtil.getData( font ) ); } private static float estimateAvgCharWidth( Font font ) { return TextSizeEstimation.getAvgCharWidth( font ); } private static float lookupAvgCharWidth( Font font ) { return getProbeResult( font ).getAvgCharWidth(); } private static ProbeResult getProbeResult( Font font ) { FontData data = FontUtil.getData( font ); return ProbeResultStore.getInstance().getProbeResult( data ); } private TextSizeUtil() { // prevent instance creation } }