Improvement for TextSize Estimation? [message #1739729] |
Thu, 04 August 2016 11:55 |
Gunnar Adams Messages: 49 Registered: May 2016 |
Member |
|
|
Hi,
our application uses a LOT of dynamically generated texts (in TabFolders, Labels, etc.).
Although the textsize determination logic works quite well, this leads to some wrong layouts which are not always corrected as soon as the text size of the respective object has been calculated on the client size.
In my opinion, a better estimate could be calculated by using AWT fonts and FontMetrics.stringWidth(). This should approximate the actual result on the client-side more closely than a multiplication of an average character width by the length of the string.
I understand, that this approach probably isn't something that should make it into RWT in general, but wouldn't it be possible to make the calls into the TextSizeEstimation class pluggable, i.e. generate an interface and a setter for the TextSizeEstimation implementation to be used in TextSizeUtil?
My suggestion would be something along the following lines:
In TextSizeEstimation.java:
/**
* Returns the width of a given string in pixels. Line breaks are ignored.
*/
private static int getLineWidth( String line, Font font ) {
if (lwest != null) {
return lwest.estimateLineWidth(line, font);
} else {
return Math.round( getAvgCharWidth( font ) * line.length() );
}
}
private static ILineWidthEstimator lwest = null;
public static void setLineWidthEstimator(ILineWidthEstimator lwest) {
TextSizeEstimation.lwest = lwest;
}
New interface:
package org.eclipse.rap.rwt.internal.textsize;
import org.eclipse.swt.graphics.Font;
public interface ILineWidthEstimator {
public int estimateLineWidth(String line, Font font );
}
and the implementation:
package com.surecomp.sdos.rwtclient.swt.utils;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.util.StringTokenizer;
import org.eclipse.rap.rwt.internal.textsize.ILineWidthEstimator;
import org.eclipse.swt.graphics.Device;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
public class LineWidthEstimatorImpl implements ILineWidthEstimator {
public static BufferedImage img = new BufferedImage(1,1,BufferedImage.TYPE_4BYTE_ABGR);
public LineWidthEstimatorImpl() {
}
@Override
public int estimateLineWidth(String line, Font font) {
// TODO Auto-generated method stub
FontData[] fontdata = font.getFontData();
java.awt.Font awtfont = toAwtFont(font.getDevice(), fontdata[0], true);
Graphics2D g = (Graphics2D) img.getGraphics();
g.setFont(awtfont);
return g.getFontMetrics().stringWidth(line);
}
public static java.awt.Font toAwtFont(Device device, FontData fontData,
boolean ensureSameSize) {
int height = (int) Math.round(fontData.getHeight());
StringTokenizer st = new StringTokenizer(fontData.getName(), ",");
return new java.awt.Font(st.nextToken(), fontData.getStyle(),
height);
}
}
This seems to work quite well, although the limitation to the first name in the CSS font name list, of course, may cause problems on systems, which do not have the exact same font installed.
Thank you very much for your comments and ideas.
Best regards,
Gunnar
[Updated on: Thu, 04 August 2016 11:57] Report message to a moderator
|
|
|
|
Re: Improvement for TextSize Estimation? [message #1740068 is a reply to message #1739731] |
Mon, 08 August 2016 20:48 |
|
I just ran across this timely post about a different approach to the same problem[1]. The idea that I found interesting was to assign a relative width to each letter. Thus the letter 'f' gets assigned a much smaller value than 'm', etc. This seems like a good heuristic to improve the accuracy of the initial estimate. Obviously you could go to the extreme of pre-computing for every font, but I think it would be enough of an improvement to just pre-compute an average across all non-fixed-width fonts.
[1] https://dev.to/ben/determining-the-width-of-a-string
Cole Markham
|
|
|
Powered by
FUDForum. Page generated in 0.03387 seconds