eclipse-platform / eclipse.platform.swt

Eclipse SWT
https://www.eclipse.org/swt/
Eclipse Public License 2.0
113 stars 132 forks source link

TextLayout Produces Wrong Lines for '\r\n' #184

Open tsmaeder opened 2 years ago

tsmaeder commented 2 years ago

Descritption

When having a sequence of `\r\n\r\n' and a style range that intersects the line break, TextLayout produces too many lines.

The sequence `some text\r\n\r\nmore text? should produce a single empty line between the two text lines, but it produces two empty lines if the style range is set appropriately.

To Reproduce Run the example below:

Example Snippet ``` / * Copyright (c) 2000, 2016 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at * https://www.eclipse.org/legal/epl-2.0/ * * SPDX-License-Identifier: EPL-2.0 * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.swt.snippets; /* * TextLayout example snippet: text with underline and strike through * * For a list of all SWT example snippets see * http://www.eclipse.org/swt/snippets/ * * @since 3.1 */ import org.eclipse.swt.*; import org.eclipse.swt.graphics.*; import org.eclipse.swt.widgets.*; public class Snippet256a { private static FontData[] getFontData(Font font, int style) { FontData[] fontDatas = font.getFontData(); for (FontData fontData : fontDatas) { fontData.setStyle(style); } return fontDatas; } public static void main(String[] args) { Display display = new Display(); final Shell shell = new Shell(display, SWT.SHELL_TRIM | SWT.DOUBLE_BUFFERED); shell.setText("Underline, Strike Out"); String text = "Here is \r\n\r\nsome text that is \r\nunderlined or struck out or both."; FontData[] fontData = getFontData(shell.getFont(), SWT.BOLD); Font font = new Font(shell.getDisplay(), fontData); final TextLayout layout = new TextLayout(display); layout.setText(text); TextStyle style1 = new TextStyle(font, null, null); layout.setStyle(style1, 0, 10); int[] offsets = layout.getLineOffsets(); System.out.println(offsets.length); shell.addListener(SWT.Paint, event -> { Point point = new Point(10, 10); int width = shell.getClientArea().width - 2 * point.x; layout.setWidth(width); layout.draw(event.gc, point.x, point.y); }); shell.open(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) display.sleep(); } layout.dispose(); display.dispose(); } } ```

Environment:

tsmaeder commented 2 years ago

My suspicion is that when the style range changes (from bold to normal) between the \r and \r characters, the ScriptItemize function returns two items (because "runs" must be in the same font) and we're not properly handling that case.

niraj-modi commented 2 years ago

My suspicion is that when the style range changes (from bold to normal) between the \r and \r characters, the ScriptItemize function returns two items (because "runs" must be in the same font) and we're not properly handling that case.

IMO, results from ScriptItemize function is not that incorrect. Say instead of font(from bold to normal) user may have different font sizes(from 100 to normal) between \r and \n characters, which kind of justifies the current behavior of ScriptItemize function.

Test Snippet with different font-size ``` /* Copyright (c) 2000, 2016 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at * https://www.eclipse.org/legal/epl-2.0/ * * SPDX-License-Identifier: EPL-2.0 * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.swt.snippets; /* * TextLayout example snippet: text with underline and strike through * * For a list of all SWT example snippets see * http://www.eclipse.org/swt/snippets/ * * @since 3.1 */ import org.eclipse.swt.*; import org.eclipse.swt.graphics.*; import org.eclipse.swt.widgets.*; public class SWTIssue184 { private static FontData[] getFontData(Font font, int style) { FontData[] fontDatas = font.getFontData(); for (FontData fontData : fontDatas) { fontData.setStyle(style); } return fontDatas; } public static void main(String[] args) { Display display = new Display(); final Shell shell = new Shell(display, SWT.SHELL_TRIM | SWT.DOUBLE_BUFFERED); shell.setText("SWTIssue184"); String text = "HeaderText:\r\nNormalText"; FontData[] fontData = getFontData(shell.getFont(), SWT.NORMAL); fontData[0].setHeight(100); Font font = new Font(shell.getDisplay(), fontData); final TextLayout layout = new TextLayout(display); layout.setText(text); TextStyle style1 = new TextStyle(font, null, null); layout.setStyle(style1, 0, text.indexOf('\r')); int[] offsets = layout.getLineOffsets(); System.out.println(offsets.length); shell.addListener(SWT.Paint, event -> { Point point = new Point(10, 10); int width = shell.getClientArea().width - 2 * point.x; layout.setWidth(width); layout.draw(event.gc, point.x, point.y); }); shell.open(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) display.sleep(); } layout.dispose(); display.dispose(); } } ```
tsmaeder commented 2 years ago

@niraj-modi I'm not questioning the result of the ScriptItemize function, I'm questioning the handling of it in the TextLayout class: clearly, \r\n should not result in starting a new line twice, but only once.

deepika-u commented 2 months ago

@tsmaeder : can you test this issue now with the pr and let us know please?