Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* $Id: 447c177626fe6507814ad27deec41e4213ed7d24 $
*
* This file is part of the iText (R) project.
* Copyright (c) 1998-2016 iText Group NV
* Authors: Balder Van Camp, Emiel Ackermann, et al.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License version 3
* as published by the Free Software Foundation with the addition of the
* following permission added to Section 15 as permitted in Section 7(a):
* FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY
* ITEXT GROUP. ITEXT GROUP DISCLAIMS THE WARRANTY OF NON INFRINGEMENT
* OF THIRD PARTY RIGHTS
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Affero General Public License for more details.
* You should have received a copy of the GNU Affero General Public License
* along with this program; if not, see http://www.gnu.org/licenses or write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA, 02110-1301 USA, or download the license from the following URL:
* http://itextpdf.com/terms-of-use/
*
* The interactive user interfaces in modified source and object code versions
* of this program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU Affero General Public License.
*
* In accordance with Section 7(b) of the GNU Affero General Public License,
* a covered work must retain the producer line in every PDF that is created
* or manipulated using iText.
*
* You can be released from the requirements of the license by purchasing
* a commercial license. Buying such a license is mandatory as soon as you
* develop commercial activities involving the iText software without
* disclosing the source code of your own applications.
* These activities include: offering paid services to customers as an ASP,
* serving PDFs on the fly in a web application, shipping iText with a closed
* source product.
*
* For more information, please contact iText Software Corp. at this
* address: [email protected]
*/
package com.itextpdf.tool.xml.css;
import com.itextpdf.tool.xml.Tag;
import com.itextpdf.tool.xml.exceptions.CssResolverException;
import com.itextpdf.tool.xml.html.HTML;
import com.itextpdf.tool.xml.net.FileRetrieve;
import com.itextpdf.tool.xml.net.FileRetrieveImpl;
import com.itextpdf.tool.xml.pipeline.css.CSSResolver;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.*;
import java.util.Map.Entry;
/**
* Resolves CSS properties.
*
* @author redlab_b
*
*/
public class StyleAttrCSSResolver implements CSSResolver {
/**
*
*/
public static final String STYLE = HTML.Attribute.STYLE;
private final CssUtils utils;
private CssInheritanceRules inherit;
private final CssFiles cssFiles;
private FileRetrieve retrieve;
/**
* Construct a new {@link StyleAttrCSSResolver} with default settings.
*/
public StyleAttrCSSResolver() {
this(new CssFilesImpl(), CssUtils.getInstance());
}
/**
* Construct a new StyleAttrCSSResolver with the given {@link CssFiles} and the {@link DefaultCssInheritanceRules}.
*
* @param cssFiles a {@link CssFiles} implementation.
*/
public StyleAttrCSSResolver(final CssFiles cssFiles) {
this(cssFiles, CssUtils.getInstance());
}
/**
* Construct a new StyleAttrCSSResolver with the given {@link CssFiles} and {@link CssUtils} and the
* {@link DefaultCssInheritanceRules}.
*
* @param cssFiles a {@link CssFiles} implementation.
* @param utils the CssUtils to use.
*/
public StyleAttrCSSResolver(final CssFiles cssFiles, final CssUtils utils) {
this(new DefaultCssInheritanceRules(), cssFiles, utils);
}
/**
* Construct a new StyleAttrCSSResolver with the given {@link CssFiles} and {@link CssUtils}.
*
* @param rules the {@link CssInheritanceRules} to use.
* @param cssFiles a {@link CssFiles} implementation.
* @param utils the CssUtils to use.
*/
public StyleAttrCSSResolver(final CssInheritanceRules rules, final CssFiles cssFiles, final CssUtils utils) {
this(rules, cssFiles, utils, new FileRetrieveImpl());
}
/**
* Construct a new StyleAttrCSSResolver with the given {@link CssFiles} and {@link CssUtils}.
*
* @param rules the {@link CssInheritanceRules} to use.
* @param cssFiles a {@link CssFiles} implementation.
* @param utils the CssUtils to use.
* @param fileRetrieve the {@link FileRetrieve} implementation
*/
public StyleAttrCSSResolver(final CssInheritanceRules rules, final CssFiles cssFiles, final CssUtils utils, final FileRetrieve fileRetrieve) {
this.utils = utils;
this.cssFiles = cssFiles;
this.inherit = rules;
this.retrieve = fileRetrieve;
}
/**
* @param cssFiles the {@link CssFile} implementation
* @param r the {@link FileRetrieve} implementation
*/
public StyleAttrCSSResolver(final CssFiles cssFiles, final FileRetrieve r) {
this(new DefaultCssInheritanceRules(), cssFiles, CssUtils.getInstance(), r);
}
/**
* Also taking into account the CSS properties of any parent tag in the given tag.
*
* @see com.itextpdf.tool.xml.pipeline.css.CSSResolver#resolveStyles(com.itextpdf.tool.xml.Tag)
*/
public void resolveStyles(final Tag t) {
// get css for this tag from resolver
Map tagCss = new LinkedHashMap();
Map listCss = null;
if (null != cssFiles && cssFiles.hasFiles()) {
tagCss = cssFiles.getCSS(t);
if (t.getName().equalsIgnoreCase(HTML.Tag.P) || t.getName().equalsIgnoreCase(HTML.Tag.TD)) {
listCss = cssFiles.getCSS(new Tag(HTML.Tag.UL));
}
// Map css = cssFiles.getCSS(t);
// if (null != css) {
// for (Entry entry : css.entrySet()) {
// splitRules(tagCss,utils.stripDoubleSpacesAndTrim(entry.getKey()), utils.stripDoubleSpacesAndTrim(entry.getValue()));
// }
// }
}
// get css from style attr
if (null != t.getAttributes() && !t.getAttributes().isEmpty()) {
if (t.getAttributes().get(HTML.Attribute.CELLPADDING) != null) {
tagCss.putAll(utils.parseBoxValues(t.getAttributes().get(HTML.Attribute.CELLPADDING), "cellpadding-", ""));
}
if (t.getAttributes().get(HTML.Attribute.CELLSPACING) != null) {
tagCss.putAll(utils.parseBoxValues(t.getAttributes().get(HTML.Attribute.CELLSPACING), "cellspacing-", ""));
}
String styleAtt = t.getAttributes().get(HTML.Attribute.STYLE);
if (null != styleAtt && styleAtt.length() > 0) {
Map tagAttrCss = new LinkedHashMap();
String[] styles = styleAtt.split(";");
for (String s : styles) {
String[] part = s.split(":",2);
if (part.length == 2) {
String key = utils.stripDoubleSpacesTrimAndToLowerCase(part[0]);
String value = utils.stripDoubleSpacesAndTrim(part[1]);
splitRules(tagAttrCss, key, value);
}
}
for (Entry e : tagAttrCss.entrySet()) {
tagCss.put(e.getKey(), e.getValue());
}
}
}
// inherit css from parent tags, as defined in provided CssInheritanceRules or if property = inherit
Map css = t.getCSS();
if (t.getName() != null) {
if(t.getName().equalsIgnoreCase(HTML.Tag.I) || t.getName().equalsIgnoreCase(HTML.Tag.CITE)
|| t.getName().equalsIgnoreCase(HTML.Tag.EM) || t.getName().equalsIgnoreCase(HTML.Tag.VAR)
|| t.getName().equalsIgnoreCase(HTML.Tag.DFN) || t.getName().equalsIgnoreCase(HTML.Tag.ADDRESS)) {
tagCss.put(CSS.Property.FONT_STYLE, CSS.Value.ITALIC);
}
else if (t.getName().equalsIgnoreCase(HTML.Tag.B) || t.getName().equalsIgnoreCase(HTML.Tag.STRONG)) {
tagCss.put(CSS.Property.FONT_WEIGHT, CSS.Value.BOLD);
}
else if (t.getName().equalsIgnoreCase(HTML.Tag.U) || t.getName().equalsIgnoreCase(HTML.Tag.INS)) {
tagCss.put(CSS.Property.TEXT_DECORATION, CSS.Value.UNDERLINE);
}
else if (t.getName().equalsIgnoreCase(HTML.Tag.S) || t.getName().equalsIgnoreCase(HTML.Tag.STRIKE)
|| t.getName().equalsIgnoreCase(HTML.Tag.DEL)) {
tagCss.put(CSS.Property.TEXT_DECORATION, CSS.Value.LINE_THROUGH);
}
else if (t.getName().equalsIgnoreCase(HTML.Tag.BIG)){
tagCss.put(CSS.Property.FONT_SIZE, CSS.Value.LARGER);
}
else if (t.getName().equalsIgnoreCase(HTML.Tag.SMALL)){
tagCss.put(CSS.Property.FONT_SIZE, CSS.Value.SMALLER);
}
}
if (listCss != null && listCss.containsKey(CSS.Property.LIST_STYLE_TYPE)) {
css.put(CSS.Property.LIST_STYLE_TYPE, listCss.get(CSS.Property.LIST_STYLE_TYPE));
}
if (mustInherit(t.getName()) && null != t.getParent() && null != t.getParent().getCSS()) {
if (null != this.inherit) {
for (Entry entry : t.getParent().getCSS().entrySet()) {
String key = entry.getKey();
if ((tagCss.containsKey(key) && CSS.Value.INHERIT.equals(tagCss.get(key)) ) || canInherite(t, key)) {
if (key.contains(CSS.Property.CELLPADDING)
&& (HTML.Tag.TD.equals(t.getName()) || HTML.Tag.TH.equals(t.getName()))) {
String paddingKey = key.replace(CSS.Property.CELLPADDING, CSS.Property.PADDING);
//if (!tagCss.containsKey(paddingKey)) {
tagCss.put(paddingKey, entry.getValue());
//continue;
//}
} else {
//splitRules(css, key, entry.getValue());
css.put(key, entry.getValue());
}
}
}
} else {
css.putAll(t.getParent().getCSS());
}
}
if (t.getName() != null) {
if (t.getName().equals(HTML.Tag.FONT)) {
String font_family = t.getAttributes().get(HTML.Attribute.FACE);
if (font_family != null) css.put(CSS.Property.FONT_FAMILY, font_family);
String color = t.getAttributes().get(HTML.Attribute.COLOR);
if (color != null) css.put(CSS.Property.COLOR, color);
String size = t.getAttributes().get(HTML.Attribute.SIZE);
if (size != null) {
if(size.equals("1")) css.put(CSS.Property.FONT_SIZE, CSS.Value.XX_SMALL);
else if(size.equals("2")) css.put(CSS.Property.FONT_SIZE, CSS.Value.X_SMALL);
else if(size.equals("3")) css.put(CSS.Property.FONT_SIZE, CSS.Value.SMALL);
else if(size.equals("4")) css.put(CSS.Property.FONT_SIZE, CSS.Value.MEDIUM);
else if(size.equals("5")) css.put(CSS.Property.FONT_SIZE, CSS.Value.LARGE);
else if(size.equals("6")) css.put(CSS.Property.FONT_SIZE, CSS.Value.X_LARGE);
else if(size.equals("7")) css.put(CSS.Property.FONT_SIZE, CSS.Value.XX_LARGE);
}
} else if (t.getName().equals(HTML.Tag.A)) {
css.put(CSS.Property.TEXT_DECORATION, CSS.Value.UNDERLINE);
css.put(CSS.Property.COLOR, "blue");
}
}
// overwrite properties (if value != inherit)
for (Entry e : tagCss.entrySet()) {
if (!CSS.Value.INHERIT.equalsIgnoreCase(e.getValue())) {
if (e.getKey().equals(CSS.Property.TEXT_DECORATION)) {
String oldValue = css.get(e.getKey());
css.put(e.getKey(), mergeTextDecorationRules(oldValue, e.getValue()));
} else {
css.put(e.getKey(), e.getValue());
}
}
}
}
private String mergeTextDecorationRules(String oldRule, String newRule) {
if (CSS.Value.NONE.equals(newRule))
return newRule;
TreeSet attrSet = new TreeSet();
if (oldRule != null)
Collections.addAll(attrSet, oldRule.split("\\s+"));
if (newRule != null)
Collections.addAll(attrSet, newRule.split("\\s+"));
StringBuilder resultantStr = new StringBuilder();
for (String attr : attrSet) {
if (attr.equals(CSS.Value.NONE) || attr.equals(CSS.Value.INHERIT))
continue;
if (resultantStr.length() > 0)
resultantStr.append(' ');
resultantStr.append(attr);
}
return resultantStr.length() == 0 ? null : resultantStr.toString();
}
/**
* @param css the css map to populate
* @param key the property
* @param value the value
*/
private void splitRules(final Map css, final String key, final String value) {
if (CSS.Property.BORDER.equalsIgnoreCase(key)) {
css.putAll(utils.parseBorder(value));
} else if (CSS.Property.BORDER_TOP.equalsIgnoreCase(key)) {
css.putAll(utils.parseBorder(value, CSS.Property.BORDER_TOP));
} else if (CSS.Property.BORDER_BOTTOM.equalsIgnoreCase(key)) {
css.putAll(utils.parseBorder(value, CSS.Property.BORDER_BOTTOM));
} else if (CSS.Property.BORDER_LEFT.equalsIgnoreCase(key)) {
css.putAll(utils.parseBorder(value, CSS.Property.BORDER_LEFT));
} else if (CSS.Property.BORDER_RIGHT.equalsIgnoreCase(key)) {
css.putAll(utils.parseBorder(value, CSS.Property.BORDER_RIGHT));
} else if (CSS.Property.MARGIN.equalsIgnoreCase(key)) {
css.putAll(utils.parseBoxValues(value, "margin-", ""));
} else if (CSS.Property.BORDER_WIDTH.equalsIgnoreCase(key)) {
css.putAll(utils.parseBoxValues(value, "border-", "-width"));
} else if (CSS.Property.BORDER_STYLE.equalsIgnoreCase(key)) {
css.putAll(utils.parseBoxValues(value, "border-", "-style"));
} else if (CSS.Property.BORDER_COLOR.equalsIgnoreCase(key)) {
css.putAll(utils.parseBoxValues(value, "border-", "-color"));
} else if (CSS.Property.PADDING.equalsIgnoreCase(key)) {
css.putAll(utils.parseBoxValues(value, "padding-", ""));
} else if (CSS.Property.FONT.equalsIgnoreCase(key)) {
css.putAll(utils.processFont(value));
} else if (CSS.Property.LIST_STYLE.equalsIgnoreCase(key)) {
css.putAll(utils.processListStyle(value));
} else if (key.toLowerCase().contains(CSS.Property.BACKGROUND)) {
Map backgroundStyles = utils.processBackground(value);
for (String backgroundKey : backgroundStyles.keySet()) {
if (!css.containsKey(backgroundKey)) {
css.put(backgroundKey, backgroundStyles.get(backgroundKey));
}
}
} else {
css.put(key, value);
}
}
/**
* By setting an implementation of {@link CssInheritanceRules} a developer can set rules on what css selectors are
* inherited from parent tags.
*
* @param cssInheritanceRules the inherit to set
*/
public void setCssInheritance(final CssInheritanceRules cssInheritanceRules) {
this.inherit = cssInheritanceRules;
}
/**
* Defaults to true if no {@link CssInheritanceRules} implementation set.
*
* @param t
* @param property
* @return true if may be inherited false otherwise
*/
private boolean canInherite(final Tag t, final String property) {
if (null != this.inherit) {
return this.inherit.inheritCssSelector(t, property);
}
return true;
}
/**
* Defaults to true if no {@link CssInheritanceRules} implementation set.
*
* @param tag
* @return true if must be inherited false otherwise
*/
private boolean mustInherit(final String tag) {
if (null != this.inherit) {
return this.inherit.inheritCssTag(tag);
}
return true;
}
/*
* (non-Javadoc)
* @see com.itextpdf.tool.xml.pipeline.css.CSSResolver#addCss(java.lang.String, java.lang.String)
*/
public void addCss(final String content, final String charSet, final boolean isPersistent) throws CssResolverException {
CssFileProcessor proc = new CssFileProcessor();
try {
retrieve.processFromStream(new ByteArrayInputStream(content.getBytes(charSet)), proc);
CssFile css = proc.getCss();
css.isPersistent(isPersistent);
this.cssFiles.add(css);
} catch (UnsupportedEncodingException e) {
throw new CssResolverException(e);
} catch (IOException e) {
throw new CssResolverException(e);
}
}
/**
* Add a file to the CssFiles Collection.
*
* @param href the path, if it starts with http we try to retrieve the file
* from the net, if not we try a normal file operation.
*/
public void addCssFile(final String href, final boolean isPersistent) throws CssResolverException {
CssFileProcessor cssFileProcessor = new CssFileProcessor();
try {
retrieve.processFromHref(href, cssFileProcessor);
} catch (IOException e) {
throw new CssResolverException(e);
}
CssFile css = cssFileProcessor.getCss();
css.isPersistent(isPersistent);
this.cssFiles.add(css);
}
/**
* Add a file to the CssFiles Collection.
* @param file the CssFile to add.
*/
public void addCss(final CssFile file) {
this.cssFiles.add(file);
}
/* (non-Javadoc)
* @see com.itextpdf.tool.xml.pipeline.css.CSSResolver#addCss(java.lang.String)
*/
public void addCss(final String content, final boolean isPersistent) throws CssResolverException {
CssFileProcessor proc = new CssFileProcessor();
FileRetrieve retrieve = new FileRetrieveImpl();
try {
retrieve.processFromStream(new ByteArrayInputStream(content.getBytes()), proc);
CssFile css = proc.getCss();
css.isPersistent(isPersistent);
this.cssFiles.add(css);
} catch (UnsupportedEncodingException e) {
throw new CssResolverException(e);
} catch (IOException e) {
throw new CssResolverException(e);
}
}
/**
* @param inherit the inherit to set
*/
public void setCssInheritanceRules(final CssInheritanceRules inherit) {
this.inherit = inherit;
}
/**
* The {@link FileRetrieve} implementation to use in {@link StyleAttrCSSResolver#addCss(String, boolean)}.
* @param retrieve the retrieve to set
*/
public void setFileRetrieve(final FileRetrieve retrieve) {
this.retrieve = retrieve;
}
/* (non-Javadoc)
* @see com.itextpdf.tool.xml.pipeline.css.CSSResolver#clear()
*/
public CSSResolver clear() throws CssResolverException {
cssFiles.clear();
return this;
}
}