-
Notifications
You must be signed in to change notification settings - Fork 356
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Base64 encode fonts and images for PDF rendering #1363
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
/* | ||
* Encoded FontAwesome ttf | ||
*/ | ||
|
||
@font-face { | ||
font-family: 'FontAwesome'; | ||
src: url(<%= asset_data_uri("font-awesome/fontawesome-webfont.ttf") %>); | ||
font-weight: normal; | ||
font-style: normal; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
/* | ||
* Encoded PatternFly ttf | ||
*/ | ||
|
||
@font-face { | ||
font-family: "PatternFlyIcons-webfont"; | ||
src: url(<%= asset_data_uri("patternfly/PatternFlyIcons-webfont.ttf") %>); | ||
font-weight: normal; | ||
font-style: normal; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
body {font: 13px/1.231 Arial,Helvetica,sans-serif;} | ||
|
||
table { border-spacing:0px;border-left: 1px solid #d1d1d1;border-collapse:separate; color: #4d5258;} | ||
table thead tr th {height: 19px;margin: 0;padding: 4px;padding-left:10px;border-right: 1px solid #d1d1d1;border-left: 0px !important;border-top: 1px solid #d1d1d1;border-bottom: 1px #d1d1d1 solid;font: normal 12px Arial,Helvetica,sans-serif !important;line-height: 19px;} | ||
table thead tr th {background: #f5f5f5} | ||
table tbody tr.row1-nocursor {background: #f5f5f5} | ||
table tbody tr td {border: 1px solid transparent;border-right: 1px solid #d1d1d1;border-bottom-color: #e7e7e7;padding: 2px 2px 2px 10px;margin: 0;vertical-align: middle;cursor: default;color: #4d5258;} | ||
table tbody tr td.group { border-top: 1px solid #fff; background: #ececec; font: normal 12px Arial,Helvetica,sans-serif;} | ||
|
||
table tbody tr td.miq_rpt_red_bg, table.adminlist tbody tr td.miq_rpt_red_bg, .miq_rpt_red_bg {background: #fbdbdb !important;} | ||
table tbody tr td.miq_rpt_yellow_bg, table.adminlist tbody tr td.miq_rpt_yellow_bg, .miq_rpt_yellow_bg {background-color: #ffdc99 !important;} | ||
table tbody tr td.miq_rpt_green_bg, table.adminlist tbody tr td.miq_rpt_green_bg, .miq_rpt_green_bg {background-color: #cef7c9 !important;} | ||
table tbody tr td.miq_rpt_blue_bg, table.adminlist tbody tr td.miq_rpt_blue_bg, .miq_rpt_blue_bg {background-color: #76badf !important;} | ||
table tbody tr td.miq_rpt_purple_bg, table.adminlist tbody tr td.miq_rpt_purple_bg, .miq_rpt_purple_bg {background-color: #c0acdc !important;} | ||
table tbody tr td.miq_rpt_maroon_bg, table.adminlist tbody tr td.miq_rpt_maroon_bg, .miq_rpt_maroon_bg {background-color: #d4edfa !important;} | ||
table tbody tr td.miq_rpt_gray_bg, table.adminlist tbody tr td.miq_rpt_gray_bg, .miq_rpt_gray_bg {background-color: #d1d1d1 !important;} | ||
|
||
.miq_rpt_red_text {color: #cc0000; font-weight: bold} | ||
.miq_rpt_yellow_text {color:#cccc00; font-weight: bold} | ||
.miq_rpt_green_text {color: #3f9c35; font-weight: bold} | ||
.miq_rpt_blue_text {color: #006e9c; font-weight: bold} | ||
.miq_rpt_purple_text {color: #925bad; font-weight: bold} | ||
.miq_rpt_maroon_text {color: #76badf; font-weight: bold} | ||
.miq_rpt_gray_text {color: gray; font-weight: bold} | ||
@page { prince-shrink-to-fit: auto } |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
body {font: 12px/1.231 Arial,Helvetica,sans-serif; padding-top: 100px;} | ||
|
||
#xyz_main { | ||
position: absolute; | ||
top: 0px; | ||
left: 50%; | ||
height: 200px !important; | ||
width: 100px; | ||
margin-left: -55px; | ||
text-align: left; | ||
} | ||
|
||
#quadicon {color: #e3e4e4;float:left; height: 72px; padding: 0px 1px 1px 0px;position: relative;text-transform: none;width: 72px;} | ||
#quadicon img {border:0px;} | ||
|
||
.flobj { position: absolute;z-index: auto;width: 72px;} | ||
.flobj p { margin: 0 0 0 0;padding: 0;color: #e3e4e4;vertical-align: middle;text-align:center;text-transform: none;text-shadow: 0 0 3px #000;font: normal 16px OpenSansSemibold,Arial,Helvetica,sans-serif !important;} | ||
.a72 { padding: 3px 0 0 5px; width: 28px; height: 28px;font-size: 1.3em;line-height: 1.8em;} | ||
.b72 { padding: 3px 0 0 37px; width: 28px; height: 28px;font-size: 1.3em;line-height: 1.8em;} | ||
.c72 { padding: 38px 0 0 5px; width: 31px; height: 31px;font-size: 1.3em;line-height: 1.7em;} | ||
.d72 { padding: 38px 0 0 39px; width: 31px; height: 31px;font-size: 1.3em;line-height: 1.7em;} | ||
.e72 { padding: 6px 0 0 6px; width: 35px; height: 35px;font-size: 1.3em;line-height: 2em;} | ||
.f72 { padding: 22px 0 0 24px; width: 24px; height: 24px;} | ||
.g72 { padding: 16px 0 0 19px; width: 24px; height: 24px;} | ||
.b72 img {margin-top: -3px; width: 34px; height: 34px;} | ||
.a72 img,.c72 img,.d72 img{ width: 28px; height: 28px;} | ||
.f72 img,.f72 img { width: 24px; height: 24px;} | ||
.g72 img,.g72 img { width: 36px; height: 36px;} | ||
.e72 img { width: 60px; height: 60px;} | ||
|
||
dl{float:left;width:100%;} | ||
dl.col2 dd {float:left;width:47%;margin:0;margin-right:15px;padding:0;} | ||
|
||
table {background-color: #ededed;border-spacing: 1px;margin-bottom: 15px;width: 100%;color: #4b4b4b;} | ||
table tr th {height: 19px;padding: 4px;padding-left:10px;font: normal 12px Arial,Helvetica,sans-serif !important;line-height: 19px;} | ||
table tr td.label{font: 12px Arial,Helvetica,sans-serif;width: 33%; text-align: right;cursor: default;} | ||
table tr td {background: #fff; vertical-align: top; padding: 3px 6px 3px 6px} | ||
table tr td img {height: 16px;width: 16px;float: left; padding-right: 3px; } | ||
table tr.row0 td {background: #fff} | ||
table tr.row1 td {background: #f5f5f5} | ||
|
||
.b72 .stretch { | ||
background-repeat: no-repeat; | ||
width: 35px; | ||
height: 32px; | ||
margin: -3px 0 -2px 1px; | ||
border-top-right-radius: 15px; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,25 +1,6 @@ | ||
body {font: 13px/1.231 Arial,Helvetica,sans-serif;} | ||
|
||
table { border-spacing:0px;border-left: 1px solid #d1d1d1;border-collapse:separate; color: #4d5258;} | ||
table thead tr th {height: 19px;margin: 0;padding: 4px;padding-left:10px;border-right: 1px solid #d1d1d1;border-left: 0px !important;border-top: 1px solid #d1d1d1;border-bottom: 1px #d1d1d1 solid;font: normal 12px Arial,Helvetica,sans-serif !important;line-height: 19px;} | ||
table thead tr th {background: #f5f5f5} | ||
table tbody tr.row1-nocursor {background: #f5f5f5} | ||
table tbody tr td {border: 1px solid transparent;border-right: 1px solid #d1d1d1;border-bottom-color: #e7e7e7;padding: 2px 2px 2px 10px;margin: 0;vertical-align: middle;cursor: default;color: #4d5258;} | ||
table tbody tr td.group { border-top: 1px solid #fff; background: #ececec; font: normal 12px Arial,Helvetica,sans-serif;} | ||
|
||
table tbody tr td.miq_rpt_red_bg, table.adminlist tbody tr td.miq_rpt_red_bg, .miq_rpt_red_bg {background: #fbdbdb !important;} | ||
table tbody tr td.miq_rpt_yellow_bg, table.adminlist tbody tr td.miq_rpt_yellow_bg, .miq_rpt_yellow_bg {background-color: #ffdc99 !important;} | ||
table tbody tr td.miq_rpt_green_bg, table.adminlist tbody tr td.miq_rpt_green_bg, .miq_rpt_green_bg {background-color: #cef7c9 !important;} | ||
table tbody tr td.miq_rpt_blue_bg, table.adminlist tbody tr td.miq_rpt_blue_bg, .miq_rpt_blue_bg {background-color: #76badf !important;} | ||
table tbody tr td.miq_rpt_purple_bg, table.adminlist tbody tr td.miq_rpt_purple_bg, .miq_rpt_purple_bg {background-color: #c0acdc !important;} | ||
table tbody tr td.miq_rpt_maroon_bg, table.adminlist tbody tr td.miq_rpt_maroon_bg, .miq_rpt_maroon_bg {background-color: #d4edfa !important;} | ||
table tbody tr td.miq_rpt_gray_bg, table.adminlist tbody tr td.miq_rpt_gray_bg, .miq_rpt_gray_bg {background-color: #d1d1d1 !important;} | ||
|
||
.miq_rpt_red_text {color: #cc0000; font-weight: bold} | ||
.miq_rpt_yellow_text {color:#cccc00; font-weight: bold} | ||
.miq_rpt_green_text {color: #3f9c35; font-weight: bold} | ||
.miq_rpt_blue_text {color: #006e9c; font-weight: bold} | ||
.miq_rpt_purple_text {color: #925bad; font-weight: bold} | ||
.miq_rpt_maroon_text {color: #76badf; font-weight: bold} | ||
.miq_rpt_gray_text {color: gray; font-weight: bold} | ||
@page { prince-shrink-to-fit: auto } | ||
/* | ||
* This sheet is used by PDFs generated with MiqReportResult | ||
*= require pdf/_report | ||
*= require pdf/_fontawesome | ||
*= require pdf/_patternfly | ||
*/ |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,40 +1,6 @@ | ||
body {font: 12px/1.231 Arial,Helvetica,sans-serif; padding-top: 100px;} | ||
|
||
#xyz_main { | ||
position: absolute; | ||
top: 0px; | ||
left: 50%; | ||
height: 200px !important; | ||
width: 100px; | ||
margin-left: -55px; | ||
text-align: left; | ||
} | ||
|
||
#quadicon {color: #e3e4e4;float:left; height: 72px; padding: 0px 1px 1px 0px;position: relative;text-transform: none;width: 72px;} | ||
#quadicon img {border:0px;} | ||
|
||
.flobj { position: absolute;z-index: auto;width: 72px;} | ||
.flobj p { margin: 0 0 0 0;padding: 0;color: #e3e4e4;vertical-align: middle;text-align:center;text-transform: none;text-shadow: 0 0 3px #000;font: normal 16px OpenSansSemibold,Arial,Helvetica,sans-serif !important;} | ||
.a72 { padding: 3px 0 0 5px; width: 28px; height: 28px;font-size: 1.3em;line-height: 1.8em;} | ||
.b72 { padding: 3px 0 0 37px; width: 28px; height: 28px;font-size: 1.3em;line-height: 1.8em;} | ||
.c72 { padding: 38px 0 0 5px; width: 31px; height: 31px;font-size: 1.3em;line-height: 1.7em;} | ||
.d72 { padding: 38px 0 0 39px; width: 31px; height: 31px;font-size: 1.3em;line-height: 1.7em;} | ||
.e72 { padding: 6px 0 0 6px; width: 35px; height: 35px;font-size: 1.3em;line-height: 2em;} | ||
.f72 { padding: 22px 0 0 24px; width: 24px; height: 24px;} | ||
.g72 { padding: 16px 0 0 19px; width: 24px; height: 24px;} | ||
.b72 img {margin-top: -3px; width: 34px; height: 34px;} | ||
.a72 img,.c72 img,.d72 img{ width: 28px; height: 28px;} | ||
.f72 img,.f72 img { width: 24px; height: 24px;} | ||
.g72 img,.g72 img { width: 36px; height: 36px;} | ||
.e72 img { width: 60px; height: 60px;} | ||
|
||
dl{float:left;width:100%;} | ||
dl.col2 dd {float:left;width:47%;margin:0;margin-right:15px;padding:0;} | ||
|
||
table {background-color: #ededed;border-spacing: 1px;margin-bottom: 15px;width: 100%;color: #4b4b4b;} | ||
table tr th {height: 19px;padding: 4px;padding-left:10px;font: normal 12px Arial,Helvetica,sans-serif !important;line-height: 19px;} | ||
table tr td.label{font: 12px Arial,Helvetica,sans-serif;width: 33%; text-align: right;cursor: default;} | ||
table tr td {background: #fff; vertical-align: top; padding: 3px 6px 3px 6px} | ||
table tr td img {height: 16px;width: 16px;float: left; padding-right: 3px; } | ||
table tr.row0 td {background: #fff} | ||
table tr.row1 td {background: #f5f5f5} | ||
/* | ||
* This sheet is used by PDFs generated from ApplicationController::ReportDownloads#set_summary_pdf_data | ||
*= require pdf/_summary | ||
*= require pdf/_fontawesome | ||
*= require pdf/_patternfly | ||
*/ |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
module ImageEncodeHelper | ||
def encodable_image_tag(source, options = {}) | ||
image_tag(encodable_image_source(source), options) | ||
end | ||
|
||
def encodable_image_source(source) | ||
if base64_encode_images? && source.present? | ||
base64_encoded_uri(source) | ||
else | ||
path_to_image(source) | ||
end | ||
end | ||
|
||
def base64_encode_images? | ||
@base64_encode_images | ||
end | ||
|
||
def base64_encoded_uri(source) | ||
asset = Rails.application.assets[source] | ||
|
||
if asset.content_type == 'image/svg+xml' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we actually need a special SVG branch here? Guess what, base64 encoded images are smaller :) - for our SVGs, the size sum is 1215 kB URL-encoded and 1189 kB base64 encoded. So, simpler code and smaller images... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Are you sure that's not a bug in the base64 branch of code? Unless prince's uri parser is signifcantly broken, this should not happen, so it feels like this may be exposing a bug there. Are you sure there's not a working non-home-cooked way of converting files to data uris? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Sounds like we need to run all of our images through an optimizer. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is more about base64 reliably taking 8/6ths of space, while URL-encoding a SVG tends to preserve most bytes, but for about a fifth, it makes them 3 times larger. But really, my concern here is mostly about having a hand-rolled solution to encode URLs in 2 different ways. If we used something ..established, I don't care what the resulting format is. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I googled for a while but did not find one. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Even URI::Data supports just parsing them. Oh well. |
||
encoding = 'charset=utf-8' | ||
data = ERB::Util.url_encode(asset.source).gsub('+', '%20') | ||
else | ||
encoding = 'base64' | ||
data = Base64.strict_encode64(asset.source) | ||
end | ||
|
||
"data:#{asset.content_type};#{encoding},#{data}" | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
- if item[:icon] | ||
%i{:class => item[:icon], :title => item[:title]} | ||
- elsif item[:image] | ||
= image_tag(image_path(item[:image]), :alt => item[:title], :title => item[:title]) | ||
= encodable_image_tag(item[:image], :alt => item[:title], :title => item[:title]) |
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Upstream code does not have Prince by default, though I think the only other choice is the NullPdf plugin. Even so, if/when we ever create a new PDF plugin, will this base64 encoding of images still be needed there? If not, should this be a property of the PDF plugin system?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Additionally, I don't really like this instance variable hanging out here. I think it might be better if the ImageEncodeHelper has an attr_accessor for this value (it already has the predicate getter), and then either the default is set in that getter on first access, or the value is set here through the setter
self.base64_encode_images = true
This might allow for better testing as well, so you can just call a method instead of doing some nasty instance_variable_set in the test.