/// <summary>Resolves a content property.</summary>
 /// <param name="styles">the styles map</param>
 /// <param name="contentContainer">the content container</param>
 /// <param name="context">the CSS context</param>
 private void ResolveContentProperty(IDictionary <String, String> styles, INode contentContainer, CssContext
                                     context)
 {
     if (contentContainer is CssPseudoElementNode || contentContainer is PageMarginBoxContextNode)
     {
         IList <INode> resolvedContent = CssContentPropertyResolver.ResolveContent(styles, contentContainer, context
                                                                                   );
         if (resolvedContent != null)
         {
             foreach (INode child in resolvedContent)
             {
                 contentContainer.AddChild(child);
             }
         }
     }
     if (contentContainer is IElementNode)
     {
         context.GetCounterManager().AddTargetCounterIfRequired((IElementNode)contentContainer);
         context.GetCounterManager().AddTargetCountersIfRequired((IElementNode)contentContainer);
     }
 }
Example #2
0
        /// <summary>Resolves content.</summary>
        /// <param name="styles">the styles map</param>
        /// <param name="contentContainer">the content container</param>
        /// <param name="context">the CSS context</param>
        /// <returns>
        /// a list of
        /// <see cref="iText.StyledXmlParser.Node.INode"/>
        /// instances
        /// </returns>
        internal static IList <INode> ResolveContent(IDictionary <String, String> styles, INode contentContainer, CssContext
                                                     context)
        {
            String        contentStr = styles.Get(CssConstants.CONTENT);
            IList <INode> result     = new List <INode>();

            if (contentStr == null || CssConstants.NONE.Equals(contentStr) || CssConstants.NORMAL.Equals(contentStr))
            {
                return(null);
            }
            CssDeclarationValueTokenizer tokenizer = new CssDeclarationValueTokenizer(contentStr);

            CssDeclarationValueTokenizer.Token token;
            CssQuotes quotes = null;

            while ((token = tokenizer.GetNextValidToken()) != null)
            {
                if (token.IsString())
                {
                    result.Add(new CssContentPropertyResolver.ContentTextNode(contentContainer, token.GetValue()));
                }
                else
                {
                    if (token.GetValue().StartsWith(CssConstants.COUNTERS + "("))
                    {
                        String paramsStr = token.GetValue().JSubstring(CssConstants.COUNTERS.Length + 1, token.GetValue().Length -
                                                                       1);
                        String[] @params = iText.IO.Util.StringUtil.Split(paramsStr, ",");
                        if (@params.Length == 0)
                        {
                            return(ErrorFallback(contentStr));
                        }
                        // Counters are denoted by case-sensitive identifiers
                        String counterName          = @params[0].Trim();
                        String counterSeparationStr = @params[1].Trim();
                        counterSeparationStr = counterSeparationStr.JSubstring(1, counterSeparationStr.Length - 1);
                        String            listStyleType  = @params.Length > 2 ? @params[2].Trim() : null;
                        CssCounterManager counterManager = context.GetCounterManager();
                        INode             scope          = contentContainer;
                        if (CssConstants.PAGE.Equals(counterName))
                        {
                            result.Add(new PageCountElementNode(false, contentContainer));
                        }
                        else
                        {
                            if (CssConstants.PAGES.Equals(counterName))
                            {
                                result.Add(new PageCountElementNode(true, contentContainer));
                            }
                            else
                            {
                                String resolvedCounter = counterManager.ResolveCounters(counterName, counterSeparationStr, listStyleType,
                                                                                        scope);
                                if (resolvedCounter == null)
                                {
                                    logger.Error(MessageFormatUtil.Format(iText.Html2pdf.LogMessageConstant.UNABLE_TO_RESOLVE_COUNTER, counterName
                                                                          ));
                                }
                                else
                                {
                                    result.Add(new CssContentPropertyResolver.ContentTextNode(scope, resolvedCounter));
                                }
                            }
                        }
                    }
                    else
                    {
                        if (token.GetValue().StartsWith(CssConstants.COUNTER + "("))
                        {
                            String paramsStr = token.GetValue().JSubstring(CssConstants.COUNTER.Length + 1, token.GetValue().Length -
                                                                           1);
                            String[] @params = iText.IO.Util.StringUtil.Split(paramsStr, ",");
                            if (@params.Length == 0)
                            {
                                return(ErrorFallback(contentStr));
                            }
                            // Counters are denoted by case-sensitive identifiers
                            String            counterName    = @params[0].Trim();
                            String            listStyleType  = @params.Length > 1 ? @params[1].Trim() : null;
                            CssCounterManager counterManager = context.GetCounterManager();
                            INode             scope          = contentContainer;
                            if (CssConstants.PAGE.Equals(counterName))
                            {
                                result.Add(new PageCountElementNode(false, contentContainer));
                            }
                            else
                            {
                                if (CssConstants.PAGES.Equals(counterName))
                                {
                                    result.Add(new PageCountElementNode(true, contentContainer));
                                }
                                else
                                {
                                    String resolvedCounter = counterManager.ResolveCounter(counterName, listStyleType, scope);
                                    if (resolvedCounter == null)
                                    {
                                        logger.Error(MessageFormatUtil.Format(iText.Html2pdf.LogMessageConstant.UNABLE_TO_RESOLVE_COUNTER, counterName
                                                                              ));
                                    }
                                    else
                                    {
                                        result.Add(new CssContentPropertyResolver.ContentTextNode(scope, resolvedCounter));
                                    }
                                }
                            }
                        }
                        else
                        {
                            if (token.GetValue().StartsWith("url("))
                            {
                                IDictionary <String, String> attributes = new Dictionary <String, String>();
                                attributes.Put(AttributeConstants.SRC, CssUtils.ExtractUrl(token.GetValue()));
                                //TODO: probably should add user agent styles on CssContentElementNode creation, not here.
                                attributes.Put(AttributeConstants.STYLE, CssConstants.DISPLAY + ":" + CssConstants.INLINE_BLOCK);
                                result.Add(new CssContentElementNode(contentContainer, TagConstants.IMG, attributes));
                            }
                            else
                            {
                                if (CssGradientUtil.IsCssLinearGradientValue(token.GetValue()))
                                {
                                    IDictionary <String, String> attributes = new Dictionary <String, String>();
                                    attributes.Put(AttributeConstants.STYLE, CssConstants.BACKGROUND_IMAGE + ":" + token.GetValue() + ";" + CssConstants
                                                   .HEIGHT + ":" + CssConstants.INHERIT + ";" + CssConstants.WIDTH + ":" + CssConstants.INHERIT + ";");
                                    result.Add(new CssContentElementNode(contentContainer, TagConstants.DIV, attributes));
                                }
                                else
                                {
                                    if (token.GetValue().StartsWith("attr(") && contentContainer is CssPseudoElementNode)
                                    {
                                        int endBracket = token.GetValue().IndexOf(')');
                                        if (endBracket > 5)
                                        {
                                            String attrName = token.GetValue().JSubstring(5, endBracket);
                                            if (attrName.Contains("(") || attrName.Contains(" ") || attrName.Contains("'") || attrName.Contains("\""))
                                            {
                                                return(ErrorFallback(contentStr));
                                            }
                                            IElementNode element = (IElementNode)contentContainer.ParentNode();
                                            String       value   = element.GetAttribute(attrName);
                                            result.Add(new CssContentPropertyResolver.ContentTextNode(contentContainer, value == null ? "" : value));
                                        }
                                    }
                                    else
                                    {
                                        if (token.GetValue().EndsWith("quote") && contentContainer is IStylesContainer)
                                        {
                                            if (quotes == null)
                                            {
                                                quotes = CssQuotes.CreateQuotes(styles.Get(CssConstants.QUOTES), true);
                                            }
                                            String value = quotes.ResolveQuote(token.GetValue(), context);
                                            if (value == null)
                                            {
                                                return(ErrorFallback(contentStr));
                                            }
                                            result.Add(new CssContentPropertyResolver.ContentTextNode(contentContainer, value));
                                        }
                                        else
                                        {
                                            if (token.GetValue().StartsWith(CssConstants.ELEMENT + "(") && contentContainer is PageMarginBoxContextNode
                                                )
                                            {
                                                String paramsStr = token.GetValue().JSubstring(CssConstants.ELEMENT.Length + 1, token.GetValue().Length -
                                                                                               1);
                                                String[] @params = iText.IO.Util.StringUtil.Split(paramsStr, ",");
                                                if (@params.Length == 0)
                                                {
                                                    return(ErrorFallback(contentStr));
                                                }
                                                String name = @params[0].Trim();
                                                String runningElementOccurrence = null;
                                                if (@params.Length > 1)
                                                {
                                                    runningElementOccurrence = @params[1].Trim();
                                                }
                                                result.Add(new PageMarginRunningElementNode(name, runningElementOccurrence));
                                            }
                                            else
                                            {
                                                return(ErrorFallback(contentStr));
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return(result);
        }