File: drawGlyph.cpp

package info (click to toggle)
lasi 1.1.0-2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye, buster
  • size: 1,420 kB
  • ctags: 1,269
  • sloc: cpp: 1,049; makefile: 13
file content (174 lines) | stat: -rw-r--r-- 5,293 bytes parent folder | download | duplicates (3)
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);
}