Merge with MPC-HC 6d1472b2f18266d92e5bc068667de348c0cd3b3b.
[xy_vsfilter.git] / src / subtitles / libssf / GlyphPath.cpp
blob6397d105260cd68c0ef97624b2e594936a86f65d
1 /*
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)
8 * any later version.
9 *
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
22 #include "stdafx.h"
23 #include "GlyphPath.h"
25 namespace ssf
27 GlyphPath::GlyphPath(const GlyphPath& path)
29 *this = 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()
45 types.RemoveAll();
46 points.RemoveAll();
49 void GlyphPath::MovePoints(const CPoint& o)
51 size_t n = points.GetCount();
52 POINT* p = points.GetData();
54 unsigned int i = 0;
56 if(!!(g_cpuid.m_flags & CCpuID::sse2) && !((DWORD_PTR)p & 7))
58 for( ; i < n && ((DWORD_PTR)&p[i] & 15); i++)
60 p[i].x += o.x;
61 p[i].y += o.y;
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));
79 for(; i < n; i++)
81 p[i].x += o.x;
82 p[i].y += o.y;
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))
99 end = i-1;
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);
133 CPoint p;
135 if(angle_diff < 0)
137 if(angle_diff > -M_PI/8) {if(scale < 1) scale = 1;}
138 else {if(scale < 0.50) scale = 0.50;}
140 else
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);
154 points[k] = cur + p;
156 prev = cur;
157 cur = next;
160 start = end+1;