Download
Getting Started
Members
Projects
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
More
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
Toggle navigation
Bugzilla – Attachment 283698 Details for
Bug 565537
hotswap crashes JVM (bad stackmap)
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
Log In
[x]
|
Terms of Use
|
Copyright Agent
Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read
this important communication.
EclipseHotswapCrash.java: has Java method that crashes when hotswapped.
EclipseHotswapCrash.java (text/plain), 9.43 KB, created by
Nathan Sweet
on 2020-07-25 07:23:33 EDT
(
hide
)
Description:
EclipseHotswapCrash.java: has Java method that crashes when hotswapped.
Filename:
MIME Type:
Creator:
Nathan Sweet
Created:
2020-07-25 07:23:33 EDT
Size:
9.43 KB
patch
obsolete
> >import java.util.ArrayList; > >public class EclipseHotswapCrash { > static public void main (String[] args) throws Exception { > BitmapFont font = new BitmapFont(); > GlyphLayout layout = new GlyphLayout(); > Color color = new Color(); > layout.setText(font, "ab", 0, 2, color, 100, 0, true, null); > } > > static public class GlyphLayout { > static private final Pool<GlyphRun> glyphRunPool = new Pool(GlyphRun.class); > static private final Pool<Color> colorPool = new Pool(Color.class); > static private final ArrayList<Color> colorStack = new ArrayList(4); > > public final ArrayList<GlyphRun> runs = new ArrayList(1); > public float width, height; > > public void setText (BitmapFont font, CharSequence str, int start, int end, Color color, float targetWidth, int halign, > boolean wrap, String truncate) { > > if (str.equals("ab")) // > System.out.println(); // Set breakpoint here, modify "ab" -> "abc", save, hotswap crashes. > > ArrayList<GlyphRun> runs = this.runs; > glyphRunPool.freeAll(runs); > runs.clear(); > > BitmapFontData fontData = font.data; > if (start == end) { // Empty string. > width = 0; > height = fontData.capHeight; > return; > } > > if (truncate != null) > wrap = true; // Ensures truncate code runs, doesn't actually cause wrapping. > else if (targetWidth <= fontData.spaceXadvance * 3) // > wrap = false; // Avoid one line per character, which is very inefficient. > > Color nextColor = color; > boolean markupEnabled = fontData.markupEnabled; > if (markupEnabled) { > for (int i = 1, n = colorStack.size(); i < n; i++) > colorPool.free(colorStack.get(i)); > colorStack.clear(); > colorStack.add(color); > } > > float x = 0, y = 0, down = fontData.down; > Glyph lastGlyph = null; > int runStart = start; > outer: > while (true) { > // Each run is delimited by newline or left square bracket. > int runEnd = -1; > boolean newline = false; > if (start == end) { > if (runStart == end) break; // End of string with no run to process, we're done. > runEnd = end; // End of string, process last run. > } else { > switch (str.charAt(start++)) { > case '\n': > // End of line. > runEnd = start - 1; > newline = true; > break; > case '[': > // Possible color tag. > if (markupEnabled) { > int length = 0; > if (length >= 0) { > runEnd = start - 1; > start += length + 1; > nextColor = colorStack.get(colorStack.size() - 1); > } else if (length == -2) { > start++; // Skip first of "[[" escape sequence. > continue outer; > } > } > break; > } > } > > if (runEnd != -1) { > runEnded: > if (runEnd != runStart) { // Eg, when a color tag is at text start or a line is "\n". > // Store the run that has ended. > GlyphRun run = glyphRunPool.obtain(); > run.color.set(color); > fontData.getGlyphs(run, str, runStart, runEnd, lastGlyph); > if (run.glyphs.size() == 0) { > glyphRunPool.free(run); > break runEnded; > } > if (lastGlyph != null) { // Move back the width of the last glyph from the previous run. > x -= lastGlyph.fixedWidth ? lastGlyph.xadvance * fontData.scaleX > : (lastGlyph.width + lastGlyph.xoffset) * fontData.scaleX - fontData.padRight; > } > lastGlyph = run.glyphs.get(run.glyphs.size() - 1); > run.x = x; > run.y = y; > if (newline || runEnd == end) adjustLastGlyph(fontData, run); > runs.add(run); > > int n = run.xAdvances.size(); > if (!wrap || n == 0) break runEnded; // No wrap or truncate, or no glyphs. > > // Wrap or truncate. > ArrayList<Float> xAdvances = run.xAdvances; > x += xAdvances.get(0) + xAdvances.get(1); // X offset relative to the drawing position + first xAdvance. > for (int i = 2; i < n; i++) { > Glyph glyph = run.glyphs.get(i - 1); > float glyphWidth = (glyph.width + glyph.xoffset) * fontData.scaleX - fontData.padRight; > if (x + glyphWidth <= targetWidth) { > // Glyph fits. > x += xAdvances.get(i); > continue; > } > > if (truncate != null) { > // Truncate. > truncate(fontData, run, targetWidth, truncate, i, glyphRunPool); > break outer; > } > > // Wrap. > int wrapIndex = fontData.getWrapIndex(run.glyphs, i); > if ((wrapIndex == 0 && run.x == 0) // Require at least one glyph per line. > || wrapIndex >= run.glyphs.size()) { // Wrap at least the glyph that didn't fit. > wrapIndex = i - 1; > } > GlyphRun next; > if (wrapIndex == 0) { // Move entire run to next line. > next = run; > > // Remove leading whitespace. > for (int glyphCount = run.glyphs.size(); wrapIndex < glyphCount; wrapIndex++) > if (!fontData.isWhitespace((char)run.glyphs.get(wrapIndex).id)) break; > if (wrapIndex > 0) { > for (int ii = 0; ii < wrapIndex - 1; ii++) > run.glyphs.remove(0); > for (int ii = 0; ii < wrapIndex - 1; ii++) > run.xAdvances.remove(1); > } > xAdvances.set(0, -run.glyphs.get(0).xoffset * fontData.scaleX - fontData.padLeft); > > if (runs.size() > 1) { // Previous run is now at the end of a line. > // Remove trailing whitespace and adjust last glyph. > GlyphRun previous = runs.get(runs.size() - 2); > int lastIndex = previous.glyphs.size() - 1; > for (; lastIndex > 0; lastIndex--) > if (!fontData.isWhitespace((char)previous.glyphs.get(lastIndex).id)) break; > while (previous.glyphs.size() > lastIndex + 1) > previous.glyphs.remove(previous.glyphs.size() - 1); > while (previous.xAdvances.size() > lastIndex + 1) > previous.xAdvances.remove(previous.xAdvances.size() - 1); > adjustLastGlyph(fontData, previous); > } > } else { > next = wrap(fontData, run, wrapIndex, i); > if (next == null) { // All wrapped glyphs were whitespace. > x = 0; > y += down; > lastGlyph = null; > break; > } > runs.add(next); > } > > // Start the loop over with the new run on the next line. > n = next.xAdvances.size(); > xAdvances = next.xAdvances; > x = xAdvances.get(0); > if (n > 1) x += xAdvances.get(1); > y += down; > next.x = 0; > next.y = y; > i = 1; > run = next; > lastGlyph = null; > } > } > > runStart = start; > color = nextColor; > } > } > } > > /** @param truncate May be empty string. */ > private void truncate (BitmapFontData fontData, GlyphRun run, float targetWidth, String truncate, int widthIndex, > Pool<GlyphRun> glyphRunPool) { > } > > /** Breaks a run into two runs at the specified wrapIndex. > * @return May be null if second run is all whitespace. */ > private GlyphRun wrap (BitmapFontData fontData, GlyphRun first, int wrapIndex, int widthIndex) { > return first; > } > > /** Adjusts the xadvance of the last glyph to use its width instead of xadvance. */ > private void adjustLastGlyph (BitmapFontData fontData, GlyphRun run) { > Glyph last = run.glyphs.get(run.glyphs.size() - 1); > if (last.fixedWidth) return; > float width = (last.width + last.xoffset) * fontData.scaleX - fontData.padRight; > run.xAdvances.set(run.xAdvances.size() - 1, width); > } > > /** Stores glyphs and positions for a piece of text which is a single color and does not span multiple lines. > * @author Nathan Sweet */ > static public class GlyphRun { > public ArrayList<Glyph> glyphs = new ArrayList(); > /** Contains glyphs.size+1 entries: First entry is X offset relative to the drawing position. Subsequent entries are the > * X advance relative to previous glyph position. Last entry is the width of the last glyph. */ > public ArrayList<Float> xAdvances = new ArrayList(); > public float x, y, width; > public final Color color = new Color(); > } > } > > static public class BitmapFont { > public BitmapFontData data = new BitmapFontData(); > } > > static public class BitmapFontData { > public float capHeight; > public int spaceXadvance; > public boolean markupEnabled; > public float down; > public float scaleX = 1; > public int padRight; > public int padLeft; > public float blankLineScale; > > public void getGlyphs (GlyphLayout.GlyphRun run, CharSequence str, int runStart, int runEnd, Glyph lastGlyph) { > run.xAdvances.add(1f); > for (int i = 0, n = str.length(); i < n; i++) { > run.xAdvances.add(16f); > run.glyphs.add(new Glyph(str.charAt(i))); > } > } > > public int getWrapIndex (ArrayList<Glyph> glyphs, int i) { > return i; > } > > public boolean isWhitespace (char id) { > return false; > } > } > > static public class Color { > public void set (Color color) { > } > } > > static public class Glyph { > public int id; > public int srcX; > public int srcY; > public int width = 16, height = 16; > public float u, v, u2, v2; > public int xoffset, yoffset; > public int xadvance = 16; > public byte[][] kerning; > public boolean fixedWidth; > > public Glyph (int id) { > this.id = id; > } > } > > static public class Pool<T> { > private Class<T> type; > > public Pool (Class<T> type) { > this.type = type; > } > > public void freeAll (ArrayList<T> runs) { > } > > public void free (T color) { > } > > public T obtain () { > try { > return type.newInstance(); > } catch (Exception ex) { > throw new RuntimeException(ex); > } > } > } >}
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 565537
: 283698 |
283699
|
283700
|
283702
|
283765