Results 1 to 4 of 4
  1. #1
    ozzyman's Avatar
    ozzyman is offline Senior Member
    Join Date
    Mar 2011
    Location
    London, UK
    Posts
    797
    Blog Entries
    2
    Rep Power
    4

    Default Need help calculating new line break width

    Please look at the for loop in this print method.

    I'm trying to find line breaks in a String of text that gets printed.
    Then wherever there's a line break, i need to measure the width:
    from start char position to line break char position
    and then set layout to the nextLayout of that width.

    At the moment all I can do is break too early & often.
    I think there's something wrong with the width calculation.

    Please have a look, any feedback would be greatly appreciated.

    Java Code:
        public int print(Graphics g, PageFormat pf, int page) throws PrinterException {
            if (page > 0) return NO_SUCH_PAGE;
     
            Graphics2D g2d = (Graphics2D)g;
            g2d.translate(pf.getImageableX()+mmToPixel(padLeft), pf.getImageableY());
     
            as = new AttributedString(msg);
            paragraph = as.getIterator();
            paragraphStart = paragraph.getBeginIndex();
            paragraphEnd = paragraph.getEndIndex();
            frc = g2d.getFontRenderContext();
            lineMeasurer = new LineBreakMeasurer(paragraph, frc);
            drawPosY = 0;
     
            lineMeasurer.setPosition(paragraphStart);
            while (lineMeasurer.getPosition() < paragraphEnd) {
                int startPosition = lineMeasurer.getPosition();
                TextLayout [COLOR=seagreen]layout[/COLOR] = lineMeasurer.nextLayout(breakWidth);
     
                [COLOR=red]for[/COLOR] (int i=startPosition; i<lineMeasurer.getPosition(); i++) {
                    if (msg.charAt(i) == '\n') {
                        lineMeasurer.setPosition(startPosition);
                        [COLOR=seagreen]layout[/COLOR] = lineMeasurer.nextLayout([COLOR=magenta]mmToPixel(i-startPosition)[/COLOR]);
                        break;
                    }
                }
     
                drawPosX = layout.isLeftToRight()? 0 : breakWidth - layout.getAdvance();
     
                drawPosY += layout.getAscent();
                layout.draw(g2d, drawPosX, drawPosY);
                drawPosY += layout.getDescent() + layout.getLeading();
            }
            return PAGE_EXISTS;
        }

    Java Code:
        private float mmToPixel(float mm) {
            return ((mm/10f)/2.54f)*72f;
        }

    Thanks.

  2. #2
    DarrylBurke's Avatar
    DarrylBurke is online now Forum Police
    Join Date
    Sep 2008
    Location
    Madgaon, Goa, India
    Posts
    11,415
    Rep Power
    20

    Default

    I've never really used those classes, but maybe you can glean something from this code I wrote about 2 years ago in response to someone else's problem.
    Java Code:
    import java.awt.*;
    import java.awt.font.*;
    import java.text.AttributedString;
    import java.util.ArrayList;
    import javax.swing.*;
    
    public class MultiLineText extends JComponent {
    
      private Font font = new Font("TimesRoman", Font.PLAIN, 12);
      private String[] breakText = {"John likes sweets.  Most of all, John likes icecream and chocolate.",
        "In contrast, Mary likes fruit.",
        "Especially bananas and strawberries."
      };
      private int wrapWidth = 110;
      private ArrayList<ArrayList<TextLayout>> layouts = new ArrayList<ArrayList<TextLayout>>();
      private TextLayout layout;
    
      public MultiLineText() {
        breakLines();
      }
    
      public void breakLines() {
        for (int j = 0; j < breakText.length; j++) {
          layouts.add(new ArrayList<TextLayout>());
    
          final AttributedString attStr = new AttributedString(breakText[j]);
          attStr.addAttribute(TextAttribute.FONT, font);
          final LineBreakMeasurer measurer =
                  new LineBreakMeasurer(attStr.getIterator(),
                  new FontRenderContext(null, true, true));
    
          while (null != (layout = measurer.nextLayout(wrapWidth))) {
            layouts.get(j).add(layout);
          }
        }
      }
    
      @Override
      public void paintComponent(Graphics g) {
        Graphics2D g2 = (Graphics2D) g;
        FontMetrics metrics = g2.getFontMetrics(font);
    
        int textHeight = metrics.getHeight();
        int left = textHeight; // only for symmetry, could be different
    
        for (int i = 0; i < layouts.size(); i++) {
          int top = textHeight;
          for (int j = 0; j < layouts.get(i).size(); j++) {
            layout = layouts.get(i).get(j);
            layout.draw(g2, left, top);
    
            top += textHeight;
          }
          left += wrapWidth + textHeight;
        }
      }
    
      public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
    
          @Override
          public void run() {
            JFrame frame = new JFrame("Multi Line Text");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setSize(600, 400);
            frame.setLocationRelativeTo(null);
            frame.setResizable(false);
    
            frame.add(new MultiLineText());
            frame.setVisible(true);
          }
        });
      }
    }
    db

  3. #3
    ozzyman's Avatar
    ozzyman is offline Senior Member
    Join Date
    Mar 2011
    Location
    London, UK
    Posts
    797
    Blog Entries
    2
    Rep Power
    4

    Default

    Without the for loop I get this print output:

    Menu 2 (4/0): [2] 15.60 Menu 14
    (9/0): [14] 124.41 GT: 140.01 (
    0.00)VOID: 0.00NET: 140.01

    I now changed the for loop to this (added FontMetrics):
    Java Code:
                for (int i=startPosition; i<lineMeasurer.getPosition(); i++) {
                    if (msg.charAt(i) == '\n') {
                        lineMeasurer.setPosition(startPosition);
                        FontMetrics metrics = g.getFontMetrics();
                        int width = metrics.stringWidth(msg.substring(startPosition, i));
                        layout = lineMeasurer.nextLayout(mmToPixel(width));
                        break;
                    }
                }
    and the print output was this:
    Menu 2 (4/0): [2] 15.60 Menu 13 (9/0):
    [13] 124.41 GT: 140.01 ( 0.00)
    VOID: 0.00NET: 140.01
    but i want the print output to come out like this:
    Menu 2 (4/0):
    [2] 15.60
    Menu 14 (9/0):
    [14] 124.41
    GT: 140.01 ( 0.00)
    VOID: 0.00
    NET: 140.01
    Last edited by ozzyman; 05-04-2011 at 01:55 PM.

  4. #4
    ozzyman's Avatar
    ozzyman is offline Senior Member
    Join Date
    Mar 2011
    Location
    London, UK
    Posts
    797
    Blog Entries
    2
    Rep Power
    4

    Default

    Thanks Darryl, I'll have a look... it looks good

    Edit:

    Ahh, I saw that you created a list of TextLayouts before hand and then used those.
    And then I realised it would've been so much easier to break the text before-hand like you did,
    each line into a new array, and each string in the array having its own TextLayout.

    Thanks so much...problem should be sorted in no time :)

    Edit:

    perfecto :)
    Last edited by ozzyman; 05-04-2011 at 02:18 PM.

Similar Threads

  1. Xml Rendering BASE64 break line problem
    By justinazz in forum XML
    Replies: 0
    Last Post: 01-05-2011, 04:46 PM
  2. array.width?
    By noobgrammer in forum New To Java
    Replies: 2
    Last Post: 07-01-2010, 02:35 AM
  3. How to set line width in Graphics object?
    By inc_123 in forum New To Java
    Replies: 8
    Last Post: 08-15-2009, 10:34 PM
  4. Line break for textlayout
    By Java Tip in forum java.awt
    Replies: 0
    Last Post: 06-25-2008, 10:32 AM
  5. Line break in tool tip..how??
    By sandor in forum AWT / Swing
    Replies: 1
    Last Post: 05-16-2007, 01:45 AM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •