2 * Copyright (C) 2003-2006 Gabest
3 * http://www.gabest.org
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with GNU Make; see the file COPYING. If not, write to
17 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18 * http://www.gnu.org/copyleft/gpl.html
23 #include "GlyphPath.h"
27 GlyphPath::GlyphPath(const GlyphPath
& path
)
32 void GlyphPath::operator = (const GlyphPath
& path
)
34 types
.Copy(path
.types
);
35 points
.Copy(path
.points
);
38 bool GlyphPath::IsEmpty()
40 return types
.IsEmpty() || points
.IsEmpty();
43 void GlyphPath::RemoveAll()
49 void GlyphPath::MovePoints(const CPoint
& o
)
51 size_t n
= points
.GetCount();
52 POINT
* p
= points
.GetData();
56 if(!!(g_cpuid
.m_flags
& CCpuID::sse2
) && !((DWORD_PTR
)p
& 7))
58 for( ; i
< n
&& ((DWORD_PTR
)&p
[i
] & 15); i
++)
64 __m128i oo
= _mm_set_epi32(o
.y
, o
.x
, o
.y
, o
.x
);
66 for(unsigned int j
= i
+ ((n
- i
) & ~7); i
< j
; i
+= 8)
68 __m128i r0
= _mm_load_si128((__m128i
*)&p
[i
+0]);
69 __m128i r1
= _mm_load_si128((__m128i
*)&p
[i
+2]);
70 __m128i r2
= _mm_load_si128((__m128i
*)&p
[i
+4]);
71 __m128i r3
= _mm_load_si128((__m128i
*)&p
[i
+6]);
72 _mm_store_si128((__m128i
*)&p
[i
+0], _mm_add_epi32(r0
, oo
));
73 _mm_store_si128((__m128i
*)&p
[i
+2], _mm_add_epi32(r1
, oo
));
74 _mm_store_si128((__m128i
*)&p
[i
+4], _mm_add_epi32(r2
, oo
));
75 _mm_store_si128((__m128i
*)&p
[i
+6], _mm_add_epi32(r3
, oo
));
86 void GlyphPath::Enlarge(const GlyphPath
& src
, float size
)
88 types
.SetCount(src
.types
.GetCount());
89 points
.SetCount(src
.points
.GetCount());
91 memcpy(types
.GetData(), src
.types
.GetData(), types
.GetCount());
93 size_t start
= 0, end
= 0;
95 for(size_t i
= 0, j
= src
.types
.GetCount(); i
<= j
; i
++)
97 if(i
> 0 && (i
== j
|| (src
.types
[i
] & ~PT_CLOSEFIGURE
) == PT_MOVETO
))
101 bool cw
= true; // TODO: determine orientation (ttf is always cw and we are sill before Transform)
102 float rotate
= cw
? -M_PI_2
: M_PI_2
;
104 CPoint prev
= src
.points
[end
];
105 CPoint cur
= src
.points
[start
];
107 for(size_t k
= start
; k
<= end
; k
++)
109 CPoint next
= k
< end
? src
.points
[k
+1] : src
.points
[start
];
111 for(int l
= k
-1; prev
== cur
; l
--)
113 if(l
< (int)start
) l
= end
;
114 prev
= src
.points
[l
];
117 for(int l
= k
+1; next
== cur
; l
++)
119 if(l
> (int)end
) l
= start
;
120 next
= src
.points
[l
];
123 CPoint in
= cur
- prev
;
124 CPoint out
= next
- cur
;
126 float angle_in
= atan2((float)in
.y
, (float)in
.x
);
127 float angle_out
= atan2((float)out
.y
, (float)out
.x
);
128 float angle_diff
= angle_out
- angle_in
;
129 if(angle_diff
< 0) angle_diff
+= M_PI
*2;
130 if(angle_diff
> M_PI
) angle_diff
-= M_PI
*2;
131 float scale
= cos(angle_diff
/ 2);
137 if(angle_diff
> -M_PI
/8) {if(scale
< 1) scale
= 1;}
138 else {if(scale
< 0.50) scale
= 0.50;}
142 if(angle_diff
< M_PI
/8) {if(scale
< 0.75) scale
= 0.75;}
143 else {if(scale
< 0.25) scale
= 0.25;}
146 if(scale
< 0.1) scale
= 0.1;
148 float angle
= angle_in
+ angle_diff
/ 2 - rotate
;
149 float radius
= -size
/ scale
; // FIXME
151 p
.x
= (int)(radius
* cos(angle
) + 0.5);
152 p
.y
= (int)(radius
* sin(angle
) + 0.5);