/** * Handle the closing of a tag. * * @param g Graphics used to retrieve the font metrics. * @param tag The closing tag without '</' and '>'. * @return A new TextToken corresponding to the new state. */ private TextToken closeTag(Graphics g, String tag) { TextToken textTok = new TextToken(); int i = m_heap.size() - 1; char c = tag.charAt(0); String prevTag; m_heap.removeElement(tag); if (c == 'b') m_style &= ~Font.BOLD; else if (c == 'i') m_style &= ~Font.ITALIC; if (isGfx(c)) { while (i-- > 0) { // find previous Tag of the same type in the heap prevTag = (String) m_heap.elementAt(i); if (prevTag.charAt(0) == c) { return updateGfx(g, prevTag); } } } textTok.m_font = new Font(m_name, m_style, m_size); g.setFont(textTok.m_font); return textTok; }
/** * Process this text Token to optimize tokens and evaluate the token bounding box. * * @param g Graphics to get the font metrics. * @param text Text to add to the current textTokan. * @param textTok Current TextToken. * @param isText True if the previous textToken was a Text Token so we can merge it with this. */ private void updateText(Graphics g, String text, TextToken textTok, boolean isText) { // The text exists! if (text.length() > 0) { FontMetrics fm = g.getFontMetrics(); int a = fm.getAscent(), d = fm.getDescent(), w = fm.stringWidth(text), h = fm.getHeight(); // The previous token was a text too so we must merge it with this new one. if (isText) { textTok = (TextToken) m_tokens.lastElement(); textTok.m_text += text; textTok.m_bounds.width += w; if (textTok.m_bounds.height < h) textTok.m_bounds.height = h; } // The previous token was a formating one. else { m_tokens.addElement(textTok); textTok.m_text = text; textTok.m_bounds = new Rectangle(0, 0, w, h); } if (a > m_body.m_aMax) m_body.m_aMax = a; if (d > m_body.m_dMax) m_body.m_dMax = d; m_wCur += w; } }
/** * Draws this at a position. * * @param g Graphics to draw in. * @param size Size of the Window to draw in. * @param pos Where to draw this. */ protected void drawText(Graphics gi, Dimension size, Point pos) { Graphics2D g = (Graphics2D) gi; g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); TextToken textTok; int i, n = m_tokens.size(); if (m_inCol != null) { // TODO gérer le gradient dans les swatchs // GradientPaint gradient = new GradientPaint(pos.x, pos.y, m_inCol , pos.x, pos.y + // m_bounds.height*2, Color.black ); // g.setPaint( gradient ); g.setColor(m_inCol); if (m_rounded == -1) g.fillRect(pos.x, pos.y, m_bounds.width, m_bounds.height); else g.fillRoundRect(pos.x, pos.y, m_bounds.width, m_bounds.height, m_rounded, m_rounded); } if (m_outCol != null) { // GradientPaint gradient = new GradientPaint(0, 0, m_inCol, 0, m_bounds.height, Color.black // ); // g.setPaint( gradient ); g.setColor(m_outCol); if (m_rounded == -1) g.drawRect(pos.x, pos.y, m_bounds.width, m_bounds.height); else g.drawRoundRect(pos.x, pos.y, m_bounds.width, m_bounds.height, m_rounded, m_rounded); } for (i = 0; i < n; i++) { textTok = (TextToken) m_tokens.elementAt(i); textTok.paint(g, pos); } if (false) // n==1 && m_inCol == null) // draw reflection only for one line boxes { Composite cb = g.getComposite(); Composite composite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.2f); g.setComposite(composite); g.setColor(Color.white); g.fillRoundRect(pos.x + 2, pos.y + 2, m_bounds.width - 4, m_bounds.height / 3, 5, 5); g.setComposite(cb); } m_bounds.x = pos.x; m_bounds.y = pos.y; }
/** * Creates a TextToken using a graphical tag. Such a tag is color or font related. * * @param g Graphics used to retrieve the font metrics. * @param tag A pseudo HTML tag without '<', '</' and '>'. * @return a new TextToken initialized according to the tag. */ private TextToken updateGfx(Graphics g, String tag) { TextToken textTok = new TextToken(); if (tag.startsWith("c=") || tag.startsWith("k=")) { Color color = tag.startsWith("c=") ? textTok.m_color : textTok.m_bkCol; int rgb = 0; textTok.m_font = new Font(m_name, m_style, m_size); g.setFont(textTok.m_font); try { rgb = Integer.decode(tag.substring(2)).intValue(); // #RRGGBB if (color == null || color.getRGB() == rgb) { if (tag.startsWith("c=")) { m_color = rgb; textTok.m_color = new Color(rgb); textTok.m_bkCol = m_bkCol != -1 ? new Color(m_bkCol) : null; } else { m_bkCol = rgb; textTok.m_bkCol = new Color(rgb); textTok.m_color = new Color(m_color); } } } catch (NumberFormatException e) { System.out.println("[updateTag] Wrong color format : " + tag); return null; } } else { textTok.m_color = new Color(m_color); if (tag.equals("b")) { m_style |= Font.BOLD; } else if (tag.equals("i")) { m_style |= Font.ITALIC; } else if (tag.startsWith("s=")) { m_size = Integer.parseInt(tag.substring(2)); } else if (tag.startsWith("f=")) { m_name = tag.substring(2); } else { System.out.println("[updateGfx] Syntax error Tag : " + tag); return null; } textTok.m_font = new Font(m_name, m_style, m_size); g.setFont(textTok.m_font); } return textTok; }
private void text(TextToken token) { PageElement element = new TextPageElement(token.getText()); addToBody(element); }
/** * Creates a new TextToken by parsing a pseudo-HTML tag. * * @param g Graphics used to retrieve the font metric. * @param tag A pseudo HTML tag without '<' and '>'. * @return a new TextToken initialized according to the tag. */ private TextToken updateTag(Graphics g, String tag) { String tempTag; TextToken textTok = null; char begChar; if (tag.length() > 0) { tag = tag.toLowerCase(); begChar = tag.charAt(0); // End of Tag, we returns except for the case </p> if (begChar == '/') { char nxtChar = tag.charAt(1); tempTag = (String) m_heap.lastElement(); if (tempTag.charAt(0) == nxtChar) // ! very simple verification ! { textTok = closeTag(g, tempTag); if (nxtChar != 'p') return textTok; } else { System.out.println("[updateTag] no corresponding opened Tag : " + tag); return null; } } FormatToken prevTok = m_curTok; Insets prevMrg = prevTok.m_margin, margin = m_body.m_margin; int flags = m_body.m_flags, width = m_wCur + (prevMrg != null ? prevMrg.left + prevMrg.right : 0); // Start of Tag + </p> if (tag.equals("br") || begChar == 'p' || tag.equals("/p")) { if (tag.equals("br")) { if (prevMrg != null) margin = prevMrg; flags = prevTok.m_flags; } // We specify new margins if (begChar == 'p') { String alignStr = readAtt(tag, "a"); if (alignStr != null) { char align = Character.toLowerCase(alignStr.charAt(0)); flags = align == 'r' ? RIGHT_BIT : (align == 'c' ? CENTER_BIT : 0); } margin = readMargin(tag); if (tag.length() > 1 && alignStr == null && margin == null) { flags = m_body.m_flags; System.out.println("[updateTag] syntax error Tag : " + tag); return null; } else { m_heap.addElement(tag); } } // update pr�vious format Token prevTok.m_aMax = m_body.m_aMax; prevTok.m_dMax = m_body.m_dMax; prevTok.m_width = width; // reset current vars m_body.m_aMax = 0; m_body.m_dMax = 0; m_wCur = 0; // Stores the max width of all lines including its margins if (width > m_body.m_width) m_body.m_width = width; m_curTok = new FormatToken(); m_curTok.m_flags = flags; m_curTok.m_margin = margin == null ? m_body.m_margin : margin; m_tokens.addElement(m_curTok); textTok = new TextToken(); textTok.m_color = new Color(m_color); textTok.m_font = new Font(m_name, m_style, m_size); } else if (isGfx(begChar)) { textTok = updateGfx(g, tag); m_heap.addElement(tag); } else { System.out.println("[updateTag] Unknown Tag : " + tag); textTok = null; } } return textTok; }
/** * Parses this to extract the Tokens using a line of text. This is necessary to evaluate the * rendering of the text (color, size, alignment...). * * @param g The graphics used to retrieve the font metrics. * @param htmlText A string of text with or without HTML tags to parse. */ protected void parseText(Graphics g, String htmlText) { StringTokenizer tokenizer = new StringTokenizer(htmlText, "<>", true); String tokenStr, nextStr, prevStr = tokenizer.nextToken(); boolean hasMore = tokenizer.hasMoreTokens(), isText = false; Font font = new Font(m_name, m_style, m_size); TextToken textTok = new TextToken(); textTok.m_color = new Color(m_color); textTok.m_font = font; m_curTok = new FormatToken(); m_curTok.m_flags = m_body.m_flags; m_curTok.m_margin = m_body.m_margin; m_tokens.addElement(m_curTok); g.setFont(font); while (hasMore) { tokenStr = tokenizer.nextToken(); hasMore = tokenizer.hasMoreTokens(); // A start of Tag if (prevStr.equals("<")) { nextStr = hasMore ? tokenizer.nextToken() : null; // A closed Tag if (hasMore && nextStr.equals(">")) // tag { textTok = updateTag(g, tokenStr); // An real Tag if (textTok != null) { isText = false; } // An unknown Tag. Handle it as normal text. else { textTok = new TextToken(); updateText(g, "<" + tokenStr + ">", textTok, isText); isText = true; } prevStr = tokenizer.hasMoreTokens() ? tokenizer.nextToken() : null; } // An unclosed Tag. Handle it as normal text. else { updateText(g, "<" + tokenStr, textTok, isText); prevStr = nextStr; isText = true; } } // Normal text else { updateText(g, prevStr, textTok, isText); prevStr = tokenStr; isText = true; } hasMore = tokenizer.hasMoreTokens(); } // Don't forget the last or only piece of text if (prevStr != null) { updateText(g, prevStr, textTok, isText); } updateTag(g, "br"); // to set last line position updateBounds(); }