2012-08-10 13:30:41 +00:00
|
|
|
/*
|
|
|
|
* Misc functions
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* by WangLu
|
|
|
|
* 2012.08.10
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef UTIL_H__
|
|
|
|
#define UTIL_H__
|
|
|
|
|
|
|
|
#include <algorithm>
|
2012-08-14 13:23:33 +00:00
|
|
|
#include <istream>
|
2012-08-10 13:30:41 +00:00
|
|
|
#include <ostream>
|
2012-08-27 10:37:00 +00:00
|
|
|
#include <iostream>
|
2012-08-30 15:36:30 +00:00
|
|
|
#include <cmath>
|
2012-09-07 16:38:41 +00:00
|
|
|
#include <cstdarg>
|
2012-08-14 13:23:33 +00:00
|
|
|
|
2012-08-14 18:28:19 +00:00
|
|
|
#include <GfxState.h>
|
2012-08-27 07:56:16 +00:00
|
|
|
#include <GfxFont.h>
|
2012-08-14 18:28:19 +00:00
|
|
|
#include <CharTypes.h>
|
2012-08-10 13:30:41 +00:00
|
|
|
#include <UTF8.h>
|
2012-08-27 07:56:16 +00:00
|
|
|
#include <GlobalParams.h>
|
2012-09-06 16:58:23 +00:00
|
|
|
#include <Object.h>
|
2012-08-10 13:30:41 +00:00
|
|
|
|
|
|
|
#include "Consts.h"
|
|
|
|
|
2012-08-14 13:23:33 +00:00
|
|
|
using std::istream;
|
|
|
|
using std::ostream;
|
2012-08-14 18:28:19 +00:00
|
|
|
using std::noskipws;
|
2012-08-15 04:27:41 +00:00
|
|
|
using std::endl;
|
|
|
|
using std::flush;
|
2012-08-27 10:37:00 +00:00
|
|
|
using std::cerr;
|
2012-08-30 15:36:30 +00:00
|
|
|
using std::floor;
|
2012-09-07 17:09:09 +00:00
|
|
|
using std::max;
|
2012-08-14 13:23:33 +00:00
|
|
|
|
2012-08-14 15:35:53 +00:00
|
|
|
// mute gcc warning of unused function
|
2012-08-14 06:35:55 +00:00
|
|
|
namespace
|
|
|
|
{
|
|
|
|
template <class T>
|
2012-08-14 15:35:53 +00:00
|
|
|
void dummy(){ auto _ = &mapUCS2; }
|
2012-08-14 06:35:55 +00:00
|
|
|
}
|
|
|
|
|
2012-08-10 13:30:41 +00:00
|
|
|
static inline bool _equal(double x, double y) { return std::abs(x-y) < EPS; }
|
|
|
|
static inline bool _is_positive(double x) { return x > EPS; }
|
|
|
|
static inline bool _tm_equal(const double * tm1, const double * tm2, int size = 6)
|
|
|
|
{
|
|
|
|
for(int i = 0; i < size; ++i)
|
|
|
|
if(!_equal(tm1[i], tm2[i]))
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-09-06 16:58:23 +00:00
|
|
|
static inline long long hash_ref(const Ref * id)
|
|
|
|
{
|
|
|
|
return (((long long)(id->num)) << (sizeof(id->gen)*8)) | (id->gen);
|
|
|
|
}
|
|
|
|
|
2012-08-17 07:25:10 +00:00
|
|
|
/*
|
|
|
|
* http://en.wikipedia.org/wiki/HTML_decimal_character_rendering
|
|
|
|
*/
|
|
|
|
static inline bool isLegalUnicode(Unicode u)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
if((u == 9) || (u == 10) || (u == 13))
|
|
|
|
return true;
|
|
|
|
*/
|
|
|
|
|
|
|
|
if(u <= 31)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if((u >= 127) && (u <= 159))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if((u >= 0xd800) && (u <= 0xdfff))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-08-27 15:09:01 +00:00
|
|
|
static inline Unicode map_to_private(CharCode code)
|
2012-08-26 23:26:30 +00:00
|
|
|
{
|
2012-08-27 07:56:16 +00:00
|
|
|
Unicode private_mapping = (Unicode)(code + 0xE000);
|
2012-08-27 10:37:00 +00:00
|
|
|
if(private_mapping > 0xF8FF)
|
|
|
|
{
|
|
|
|
private_mapping = (Unicode)((private_mapping - 0xF8FF) + 0xF0000);
|
|
|
|
if(private_mapping > 0xFFFFD)
|
|
|
|
{
|
|
|
|
private_mapping = (Unicode)((private_mapping - 0xFFFFD) + 0x100000);
|
|
|
|
if(private_mapping > 0x10FFFD)
|
|
|
|
{
|
|
|
|
cerr << "Warning: all private use unicode are used" << endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-08-27 15:09:01 +00:00
|
|
|
return private_mapping;
|
|
|
|
}
|
2012-08-27 10:37:00 +00:00
|
|
|
|
2012-08-27 15:09:01 +00:00
|
|
|
/*
|
2012-08-27 16:06:09 +00:00
|
|
|
* Try to determine the Unicode value directly from the information in the font
|
2012-08-27 15:09:01 +00:00
|
|
|
*/
|
2012-08-27 16:06:09 +00:00
|
|
|
static inline Unicode unicode_from_font (CharCode code, GfxFont * font)
|
2012-08-27 15:09:01 +00:00
|
|
|
{
|
2012-08-27 07:56:16 +00:00
|
|
|
if(!font->isCIDFont())
|
|
|
|
{
|
|
|
|
char * cname = dynamic_cast<Gfx8BitFont*>(font)->getCharName(code);
|
|
|
|
// may be untranslated ligature
|
|
|
|
if(cname)
|
|
|
|
{
|
|
|
|
Unicode ou = globalParams->mapNameToUnicode(cname);
|
|
|
|
|
|
|
|
if(isLegalUnicode(ou))
|
|
|
|
return ou;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-27 15:09:01 +00:00
|
|
|
return map_to_private(code);
|
2012-08-26 23:26:30 +00:00
|
|
|
}
|
|
|
|
|
2012-08-27 16:06:09 +00:00
|
|
|
/*
|
|
|
|
* We have to use a single Unicode value to reencode fonts
|
|
|
|
* if we got multi-unicode values, it might be expanded ligature, try to restore it
|
|
|
|
* if we cannot figure it out at the end, use a private mapping
|
|
|
|
*/
|
|
|
|
static inline Unicode check_unicode(Unicode * u, int len, CharCode code, GfxFont * font)
|
|
|
|
{
|
|
|
|
if(len == 0)
|
|
|
|
return map_to_private(code);
|
|
|
|
|
|
|
|
if(len == 1)
|
|
|
|
{
|
|
|
|
if(isLegalUnicode(*u))
|
|
|
|
return *u;
|
|
|
|
}
|
|
|
|
|
|
|
|
return unicode_from_font(code, font);
|
|
|
|
}
|
|
|
|
|
2012-08-10 13:30:41 +00:00
|
|
|
static inline void outputUnicodes(std::ostream & out, const Unicode * u, int uLen)
|
|
|
|
{
|
|
|
|
for(int i = 0; i < uLen; ++i)
|
|
|
|
{
|
|
|
|
switch(u[i])
|
|
|
|
{
|
|
|
|
case '&':
|
|
|
|
out << "&";
|
|
|
|
break;
|
|
|
|
case '\"':
|
|
|
|
out << """;
|
|
|
|
break;
|
|
|
|
case '\'':
|
|
|
|
out << "'";
|
|
|
|
break;
|
|
|
|
case '<':
|
|
|
|
out << "<";
|
|
|
|
break;
|
|
|
|
case '>':
|
|
|
|
out << ">";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
{
|
|
|
|
char buf[4];
|
|
|
|
auto n = mapUTF8(u[i], buf, 4);
|
|
|
|
out.write(buf, n);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-14 09:13:29 +00:00
|
|
|
static inline bool operator < (const GfxRGB & rgb1, const GfxRGB & rgb2)
|
|
|
|
{
|
|
|
|
if(rgb1.r < rgb2.r) return true;
|
|
|
|
if(rgb1.r > rgb2.r) return false;
|
|
|
|
if(rgb1.g < rgb2.g) return true;
|
|
|
|
if(rgb1.g > rgb2.g) return false;
|
|
|
|
return (rgb1.b < rgb2.b);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool operator == (const GfxRGB & rgb1, const GfxRGB & rgb2)
|
|
|
|
{
|
|
|
|
return ((rgb1.r == rgb2.r) && (rgb1.g == rgb2.g) && (rgb1.b == rgb1.b));
|
|
|
|
}
|
2012-08-10 13:30:41 +00:00
|
|
|
|
2012-08-14 09:24:54 +00:00
|
|
|
// we may need more info of a font in the future
|
|
|
|
class FontInfo
|
|
|
|
{
|
|
|
|
public:
|
2012-08-27 15:09:01 +00:00
|
|
|
long long id;
|
|
|
|
bool use_tounicode;
|
2012-08-30 15:36:30 +00:00
|
|
|
double ascent, descent;
|
2012-08-14 09:24:54 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
// wrapper of the transform matrix double[6]
|
|
|
|
// Transform Matrix
|
|
|
|
class TM
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
TM() {}
|
|
|
|
TM(const double * m) {memcpy(_, m, sizeof(_));}
|
|
|
|
bool operator < (const TM & m) const {
|
2012-08-16 06:30:12 +00:00
|
|
|
// Note that we only care about the first 4 elements
|
|
|
|
for(int i = 0; i < 4; ++i)
|
2012-08-14 09:24:54 +00:00
|
|
|
{
|
|
|
|
if(_[i] < m._[i] - EPS)
|
|
|
|
return true;
|
|
|
|
if(_[i] > m._[i] + EPS)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
bool operator == (const TM & m) const {
|
2012-08-16 06:30:12 +00:00
|
|
|
return _tm_equal(_, m._, 4);
|
2012-08-14 09:24:54 +00:00
|
|
|
}
|
|
|
|
double _[6];
|
|
|
|
};
|
|
|
|
|
2012-08-15 03:15:33 +00:00
|
|
|
class base64stream
|
2012-08-14 13:23:33 +00:00
|
|
|
{
|
2012-08-14 18:28:19 +00:00
|
|
|
public:
|
2012-08-14 13:23:33 +00:00
|
|
|
|
2012-08-15 10:48:11 +00:00
|
|
|
base64stream(istream & in) : in(&in) { }
|
|
|
|
base64stream(istream && in) : in(&in) { }
|
2012-08-14 18:28:19 +00:00
|
|
|
|
|
|
|
ostream & dumpto(ostream & out)
|
2012-08-14 13:48:57 +00:00
|
|
|
{
|
2012-08-14 18:28:19 +00:00
|
|
|
unsigned char buf[3];
|
2012-08-15 03:15:33 +00:00
|
|
|
while(in->read((char*)buf, 3))
|
2012-08-14 18:28:19 +00:00
|
|
|
{
|
2012-08-15 03:15:33 +00:00
|
|
|
out << base64_encoding[(buf[0] & 0xfc)>>2]
|
|
|
|
<< base64_encoding[((buf[0] & 0x03)<<4) | ((buf[1] & 0xf0)>>4)]
|
|
|
|
<< base64_encoding[((buf[1] & 0x0f)<<2) | ((buf[2] & 0xc0)>>6)]
|
|
|
|
<< base64_encoding[(buf[2] & 0x3f)];
|
2012-08-14 18:28:19 +00:00
|
|
|
}
|
2012-08-15 03:15:33 +00:00
|
|
|
auto cnt = in->gcount();
|
2012-08-14 18:28:19 +00:00
|
|
|
if(cnt > 0)
|
|
|
|
{
|
|
|
|
for(int i = cnt; i < 3; ++i)
|
|
|
|
buf[i] = 0;
|
2012-08-15 03:15:33 +00:00
|
|
|
|
|
|
|
out << base64_encoding[(buf[0] & 0xfc)>>2]
|
|
|
|
<< base64_encoding[((buf[0] & 0x03)<<4) | ((buf[1] & 0xf0)>>4)];
|
|
|
|
|
2012-08-14 18:28:19 +00:00
|
|
|
if(cnt > 1)
|
|
|
|
{
|
|
|
|
out << base64_encoding[(buf[1] & 0x0f)<<2];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
out << '=';
|
|
|
|
}
|
2012-08-14 13:48:57 +00:00
|
|
|
out << '=';
|
2012-08-14 18:28:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return out;
|
2012-08-14 13:48:57 +00:00
|
|
|
}
|
2012-08-14 18:28:19 +00:00
|
|
|
|
|
|
|
private:
|
2012-09-09 05:58:15 +00:00
|
|
|
static const char * base64_encoding = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
2012-08-15 03:15:33 +00:00
|
|
|
istream * in;
|
2012-08-14 18:28:19 +00:00
|
|
|
};
|
|
|
|
|
2012-08-15 03:15:33 +00:00
|
|
|
static inline ostream & operator << (ostream & out, base64stream & bf) { return bf.dumpto(out); }
|
|
|
|
static inline ostream & operator << (ostream & out, base64stream && bf) { return bf.dumpto(out); }
|
2012-08-10 13:30:41 +00:00
|
|
|
|
2012-09-07 16:38:41 +00:00
|
|
|
class string_formatter
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
string_formatter() { buf.reserve(64); }
|
|
|
|
/*
|
|
|
|
* Important:
|
|
|
|
* there is only one buffer, so new strings will replace old ones
|
|
|
|
*/
|
|
|
|
const char * operator () (const char * format, ...) {
|
|
|
|
va_list vlist;
|
|
|
|
va_start(vlist, format);
|
|
|
|
int l = vsnprintf(&buf.front(), buf.capacity(), format, vlist);
|
|
|
|
va_end(vlist);
|
2012-09-07 17:09:09 +00:00
|
|
|
if(l >= (int)buf.capacity())
|
2012-09-07 16:38:41 +00:00
|
|
|
{
|
2012-09-07 17:09:09 +00:00
|
|
|
buf.reserve(max((long)(l+1), (long)buf.capacity() * 2));
|
2012-09-07 16:38:41 +00:00
|
|
|
va_start(vlist, format);
|
|
|
|
l = vsnprintf(&buf.front(), buf.capacity(), format, vlist);
|
|
|
|
va_end(vlist);
|
|
|
|
}
|
|
|
|
if(l < 0) return nullptr;
|
|
|
|
assert(l < (int)buf.capacity());
|
|
|
|
return &buf.front();
|
|
|
|
}
|
|
|
|
private:
|
|
|
|
std::vector<char> buf;
|
|
|
|
};
|
|
|
|
|
2012-08-10 13:30:41 +00:00
|
|
|
#endif //UTIL_H__
|