/** * 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; }
/** * 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; }
/** * 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(); }