/** @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 #include #include #include #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(data); FT_Vector to = *pftVec; state->os() << to << " " << cmd << endl; state->setStartPt(to); return 0; } static int moveTo(const FT_Vector* pftVec, void* data) { StateOfDrawGlyph* const state = reinterpret_cast(data); state->os() << (state->isNewPath() ? "newpath" : "closepath") << endl; state->setNewPathFalse(); xTo(pftVec, data, "moveto"); return 0; } static int lineTo(const FT_Vector* pftVec, void* data) { xTo(pftVec, data, "lineto"); return 0; } static int cubicTo(const FT_Vector* ctrlPt1, const FT_Vector* ctrlPt2, const FT_Vector* pEndPt, void* data) { StateOfDrawGlyph* const state = reinterpret_cast(data); state->os() << *ctrlPt1 << " " << *ctrlPt2 << " " << *pEndPt << " curveto" << endl; state->setStartPt(*pEndPt); return 0; } static int conicTo(const FT_Vector* pCtrlPt, const FT_Vector* pEndPt, void* data) { StateOfDrawGlyph* const state = reinterpret_cast(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(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); evalReturnCode( FT_Outline_Decompose( &reinterpret_cast(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); }