-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path3DGlyph.cpp
129 lines (100 loc) · 3.43 KB
/
3DGlyph.cpp
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
#include "stdafx.h"
#include "3DGlyph.h"
#ifndef GGO_UNHINTED
#define GGO_UNHINTED 0x0100
#endif
static inline double fx_to_dbl(const FIXED& p)
{
return double(p.value) + double(p.fract) * (1.0 / 65536.0);
}
C3DGlyph::C3DGlyph()
{
}
C3DGlyph::~C3DGlyph()
{
}
glm::dvec3 C3DGlyph::GetBoundingBox() const
{
ATLASSERT(!m_vecVertices.empty());
return m_vecVertices[1] - m_vecVertices[0];
}
bool C3DGlyph::Create(WCHAR c, const LOGFONT* pLogFont, bool bHinted /*= false*/)
{
Clear();
CClientDC hdc(NULL);
ATLASSERT(pLogFont);
// create font and select it
CFont newFont;
if (!newFont.CreateFontIndirect(pLogFont))
{
return false;
}
const double lfScale = 25.0;
bool bResult = false;
auto pOldFont = hdc.SelectFont(newFont);
GLYPHMETRICS gm = { 0 };
MAT2 mat2 = { 0 };
mat2.eM11.value = 1;
mat2.eM22.value = 1;
ULONG buf_size = 16384 - 32;
CTempBuffer<uint8_t> gbuf(buf_size);
int total_size = ::GetGlyphOutlineW(hdc, c, GGO_NATIVE | (bHinted ? 0 : GGO_UNHINTED), &gm, buf_size, gbuf, &mat2);
if (total_size > 0)
{
bResult = true;
// store bounding box (lower-left, upper-right)
m_vecVertices.push_back(glm::dvec4(0, 0, 0, 1));
m_vecVertices.push_back(glm::dvec4((double)((gm.gmBlackBoxX > (UINT)gm.gmCellIncX) ? gm.gmBlackBoxX : (UINT)gm.gmCellIncX) / lfScale, ((double)gm.gmBlackBoxY) / lfScale * (-1.0), 0, 1));
const uint8_t* cur_glyph = gbuf;
const uint8_t* end_glyph = gbuf + total_size;
while (cur_glyph < end_glyph)
{
const TTPOLYGONHEADER* th = (const TTPOLYGONHEADER*)cur_glyph;
const uint8_t* end_poly = cur_glyph + th->cb;
const uint8_t* cur_poly = cur_glyph + sizeof(TTPOLYGONHEADER);
m_vecVertices.push_back(glm::dvec4(fx_to_dbl(th->pfxStart.x) / lfScale, -fx_to_dbl(th->pfxStart.y) / lfScale, 0, 1));
m_vecFaces.push_back(face_t(m_vecVertices.size()-1, PT_MOVETO));
while (cur_poly < end_poly)
{
const TTPOLYCURVE* pc = (const TTPOLYCURVE*)cur_poly;
if (pc->wType == TT_PRIM_LINE)
{
for (int i = 0; i < pc->cpfx; i++)
{
m_vecVertices.push_back(glm::dvec4(fx_to_dbl(pc->apfx[i].x) / lfScale, -fx_to_dbl(pc->apfx[i].y) / lfScale, 0, 1));
m_vecFaces.push_back(face_t(m_vecVertices.size() - 1, PT_LINETO));
}
}
else if (pc->wType == TT_PRIM_QSPLINE)
{
for (int u = 0; u < pc->cpfx - 1; u++)
{
// B is always the current point
POINTFX pnt_b = pc->apfx[u];
POINTFX pnt_c = pc->apfx[u + 1];
// if not on last spline, compute C
if (u < pc->cpfx - 2)
{
// midpoint (x,y)
*(int*)&pnt_c.x = (*(int*)&pnt_b.x + *(int*)&pnt_c.x) / 2;
*(int*)&pnt_c.y = (*(int*)&pnt_b.y + *(int*)&pnt_c.y) / 2;
}
m_vecVertices.push_back(glm::dvec4(fx_to_dbl(pnt_b.x) / lfScale, -fx_to_dbl(pnt_b.y) / lfScale, 0, 1));
m_vecFaces.push_back(face_t(m_vecVertices.size() - 1, PT_BEZIERTO));
m_vecVertices.push_back(glm::dvec4(fx_to_dbl(pnt_c.x) / lfScale, -fx_to_dbl(pnt_c.y) / lfScale, 0, 1));
m_vecFaces.push_back(face_t(m_vecVertices.size() - 1, PT_BEZIERTO));
}
}
cur_poly += sizeof(WORD) * 2 + sizeof(POINTFX) * pc->cpfx;
}
cur_glyph += th->cb;
m_vecVertices.push_back(glm::dvec4(0, 0, 0, 1));
m_vecFaces.push_back(face_t(m_vecVertices.size() - 1, PT_CCW_EX));
}
m_vecVertices.push_back(glm::dvec4(0, 0, 0, 1));
m_vecFaces.push_back(face_t(m_vecVertices.size() - 1, PT_STOP));
}
// put back the old font
hdc.SelectFont(pOldFont);
return bResult;
}