mirror of
https://github.com/pdf2htmlEX/pdf2htmlEX.git
synced 2024-10-06 12:01:39 +00:00
316 lines
8.9 KiB
C++
316 lines
8.9 KiB
C++
/*
|
|
* install.cc
|
|
*
|
|
* maintaining all known styles
|
|
*
|
|
* by WangLu
|
|
* 2012.08.14
|
|
*/
|
|
|
|
#include <iostream>
|
|
#include <cmath>
|
|
#include <algorithm>
|
|
|
|
#include <GlobalParams.h>
|
|
|
|
#include "Param.h"
|
|
#include "HTMLRenderer.h"
|
|
#include "util/namespace.h"
|
|
#include "util/math.h"
|
|
#include "util/misc.h"
|
|
|
|
namespace pdf2htmlEX {
|
|
|
|
using std::abs;
|
|
using std::cerr;
|
|
using std::endl;
|
|
|
|
const FontInfo * HTMLRenderer::install_font(GfxFont * font)
|
|
{
|
|
assert(sizeof(long long) == 2*sizeof(int));
|
|
|
|
long long fn_id = (font == nullptr) ? 0 : hash_ref(font->getID());
|
|
|
|
auto iter = font_name_map.find(fn_id);
|
|
if(iter != font_name_map.end())
|
|
return &(iter->second);
|
|
|
|
long long new_fn_id = font_name_map.size();
|
|
|
|
auto cur_info_iter = font_name_map.insert(make_pair(fn_id, FontInfo({new_fn_id, true}))).first;
|
|
|
|
if(font == nullptr)
|
|
{
|
|
export_remote_default_font(new_fn_id);
|
|
return &(cur_info_iter->second);
|
|
}
|
|
|
|
cur_info_iter->second.ascent = font->getAscent();
|
|
cur_info_iter->second.descent = font->getDescent();
|
|
|
|
if(param->debug)
|
|
{
|
|
cerr << "Install font: (" << (font->getID()->num) << ' ' << (font->getID()->gen) << ") -> " << "f" << hex << new_fn_id << dec << endl;
|
|
}
|
|
|
|
if(font->getType() == fontType3) {
|
|
cerr << "Type 3 fonts are unsupported and will be rendered as Image" << endl;
|
|
export_remote_default_font(new_fn_id);
|
|
return &(cur_info_iter->second);
|
|
}
|
|
if(font->getWMode()) {
|
|
cerr << "Writing mode is unsupported and will be rendered as Image" << endl;
|
|
export_remote_default_font(new_fn_id);
|
|
return &(cur_info_iter->second);
|
|
}
|
|
|
|
auto * font_loc = font->locateFont(xref, gTrue);
|
|
if(font_loc != nullptr)
|
|
{
|
|
switch(font_loc -> locType)
|
|
{
|
|
case gfxFontLocEmbedded:
|
|
install_embedded_font(font, cur_info_iter->second);
|
|
break;
|
|
case gfxFontLocExternal:
|
|
install_external_font(font, cur_info_iter->second);
|
|
break;
|
|
case gfxFontLocResident:
|
|
install_base_font(font, font_loc, cur_info_iter->second);
|
|
break;
|
|
default:
|
|
cerr << "TODO: other font loc" << endl;
|
|
export_remote_default_font(new_fn_id);
|
|
break;
|
|
}
|
|
delete font_loc;
|
|
}
|
|
else
|
|
{
|
|
export_remote_default_font(new_fn_id);
|
|
}
|
|
|
|
return &(cur_info_iter->second);
|
|
}
|
|
|
|
void HTMLRenderer::install_embedded_font(GfxFont * font, FontInfo & info)
|
|
{
|
|
auto path = dump_embedded_font(font, info.id);
|
|
|
|
if(path != "")
|
|
{
|
|
embed_font(path, font, info);
|
|
export_remote_font(info, param->font_suffix, param->font_format, font);
|
|
}
|
|
else
|
|
{
|
|
export_remote_default_font(info.id);
|
|
}
|
|
}
|
|
|
|
void HTMLRenderer::install_base_font(GfxFont * font, GfxFontLoc * font_loc, FontInfo & info)
|
|
{
|
|
string psname(font_loc->path->getCString());
|
|
string basename = psname.substr(0, psname.find('-'));
|
|
|
|
GfxFontLoc * localfontloc = font->locateFont(xref, gFalse);
|
|
if(param->embed_base_font)
|
|
{
|
|
if(localfontloc != nullptr)
|
|
{
|
|
embed_font(localfontloc->path->getCString(), font, info);
|
|
export_remote_font(info, param->font_suffix, param->font_format, font);
|
|
delete localfontloc;
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
cerr << "Cannot embed base font: f" << hex << info.id << dec << ' ' << psname << endl;
|
|
// fallback to exporting by name
|
|
}
|
|
|
|
}
|
|
|
|
string cssfont;
|
|
auto iter = BASE_14_FONT_CSS_FONT_MAP.find(basename);
|
|
if(iter == BASE_14_FONT_CSS_FONT_MAP.end())
|
|
{
|
|
cerr << "PS Font: " << basename << " not found in the base 14 font map" << endl;
|
|
cssfont = "";
|
|
}
|
|
else
|
|
cssfont = iter->second;
|
|
|
|
// still try to get an idea of read ascent/descent
|
|
if(localfontloc != nullptr)
|
|
{
|
|
// fill in ascent/descent only, do not embed
|
|
embed_font(string(localfontloc->path->getCString()), font, info, true);
|
|
delete localfontloc;
|
|
}
|
|
else
|
|
{
|
|
info.ascent = font->getAscent();
|
|
info.descent = font->getDescent();
|
|
}
|
|
|
|
export_local_font(info, font, psname, cssfont);
|
|
}
|
|
|
|
void HTMLRenderer::install_external_font(GfxFont * font, FontInfo & info)
|
|
{
|
|
string fontname(font->getName()->getCString());
|
|
|
|
// resolve bad encodings in GB
|
|
auto iter = GB_ENCODED_FONT_NAME_MAP.find(fontname);
|
|
if(iter != GB_ENCODED_FONT_NAME_MAP.end())
|
|
{
|
|
fontname = iter->second;
|
|
cerr << "Warning: workaround for font names in bad encodings." << endl;
|
|
}
|
|
|
|
GfxFontLoc * localfontloc = font->locateFont(xref, gFalse);
|
|
|
|
if(param->embed_external_font)
|
|
{
|
|
if(localfontloc != nullptr)
|
|
{
|
|
embed_font(string(localfontloc->path->getCString()), font, info);
|
|
export_remote_font(info, param->font_suffix, param->font_format, font);
|
|
delete localfontloc;
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
cerr << "Cannot embed external font: f" << hex << info.id << dec << ' ' << fontname << endl;
|
|
// fallback to exporting by name
|
|
}
|
|
}
|
|
|
|
// still try to get an idea of read ascent/descent
|
|
if(localfontloc != nullptr)
|
|
{
|
|
// fill in ascent/descent only, do not embed
|
|
embed_font(string(localfontloc->path->getCString()), font, info, true);
|
|
delete localfontloc;
|
|
}
|
|
else
|
|
{
|
|
info.ascent = font->getAscent();
|
|
info.descent = font->getDescent();
|
|
}
|
|
|
|
export_local_font(info, font, fontname, "");
|
|
}
|
|
|
|
long long HTMLRenderer::install_font_size(double font_size)
|
|
{
|
|
auto iter = font_size_map.lower_bound(font_size - EPS);
|
|
if((iter != font_size_map.end()) && (equal(iter->first, font_size)))
|
|
return iter->second;
|
|
|
|
long long new_fs_id = font_size_map.size();
|
|
font_size_map.insert(make_pair(font_size, new_fs_id));
|
|
export_font_size(new_fs_id, font_size);
|
|
return new_fs_id;
|
|
}
|
|
|
|
long long HTMLRenderer::install_transform_matrix(const double * tm)
|
|
{
|
|
Matrix m;
|
|
memcpy(m.m, tm, sizeof(m.m));
|
|
|
|
auto iter = transform_matrix_map.lower_bound(m);
|
|
if((iter != transform_matrix_map.end()) && (tm_equal(m.m, iter->first.m, 4)))
|
|
return iter->second;
|
|
|
|
long long new_tm_id = transform_matrix_map.size();
|
|
transform_matrix_map.insert(make_pair(m, new_tm_id));
|
|
export_transform_matrix(new_tm_id, tm);
|
|
return new_tm_id;
|
|
}
|
|
|
|
long long HTMLRenderer::install_letter_space(double letter_space)
|
|
{
|
|
auto iter = letter_space_map.lower_bound(letter_space - EPS);
|
|
if((iter != letter_space_map.end()) && (equal(iter->first, letter_space)))
|
|
return iter->second;
|
|
|
|
long long new_ls_id = letter_space_map.size();
|
|
letter_space_map.insert(make_pair(letter_space, new_ls_id));
|
|
export_letter_space(new_ls_id, letter_space);
|
|
return new_ls_id;
|
|
}
|
|
|
|
long long HTMLRenderer::install_word_space(double word_space)
|
|
{
|
|
auto iter = word_space_map.lower_bound(word_space - EPS);
|
|
if((iter != word_space_map.end()) && (equal(iter->first, word_space)))
|
|
return iter->second;
|
|
|
|
long long new_ws_id = word_space_map.size();
|
|
word_space_map.insert(make_pair(word_space, new_ws_id));
|
|
export_word_space(new_ws_id, word_space);
|
|
return new_ws_id;
|
|
}
|
|
|
|
long long HTMLRenderer::install_color(const GfxRGB * rgb)
|
|
{
|
|
const GfxRGB & c = *rgb;
|
|
auto iter = color_map.find(c);
|
|
if(iter != 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);
|
|
return new_color_id;
|
|
}
|
|
|
|
long long HTMLRenderer::install_whitespace(double ws_width, double & actual_width)
|
|
{
|
|
// ws_width is already mulitpled by draw_scale
|
|
auto iter = whitespace_map.lower_bound(ws_width - param->h_eps);
|
|
if((iter != whitespace_map.end()) && (abs(iter->first - ws_width) < param->h_eps))
|
|
{
|
|
actual_width = iter->first;
|
|
return iter->second;
|
|
}
|
|
|
|
actual_width = ws_width;
|
|
long long new_ws_id = whitespace_map.size();
|
|
whitespace_map.insert(make_pair(ws_width, new_ws_id));
|
|
export_whitespace(new_ws_id, ws_width);
|
|
return new_ws_id;
|
|
}
|
|
|
|
long long HTMLRenderer::install_rise(double rise)
|
|
{
|
|
auto iter = rise_map.lower_bound(rise - param->v_eps);
|
|
if((iter != rise_map.end()) && (abs(iter->first - rise) < param->v_eps))
|
|
{
|
|
return iter->second;
|
|
}
|
|
|
|
long long new_rise_id = rise_map.size();
|
|
rise_map.insert(make_pair(rise, new_rise_id));
|
|
export_rise(new_rise_id, rise);
|
|
return new_rise_id;
|
|
}
|
|
|
|
long long HTMLRenderer::install_height(double height)
|
|
{
|
|
auto iter = height_map.lower_bound(height - EPS);
|
|
if((iter != height_map.end()) && (abs(iter->first - height) < EPS))
|
|
{
|
|
return iter->second;
|
|
}
|
|
|
|
long long new_height_id = height_map.size();
|
|
height_map.insert(make_pair(height, new_height_id));
|
|
export_height(new_height_id, height);
|
|
return new_height_id;
|
|
}
|
|
|
|
} // namespace pdf2htmlEX
|