ultimatepp/uppdev/SDraw/FontWin32.cpp
cxl 3d718b6028 SDraw dev
git-svn-id: svn://ultimatepp.org/upp/trunk@721 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2009-01-02 21:50:57 +00:00

130 lines
4.2 KiB
C++

#include "SDraw.h"
//----------------------------------------------------------------------------
// Anti-Grain Geometry - Version 2.4
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all coM_PIes.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
//----------------------------------------------------------------------------
// Contact: mcseem@antigrain.com
// mcseemagg@yahoo.com
// http://www.antigrain.com
//----------------------------------------------------------------------------
//
// Arc generator. Produces at most 4 consecutive cubic bezier curves, i.e.,
// 4, 7, 10, or 13 vertices.
//
//----------------------------------------------------------------------------
// Recycled for U++ by Miroslav Fidler 2008
NAMESPACE_UPP
#ifdef PLATFORM_WIN32
inline double fx_to_dbl(const FIXED& p) {
return double(p.value) + double(p.fract) * (1.0 / 65536.0);
}
void RenderCharPath(const char* gbuf, unsigned total_size, SDraw& sw, double xx, double yy)
{
const char* cur_glyph = gbuf;
const char* end_glyph = gbuf + total_size;
while(cur_glyph < end_glyph) {
const TTPOLYGONHEADER* th = (TTPOLYGONHEADER*)cur_glyph;
const char* end_poly = cur_glyph + th->cb;
const char* cur_poly = cur_glyph + sizeof(TTPOLYGONHEADER);
sw.MoveTo(xx + fx_to_dbl(th->pfxStart.x), yy - fx_to_dbl(th->pfxStart.y));
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++)
sw.LineTo(xx + fx_to_dbl(pc->apfx[i].x), yy - fx_to_dbl(pc->apfx[i].y));
if (pc->wType == TT_PRIM_QSPLINE)
{
int u;
for (u = 0; u < pc->cpfx - 1; u++) // Walk through points in spline
{
POINTFX pnt_b = pc->apfx[u]; // B is always the current point
POINTFX pnt_c = pc->apfx[u+1];
if (u < pc->cpfx - 2) // If not on last spline, compute C
{
// 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;
}
sw.Quadratic(xx + fx_to_dbl(pnt_b.x), yy - fx_to_dbl(pnt_b.y),
xx + fx_to_dbl(pnt_c.x), yy - fx_to_dbl(pnt_c.y));
}
}
cur_poly += sizeof(WORD) * 2 + sizeof(POINTFX) * pc->cpfx;
}
cur_glyph += th->cb;
}
}
struct FontChar {
Font fnt;
int chr;
bool operator==(const FontChar& b) const { return fnt == b.fnt && chr == b.chr; }
unsigned GetHashValue() const { return CombineHash(fnt, chr); }
};
struct sMakeCharOutline : LRUCache<String, FontChar>::Maker {
FontChar fc;
FontChar Key() const { return fc; }
int Make(String& s) const {
RTIMING("Make");
static ScreenDraw w;
w.SetFont(fc.fnt);
GLYPHMETRICS gm;
MAT2 m_matrix;
memset(&m_matrix, 0, sizeof(m_matrix));
m_matrix.eM11.value = 1;
m_matrix.eM22.value = 1;
s.Clear();
int gsz = GetGlyphOutlineW(w.GetHandle(), fc.chr, GGO_NATIVE, &gm, 0, NULL, &m_matrix);
if(gsz < 0)
return 0;
StringBuffer gb(gsz);
gsz = GetGlyphOutlineW(w.GetHandle(), fc.chr, GGO_NATIVE, &gm, gsz, ~gb, &m_matrix);
if(gsz < 0)
return 0;
s = gb;
return gsz;
}
};
void Character(SDraw& sw, double x, double y, int ch, Font fnt)
{
RTIMING("Character");
String s;
INTERLOCKED {
static LRUCache<String, FontChar> cache;
cache.Shrink(100000);
sMakeCharOutline h;
h.fc.fnt = fnt;
h.fc.chr = ch;
s = cache.Get(h);
}
RenderCharPath(s, s.GetLength(), sw, x, y);
}
#endif
END_UPP_NAMESPACE