Skip to content

Commit 530e9a0

Browse files
committed
Support base64 images in css content property
1 parent 08a16b6 commit 530e9a0

7 files changed

Lines changed: 49 additions & 7 deletions

File tree

Source/Demo/Common/HtmlRenderer.Demo.Common.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,9 @@
155155
<ItemGroup>
156156
<EmbeddedResource Include="Resources\image32.png" />
157157
</ItemGroup>
158+
<ItemGroup>
159+
<EmbeddedResource Include="TestSamples\32.Image in css content.htm" />
160+
</ItemGroup>
158161
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
159162
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
160163
Other similar extension points exist, see Microsoft.Common.targets.

Source/Demo/Common/TestSamples/32.Image in css content.htm

Lines changed: 14 additions & 0 deletions
Large diffs are not rendered by default.

Source/HtmlRenderer/Core/Dom/CssBoxImage.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ public RImage Image
6969
/// <param name="g">the device to draw to</param>
7070
protected override void PaintImp(RGraphics g)
7171
{
72-
// load image iff it is in visible rectangle
72+
// load image if it is in visible rectangle
7373
if (_imageLoadHandler == null)
7474
{
7575
_imageLoadHandler = new ImageLoadHandler(HtmlContainer, OnLoadImageComplete);
@@ -138,7 +138,11 @@ internal override void MeasureWordsSize(RGraphics g)
138138
if (_imageLoadHandler == null && (HtmlContainer.AvoidAsyncImagesLoading || HtmlContainer.AvoidImagesLateLoading))
139139
{
140140
_imageLoadHandler = new ImageLoadHandler(HtmlContainer, OnLoadImageComplete);
141-
_imageLoadHandler.LoadImage(GetAttribute("src"), HtmlTag != null ? HtmlTag.Attributes : null);
141+
142+
if (this.Content != null && this.Content != CssConstants.Normal)
143+
_imageLoadHandler.LoadImage(this.Content, HtmlTag != null ? HtmlTag.Attributes : null);
144+
else
145+
_imageLoadHandler.LoadImage(GetAttribute("src"), HtmlTag != null ? HtmlTag.Attributes : null);
142146
}
143147

144148
MeasureWordSpacing(g);

Source/HtmlRenderer/Core/Dom/CssBoxProperties.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ internal abstract class CssBoxProperties
5353
private string _borderCollapse = "separate";
5454
private string _bottom;
5555
private string _color = "black";
56+
private string _content = "normal";
5657
private string _cornerNwRadius = "0";
5758
private string _cornerNeRadius = "0";
5859
private string _cornerSeRadius = "0";
@@ -474,6 +475,12 @@ public string Color
474475
}
475476
}
476477

478+
public string Content
479+
{
480+
get { return _content; }
481+
set { _content = value; }
482+
}
483+
477484
public string Display
478485
{
479486
get { return _display; }
@@ -646,8 +653,7 @@ public string ListStyleType
646653
set { _listStyleType = value; }
647654
}
648655

649-
#endregion
650-
656+
#endregion CSS Properties
651657

652658
/// <summary>
653659
/// Gets or sets the location of the box

Source/HtmlRenderer/Core/Parse/CssParser.cs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,12 @@ private Dictionary<string, string> ParseCssBlockProperties(string blockSource)
395395
while (startIdx < blockSource.Length)
396396
{
397397
int endIdx = blockSource.IndexOfAny(_cssBlockSplitters, startIdx);
398+
399+
// If blockSource contains "data:image" then skip first semicolon since it is a part of image definition
400+
// example: "url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA......"
401+
if (startIdx >= 0 && endIdx - startIdx >= 10 && blockSource.Length - startIdx >= 10 && blockSource.IndexOf("data:image", startIdx, endIdx - startIdx) >= 0)
402+
endIdx = blockSource.IndexOfAny(_cssBlockSplitters, endIdx + 1);
403+
398404
if (endIdx < 0)
399405
endIdx = blockSource.Length - 1;
400406

@@ -485,7 +491,11 @@ private void AddProperty(string propName, string propValue, Dictionary<string, s
485491
}
486492
else if (propName == "background-image")
487493
{
488-
properties["background-image"] = ParseBackgroundImageProperty(propValue);
494+
properties["background-image"] = ParseImageProperty(propValue);
495+
}
496+
else if (propName == "content")
497+
{
498+
properties["content"] = ParseImageProperty(propValue);
489499
}
490500
else if (propName == "font-family")
491501
{
@@ -584,7 +594,7 @@ private void ParseFontProperty(string propValue, Dictionary<string, string> prop
584594
/// </summary>
585595
/// <param name="propValue">the value of the property to parse</param>
586596
/// <returns>parsed value</returns>
587-
private static string ParseBackgroundImageProperty(string propValue)
597+
private static string ParseImageProperty(string propValue)
588598
{
589599
int startIdx = propValue.IndexOf("url(", StringComparison.InvariantCultureIgnoreCase);
590600
if (startIdx > -1)

Source/HtmlRenderer/Core/Utils/CssUtils.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,8 @@ public static string GetPropertyValue(CssBox cssBox, string propName)
146146
return cssBox.BackgroundGradientAngle;
147147
case "color":
148148
return cssBox.Color;
149+
case "content":
150+
return cssBox.Content;
149151
case "display":
150152
return cssBox.Display;
151153
case "direction":
@@ -326,6 +328,9 @@ public static void SetPropertyValue(CssBox cssBox, string propName, string value
326328
case "color":
327329
cssBox.Color = value;
328330
break;
331+
case "content":
332+
cssBox.Content = value;
333+
break;
329334
case "display":
330335
cssBox.Display = value;
331336
break;

Source/HtmlRenderer/Core/Utils/HtmlConstants.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ internal static class HtmlConstants
128128
// public const string cols = "cols";
129129
// public const string colspan = "colspan";
130130
// public const string compact = "compact";
131-
// public const string content = "content";
131+
public const string content = "content";
132132
// public const string coords = "coords";
133133
// public const string data = "data";
134134
// public const string datetime = "datetime";

0 commit comments

Comments
 (0)