mirror of
https://github.com/pdf2htmlEX/pdf2htmlEX.git
synced 2024-12-22 13:00:08 +00:00
improve ascent/descent for type 3 fonts
This commit is contained in:
parent
8812bb52fb
commit
09856c0910
@ -58,6 +58,7 @@ string HTMLRenderer::dump_embedded_font (GfxFont * font, FontInfo & info)
|
|||||||
string filepath;
|
string filepath;
|
||||||
|
|
||||||
long long fn_id = info.id;
|
long long fn_id = info.id;
|
||||||
|
info.font_size_scale = 1.0;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -195,13 +196,17 @@ string HTMLRenderer::dump_type3_font (GfxFont * font, FontInfo & info)
|
|||||||
auto * cur_font = font_engine.getFont(font, cur_doc, true, xref);
|
auto * cur_font = font_engine.getFont(font, cur_doc, true, xref);
|
||||||
auto used_map = preprocessor.get_code_map(hash_ref(font->getID()));
|
auto used_map = preprocessor.get_code_map(hash_ref(font->getID()));
|
||||||
|
|
||||||
|
//calculate transformed metrics
|
||||||
double * font_bbox = font->getFontBBox();
|
double * font_bbox = font->getFontBBox();
|
||||||
// TODO: font matrix may not exists
|
// TODO: font matrix may not exists
|
||||||
double * font_matrix = font->getFontMatrix();
|
double * font_matrix = font->getFontMatrix();
|
||||||
|
|
||||||
//calculate transformations
|
|
||||||
double transformed_bbox[4];
|
double transformed_bbox[4];
|
||||||
memcpy(transformed_bbox, font_bbox, 4 * sizeof(double));
|
memcpy(transformed_bbox, font_bbox, 4 * sizeof(double));
|
||||||
|
// add the origin to the bbox
|
||||||
|
if(transformed_bbox[0] > 0) transformed_bbox[0] = 0;
|
||||||
|
if(transformed_bbox[1] > 0) transformed_bbox[1] = 0;
|
||||||
|
if(transformed_bbox[2] < 0) transformed_bbox[2] = 0;
|
||||||
|
if(transformed_bbox[3] < 0) transformed_bbox[3] = 0;
|
||||||
tm_transform_bbox(font_matrix, transformed_bbox);
|
tm_transform_bbox(font_matrix, transformed_bbox);
|
||||||
double transformed_bbox_width = transformed_bbox[2] - transformed_bbox[0];
|
double transformed_bbox_width = transformed_bbox[2] - transformed_bbox[0];
|
||||||
double transformed_bbox_height = transformed_bbox[3] - transformed_bbox[1];
|
double transformed_bbox_height = transformed_bbox[3] - transformed_bbox[1];
|
||||||
@ -212,10 +217,10 @@ string HTMLRenderer::dump_type3_font (GfxFont * font, FontInfo & info)
|
|||||||
std::cerr << std::endl;
|
std::cerr << std::endl;
|
||||||
// we want the glyphs is rendered in a box of size around 100 x 100
|
// we want the glyphs is rendered in a box of size around 100 x 100
|
||||||
// for rectangles, the longer edge should be 100
|
// for rectangles, the longer edge should be 100
|
||||||
info.type3_font_size_scale = std::max(transformed_bbox_width, transformed_bbox_height);
|
info.font_size_scale = std::max(transformed_bbox_width, transformed_bbox_height);
|
||||||
|
|
||||||
const double GLYPH_DUMP_SIZE = 100.0;
|
const double GLYPH_DUMP_SIZE = 100.0;
|
||||||
double scale = GLYPH_DUMP_SIZE / info.type3_font_size_scale;
|
double scale = GLYPH_DUMP_SIZE / info.font_size_scale;
|
||||||
|
|
||||||
// determine the position of the origin of the glyph
|
// determine the position of the origin of the glyph
|
||||||
double ox, oy;
|
double ox, oy;
|
||||||
@ -224,9 +229,11 @@ string HTMLRenderer::dump_type3_font (GfxFont * font, FontInfo & info)
|
|||||||
ox -= transformed_bbox[0];
|
ox -= transformed_bbox[0];
|
||||||
oy -= transformed_bbox[1];
|
oy -= transformed_bbox[1];
|
||||||
|
|
||||||
|
// we choose ttf as it does not use char names
|
||||||
// dump each glyph into svg and combine them
|
// or actually we don't use char names for ttf (see embed_font)
|
||||||
ffw_new_font();
|
ffw_new_font();
|
||||||
|
ffw_set_metric(transformed_bbox[3] / transformed_bbox_height, transformed_bbox[1] / transformed_bbox_height);
|
||||||
|
// dump each glyph into svg and combine them
|
||||||
for(int code = 0; code < 256; ++code)
|
for(int code = 0; code < 256; ++code)
|
||||||
{
|
{
|
||||||
if(!used_map[code]) continue;
|
if(!used_map[code]) continue;
|
||||||
@ -331,8 +338,6 @@ string HTMLRenderer::dump_type3_font (GfxFont * font, FontInfo & info)
|
|||||||
ffw_import_svg_glyph(code, glyph_filename.c_str());
|
ffw_import_svg_glyph(code, glyph_filename.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
// we choose ttf as it does not use char names
|
|
||||||
// or actually we don't use char names for ttf (see embed_font)
|
|
||||||
string font_filename = (char*)str_fmt("%s/f%llx.ttf", param.tmp_dir.c_str(), fn_id);
|
string font_filename = (char*)str_fmt("%s/f%llx.ttf", param.tmp_dir.c_str(), fn_id);
|
||||||
tmp_files.add(font_filename);
|
tmp_files.add(font_filename);
|
||||||
ffw_save(font_filename.c_str());
|
ffw_save(font_filename.c_str());
|
||||||
@ -400,7 +405,8 @@ void HTMLRenderer::embed_font(const string & filepath, GfxFont * font, FontInfo
|
|||||||
|
|
||||||
if(get_metric_only)
|
if(get_metric_only)
|
||||||
{
|
{
|
||||||
ffw_metric(&info.ascent, &info.descent);
|
ffw_fix_metric();
|
||||||
|
ffw_get_metric(&info.ascent, &info.descent);
|
||||||
ffw_close();
|
ffw_close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -647,8 +653,7 @@ void HTMLRenderer::embed_font(const string & filepath, GfxFont * font, FontInfo
|
|||||||
cur_width = font_cid->getWidth(buf, 2) ;
|
cur_width = font_cid->getWidth(buf, 2) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(info.is_type3)
|
cur_width /= info.font_size_scale;
|
||||||
cur_width /= info.type3_font_size_scale;
|
|
||||||
|
|
||||||
if(u == ' ')
|
if(u == ' ')
|
||||||
{
|
{
|
||||||
@ -693,8 +698,7 @@ void HTMLRenderer::embed_font(const string & filepath, GfxFont * font, FontInfo
|
|||||||
char buf[2] = {0, ' '};
|
char buf[2] = {0, ' '};
|
||||||
info.space_width = font_cid->getWidth(buf, 2);
|
info.space_width = font_cid->getWidth(buf, 2);
|
||||||
}
|
}
|
||||||
if(info.is_type3)
|
info.space_width /= info.font_size_scale;
|
||||||
info.space_width /= info.type3_font_size_scale;
|
|
||||||
|
|
||||||
/* See comments above */
|
/* See comments above */
|
||||||
if(equal(info.space_width,0))
|
if(equal(info.space_width,0))
|
||||||
@ -777,7 +781,8 @@ void HTMLRenderer::embed_font(const string & filepath, GfxFont * font, FontInfo
|
|||||||
tmp_files.add(fn);
|
tmp_files.add(fn);
|
||||||
|
|
||||||
ffw_load_font(cur_tmp_fn.c_str());
|
ffw_load_font(cur_tmp_fn.c_str());
|
||||||
ffw_metric(&info.ascent, &info.descent);
|
ffw_fix_metric();
|
||||||
|
ffw_get_metric(&info.ascent, &info.descent);
|
||||||
if(param.override_fstype)
|
if(param.override_fstype)
|
||||||
ffw_override_fstype();
|
ffw_override_fstype();
|
||||||
ffw_save(fn.c_str());
|
ffw_save(fn.c_str());
|
||||||
|
@ -274,11 +274,6 @@ void HTMLRenderer::check_state_change(GfxState * state)
|
|||||||
|
|
||||||
double new_draw_font_size = cur_font_size;
|
double new_draw_font_size = cur_font_size;
|
||||||
|
|
||||||
if(cur_text_state.font_info->is_type3 && param.process_type3)
|
|
||||||
{
|
|
||||||
new_draw_font_size *= cur_text_state.font_info->type3_font_size_scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(is_positive(new_draw_text_scale))
|
if(is_positive(new_draw_text_scale))
|
||||||
{
|
{
|
||||||
// scale both font size and matrix
|
// scale both font size and matrix
|
||||||
|
@ -26,9 +26,11 @@ struct FontInfo
|
|||||||
* we have to scale the font to about 1,
|
* we have to scale the font to about 1,
|
||||||
* then apply the scaling when using the font
|
* then apply the scaling when using the font
|
||||||
*
|
*
|
||||||
* The scaling factor is stored as type3_font_size_scale
|
* The scaling factor is stored as font_size_scale
|
||||||
|
*
|
||||||
|
* The value is 1 for other fonts
|
||||||
*/
|
*/
|
||||||
double type3_font_size_scale;
|
double font_size_scale;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct HTMLTextState
|
struct HTMLTextState
|
||||||
|
@ -60,7 +60,10 @@ void HTMLTextLine::append_state(const HTMLTextState & text_state)
|
|||||||
states.back().hash_umask = 0;
|
states.back().hash_umask = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
(HTMLTextState&)(states.back()) = text_state;
|
HTMLTextState & last_state = states.back();
|
||||||
|
last_state = text_state;
|
||||||
|
//apply font scale
|
||||||
|
last_state.font_size *= last_state.font_info->font_size_scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HTMLTextLine::dump_text(ostream & out)
|
void HTMLTextLine::dump_text(ostream & out)
|
||||||
@ -251,7 +254,8 @@ void HTMLTextLine::prepare(void)
|
|||||||
// note that vertical_align cannot be calculated here
|
// note that vertical_align cannot be calculated here
|
||||||
for(auto iter = states.begin(); iter != states.end(); ++iter)
|
for(auto iter = states.begin(); iter != states.end(); ++iter)
|
||||||
{
|
{
|
||||||
iter->ids[State::FONT_ID] = iter->font_info->id;
|
auto font_info = iter->font_info;
|
||||||
|
iter->ids[State::FONT_ID] = font_info->id;
|
||||||
iter->ids[State::FONT_SIZE_ID] = all_manager.font_size.install(iter->font_size);
|
iter->ids[State::FONT_SIZE_ID] = all_manager.font_size.install(iter->font_size);
|
||||||
iter->ids[State::FILL_COLOR_ID] = all_manager.fill_color.install(iter->fill_color);
|
iter->ids[State::FILL_COLOR_ID] = all_manager.fill_color.install(iter->fill_color);
|
||||||
iter->ids[State::STROKE_COLOR_ID] = all_manager.stroke_color.install(iter->stroke_color);
|
iter->ids[State::STROKE_COLOR_ID] = all_manager.stroke_color.install(iter->stroke_color);
|
||||||
@ -260,10 +264,10 @@ void HTMLTextLine::prepare(void)
|
|||||||
iter->hash();
|
iter->hash();
|
||||||
|
|
||||||
accum_vertical_align += iter->vertical_align;
|
accum_vertical_align += iter->vertical_align;
|
||||||
double cur_ascent = accum_vertical_align + iter->font_info->ascent * iter->font_size;
|
double cur_ascent = accum_vertical_align + font_info->ascent * iter->font_size;
|
||||||
if(cur_ascent > ascent)
|
if(cur_ascent > ascent)
|
||||||
ascent = cur_ascent;
|
ascent = cur_ascent;
|
||||||
double cur_descent = accum_vertical_align + iter->font_info->descent * iter->font_size;
|
double cur_descent = accum_vertical_align + font_info->descent * iter->font_size;
|
||||||
if(cur_descent < descent)
|
if(cur_descent < descent)
|
||||||
descent = cur_descent;
|
descent = cur_descent;
|
||||||
}
|
}
|
||||||
|
@ -302,29 +302,22 @@ int ffw_get_em_size(void)
|
|||||||
return cur_fv->sf->ascent + cur_fv->sf->descent;
|
return cur_fv->sf->ascent + cur_fv->sf->descent;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ffw_metric(double * ascent, double * descent)
|
void ffw_fix_metric()
|
||||||
|
{
|
||||||
|
double ascent, descent;
|
||||||
|
ffw_get_metric(&ascent, &descent);
|
||||||
|
//debug
|
||||||
|
printf("fix metrix: %lf %lf\n", ascent, descent);
|
||||||
|
ffw_set_metric(ascent, descent);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ffw_get_metric(double * ascent, double * descent)
|
||||||
{
|
{
|
||||||
SplineFont * sf = cur_fv->sf;
|
SplineFont * sf = cur_fv->sf;
|
||||||
struct pfminfo * info = &sf->pfminfo;
|
|
||||||
|
|
||||||
SFDefaultOS2Info(info, sf, sf->fontname);
|
|
||||||
info->pfmset = 1;
|
|
||||||
sf->changed = 1;
|
|
||||||
|
|
||||||
DBounds bb;
|
DBounds bb;
|
||||||
SplineFontFindBounds(sf, &bb);
|
SplineFontFindBounds(sf, &bb);
|
||||||
|
|
||||||
/*
|
|
||||||
printf("bb %lf %lf\n", bb.maxy, bb.miny);
|
|
||||||
printf("_ %d %d\n", sf->ascent, sf->descent);
|
|
||||||
printf("win %d %d\n", info->os2_winascent, info->os2_windescent);
|
|
||||||
printf("%d %d\n", info->winascent_add, info->windescent_add);
|
|
||||||
printf("typo %d %d\n", info->os2_typoascent, info->os2_typodescent);
|
|
||||||
printf("%d %d\n", info->typoascent_add, info->typodescent_add);
|
|
||||||
printf("hhead %d %d\n", info->hhead_ascent, info->hhead_descent);
|
|
||||||
printf("%d %d\n", info->hheadascent_add, info->hheaddescent_add);
|
|
||||||
*/
|
|
||||||
|
|
||||||
int em = sf->ascent + sf->descent;
|
int em = sf->ascent + sf->descent;
|
||||||
|
|
||||||
if (em > 0)
|
if (em > 0)
|
||||||
@ -336,10 +329,21 @@ void ffw_metric(double * ascent, double * descent)
|
|||||||
{
|
{
|
||||||
*ascent = *descent = 0;
|
*ascent = *descent = 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ffw_set_metric(double ascent, double descent)
|
||||||
|
{
|
||||||
|
SplineFont * sf = cur_fv->sf;
|
||||||
|
struct pfminfo * info = &sf->pfminfo;
|
||||||
|
|
||||||
|
SFDefaultOS2Info(info, sf, sf->fontname);
|
||||||
|
info->pfmset = 1;
|
||||||
|
sf->changed = 1;
|
||||||
|
|
||||||
|
int em = sf->ascent + sf->descent;
|
||||||
|
int a = floor(ascent * em + 0.5);
|
||||||
|
int d = floor(descent * em + 0.5);
|
||||||
|
|
||||||
int a = floor(bb.maxy + 0.5);
|
|
||||||
int d = floor(bb.miny + 0.5);
|
|
||||||
|
|
||||||
if(a < 0) a = 0;
|
if(a < 0) a = 0;
|
||||||
if(d > 0) d = 0;
|
if(d > 0) d = 0;
|
||||||
|
|
||||||
@ -354,7 +358,6 @@ void ffw_metric(double * ascent, double * descent)
|
|||||||
* But have to unify them, for different browsers on different platforms
|
* But have to unify them, for different browsers on different platforms
|
||||||
* Things may become easier when there are CSS rules for baseline-based positioning.
|
* Things may become easier when there are CSS rules for baseline-based positioning.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
info->os2_winascent = a;
|
info->os2_winascent = a;
|
||||||
info->os2_typoascent = a;
|
info->os2_typoascent = a;
|
||||||
info->hhead_ascent = a;
|
info->hhead_ascent = a;
|
||||||
@ -430,13 +433,23 @@ void ffw_import_svg_glyph(int code, const char * filename)
|
|||||||
if(enc == -1)
|
if(enc == -1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
SFMakeChar(cur_fv->sf, cur_fv->map, enc);
|
SplineChar * sc = SFMakeChar(cur_fv->sf, cur_fv->map, enc);
|
||||||
|
|
||||||
memset(cur_fv->selected, 0, cur_fv->map->enccount);
|
memset(cur_fv->selected, 0, cur_fv->map->enccount);
|
||||||
cur_fv->selected[enc] = 1;
|
cur_fv->selected[enc] = 1;
|
||||||
int ok = FVImportImages(cur_fv, (char*)filename, fv_svg, 0, -1);
|
int ok = FVImportImages(cur_fv, (char*)filename, fv_svg, 0, -1);
|
||||||
if(!ok)
|
if(!ok)
|
||||||
err("Import SVG glyph failed");
|
err("Import SVG glyph failed");
|
||||||
|
|
||||||
|
// correct the origin
|
||||||
|
{
|
||||||
|
real transform[6];
|
||||||
|
transform[0] = 1.0;
|
||||||
|
transform[3] = 1.0;
|
||||||
|
transform[1] = transform[2] = transform[4];
|
||||||
|
transform[5] = cur_fv->sf->descent;
|
||||||
|
FVTrans(cur_fv, sc, transform, NULL, fvt_alllayers | fvt_dontmovewidth);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ffw_auto_hint(void)
|
void ffw_auto_hint(void)
|
||||||
|
@ -48,8 +48,14 @@ void ffw_add_empty_char(int32_t unicode, int width);
|
|||||||
////////////////////////
|
////////////////////////
|
||||||
// metrics
|
// metrics
|
||||||
int ffw_get_em_size(void);
|
int ffw_get_em_size(void);
|
||||||
// fix metrics and get them
|
// manipulate ascent and descent
|
||||||
void ffw_metric(double * ascent, double * descent);
|
// asscent is between 0 and 1
|
||||||
|
// descent is between -1 and 0
|
||||||
|
void ffw_fix_metric();
|
||||||
|
// get ascent/descent based on the shape
|
||||||
|
void ffw_get_metric(double * ascent, double * descent);
|
||||||
|
// set corresponding fields
|
||||||
|
void ffw_set_metric(double ascent, double descent);
|
||||||
|
|
||||||
void ffw_set_widths(int * width_list, int mapping_len,
|
void ffw_set_widths(int * width_list, int mapping_len,
|
||||||
int stretch_narrow, int squeeze_wide);
|
int stretch_narrow, int squeeze_wide);
|
||||||
|
Loading…
Reference in New Issue
Block a user