1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
|
/** @file
* libLASi provides a C++ output stream interface for writing multi-language Postscript documents.
* Copyright (C) 2003 Larry Siden.
* See README file in project root directory for copyright and contact info.
* See COPYING file in project root for terms of re-distribution.
*/
#include <ostream>
#include <ft2build.h>
#include FT_OUTLINE_H
#include <algorithm>
#include <LASi.h>
#include <config.h>
#include "glyphMgr.h"
#include "util.h"
#include "memory.h"
using namespace std;
using namespace LASi;
static FT_Vector operator + (const FT_Vector& vec1, const FT_Vector& vec2) {
FT_Vector vec;
vec.x = vec1.x + vec2.x;
vec.y = vec1.y + vec2.y;
return vec;
}
static FT_Vector operator * (const FT_Vector& vec1, const int n) {
FT_Vector vec2;
vec2.x = n * vec1.x;
vec2.y = n * vec1.y;
return vec2;
}
static FT_Vector operator * (const int n, const FT_Vector& vec1) {
return operator*(vec1, n);
}
static FT_Vector operator / (const FT_Vector& vec1, const int n) {
FT_Vector vec2;
vec2.x = vec1.x / n;
vec2.y = vec1.y / n;
return vec2;
}
//static FT_Vector operator / (const int n, const FT_Vector& vec1) {
// return operator/(vec1, n);
//}
static ostream& operator<<(ostream& os, const FT_Vector& ftVec) {
os << ftVec.x / 64.0 << " " << ftVec.y / 64.0;
return os;
}
struct StateOfDrawGlyph {
private:
std::ostream& _os;
FT_Vector _startPt;
bool _isNewPath;
public:
StateOfDrawGlyph(std::ostream& os)
: _os(os), _isNewPath(true)
{
_startPt.x = 0;
_startPt.y = 0;
}
std::ostream& os() {return _os;}
FT_Vector startPt() {return _startPt;}
void setStartPt(const FT_Vector pt) {_startPt = pt;}
bool isNewPath() {return _isNewPath;}
void setNewPathFalse() {_isNewPath = false;}
};
static int xTo(const FT_Vector* pftVec, void* const data, const char* const cmd) {
StateOfDrawGlyph* const state = reinterpret_cast<StateOfDrawGlyph* const>(data);
FT_Vector to = *pftVec;
state->os() << to << " " << cmd << endl;
state->setStartPt(to);
return 0;
}
#ifdef HAVE_FT2_2PLUS
static int moveTo(const FT_Vector* pftVec, void* data) {
#else
static int moveTo(FT_Vector* pftVec, void* data) {
#endif
StateOfDrawGlyph* const state = reinterpret_cast<StateOfDrawGlyph* const>(data);
state->os() << (state->isNewPath() ? "newpath" : "closepath") << endl;
state->setNewPathFalse();
xTo(pftVec, data, "moveto");
return 0;
}
#ifdef HAVE_FT2_2PLUS
static int lineTo(const FT_Vector* pftVec, void* data) {
#else
static int lineTo(FT_Vector* pftVec, void* data) {
#endif
xTo(pftVec, data, "lineto");
return 0;
}
#ifdef HAVE_FT2_2PLUS
static int cubicTo(const FT_Vector* ctrlPt1, const FT_Vector* ctrlPt2, const FT_Vector* pEndPt, void* data) {
#else
static int cubicTo(FT_Vector* ctrlPt1, FT_Vector* ctrlPt2, FT_Vector* pEndPt, void* data) {
#endif
StateOfDrawGlyph* const state = reinterpret_cast<StateOfDrawGlyph* const>(data);
state->os() << *ctrlPt1 << " " << *ctrlPt2 << " " << *pEndPt << " curveto" << endl;
state->setStartPt(*pEndPt);
return 0;
}
#ifdef HAVE_FT2_2PLUS
static int conicTo(const FT_Vector* pCtrlPt, const FT_Vector* pEndPt, void* data) {
#else
static int conicTo(FT_Vector* pCtrlPt, FT_Vector* pEndPt, void* data) {
#endif
StateOfDrawGlyph* const state = reinterpret_cast<StateOfDrawGlyph* const>(data);
FT_Vector ctrlPt1 = (state->startPt() + 2 * *pCtrlPt) / 3;
FT_Vector ctrlPt2 = (*pEndPt + 2 * *pCtrlPt) / 3;
return cubicTo(&ctrlPt1, &ctrlPt2, pEndPt, data);
}
static const FT_Outline_Funcs outlineFuncs = {moveTo, lineTo, conicTo, cubicTo};
void PostscriptDocument::write_glyph_routine_to_stream::operator()(PostscriptDocument::GlyphMap::value_type v)
{
const GlyphId& glyphId = v.first;
const FreetypeGlyphMgr& glyphMgr = v.second;
const FT_Glyph glyph = static_cast<FT_Glyph>(glyphMgr);
const ios::fmtflags oldflags = os.setf(ios::showpos);
const int oldPrecision = os.precision();
os.precision(4);
os << endl << '/' << glyphId.str() << " {" << endl;
os << "/myFontsize exch def" << endl; // bind argument to name
// calculate drawing scale factor
os << "/scalefactor myFontsize " << PostscriptDocument::DRAWING_SCALE << " div def" << endl; // divide myFontsize by DRAWING_SCALE
os << "gsave" << endl;
os << "currentpoint translate" << endl; // put x, y coordinates of current point on top of stack
os << "scalefactor dup scale" << endl; // set the x and y scales in the PS transformation matrix
StateOfDrawGlyph state(os);
if (glyph->format == ft_glyph_format_outline) {
evalReturnCode(
FT_Outline_Decompose(
&reinterpret_cast<FT_OutlineGlyph>(glyph)->outline, &outlineFuncs, &state),
"FT_Outline_Decompose");
//
// 2006.05.01.ET BUG FIX: Various "space" characters
// don't actually draw anything, so "fill" can produce
// undesired artifacts on pre-existing paths ...
//
if (!state.isNewPath()) {
os << "fill" << endl;
}
}
os << "grestore" << endl;
// advance position by width of character (in 16.16 format)
os << "scalefactor " << glyph->advance.x / (double)0x10000 << " mul 0 rmoveto" << endl;
os << "} def" << endl;
// restore os flags and precision
os.flags(oldflags);
os.precision(oldPrecision);
}
|