package org.mt4j.components.css.parser; import java.util.ArrayList; import java.util.List; import java.util.StringTokenizer; import org.mt4j.AbstractMTApplication; import org.mt4j.components.css.style.CSSBackgroundPosition; import org.mt4j.components.css.style.CSSFont; import org.mt4j.components.css.style.CSSSelector; import org.mt4j.components.css.style.CSSStyle; import org.mt4j.components.css.style.CSSStyle.BackgroundRepeat; import org.mt4j.components.css.util.CSSKeywords; import org.mt4j.components.css.util.CSSKeywords.CSSBorderStyle; import org.mt4j.components.css.util.CSSKeywords.CSSFontFamily; import org.mt4j.components.css.util.CSSKeywords.CSSFontStyle; import org.mt4j.components.css.util.CSSKeywords.CSSFontWeight; import org.mt4j.components.css.util.CSSKeywords.CSSSelectorType; import org.mt4j.components.css.util.CSSKeywords.Position; import org.mt4j.components.css.util.CSSKeywords.PositionType; import org.mt4j.components.css.util.CSSKeywords.cssproperties; import org.mt4j.util.MTColor; import org.mt4j.util.logging.ILogger; import org.mt4j.util.logging.MTLoggerFactory; import org.w3c.css.sac.CSSException; import org.w3c.css.sac.DocumentHandler; import org.w3c.css.sac.InputSource; import org.w3c.css.sac.LexicalUnit; import org.w3c.css.sac.SACMediaList; import org.w3c.css.sac.SelectorList; import processing.core.PImage; /** * The Class CSSHandler consists of the CSS parsing rules */ public class CSSHandler implements DocumentHandler{ /** The logger. */ ILogger logger = null; /** The styles. */ List<CSSStyle> styles = null; /** The active styles. */ List<CSSStyle> activeStyles = new ArrayList<CSSStyle>(); /** The current font. */ CSSFont currentFont = null; /** The app. */ AbstractMTApplication app = null; /** The default font size. */ float defaultFontSize = 16f; /** * Instantiates a new CSS handler. * * @param app the MTApplication * @param styles the List, to which the styles are added */ public CSSHandler(AbstractMTApplication app, List<CSSStyle> styles) { logger = MTLoggerFactory.getLogger(CSSHandler.class.getName()); this.styles = styles; this.app = app; } /* (non-Javadoc) * @see org.w3c.css.sac.DocumentHandler#comment(java.lang.String) */ public void comment(String arg0) throws CSSException { //Don't hand comments } /* (non-Javadoc) * @see org.w3c.css.sac.DocumentHandler#endDocument(org.w3c.css.sac.InputSource) */ public void endDocument(InputSource arg0) throws CSSException { //Document done, nothing to do } /* (non-Javadoc) * @see org.w3c.css.sac.DocumentHandler#endFontFace() */ public void endFontFace() throws CSSException { // } /* (non-Javadoc) * @see org.w3c.css.sac.DocumentHandler#endMedia(org.w3c.css.sac.SACMediaList) */ public void endMedia(SACMediaList arg0) throws CSSException { // } /* (non-Javadoc) * @see org.w3c.css.sac.DocumentHandler#endPage(java.lang.String, java.lang.String) */ public void endPage(String arg0, String arg1) throws CSSException { // } /* (non-Javadoc) * @see org.w3c.css.sac.DocumentHandler#endSelector(org.w3c.css.sac.SelectorList) */ public void endSelector(SelectorList arg0) throws CSSException { if (currentFont != null && currentFont.isModified()) { for (CSSStyle s: activeStyles) { s.setCssfont(currentFont); } } currentFont = new CSSFont(); activeStyles.clear(); } /* (non-Javadoc) * @see org.w3c.css.sac.DocumentHandler#ignorableAtRule(java.lang.String) */ public void ignorableAtRule(String arg0) throws CSSException { // } /* (non-Javadoc) * @see org.w3c.css.sac.DocumentHandler#importStyle(java.lang.String, org.w3c.css.sac.SACMediaList, java.lang.String) */ public void importStyle(String arg0, SACMediaList arg1, String arg2) throws CSSException { // } /* (non-Javadoc) * @see org.w3c.css.sac.DocumentHandler#namespaceDeclaration(java.lang.String, java.lang.String) */ public void namespaceDeclaration(String arg0, String arg1) throws CSSException { // } /* (non-Javadoc) * @see org.w3c.css.sac.DocumentHandler#property(java.lang.String, org.w3c.css.sac.LexicalUnit, boolean) */ public void property(String name, LexicalUnit value, boolean important) throws CSSException { try { parseValue(name, value); } catch (Exception e){ e.printStackTrace(); } } /** * Parses the LexicalUnit. * * @param name the name/identifier * @param value the value */ private void parseValue(String name, LexicalUnit value) { try { //Which tag is being used? cssproperties prop = cssproperties.UNKNOWN; try { prop = cssproperties.valueOf(name.replace(" ", "").replace("-", "").toUpperCase()); } catch (IllegalArgumentException iae) { } switch (prop) { case BACKGROUNDCOLOR: MTColor color = handleColor(value); for (CSSStyle sty: activeStyles) sty.setBackgroundColor(color); break; case BACKGROUNDIMAGE: PImage backgroundImage = handleBackgroundImage(value); if (backgroundImage != null) for (CSSStyle sty: activeStyles) sty.setBackgroundImage(backgroundImage); break; case BACKGROUNDPOSITION: CSSBackgroundPosition bp = handleBackgroundPosition(value, value.getNextLexicalUnit()); if (bp != null) { for (CSSStyle sty: activeStyles) sty.setBackgroundPosition(bp); } case BACKGROUND: List<LexicalUnit> parameters = new ArrayList<LexicalUnit>(); parameters.add(value); while (value.getNextLexicalUnit() != null) { value = value.getNextLexicalUnit(); parameters.add(value); } //Evaluate all parameters for (int i = 0; i < parameters.size(); i++) { LexicalUnit lu = (LexicalUnit)parameters.get(i); //What type is the current parameter? switch (identifyBackgroundTag(lu)) { case 1: //Color MTColor backgroundColor = handleColor(lu); if (backgroundColor != null) for (CSSStyle sty: activeStyles) sty.setBackgroundColor(backgroundColor); break; case 2: //Background Image PImage backgroundImage2 = handleBackgroundImage(lu); if (backgroundImage2 != null) for (CSSStyle sty: activeStyles) sty.setBackgroundImage(backgroundImage2); break; case 3: //Background repeat rules BackgroundRepeat backgroundRepeat = handleBackgroundRepeat(lu); if (backgroundRepeat != null) for (CSSStyle sty: activeStyles) sty.setBackgroundRepeat(backgroundRepeat); break; case 4: //Background Position if (i+1 < parameters.size() && identifyBackgroundTag(parameters.get(i+1)) == 4) { handleBackgroundPosition(lu, parameters.get(i+1)); i++; } else { handleBackgroundPosition(lu, null); } default: break; } } break; case BACKGROUNDREPEAT: BackgroundRepeat bR = handleBackgroundRepeat(value); if (bR != null) for (CSSStyle sty: activeStyles) sty.setBackgroundRepeat(bR); break; case COLOR: color = handleColor(value); if (currentFont == null) currentFont = new CSSFont(color); else currentFont.setColor(color); break; case WIDTH: LexicalUnit parameter = value; for (CSSStyle sty: activeStyles) { sty.setWidth(parseMeasuringUnit(parameter,100)); if (parameter.getLexicalUnitType() == LexicalUnit.SAC_PERCENTAGE) sty.setWidthPercentage(true); } break; case HEIGHT: parameter = value; for (CSSStyle sty: activeStyles) { sty.setHeight(parseMeasuringUnit(parameter, 100)); if (parameter.getLexicalUnitType() == LexicalUnit.SAC_PERCENTAGE) sty.setHeightPercentage(true); } break; case BORDER: parameters = new ArrayList<LexicalUnit>(); parameters.add(value); //Add all parameters to list while (value.getNextLexicalUnit() != null) { value = value.getNextLexicalUnit(); parameters.add(value); } //Evaluate all Parameters for (LexicalUnit lu: parameters) { switch (identifyBorderTag(lu)) { case 1: //Border width float width = handleBorderWidth(value); for (CSSStyle sty: activeStyles) sty.setBorderWidth(width); break; case 2: //Border style CSSBorderStyle style = parseBorderStyle(value); for (CSSStyle sty: activeStyles) sty.setBorderStyle(style); break; case 3: //Border color color = handleColor(value); for (CSSStyle sty: activeStyles) sty.setBorderColor(color); break; default: break; } } break; case BORDERWIDTH: float width = handleBorderWidth(value); for (CSSStyle sty: activeStyles) sty.setBorderWidth(width); break; case BORDERCOLOR: color = handleColor(value); for (CSSStyle sty: activeStyles) sty.setBorderColor(color); break; case BORDERSTYLE: CSSBorderStyle style = parseBorderStyle(value); for (CSSStyle sty: activeStyles) sty.setBorderStyle(style); break; case PADDING: parameter = value; for (CSSStyle sty: activeStyles) sty.setPaddingWidth(parseMeasuringUnit(parameter,1)); break; case FONTSIZE: parameter = value; //Is the font-size a measuring unit or a string? if (CSSKeywords.isMeasuringUnit(parameter)) { if (currentFont == null) currentFont = new CSSFont((int) (parseMeasuringUnit(parameter,defaultFontSize) * (72f/100f))); else currentFont.setFontsize((int) (parseMeasuringUnit(parameter,defaultFontSize)* (72f/100f))); } else if (CSSKeywords.isString(parameter)){ if (currentFont == null) currentFont = new CSSFont(handleFontSizeString(parameter)); else currentFont.setFontsize(handleFontSizeString(parameter)); } break; case VISIBILITY: boolean visible; visible = parseBoolean(value); for (CSSStyle sty: activeStyles) sty.setVisibility(visible); break; case FONTFAMILY: handleFontFamily(value); break; case FONT: parameters = new ArrayList<LexicalUnit>(); parameters.add(value); //Add all parameters to list while (value.getNextLexicalUnit() != null) { value = value.getNextLexicalUnit(); parameters.add(value); } //Evaluate all parameters for (LexicalUnit lu: parameters) { switch (identifyFontTag(lu)) { case 1: //Font size parameter = lu; if (CSSKeywords.isMeasuringUnit(parameter)) { if (currentFont == null) currentFont = new CSSFont((int) (parseMeasuringUnit(parameter,defaultFontSize) * (72f/100f))); else currentFont.setFontsize((int) (parseMeasuringUnit(parameter,defaultFontSize)* (72f/100f))); } else if (CSSKeywords.isString(parameter)){ if (currentFont == null) currentFont = new CSSFont(handleFontSizeString(parameter)); else currentFont.setFontsize(handleFontSizeString(parameter)); } break; case 2: //Font weight handleFontWeight(lu); break; case 3: //Font style handleFontStyle(lu); break; case 4: //Font family handleFontFamily(lu); break; default: break; } } break; case FONTSTYLE: handleFontStyle(value); break; case FONTWEIGHT: handleFontWeight(value); break; case OPACITY: if (CSSKeywords.isMeasuringUnit(value)) { System.out.println("Raw Opacity: " + value.getFloatValue() + " Type: " + value.getLexicalUnitType()); float opacity = parseMeasuringUnit(value, 1); System.out.println("Processed Opacity: " + opacity); for (CSSStyle sty: activeStyles) sty.setOpacity(opacity * 255); } break; case UNKNOWN: default: logger.error("Unknown Identifier: " + name.replace(" ", "").replace("-", "").toUpperCase()); break; }} catch (Exception e) { e.printStackTrace(); } } private CSSBackgroundPosition handleBackgroundPosition(LexicalUnit value, LexicalUnit value2) { LexicalUnit part1 = value; LexicalUnit part2 = value2; CSSBackgroundPosition returnValue = new CSSBackgroundPosition(); if (part1.getLexicalUnitType() == LexicalUnit.SAC_IDENT || part1.getLexicalUnitType() == LexicalUnit.SAC_STRING_VALUE) { //Must be a keyword try { Position xPos = Position.valueOf(part1.getStringValue()); returnValue.setxKeywordPosition(xPos); returnValue.setxType(PositionType.KEYWORD); } catch (Exception e) { return null; } } else if (part1.getLexicalUnitType() == LexicalUnit.SAC_PERCENTAGE) { returnValue.setxPos(part1.getFloatValue()); returnValue.setxType(PositionType.RELATIVE); } else if (CSSKeywords.isMeasuringUnit(part1)) { returnValue.setxPos(part1.getFloatValue()); returnValue.setxType(PositionType.ABSOLUTE); } if (part2 != null) { if (part2.getLexicalUnitType() == LexicalUnit.SAC_IDENT || part2.getLexicalUnitType() == LexicalUnit.SAC_STRING_VALUE) { //Must be a keyword try { Position xPos = Position.valueOf(part2.getStringValue()); returnValue.setyKeywordPosition(xPos); returnValue.setyType(PositionType.KEYWORD); } catch (Exception e) { returnValue.setyKeywordPosition(returnValue.getxKeywordPosition()); returnValue.setyPos(returnValue.getxPos()); returnValue.setyType(returnValue.getxType()); } } else if (part2.getLexicalUnitType() == LexicalUnit.SAC_PERCENTAGE) { returnValue.setyPos(part2.getFloatValue()); returnValue.setyType(PositionType.RELATIVE); } else if (CSSKeywords.isMeasuringUnit(part2)) { returnValue.setyPos(part2.getFloatValue()); returnValue.setyType(PositionType.ABSOLUTE); } } else { returnValue.setyKeywordPosition(returnValue.getxKeywordPosition()); returnValue.setyPos(returnValue.getxPos()); returnValue.setyType(returnValue.getxType()); } return returnValue; } /** * Identifies the parameter type in a Font: tag * * @param lu the LexicalUnit * @return the parameter type * 0: Unknown * 1: font-size * 2: font-weight * 3: font-style * 4: font-family */ private int identifyFontTag(LexicalUnit lu) { //0: Unknown //1: font-size //2: font-weight //3: font-style //4: font-family if (CSSKeywords.isMeasuringUnit(lu)) { if (lu.getFloatValue() >= 100) return 2; else return 1; } if (CSSKeywords.isFontWeight(lu)) return 2; if (CSSKeywords.isFontFamily(lu)) return 4; if (CSSKeywords.isFontStyle(lu)) return 3; return 0; } /** * Identifies the parameter type in a Border: tag * * @param lu the LexicalUnit * @return the parameter type * 0: Unknown * 1: Border-Width * 2: Border-Style * 3. Border-Color */ private int identifyBorderTag(LexicalUnit lu) { //0: Unknown //1: Border-Width //2: Border-Style //3. Border-Color if (lu.getLexicalUnitType() == LexicalUnit.SAC_RGBCOLOR) return 3; if (CSSKeywords.isMeasuringUnit(lu)) return 1; if (lu.getLexicalUnitType() == LexicalUnit.SAC_IDENT) { if (CSSKeywords.isBorderStyle(lu)) return 2; if (CSSKeywords.isColor(lu)) return 3; } return 0; } /** * Handles the background-repeat: tag * * @param value the LexicalUnit * @return the background repeat type */ private BackgroundRepeat handleBackgroundRepeat(LexicalUnit value) { logger.debug("Background Repeat Type: " + value.getLexicalUnitType()); if (value.getLexicalUnitType() == LexicalUnit.SAC_IDENT) { if (value.getStringValue().replaceAll(" ", "").equalsIgnoreCase("REPEAT-X")) return BackgroundRepeat.XREPEAT; if (value.getStringValue().replaceAll(" ", "").equalsIgnoreCase("REPEAT-Y")) return BackgroundRepeat.YREPEAT; if (value.getStringValue().replaceAll(" ", "").equalsIgnoreCase("REPEAT")) return BackgroundRepeat.REPEAT; if (value.getStringValue().replaceAll(" ", "").equalsIgnoreCase("NO-REPEAT")) return BackgroundRepeat.NONE; } return null; } /** * Identifies the parameter types in a Background: tag * * @param value the LexicalUnit * @return the parameter type * 0: Unknown * 1: Color * 2: Background-Image * 3: Repeat */ private int identifyBackgroundTag(LexicalUnit value) { //Return Values: //0: Unknown //1: Color //2: Background-Image //3: Repeat if (value.getLexicalUnitType() == LexicalUnit.SAC_RGBCOLOR) return 1; if (value.getLexicalUnitType() == LexicalUnit.SAC_URI) return 2; if (value.getLexicalUnitType() == LexicalUnit.SAC_IDENT) { if (CSSKeywords.isColor(value)) return 1; if (CSSKeywords.isBackgroundRepeat(value)) return 3; if (CSSKeywords.isBackgroundPosition(value)) return 4; if (CSSKeywords.isBackgroundAttachment(value)) return 0; } if (CSSKeywords.isMeasuringUnit(value)) return 4; return 0; } /** * Handles the border-width: tag * * @param lu the LexicalUnit * @return the border width */ private float handleBorderWidth(LexicalUnit lu) { if (CSSKeywords.isMeasuringUnit(lu)) { return parseMeasuringUnit(lu,1); } if (CSSKeywords.isString(lu)) { if (CSSKeywords.isBorderWidth(lu)) { if (lu.getStringValue().replaceAll(" ", "").equalsIgnoreCase("THIN")) return 0.5f; if (lu.getStringValue().replaceAll(" ", "").equalsIgnoreCase("MEDIUM")) return 1f; if (lu.getStringValue().replaceAll(" ", "").equalsIgnoreCase("THICK")) return 2f; } } return 0f; } /** * Handles background-image: tag * * @param value the LexicalUnit * @return the background image (as PImage) */ private PImage handleBackgroundImage(LexicalUnit value) { if (value.getLexicalUnitType() == LexicalUnit.SAC_URI) { try { return app.loadImage(value.getStringValue()); } catch (Exception e) { e.printStackTrace(); return null; } } return null; } /** * Handles the font-size: tag, if it's a string * * @param parameter the LexicalUnit * @return the font size */ private int handleFontSizeString(LexicalUnit parameter) { if (parameter.getStringValue().toUpperCase().contains("SMALLER")) return 8; if (parameter.getStringValue().toUpperCase().contains("BIGGER")) return 30; if (parameter.getStringValue().toUpperCase().contains("SMALL")) return 12; if (parameter.getStringValue().toUpperCase().contains("BIG")) return 24; return 16; } /** * Handles the font-weight: tag * * @param value the LexicalUnit */ private void handleFontWeight(LexicalUnit value) { CSSFontWeight weight = CSSFontWeight.NORMAL; if (currentFont == null) currentFont = new CSSFont(weight); switch (value.getLexicalUnitType()) { case LexicalUnit.SAC_IDENT: case LexicalUnit.SAC_STRING_VALUE: if (value.getStringValue().toUpperCase().contains("BOLD")) {currentFont.setWeight(CSSFontWeight.BOLD); break;} if (value.getStringValue().toUpperCase().contains("LIGHT")) {currentFont.setWeight(CSSFontWeight.LIGHT); break;} currentFont.setWeight(CSSFontWeight.NORMAL); break; case LexicalUnit.SAC_INTEGER: if (value.getIntegerValue() < 400) {currentFont.setWeight(CSSFontWeight.LIGHT); break;} if (value.getIntegerValue() > 600) {currentFont.setWeight(CSSFontWeight.BOLD); break;} currentFont.setWeight(CSSFontWeight.NORMAL); break; default: break; } } /** * Handles the font-family: tag * * @param value the LexicalUnit */ private void handleFontFamily(LexicalUnit value) { CSSFontFamily family = CSSFontFamily.CUSTOM; if (currentFont == null) currentFont = new CSSFont(family); if (value.getLexicalUnitType() == LexicalUnit.SAC_IDENT || value.getLexicalUnitType() == LexicalUnit.SAC_STRING_VALUE) { if (value.getStringValue().toUpperCase().contains("TTF")) { currentFont.setFamily(CSSFontFamily.CUSTOM); currentFont.setCustomType(value.getStringValue()); return;} if (value.getStringValue().toUpperCase().contains("MONO")) {currentFont.setFamily(CSSFontFamily.MONO); return;} if (value.getStringValue().toUpperCase().contains("SANS")) {currentFont.setFamily(CSSFontFamily.SANS); return;} if (value.getStringValue().toUpperCase().contains("SERIF")) {currentFont.setFamily(CSSFontFamily.SERIF); return;} } else { logger.debug(value.getLexicalUnitType()); } } /** * Handles the font-style: tag * * @param value the LexicalUnit */ private void handleFontStyle(LexicalUnit value) { CSSFontStyle style = CSSFontStyle.NORMAL; if (currentFont == null) currentFont = new CSSFont(style); if (value.getLexicalUnitType() == LexicalUnit.SAC_IDENT || value.getLexicalUnitType() == LexicalUnit.SAC_STRING_VALUE) { if (value.getStringValue().toUpperCase().contains("ITALIC")) {currentFont.setStyle(CSSFontStyle.ITALIC); return;} if (value.getStringValue().toUpperCase().contains("OBLIQUE")) {currentFont.setStyle(CSSFontStyle.OBLIQUE); return;} } } /** * Handles color values, either as RGBCOLOR or as String * * @param value LexicalUnit * @return the Color (as MTColor) */ private MTColor handleColor(LexicalUnit value){ switch (value.getLexicalUnitType()) { case LexicalUnit.SAC_RGBCOLOR: try { LexicalUnit parameters = value.getParameters(); float red = parseMeasuringUnit(parameters, 255); parameters = parameters.getNextLexicalUnit().getNextLexicalUnit(); float green = parseMeasuringUnit(parameters, 255); parameters = parameters.getNextLexicalUnit().getNextLexicalUnit(); float blue = parseMeasuringUnit(parameters, 255); return new MTColor(red, green, blue, 255); } catch (Exception e) {e.printStackTrace();}; break; case LexicalUnit.SAC_STRING_VALUE: case LexicalUnit.SAC_IDENT: if (value.getStringValue().equalsIgnoreCase("black")) return MTColor.BLACK; if (value.getStringValue().equalsIgnoreCase("white")) return MTColor.WHITE; if (value.getStringValue().equalsIgnoreCase("silver")) return MTColor.SILVER; if (value.getStringValue().equalsIgnoreCase("gray")) return MTColor.GRAY; if (value.getStringValue().equalsIgnoreCase("grey")) return MTColor.GREY; if (value.getStringValue().equalsIgnoreCase("maroon")) return MTColor.MAROON; if (value.getStringValue().equalsIgnoreCase("red")) return MTColor.RED; if (value.getStringValue().equalsIgnoreCase("purple")) return MTColor.PURPLE; if (value.getStringValue().equalsIgnoreCase("fuchsia")) return MTColor.FUCHSIA; if (value.getStringValue().equalsIgnoreCase("green")) return MTColor.GREEN; if (value.getStringValue().equalsIgnoreCase("lime")) return MTColor.LIME; if (value.getStringValue().equalsIgnoreCase("olive")) return MTColor.OLIVE; if (value.getStringValue().equalsIgnoreCase("yellow")) return MTColor.YELLOW; if (value.getStringValue().equalsIgnoreCase("navy")) return MTColor.NAVY; if (value.getStringValue().equalsIgnoreCase("blue")) return MTColor.BLUE; if (value.getStringValue().equalsIgnoreCase("teal")) return MTColor.TEAL; if (value.getStringValue().equalsIgnoreCase("aqua")) return MTColor.AQUA; break; } return new MTColor(0,0,0,0); } /** * Parses boolean values * * @param value the LexicalUnit * @return true, if the stringValue is "true" */ private boolean parseBoolean(LexicalUnit value) { try { return Boolean.parseBoolean(value.getStringValue()); } catch (Exception e) { e.printStackTrace(); } return false; } /** * Handles the border-style: tag * * @param value the LexicalUnit * @return the border style (CSSBorderStyle) */ private CSSBorderStyle parseBorderStyle(LexicalUnit value) { LexicalUnit parameter = value; if (parameter.getLexicalUnitType() == LexicalUnit.SAC_IDENT) { if (parameter.getStringValue().equalsIgnoreCase("dashed")) return CSSBorderStyle.DASHED; if (parameter.getStringValue().equalsIgnoreCase("dotted")) return CSSBorderStyle.DOTTED; if (parameter.getStringValue().equalsIgnoreCase("none")) return CSSBorderStyle.NONE; if (parameter.getStringValue().equalsIgnoreCase("hidden")) return CSSBorderStyle.HIDDEN; } return CSSBorderStyle.SOLID; } /** * Parses all measuring units, converts them to px * * @param value the LexicalUnit * @param referenceValue the reference value (for proportional calculations) * @return the measuring unit as px */ private float parseMeasuringUnit(LexicalUnit value, float referenceValue) { float dpi = 100f; float emtopx = 16f/72f * dpi; float inchtopx = dpi; float centtopx = (10f/254f) * dpi; float mmtopx = (1f/254f) * dpi; float pointtopx = (1f/72f) * dpi; float picatopx = (12f/72f) * dpi; try { switch (value.getLexicalUnitType()) { case LexicalUnit.SAC_CENTIMETER: return value.getFloatValue() * centtopx; case LexicalUnit.SAC_INCH: return value.getFloatValue() * inchtopx; case LexicalUnit.SAC_MILLIMETER: return value.getFloatValue() * mmtopx; case LexicalUnit.SAC_POINT: return value.getFloatValue() * pointtopx; case LexicalUnit.SAC_PICA: return value.getFloatValue() * picatopx; case LexicalUnit.SAC_EM: return (value.getFloatValue() * emtopx); case LexicalUnit.SAC_PIXEL: return value.getFloatValue(); case LexicalUnit.SAC_INTEGER: return (float) value.getIntegerValue(); case LexicalUnit.SAC_REAL: return (float) value.getFloatValue(); case LexicalUnit.SAC_PERCENTAGE: return (float) value.getFloatValue() / 100 * referenceValue; } } catch (Exception e) { e.printStackTrace(); } logger.error("Unrecognized Measuring Unit: " + value.getLexicalUnitType()); return 0; } /* (non-Javadoc) * @see org.w3c.css.sac.DocumentHandler#startDocument(org.w3c.css.sac.InputSource) */ public void startDocument(InputSource arg0) throws CSSException { } /* (non-Javadoc) * @see org.w3c.css.sac.DocumentHandler#startFontFace() */ public void startFontFace() throws CSSException { } /* (non-Javadoc) * @see org.w3c.css.sac.DocumentHandler#startMedia(org.w3c.css.sac.SACMediaList) */ public void startMedia(SACMediaList arg0) throws CSSException { } /* (non-Javadoc) * @see org.w3c.css.sac.DocumentHandler#startPage(java.lang.String, java.lang.String) */ public void startPage(String arg0, String arg1) throws CSSException { } /* (non-Javadoc) * @see org.w3c.css.sac.DocumentHandler#startSelector(org.w3c.css.sac.SelectorList) */ public void startSelector(SelectorList selectors) throws CSSException { for (int i=0; i < selectors.getLength(); i++) { styles.add(new CSSStyle(parseSelector(selectors.item(i)), app)); activeStyles.add(styles.get(styles.size()-1)); } } /** * Parses the selector. * * @param selector the org.w3c.css.sac.Selector * @return the Selector (CSSSelector) */ public CSSSelector parseSelector(org.w3c.css.sac.Selector selector) { CSSSelector newSelector = null; if (selector.toString().contains(">")) { String[] parts = selector.toString().split(">", 2); newSelector = processElement(parts[0]); newSelector.setChild(processElement(parts[1])); } else { //No Children (yet) newSelector = processElement(selector.toString()); } return newSelector; } /** * Process parts of the selector string * * @param in the selector as string * @return the Selector (CSSSelector) */ public CSSSelector processElement(String in) { CSSSelector newSelector = null; String work = String.copyValueOf(in.toCharArray()); while (work.startsWith(" ")) work = work.substring(1); while (work.endsWith(" ")) work = work.substring(0, work.length()-1); if (work.contains("*") && !work.startsWith("*")) { // replace? work = work.substring(0, 1) + work.substring(1).replace("*", ""); } if (work.startsWith("*") && !work.equals("*")) { work = work.substring(1); } work.replace(" ", ""); boolean containsSharp = false; boolean containsDot = false; boolean firstCharacterDot = false; boolean firstCharacterSharp = false; boolean containsSpace = false; if (work.contains("#")) containsSharp = true; if (work.contains(".")) containsDot = true; work = work.replaceAll("[ ]+[#]", "#").replaceAll("[ ]+[.]", "."); if (work.contains(" ")) containsSpace = true; if (work.equals("*")) { newSelector = new CSSSelector("*", CSSSelectorType.UNIVERSAL); return newSelector; } if (work.startsWith(".")) { firstCharacterDot = true; containsDot = work.substring(1).contains("."); } if (work.startsWith("#")) { firstCharacterSharp = true; containsSharp = work.substring(1).contains("#"); } if (!containsSharp && !containsDot) { newSelector = new CSSSelector(work.replace(".", "").replace("#", ""), determineType(work)); } if (containsSpace) { StringTokenizer st = new StringTokenizer(work, " "); if (st.countTokens() > 1) { String part1 = st.nextToken(); String part2 = st.nextToken(); newSelector = new CSSSelector(part1, determineType(part1)); newSelector.setSecondary(part2); newSelector.setSecondaryType(CSSSelectorType.TYPE); } return newSelector; } if (containsSharp) { if (firstCharacterSharp) { StringTokenizer st = new StringTokenizer(work.substring(1), "#"); if (st.countTokens() > 1) { newSelector = new CSSSelector(st.nextToken(), CSSSelectorType.ID); newSelector.setSecondary(st.nextToken()); newSelector.setSecondaryType(CSSSelectorType.ID); } } else { StringTokenizer st = new StringTokenizer(work, "#"); if (st.countTokens() > 1) { String part1 = st.nextToken(); String part2 = st.nextToken(); newSelector = new CSSSelector(part1, determineType(part1)); newSelector.setSecondary(part2); newSelector.setSecondaryType(CSSSelectorType.ID); } } return newSelector; } if (containsDot) { if (firstCharacterDot) { StringTokenizer st = new StringTokenizer(work.substring(1), "."); if (st.countTokens() > 1) { newSelector = new CSSSelector(st.nextToken(), CSSSelectorType.CLASS); newSelector.setSecondary(st.nextToken()); newSelector.setSecondaryType(CSSSelectorType.CLASS); } } else { StringTokenizer st = new StringTokenizer(work, "."); if (st.countTokens() > 1) { String part1 = st.nextToken(); String part2 = st.nextToken(); newSelector = new CSSSelector(part1, determineType(part1)); newSelector.setSecondary(part2); newSelector.setSecondaryType(CSSSelectorType.CLASS); } } return newSelector; } return newSelector; } /** * Gets the styles. * * @return the styles */ public List<CSSStyle> getStyles() { return styles; } /** * Determines the type of the Selector by the ".#*" characters * * @param in the in * @return the SelectorType (CSSSelectorType) */ private CSSSelectorType determineType (String in) { if (in.contains(".")) return CSSSelectorType.CLASS; if (in.contains("#")) return CSSSelectorType.ID; if (in.contains("*")) return CSSSelectorType.UNIVERSAL; return CSSSelectorType.TYPE; } }