/* * Copyright (C) 2003-2006 Gabest * http://www.gabest.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNU Make; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * http://www.gnu.org/copyleft/gpl.html * */ #include "stdafx.h" #include "GlyphPath.h" namespace ssf { GlyphPath::GlyphPath(const GlyphPath& path) { *this = path; } void GlyphPath::operator = (const GlyphPath& path) { types.Copy(path.types); points.Copy(path.points); } bool GlyphPath::IsEmpty() { return types.IsEmpty() || points.IsEmpty(); } void GlyphPath::RemoveAll() { types.RemoveAll(); points.RemoveAll(); } void GlyphPath::MovePoints(const CPoint& o) { size_t n = points.GetCount(); POINT* p = points.GetData(); unsigned int i = 0; if(!!(g_cpuid.m_flags & CCpuID::sse2) && !((DWORD_PTR)p & 7)) { for( ; i < n && ((DWORD_PTR)&p[i] & 15); i++) { p[i].x += o.x; p[i].y += o.y; } __m128i oo = _mm_set_epi32(o.y, o.x, o.y, o.x); for(unsigned int j = i + ((n - i) & ~7); i < j; i += 8) { __m128i r0 = _mm_load_si128((__m128i*)&p[i+0]); __m128i r1 = _mm_load_si128((__m128i*)&p[i+2]); __m128i r2 = _mm_load_si128((__m128i*)&p[i+4]); __m128i r3 = _mm_load_si128((__m128i*)&p[i+6]); _mm_store_si128((__m128i*)&p[i+0], _mm_add_epi32(r0, oo)); _mm_store_si128((__m128i*)&p[i+2], _mm_add_epi32(r1, oo)); _mm_store_si128((__m128i*)&p[i+4], _mm_add_epi32(r2, oo)); _mm_store_si128((__m128i*)&p[i+6], _mm_add_epi32(r3, oo)); } } for(; i < n; i++) { p[i].x += o.x; p[i].y += o.y; } } void GlyphPath::Enlarge(const GlyphPath& src, float size) { types.SetCount(src.types.GetCount()); points.SetCount(src.points.GetCount()); memcpy(types.GetData(), src.types.GetData(), types.GetCount()); size_t start = 0, end = 0; for(size_t i = 0, j = src.types.GetCount(); i <= j; i++) { if(i > 0 && (i == j || (src.types[i] & ~PT_CLOSEFIGURE) == PT_MOVETO)) { end = i-1; bool cw = true; // TODO: determine orientation (ttf is always cw and we are sill before Transform) float rotate = cw ? -M_PI_2 : M_PI_2; CPoint prev = src.points[end]; CPoint cur = src.points[start]; for(size_t k = start; k <= end; k++) { CPoint next = k < end ? src.points[k+1] : src.points[start]; for(int l = k-1; prev == cur; l--) { if(l < (int)start) l = end; prev = src.points[l]; } for(int l = k+1; next == cur; l++) { if(l > (int)end) l = start; next = src.points[l]; } CPoint in = cur - prev; CPoint out = next - cur; float angle_in = atan2((float)in.y, (float)in.x); float angle_out = atan2((float)out.y, (float)out.x); float angle_diff = angle_out - angle_in; if(angle_diff < 0) angle_diff += M_PI*2; if(angle_diff > M_PI) angle_diff -= M_PI*2; float scale = cos(angle_diff / 2); CPoint p; if(angle_diff < 0) { if(angle_diff > -M_PI/8) {if(scale < 1) scale = 1;} else {if(scale < 0.50) scale = 0.50;} } else { if(angle_diff < M_PI/8) {if(scale < 0.75) scale = 0.75;} else {if(scale < 0.25) scale = 0.25;} } if(scale < 0.1) scale = 0.1; float angle = angle_in + angle_diff / 2 - rotate; float radius = -size / scale; // FIXME p.x = (int)(radius * cos(angle) + 0.5); p.y = (int)(radius * sin(angle) + 0.5); points[k] = cur + p; prev = cur; cur = next; } start = end+1; } } } }