1
0
mirror of https://github.com/pdf2htmlEX/pdf2htmlEX.git synced 2024-07-05 01:28:39 +00:00

Merge pull request #81 from jahewson/master

Stroked Text
This commit is contained in:
Lu Wang 2013-02-01 05:35:40 -08:00
commit ba9719546e
7 changed files with 158 additions and 38 deletions

View File

@ -125,6 +125,22 @@ span {
}
.a {
}
/* transparent color - Firefox, IE, etc. */
.ct { /*fill*/
color: white;
}
.Ct { /*stroke*/
text-shadow: none;
}
/* transparent color - WebKit */
@media screen and (-webkit-min-device-pixel-ratio:0) {
.ct { /*fill*/
color: transparent;
}
.Ct { /*stroke*/
-webkit-text-stroke: 0px transparent;
}
}
.Cd { /* css drawing */
position:absolute;
transform-origin:0% 100%;

View File

@ -53,7 +53,8 @@
* s<hex> - font Size
* l<hex> - Letter spacing
* w<hex> - Word spacing
* c<hex> - Color
* c<hex> - Fill Color
* C<hex> - Stroke Color
* _<hex> - white space
* r<hex> - Rise
* h<hex> - Height
@ -235,7 +236,8 @@ class HTMLRenderer : public OutputDev
long long install_transform_matrix(const double * tm);
long long install_letter_space(double letter_space);
long long install_word_space(double word_space);
long long install_color(const GfxRGB * rgb);
long long install_fill_color(const GfxRGB * rgb);
long long install_stroke_color(const GfxRGB * rgb);
long long install_whitespace(double ws_width, double & actual_width);
long long install_rise(double rise);
long long install_height(double height);
@ -256,7 +258,8 @@ class HTMLRenderer : public OutputDev
void export_transform_matrix(long long tm_id, const double * tm);
void export_letter_space(long long ls_id, double letter_space);
void export_word_space(long long ws_id, double word_space);
void export_color(long long color_id, const GfxRGB * rgb);
void export_fill_color(long long color_id, const GfxRGB * rgb);
void export_stroke_color(long long color_id, const GfxRGB * rgb);
void export_whitespace(long long ws_id, double ws_width);
void export_rise(long long rise_id, double rise);
void export_height(long long height_id, double height);
@ -378,9 +381,10 @@ class HTMLRenderer : public OutputDev
bool word_space_changed;
// text color
long long cur_color_id;
GfxRGB cur_color;
bool color_changed;
long long cur_fill_color_id, cur_stroke_color_id;
GfxRGB cur_fill_color, cur_stroke_color;
bool cur_has_fill, cur_has_stroke;
bool fill_color_changed, stroke_color_changed;
// rise
long long cur_rise_id;
@ -428,7 +432,7 @@ class HTMLRenderer : public OutputDev
std::map<Matrix, long long, Matrix_less> transform_matrix_map;
std::map<double, long long> letter_space_map;
std::map<double, long long> word_space_map;
std::unordered_map<GfxRGB, long long, GfxRGB_hash, GfxRGB_equal> color_map;
std::unordered_map<GfxRGB, long long, GfxRGB_hash, GfxRGB_equal> fill_color_map, stroke_color_map;
std::map<double, long long> whitespace_map;
std::map<double, long long> rise_map;
std::map<double, long long> height_map;

View File

@ -187,7 +187,8 @@ void HTMLRenderer::TextLineBuffer::set_state (State & state)
{
state.ids[State::FONT_ID] = renderer->cur_font_info->id;
state.ids[State::FONT_SIZE_ID] = renderer->cur_fs_id;
state.ids[State::COLOR_ID] = renderer->cur_color_id;
state.ids[State::FILL_COLOR_ID] = renderer->cur_fill_color_id;
state.ids[State::STROKE_COLOR_ID] = renderer->cur_stroke_color_id;
state.ids[State::LETTER_SPACE_ID] = renderer->cur_ls_id;
state.ids[State::WORD_SPACE_ID] = renderer->cur_ws_id;
state.ids[State::RISE_ID] = renderer->cur_rise_id;
@ -216,8 +217,16 @@ void HTMLRenderer::TextLineBuffer::State::begin (ostream & out, const State * pr
out << ' ';
}
// out should has set hex
out << format_str[i] << ids[i];
// out should have hex set
if (ids[i] == -1)
{
// transparent
out << format_str[i] << "t";
}
else
{
out << format_str[i] << ids[i];
}
}
if(first)
@ -262,5 +271,5 @@ int HTMLRenderer::TextLineBuffer::State::diff(const State & s) const
return d;
}
const char * HTMLRenderer::TextLineBuffer::State::format_str = "fsclwr";
const char * HTMLRenderer::TextLineBuffer::State::format_str = "fscClwr";
} //namespace pdf2htmlEX

View File

@ -33,7 +33,8 @@ public:
enum {
FONT_ID,
FONT_SIZE_ID,
COLOR_ID,
FILL_COLOR_ID,
STROKE_COLOR_ID,
LETTER_SPACE_ID,
WORD_SPACE_ID,
RISE_ID,

View File

@ -178,9 +178,29 @@ void HTMLRenderer::export_word_space (long long ws_id, double word_space)
f_css.fs << ".w" << ws_id << "{word-spacing:" << round(word_space) << "px;}" << endl;
}
void HTMLRenderer::export_color (long long color_id, const GfxRGB * rgb)
void HTMLRenderer::export_fill_color (long long color_id, const GfxRGB * rgb)
{
f_css.fs << ".c" << color_id << "{color:" << (*rgb) << ";}" << endl;
f_css.fs << ".c" << color_id << "{color:" << *rgb << ";}" << endl;
}
void HTMLRenderer::export_stroke_color (long long color_id, const GfxRGB * rgb)
{
// TODO: take the stroke width from the graphics state,
// currently using 0.015em as a good default
// Firefox, IE, etc.
f_css.fs << ".C" << color_id << "{"
<< "text-shadow: "
<< "-0.015em 0 " << *rgb << ","
<< "0 0.015em " << *rgb << ","
<< "0.015em 0 " << *rgb << ","
<< "0 -0.015em " << *rgb << ";"
<< "}" << endl;
// WebKit
f_css.fs << "@media screen and (-webkit-min-device-pixel-ratio:0) {";
f_css.fs << ".C" << color_id << "{-webkit-text-stroke: 0.015em " << *rgb << ";text-shadow: none;}";
f_css.fs << "}";
}
void HTMLRenderer::export_whitespace (long long ws_id, double ws_width)

View File

@ -264,16 +264,39 @@ long long HTMLRenderer::install_word_space(double word_space)
return new_ws_id;
}
long long HTMLRenderer::install_color(const GfxRGB * rgb)
long long HTMLRenderer::install_fill_color(const GfxRGB * rgb)
{
// transparent
if (rgb == nullptr) {
return -1;
}
const GfxRGB & c = *rgb;
auto iter = color_map.find(c);
if(iter != color_map.end())
auto iter = fill_color_map.find(c);
if(iter != fill_color_map.end())
return iter->second;
long long new_color_id = color_map.size();
color_map.insert(make_pair(c, new_color_id));
export_color(new_color_id, rgb);
long long new_color_id = fill_color_map.size();
fill_color_map.insert(make_pair(c, new_color_id));
export_fill_color(new_color_id, rgb);
return new_color_id;
}
long long HTMLRenderer::install_stroke_color(const GfxRGB * rgb)
{
// transparent
if (rgb == nullptr) {
return -1;
}
const GfxRGB & c = *rgb;
auto iter = stroke_color_map.find(c);
if(iter != stroke_color_map.end())
return iter->second;
long long new_color_id = stroke_color_map.size();
stroke_color_map.insert(make_pair(c, new_color_id));
export_stroke_color(new_color_id, rgb);
return new_color_id;
}

View File

@ -74,23 +74,24 @@ void HTMLRenderer::updateRender(GfxState * state)
{
// currently Render is traced for color only
// might need something like render_changed later
color_changed = true;
fill_color_changed = true;
stroke_color_changed = true;
}
void HTMLRenderer::updateFillColorSpace(GfxState * state)
{
color_changed = true;
fill_color_changed = true;
}
void HTMLRenderer::updateStrokeColorSpace(GfxState * state)
{
color_changed = true;
stroke_color_changed = true;
}
void HTMLRenderer::updateFillColor(GfxState * state)
{
color_changed = true;
fill_color_changed = true;
}
void HTMLRenderer::updateStrokeColor(GfxState * state)
{
color_changed = true;
stroke_color_changed = true;
}
void HTMLRenderer::reset_state()
{
@ -108,8 +109,12 @@ void HTMLRenderer::reset_state()
cur_ls_id = install_letter_space(cur_letter_space);
cur_ws_id = install_word_space(cur_word_space);
cur_color.r = cur_color.g = cur_color.b = 0;
cur_color_id = install_color(&cur_color);
cur_fill_color.r = cur_fill_color.g = cur_fill_color.b = 0;
cur_stroke_color.r = cur_stroke_color.g = cur_stroke_color.b = 0;
cur_fill_color_id = install_fill_color(&cur_fill_color);
cur_stroke_color_id = install_stroke_color(&cur_stroke_color);
cur_has_stroke = false;
cur_has_fill = true;
cur_rise = 0;
cur_rise_id = install_rise(cur_rise);
@ -135,7 +140,8 @@ void HTMLRenderer::reset_state_change()
letter_space_changed = false;
word_space_changed = false;
color_changed = false;
fill_color_changed = false;
stroke_color_changed = false;
}
void HTMLRenderer::check_state_change(GfxState * state)
{
@ -350,25 +356,65 @@ void HTMLRenderer::check_state_change(GfxState * state)
}
// color
if(all_changed || color_changed)
if(all_changed || fill_color_changed || stroke_color_changed)
{
GfxRGB new_color;
/*
* Render modes 0 2 4 6 fill text (stroke or not)
* Render modes 1 5 stroke only
* Render modes 3 7 hidden (but ok, we won't even draw text)
*/
if(state->getRender() % 2 == 0)
state->getFillRGB(&new_color);
else
state->getStrokeRGB(&new_color);
if(!((new_color.r == cur_color.r) && (new_color.g == cur_color.g) && (new_color.b == cur_color.b)))
// PDF Spec. Table 106 Text rendering modes
bool is_filled, is_stroked;
switch (state->getRender()) {
case 0: is_filled = true; is_stroked = false; break;
case 1: is_filled = false; is_stroked = true; break;
case 2: is_filled = true; is_stroked = true; break;
case 3: is_filled = false; is_stroked = false; break;
case 4: is_filled = true; is_stroked = false; break;
case 5: is_filled = false; is_stroked = true; break;
case 6: is_filled = true; is_stroked = true; break;
case 7: is_filled = false; is_stroked = false; break;
}
GfxRGB new_color;
// fill
state->getFillRGB(&new_color);
if(cur_has_fill != is_filled ||
!((new_color.r == cur_fill_color.r) &&
(new_color.g == cur_fill_color.g) &&
(new_color.b == cur_fill_color.b)))
{
new_line_state = max<NewLineState>(new_line_state, NLS_SPAN);
cur_color = new_color;
cur_color_id = install_color(&new_color);
cur_fill_color = new_color;
cur_fill_color_id = install_fill_color(&new_color);
}
if (!is_filled) {
cur_fill_color_id = install_fill_color(nullptr);
}
// stroke
state->getStrokeRGB(&new_color);
if(cur_has_stroke != is_stroked ||
!((new_color.r == cur_stroke_color.r) &&
(new_color.g == cur_stroke_color.g) &&
(new_color.b == cur_stroke_color.b)))
{
new_line_state = max<NewLineState>(new_line_state, NLS_SPAN);
cur_stroke_color = new_color;
cur_stroke_color_id = install_stroke_color(&new_color);
}
if (!is_stroked) {
cur_stroke_color_id = install_stroke_color(nullptr);
}
cur_has_fill = is_filled;
cur_has_stroke = is_stroked;
}
// rise
@ -386,6 +432,7 @@ void HTMLRenderer::check_state_change(GfxState * state)
reset_state_change();
}
void HTMLRenderer::prepare_text_line(GfxState * state)
{
if(!line_opened)