package org.expeditee.gio; import java.util.List; import org.expeditee.core.Font; import org.expeditee.core.Line; import org.expeditee.core.Point; import org.expeditee.core.TextHitInfo; import org.expeditee.core.TextLayout; import org.expeditee.core.bounds.AxisAlignedBoxBounds; /** TODO: Comment. cts16 */ public abstract class TextLayoutManager { public abstract List layoutString(String string, Font font, Point start, Line[] lineBreakers, int widthLimit, int lineSpacing, boolean dontBreakWords, boolean fullJustify); public List layoutStringRelative(String string, Font font, int widthLimit, int lineSpacing, boolean dontBreakWords, boolean fullJustify) { return layoutString(string, font, Point.ORIGIN.clone(), null, widthLimit, lineSpacing, dontBreakWords, fullJustify); } public TextLayout layoutStringSimple(String string, Font font) { List layouts = layoutStringRelative(string, font, Integer.MAX_VALUE, 0, true, false); if (layouts == null || layouts.size() == 0) return null; return layouts.get(0); } public abstract float getAdvance(TextLayout layout); public abstract int getCharacterCount(TextLayout layout); public abstract TextHitInfo getNextLeftHit(TextLayout layout, int offset); public abstract TextHitInfo getNextLeftHit(TextLayout layout, TextHitInfo hit); public abstract TextHitInfo getNextRightHit(TextLayout layout, int offset); public abstract TextHitInfo getNextRightHit(TextLayout layout, TextHitInfo hit); public abstract float[] getCaretInfo(TextLayout layout, TextHitInfo hit); public abstract AxisAlignedBoxBounds getPixelBounds(TextLayout layout, float x, float y); public abstract AxisAlignedBoxBounds getLogicalHighlightShape(TextLayout layout, int firstEndpoint, int secondEndpoint); public abstract float getAscent(TextLayout layout); public abstract float getDescent(TextLayout layout); public abstract float getLeading(TextLayout layout); public abstract int getStringWidth(Font font, String string); public abstract TextHitInfo hitTestChar(TextLayout layout, float x, float y); public abstract void releaseLayout(TextLayout layout); public void releaseLayouts(List layouts) { if (layouts == null) return; for (TextLayout layout : layouts) { releaseLayout(layout); } } /** * Calculates the maximum possible distance a line can extend to the right from a given point * without crossing any of the lines in the given array. * * @param p * The coordinates of the beginning point. * * @param lines * The lines that should stop the extension. * * @return * The length of the extended line. */ public float getLineWidth(Point p, Line[] lines) { float width = (float) Integer.MAX_VALUE; for(Line l : lines) { // check for lines that cross over our y if((l.getFirstEnd().getY() >= p.getY() && l.getSecondEnd().getY() <= p.getY()) || (l.getFirstEnd().getY() <= p.getY() && l.getSecondEnd().getY() >= p.getY())) { float dX = l.getFirstEnd().getX() - l.getSecondEnd().getX(); float dY = l.getFirstEnd().getY() - l.getSecondEnd().getY(); float newWidth; if(dX == 0) { newWidth = l.getFirstEnd().getX(); } else if(dY == 0) { newWidth = Math.min(l.getFirstEnd().getX(), l.getSecondEnd().getX()); } else { newWidth = l.getFirstEnd().getX() + (p.getY() - l.getFirstEnd().getY()) * dX / dY; } if(newWidth < p.getX()) { continue; } if(newWidth < width) { width = newWidth; } } } return width - p.getX(); } }