📄 flashfontobj.cpp
字号:
//////////////////////////////////////////////////////////////////////
//
// FlashFontObj.cpp: implementation of the CFlashFontObj class.
//
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <math.h>
//#include <hash_map>
#include "ffont.h"
#include "fsprite.h"
#include "fdisplay.h"
#include "ConvertGlyph.h"
#include "FlashFontObj.h"
#include <string>
// underline and strikeout line height TWIPS
#define ULSO 50
// undeline and strikeout extent past the char TWIPS
#define ULSO_OFFSET 100
// The base tells us how big to create a font. For FLASH the font EM square is 1024 x 1024
#define FONT_BASE 1024 // was 1300
#define EM_SQUARE_SIZE 1024
#define EM_RATIO 0.792
/**************************************************************************************************************************/
void CFlashFontObj::ConvertString (const char* text, char** buf)
{
long len, i, j;
len = strlen((LPSTR)text) + 1;
*buf = new char[len];
memset (*buf, 0, len);
//COMMENTED OUT BY WBT
for (i=0,j=0; i<len-1; ++i)
{
//WBT if (text[i] >= 32 && text[i] <127)
//WBT {
(*buf)[j++] = text[i];
/*WBT }
else
{
switch (text[i])
{
case -110:
(*buf)[j++] = 39;
break;
case -109:
case -108:
(*buf)[j++] = '"';
break;
// case -70:
// buf[j++] = '';
// break;
default:
(*buf)[j++] = 64;
break;
};
}
*/ }
}
CFlashFontObj::CFlashFontObj()
{
}
CFlashFontObj::~CFlashFontObj()
{
}
short ShortFromFixed(FIXED f)
{
short ret = f.value;
if(f.fract > 0x8000) ret+=1;
return (short)ret;
}
bool CFlashFontObj::GetGlyphShape(const char *font, WORD charindex, FlashShape* s, long* advance, bool internal_ulines)
{
HDC tmphdc = CreateDC("DISPLAY", NULL, NULL, NULL);
HDC hdcScreen = CreateCompatibleDC(tmphdc);
SetMapMode(hdcScreen, MM_TEXT);
int charset = DEFAULT_CHARSET;
HFONT myfont = CreateFont(-(EM_SQUARE_SIZE * EM_RATIO),0,0,0,m_weight,m_italics ? TRUE : FALSE,m_underline ? TRUE : FALSE,m_strikeout ? TRUE : FALSE,charset,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH,font);
HGDIOBJ obj = SelectObject(hdcScreen,myfont);
OUTLINETEXTMETRIC metric;
GetOutlineTextMetrics(hdcScreen, sizeof(OUTLINETEXTMETRIC), &metric);
int ascent = (-metric.otmsUnderscorePosition);
TTPOLYGONHEADER *lastheader = NULL;
unsigned int c2=charindex;
GLYPHMETRICS gm;
DWORD size;
MAT2 matrix;
FIXED f1;
f1.value = 1;
f1.fract = 0;
FIXED f0;
f0.value = 0;
f0.fract = 0;
matrix.eM11 = f1;
matrix.eM12 = f0;
matrix.eM21 = f0;
matrix.eM22 = f1;
short x_offset;
short max_x=0;
short lastx=0;
short lasty=0;
if (advance)
*advance = 0;
if(c2 != ' ')
{
USHORT char2 = GetTTUnicodeGlyphIndex(hdcScreen, c2);
UINT text_flags;
if(char2 == 0)
{
char2 = c2;
text_flags = GGO_NATIVE;
}
else
{
text_flags = GGO_NATIVE | GGO_GLYPH_INDEX;
}
if((size = GetGlyphOutline(hdcScreen,char2,text_flags,&gm,0,NULL,&matrix)) != GDI_ERROR)
{
char *buffer = new char[size+1];
if((size = GetGlyphOutline(hdcScreen,char2,text_flags,&gm,size,buffer,&matrix)) != GDI_ERROR)
{
char *pos = (char*)buffer;
while(pos < buffer+size)
{
TTPOLYGONHEADER *header = (TTPOLYGONHEADER *)pos;
lastheader = header;
pos+=sizeof(TTPOLYGONHEADER);
short hx = ShortFromFixed(header->pfxStart.x);
short hy = -(ShortFromFixed(header->pfxStart.y)+ascent);
if (pos == buffer+sizeof(TTPOLYGONHEADER))
{
FlashShapeRecordChange c(hx, hy);
c.ChangeFillStyle1(1);
c.SetMoveTo(true);
s->AddRecord(c);
}
else
{
FlashShapeRecordChange c(hx, hy);
c.SetMoveTo(true);
s->AddRecord(c);
}
if (hx > max_x) max_x = hx;
lastx = hx;
lasty = hy;
while(pos < (char*)header+(header->cb))
{
TTPOLYCURVE *curve = (TTPOLYCURVE *)pos;
// handle polylines
if(curve->wType == TT_PRIM_LINE)
{
for(WORD i=0; i < curve->cpfx; i++)
{
short x = ShortFromFixed(curve->apfx[i].x);
short y = -(ShortFromFixed(curve->apfx[i].y)+ascent);
FlashShapeRecordStraight fsrs(x-lastx, y-lasty);
s->AddRecord(fsrs);
if (x > max_x) max_x = x;
lastx += x-lastx;
lasty += y-lasty;
}
}
// handle lines
else
{
POINTFX pfxB,pfxC;
for (int u = 0; u < curve->cpfx - 1; u++) // Walk through points in spline
{
pfxB = curve->apfx[u]; // B is always the current point
short cx_;
short cy_;
short ax_;
short ay_;
cx_ = ShortFromFixed(pfxB.x);
cy_ = ShortFromFixed(pfxB.y);
if (u < curve->cpfx - 2) // If not on last spline, compute C
{
ax_ = (cx_ + ShortFromFixed(curve->apfx[u+1].x)) / 2; // x midpoint
ay_ = (cy_ + ShortFromFixed(curve->apfx[u+1].y)) / 2; // y midpoint
}
else
{
pfxC = curve->apfx[u+1];
ax_ = ShortFromFixed(pfxC.x);
ay_ = ShortFromFixed(pfxC.y);
}
cy_=-(cy_+ascent);
ay_=-(ay_+ascent);
short cx = cx_-lastx;
short cy = cy_-lasty;
short rx = ax_-cx_;
short ry = ay_-cy_;
lastx += ax_-lastx;
lasty += ay_-lasty;
if (ax_ > max_x) max_x = ax_;
FlashShapeRecordCurved fsrc(cx,cy,rx,ry);
s->AddRecord(fsrc);
#ifdef _DEBUG_GLYPH
DBG_SET_RECT (cx_, cy_);
DBG_SET_RECT (ax_, ay_);
wsprintf (dbgStr, "BezierTo: x:%d, y:%d x2:%d, y2:%d", cx_,cy_,ax_,ay_);
SaveDebugString(dbgStr);
#endif
}
}
pos+=(sizeof(WORD)*2) + (sizeof(POINTFX)*curve->cpfx);
}
if ((hx!=lastx) || (hy!=lasty))
{
FlashShapeRecordStraight rs(hx-lastx, hy-lasty);
s->AddRecord(rs);
#ifdef _DEBUG_GLYPH
DBG_SET_RECT (hx, hy);
wsprintf (dbgStr, "LineTo2: x:%d, y:%d", hx,hy);
SaveDebugString(dbgStr);
#endif
}
lastx = hx;
lasty = hy;
}
}
else
{
return false; // ERROR
}
delete[] buffer;
}
else
{
return false; // ERROR
}
}
if (advance)
*advance = max_x;
x_offset = max_x;
if (c2 == ' ')
x_offset = 512;
if (m_last_glyph != TRUE)
x_offset += ULSO_OFFSET;
if(internal_ulines)
{
if(m_underline)
{
int lineAdjust = 0;
int lineWidth = x_offset+50;
int lineHeight = ULSO;
FlashShapeRecordChange change = FlashShapeRecordChange(0,lineAdjust);
change.ChangeFillStyle1(1);
s->AddRecord(change);
s->AddRecord(FlashShapeRecordStraight(lineWidth, 0));
s->AddRecord(FlashShapeRecordStraight(0, lineHeight));
s->AddRecord(FlashShapeRecordStraight(-lineWidth, 0));
s->AddRecord(FlashShapeRecordStraight(0, -lineHeight));
}
if(m_strikeout)
{
int lineAdjust = -512;
int lineWidth = x_offset+50;
int lineHeight = ULSO;
FlashShapeRecordChange change = FlashShapeRecordChange(0,lineAdjust);
change.ChangeFillStyle1(1);
s->AddRecord(change);
s->AddRecord(FlashShapeRecordStraight(lineWidth, 0));
s->AddRecord(FlashShapeRecordStraight(0, lineHeight));
s->AddRecord(FlashShapeRecordStraight(-lineWidth, 0));
s->AddRecord(FlashShapeRecordStraight(0, -lineHeight));
}
}
#ifdef _DEBUG_GLYPH
wsprintf (dbgStr, "RECT: left:%d top:%d right:%d bottom:%d", rmax.left, rmax.top, rmax.right, rmax.bottom);
SaveDebugString(dbgStr);
wsprintf (dbgStr, "End Shape");
SaveDebugString(dbgStr);
#endif
SelectObject(hdcScreen,obj);
DeleteObject(myfont);
DeleteObject(hdcScreen);
DeleteDC (tmphdc);
return true;
}
int CFlashFontObj::GetGlyphAdvance(const char *fontname, WORD charindex, WORD nextchar, int pointSize, BOOL usekern)
{
HDC tmphdc, hdcScreen;
KERNINGPAIR krnpair;
OUTLINETEXTMETRIC om;
int i;
BOOL ret;
tmphdc = CreateDC("DISPLAY", NULL, NULL, NULL);
hdcScreen = CreateCompatibleDC(tmphdc);
SetMapMode (hdcScreen, MM_TEXT);
GetOutlineTextMetrics(hdcScreen,sizeof(om),&om);
HFONT myfont = CreateFont(-(16*pointSize),0,0,0,m_weight,m_italics,m_underline,m_strikeout,DEFAULT_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH,fontname);
HGDIOBJ obj = SelectObject(hdcScreen,myfont);
// charindex = GetTTUnicodeGlyphIndex(hdcScreen, charindex);
ret=::GetCharWidthW(hdcScreen,charindex,charindex,&i);
#ifdef _DEBUG_INTERFACE
wsprintf (dbgStr, "GetGlyphAdvance: c1:%c c2:%c advance:%d", charindex, nextchar, i);
SaveDebugString(dbgStr);
#endif
// What about sp char? check for that as well???
if (usekern && nextchar)
{
krnpair.wFirst = charindex;
krnpair.wSecond = nextchar;
krnpair.iKernAmount = 0;
if (GetKerningPairs(hdcScreen, 1, &krnpair))
{
i += (krnpair.iKernAmount);
#ifdef _DEBUG_INTERFACE
wsprintf (dbgStr, "GetGlyphAdvance: kern:%d", krnpair.iKernAmount);
SaveDebugString(dbgStr);
#endif
}
}
SelectObject(hdcScreen,obj);
DeleteObject(myfont);
DeleteObject(hdcScreen);
DeleteDC (tmphdc);
if(ret == 0) return -1;
else return i;
}
void CFlashFontObj::WriteFontInfos(std::ostream &stream)
{
for(std::vector<FlashTagDefineFont2 *>::iterator i = fonts.begin(); i != fonts.end(); i++)
{
FlashTagDefineFont2 *pFont = (*i);
pFont->Write(stream);
delete *i;
}
fonts.clear();
font_infos.clear();
}
bool CFlashFontObj::WriteText(const char *fontname_, wchar_t *text, int x, int y, FlashRGB *color, int pointsize, BOOL italics, BOOL underline, BOOL strikeout, long weight, BOOL usekern, bool internal_ulines, std::ostream &stream, int characterId)
{
char *fontname = (char*)malloc(strlen(fontname_)+1);
strcpy(fontname, fontname_);
fontInfo fi;
fi.italics = italics;
fi.strikeout = strikeout;
fi.underline = underline;
fi.weight = weight;
fi.name = fontname;
bool firstUse = true;
FlashTagDefineFont2* font = NULL;
for(int index = 0; index < font_infos.size(); index++)
{
if(fi == font_infos[index])
{
font = fonts[index];
firstUse = false;
break;
}
}
if(font == NULL)
{
font = new FlashTagDefineFont2(FTDF2_ANSI, fontname);
font_infos.push_back(fi);
fonts.push_back(font);
}
FlashTagDefineText2* txt;
FlashTextRecordGlyph* textGlyphRec;
int i, len, advance;
long* ibadvance;
char* ibuf;
WORD *buf;
buf = (WORD *)text;
// double val;
m_italics = italics;
m_underline = underline;
m_strikeout = strikeout;
m_weight = weight;
m_last_glyph = FALSE;
m_width = 0;
m_height = 0;
int length = wcslen(buf);
len = length;
ibuf = new char[len];
ibadvance = new long[len];
memset (ibuf, 0, len);
//dfi = new FlashTagDefineFontInfo(const_cast<char *>(fontname), FTDFI_ANSI, font->GetID());
textGlyphRec = new FlashTextRecordGlyph();
for (i=0,len=0; i < length && buf[i] != 0; ++i)
{
int charId = i;
//if (!wcschr (buf, buf[i]))
{
if (!buf[i+1])
m_last_glyph = TRUE;
int definedId = font->GetGlyphId(buf[i]);
if(definedId == -1)
{
FlashShape shape;
GetGlyphShape(fontname, (WORD)buf[i], &shape, NULL, internal_ulines);
charId = font->AddShape(shape, (int)buf[i]);
//dfi->AddCode(text[i]);
}
else
{
charId = definedId;
}
ibuf[len++] = (char)charId;
}
advance = GetGlyphAdvance(fontname, buf[i], buf[i+1], pointsize, usekern);
FlashGlyphEntry e;
e.first = charId;
e.second = advance;
textGlyphRec->AddGlyph(e);
m_width += advance;
}
m_height = pointsize*24;
FlashMatrix m;
FlashRect rect(x-500, y-m_height, x+m_width+1000, y+m_height*2);
txt = new FlashTagDefineText2(rect, m);
if(characterId != 0)
{
txt->SetID(characterId);
}
FlashTextRecordStyle recStyle(true, true, true, true, font->GetID(), pointsize*20, *color, x, y);
txt->AddTextRecord( &recStyle );
txt->AddTextRecord( textGlyphRec );
txt->Write(stream);
if(!internal_ulines)
{
FlashTagSprite *sprite = new FlashTagSprite();
m_oID = sprite->GetID();
sprite->Add(new FlashTagPlaceObject2( 1, txt->GetID()));
if(m_underline)
{
int lineAdjust = 0;
int lineWidth = m_width;
int lineHeight = 45;
FlashShapeWithStyle shapeUnderline;
shapeUnderline.AddFillStyle(new FlashFillStyleSolid(*color));
FlashShapeRecordChange change = FlashShapeRecordChange(x,y+lineAdjust);
change.ChangeFillStyle1(1);
shapeUnderline.AddRecord(change);
shapeUnderline.AddRecord(FlashShapeRecordStraight(lineWidth, 0));
shapeUnderline.AddRecord(FlashShapeRecordStraight(0, lineHeight));
shapeUnderline.AddRecord(FlashShapeRecordStraight(-lineWidth, 0));
shapeUnderline.AddRecord(FlashShapeRecordStraight(0, -lineHeight));
FlashTagDefineShape3 *underlineShapeDef = new FlashTagDefineShape3(shapeUnderline);
stream << *underlineShapeDef;
sprite->Add(new FlashTagPlaceObject2( 2, underlineShapeDef->GetID()));
delete underlineShapeDef;
}
if(m_strikeout)
{
int lineAdjust = pointsize*11;
int lineWidth = m_width;
int lineHeight = pointsize*2;
FlashShapeWithStyle shapeUnderline;
shapeUnderline.AddFillStyle(new FlashFillStyleSolid(*color));
FlashShapeRecordChange change = FlashShapeRecordChange(x,y+lineAdjust);
change.ChangeFillStyle1(1);
shapeUnderline.AddRecord(change);
shapeUnderline.AddRecord(FlashShapeRecordStraight(lineWidth, 0));
shapeUnderline.AddRecord(FlashShapeRecordStraight(0, lineHeight));
shapeUnderline.AddRecord(FlashShapeRecordStraight(-lineWidth, 0));
shapeUnderline.AddRecord(FlashShapeRecordStraight(0, -lineHeight));
FlashTagDefineShape3 *underlineShapeDef = new FlashTagDefineShape3(shapeUnderline);
stream << *underlineShapeDef;
sprite->Add(new FlashTagPlaceObject( underlineShapeDef->GetID(), 1, FlashMatrix()));
delete underlineShapeDef;
}
sprite->Add(new FlashTagShowFrame());
stream << *sprite;
sprite->DeleteChildren();
delete sprite;
}
else
{
m_oID = txt->GetID();
}
delete txt;
delete ibuf;
return true;
}
std::vector <fontInfo> CFlashFontObj::font_infos;
std::vector <FlashTagDefineFont2*> CFlashFontObj::fonts;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -