/* * export.cc * * Export styles to HTML * * by WangLu * 2012.08.14 */ #include #include #include "HTMLRenderer.h" #include "util/namespace.h" #include "util/base64stream.h" #include "util/math.h" #include "util/misc.h" namespace pdf2htmlEX { using std::cerr; using std::endl; void HTMLRenderer::export_remote_font(const FontInfo & info, const string & suffix, GfxFont * font) { string mime_type, format; if(suffix == ".ttf") { format = "truetype"; mime_type = "application/x-font-ttf"; } else if(suffix == ".otf") { format = "opentype"; mime_type = "application/x-font-otf"; } else if(suffix == ".woff") { format = "woff"; mime_type = "application/font-woff"; } else if(suffix == ".eot") { format = "embedded-opentype"; mime_type = "application/vnd.ms-fontobject"; } else if(suffix == ".svg") { format = "svg"; mime_type = "image/svg+xml"; } else { cerr << "Warning: unknown font suffix: " << suffix << endl; } f_css.fs << "@font-face{" << "font-family:f" << info.id << ";" << "src:url("; { auto fn = str_fmt("f%llx%s", info.id, suffix.c_str()); if(param->single_html) { auto path = param->tmp_dir + "/" + (char*)fn; ifstream fin(path, ifstream::binary); if(!fin) throw "Cannot locate font file: " + path; f_css.fs << "'data:font/" + mime_type + ";base64," << base64stream(fin) << "'"; } else { f_css.fs << (char*)fn; } } f_css.fs << ")" << "format(\"" << format << "\");" << "}" // end of @font-face << ".f" << info.id << "{" << "font-family:f" << info.id << ";" << "line-height:" << round(info.ascent - info.descent) << ";" << "font-style:normal;" << "font-weight:normal;" << "visibility:visible;" << "}" // end of .f << endl; } static string general_font_family(GfxFont * font) { if(font->isFixedWidth()) return "monospace"; else if (font->isSerif()) return "serif"; else return "sans-serif"; } // TODO: this function is called when some font is unable to process, may use the name there as a hint void HTMLRenderer::export_remote_default_font(long long fn_id) { f_css.fs << ".f" << fn_id << "{font-family:sans-serif;visibility:hidden;}" << endl; } void HTMLRenderer::export_local_font(const FontInfo & info, GfxFont * font, const string & original_font_name, const string & cssfont) { f_css.fs << ".f" << info.id << "{"; f_css.fs << "font-family:" << ((cssfont == "") ? (original_font_name + "," + general_font_family(font)) : cssfont) << ";"; string fn = original_font_name; for(auto iter = fn.begin(); iter != fn.end(); ++iter) *iter = tolower(*iter); if(font->isBold() || (fn.find("bold") != string::npos)) f_css.fs << "font-weight:bold;"; else f_css.fs << "font-weight:normal;"; if(fn.find("oblique") != string::npos) f_css.fs << "font-style:oblique;"; else if(font->isItalic() || (fn.find("italic") != string::npos)) f_css.fs << "font-style:italic;"; else f_css.fs << "font-style:normal;"; f_css.fs << "line-height:" << round(info.ascent - info.descent) << ";"; f_css.fs << "visibility:visible;"; f_css.fs << "}" << endl; } void HTMLRenderer::export_font_size (long long fs_id, double font_size) { f_css.fs << ".s" << fs_id << "{font-size:" << round(font_size) << "px;}" << endl; } void HTMLRenderer::export_transform_matrix (long long tm_id, const double * tm) { f_css.fs << ".t" << tm_id << "{"; // always ignore tm[4] and tm[5] because // we have already shifted the origin // TODO: recognize common matices if(tm_equal(tm, ID_MATRIX, 4)) { auto prefixes = {"", "-ms-", "-moz-", "-webkit-", "-o-"}; for(auto iter = prefixes.begin(); iter != prefixes.end(); ++iter) f_css.fs << *iter << "transform:none;"; } else { auto prefixes = {"", "-ms-", "-moz-", "-webkit-", "-o-"}; for(auto iter = prefixes.begin(); iter != prefixes.end(); ++iter) { // PDF use a different coordinate system from Web f_css.fs << *iter << "transform:matrix(" << round(tm[0]) << ',' << round(-tm[1]) << ',' << round(-tm[2]) << ',' << round(tm[3]) << ','; f_css.fs << "0,0);"; } } f_css.fs << "}" << endl; } void HTMLRenderer::export_letter_space (long long ls_id, double letter_space) { f_css.fs << ".l" << ls_id << "{letter-spacing:" << round(letter_space) << "px;}" << endl; } 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_fill_color (long long color_id, const GfxRGB * rgb) { 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) { if(ws_width > 0) f_css.fs << "._" << ws_id << "{display:inline-block;width:" << round(ws_width) << "px;}" << endl; else f_css.fs << "._" << ws_id << "{display:inline;margin-left:" << round(ws_width) << "px;}" << endl; } void HTMLRenderer::export_rise (long long rise_id, double rise) { f_css.fs << ".r" << rise_id << "{top:" << round(-rise) << "px;}" << endl; } void HTMLRenderer::export_height (long long height_id, double height) { f_css.fs << ".h" << height_id << "{height:" << round(height) << "px;}" << endl; } void HTMLRenderer::export_left (long long left_id, double left) { f_css.fs << ".L" << left_id << "{left:" << round(left) << "px;}" << endl; } }