2012-08-14 08:23:15 +00:00
|
|
|
/*
|
|
|
|
* text.ccc
|
|
|
|
*
|
|
|
|
* Handling text and relative stuffs
|
|
|
|
*
|
|
|
|
* by WangLu
|
|
|
|
* 2012.08.14
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <iostream>
|
2012-08-20 21:48:21 +00:00
|
|
|
#include <algorithm>
|
2012-08-14 08:23:15 +00:00
|
|
|
|
|
|
|
#include <boost/format.hpp>
|
|
|
|
|
2012-08-27 15:09:01 +00:00
|
|
|
#include <fofi/FoFiType1C.h>
|
|
|
|
|
2012-08-14 08:23:15 +00:00
|
|
|
#include "HTMLRenderer.h"
|
2012-08-14 09:13:29 +00:00
|
|
|
#include "namespace.h"
|
2012-08-14 08:23:15 +00:00
|
|
|
|
2012-08-20 21:48:21 +00:00
|
|
|
using std::all_of;
|
|
|
|
|
2012-08-14 09:13:29 +00:00
|
|
|
string HTMLRenderer::dump_embedded_font (GfxFont * font, long long fn_id)
|
2012-08-14 08:23:15 +00:00
|
|
|
{
|
|
|
|
Object obj, obj1, obj2;
|
2012-08-27 15:09:01 +00:00
|
|
|
Object font_obj, font_obj2, fontdesc_obj;
|
|
|
|
string suffix;
|
2012-08-14 08:23:15 +00:00
|
|
|
|
2012-08-27 15:09:01 +00:00
|
|
|
try
|
|
|
|
{
|
|
|
|
// mupdf consulted
|
|
|
|
string subtype;
|
2012-08-14 08:23:15 +00:00
|
|
|
|
2012-08-27 15:09:01 +00:00
|
|
|
auto * id = font->getID();
|
2012-08-14 08:23:15 +00:00
|
|
|
|
2012-08-27 15:09:01 +00:00
|
|
|
Object ref_obj;
|
|
|
|
ref_obj.initRef(id->num, id->gen);
|
|
|
|
ref_obj.fetch(xref, &font_obj);
|
|
|
|
ref_obj.free();
|
2012-08-14 08:23:15 +00:00
|
|
|
|
2012-08-27 15:09:01 +00:00
|
|
|
if(!font_obj.isDict())
|
2012-08-14 08:23:15 +00:00
|
|
|
{
|
2012-08-27 15:09:01 +00:00
|
|
|
cerr << "Font object is not a dictionary" << endl;
|
|
|
|
throw 0;
|
2012-08-14 08:23:15 +00:00
|
|
|
}
|
|
|
|
|
2012-08-27 15:09:01 +00:00
|
|
|
Dict * dict = font_obj.getDict();
|
|
|
|
if(dict->lookup("DescendantFonts", &font_obj2)->isArray())
|
|
|
|
{
|
|
|
|
if(font_obj2.arrayGetLength() == 0)
|
|
|
|
{
|
|
|
|
cerr << "Warning: empty DescendantFonts array" << endl;
|
|
|
|
}
|
|
|
|
else
|
2012-08-14 08:23:15 +00:00
|
|
|
{
|
2012-08-27 15:09:01 +00:00
|
|
|
if(font_obj2.arrayGetLength() > 1)
|
|
|
|
cerr << "TODO: multiple entries in DescendantFonts array" << endl;
|
|
|
|
|
|
|
|
if(font_obj2.arrayGet(0, &obj2)->isDict())
|
|
|
|
{
|
|
|
|
dict = obj2.getDict();
|
|
|
|
}
|
2012-08-14 08:23:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-27 15:09:01 +00:00
|
|
|
if(!dict->lookup("FontDescriptor", &fontdesc_obj)->isDict())
|
|
|
|
{
|
|
|
|
cerr << "Cannot find FontDescriptor " << endl;
|
|
|
|
throw 0;
|
|
|
|
}
|
2012-08-14 08:23:15 +00:00
|
|
|
|
2012-08-27 15:09:01 +00:00
|
|
|
dict = fontdesc_obj.getDict();
|
|
|
|
|
|
|
|
if(dict->lookup("FontFile3", &obj)->isStream())
|
2012-08-14 08:23:15 +00:00
|
|
|
{
|
2012-08-27 15:09:01 +00:00
|
|
|
if(obj.streamGetDict()->lookup("Subtype", &obj1)->isName())
|
2012-08-14 08:23:15 +00:00
|
|
|
{
|
2012-08-27 15:09:01 +00:00
|
|
|
subtype = obj1.getName();
|
|
|
|
if(subtype == "Type1C")
|
|
|
|
{
|
|
|
|
suffix = ".cff";
|
|
|
|
}
|
|
|
|
else if (subtype == "CIDFontType0C")
|
|
|
|
{
|
|
|
|
suffix = ".cid";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
cerr << "Unknown subtype: " << subtype << endl;
|
|
|
|
throw 0;
|
|
|
|
}
|
2012-08-14 08:23:15 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2012-08-27 15:09:01 +00:00
|
|
|
cerr << "Invalid subtype in font descriptor" << endl;
|
|
|
|
throw 0;
|
2012-08-14 08:23:15 +00:00
|
|
|
}
|
|
|
|
}
|
2012-08-27 15:09:01 +00:00
|
|
|
else if (dict->lookup("FontFile2", &obj)->isStream())
|
|
|
|
{
|
|
|
|
suffix = ".ttf";
|
|
|
|
}
|
|
|
|
else if (dict->lookup("FontFile", &obj)->isStream())
|
|
|
|
{
|
|
|
|
suffix = ".pfa";
|
|
|
|
}
|
2012-08-14 08:23:15 +00:00
|
|
|
else
|
|
|
|
{
|
2012-08-27 15:09:01 +00:00
|
|
|
cerr << "Cannot find FontFile for dump" << endl;
|
|
|
|
throw 0;
|
2012-08-14 08:23:15 +00:00
|
|
|
}
|
|
|
|
|
2012-08-27 15:09:01 +00:00
|
|
|
if(suffix == "")
|
|
|
|
{
|
|
|
|
cerr << "Font type unrecognized" << endl;
|
|
|
|
throw 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
obj.streamReset();
|
2012-08-14 08:23:15 +00:00
|
|
|
|
2012-08-27 15:09:01 +00:00
|
|
|
string fn = (format("f%|1$x|")%fn_id).str();
|
|
|
|
ofstream outf;
|
|
|
|
outf.open(tmp_dir / (fn + suffix), ofstream::binary);
|
|
|
|
add_tmp_file(fn+suffix);
|
2012-08-15 04:27:41 +00:00
|
|
|
|
2012-08-27 15:09:01 +00:00
|
|
|
char buf[1024];
|
|
|
|
int len;
|
|
|
|
while((len = obj.streamGetChars(1024, (Guchar*)buf)) > 0)
|
|
|
|
{
|
|
|
|
outf.write(buf, len);
|
|
|
|
}
|
|
|
|
outf.close();
|
|
|
|
obj.streamClose();
|
|
|
|
}
|
|
|
|
catch(int)
|
2012-08-14 08:23:15 +00:00
|
|
|
{
|
2012-08-27 15:09:01 +00:00
|
|
|
cerr << format("Someting wrong when trying to dump font %|1$x|") % fn_id << endl;
|
2012-08-14 08:23:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
obj2.free();
|
|
|
|
obj1.free();
|
|
|
|
obj.free();
|
|
|
|
|
|
|
|
fontdesc_obj.free();
|
|
|
|
font_obj2.free();
|
|
|
|
font_obj.free();
|
2012-08-27 15:09:01 +00:00
|
|
|
|
2012-08-14 08:23:15 +00:00
|
|
|
return suffix;
|
|
|
|
}
|
|
|
|
|
|
|
|
void HTMLRenderer::drawString(GfxState * state, GooString * s)
|
|
|
|
{
|
|
|
|
if(s->getLength() == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
auto font = state->getFont();
|
|
|
|
if((font == nullptr) || (font->getWMode()))
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
//hidden
|
|
|
|
if((state->getRender() & 3) == 3)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// see if the line has to be closed due to state change
|
|
|
|
check_state_change(state);
|
2012-08-16 12:26:09 +00:00
|
|
|
prepare_line(state);
|
2012-08-14 08:23:15 +00:00
|
|
|
|
|
|
|
// Now ready to output
|
|
|
|
// get the unicodes
|
|
|
|
char *p = s->getCString();
|
|
|
|
int len = s->getLength();
|
|
|
|
|
|
|
|
double dx = 0;
|
|
|
|
double dy = 0;
|
2012-08-23 20:36:27 +00:00
|
|
|
double dxerr = 0;
|
2012-08-14 08:23:15 +00:00
|
|
|
double dx1,dy1;
|
|
|
|
double ox, oy;
|
|
|
|
|
|
|
|
int nChars = 0;
|
|
|
|
int nSpaces = 0;
|
|
|
|
int uLen;
|
|
|
|
|
|
|
|
CharCode code;
|
|
|
|
Unicode *u = nullptr;
|
|
|
|
|
2012-08-23 20:36:27 +00:00
|
|
|
double fs = state->getFontSize();
|
|
|
|
double cs = state->getCharSpace();
|
|
|
|
double ws = state->getWordSpace();
|
|
|
|
double hs = state->getHorizScaling();
|
|
|
|
|
2012-08-14 08:23:15 +00:00
|
|
|
while (len > 0) {
|
|
|
|
auto n = font->getNextChar(p, len, &code, &u, &uLen, &dx1, &dy1, &ox, &oy);
|
2012-08-24 06:21:20 +00:00
|
|
|
|
2012-08-14 08:23:15 +00:00
|
|
|
if(!(_equal(ox, 0) && _equal(oy, 0)))
|
|
|
|
{
|
2012-08-14 09:13:29 +00:00
|
|
|
cerr << "TODO: non-zero origins" << endl;
|
2012-08-14 08:23:15 +00:00
|
|
|
}
|
|
|
|
|
2012-08-19 20:50:28 +00:00
|
|
|
if (n == 1 && *p == ' ')
|
|
|
|
{
|
|
|
|
++nSpaces;
|
|
|
|
}
|
2012-08-24 06:21:20 +00:00
|
|
|
|
2012-08-27 16:06:09 +00:00
|
|
|
Unicode uu = (cur_font_info.use_tounicode ? check_unicode(u, uLen, code, font) : unicode_from_font(code, font));
|
2012-08-26 23:26:30 +00:00
|
|
|
outputUnicodes(html_fout, &uu, 1);
|
2012-08-14 08:23:15 +00:00
|
|
|
|
2012-08-23 20:36:27 +00:00
|
|
|
dx += dx1;
|
|
|
|
dy += dy1;
|
2012-08-14 08:23:15 +00:00
|
|
|
|
|
|
|
++nChars;
|
|
|
|
p += n;
|
|
|
|
len -= n;
|
|
|
|
}
|
|
|
|
|
2012-08-21 20:34:39 +00:00
|
|
|
// horiz_scaling is merged into ctm now,
|
2012-08-21 19:44:48 +00:00
|
|
|
// so the coordinate system is ugly
|
2012-08-23 20:36:27 +00:00
|
|
|
dx = (dx * fs + nChars * cs + nSpaces * ws) * hs;
|
2012-08-14 08:23:15 +00:00
|
|
|
|
2012-08-23 20:36:27 +00:00
|
|
|
dy *= fs;
|
2012-08-14 08:23:15 +00:00
|
|
|
|
|
|
|
cur_tx += dx;
|
|
|
|
cur_ty += dy;
|
|
|
|
|
2012-08-23 20:36:27 +00:00
|
|
|
draw_tx += dx + dxerr * state->getFontSize() * state->getHorizScaling();
|
2012-08-14 08:23:15 +00:00
|
|
|
draw_ty += dy;
|
|
|
|
}
|