tahoma2d/toonz/sources/common/tvrender/tfont_mac.cpp

853 lines
24 KiB
C++
Raw Normal View History

2016-03-19 06:57:51 +13:00
#ifndef __LP64__
#include <vector>
#include <iostream>
#include <string>
#include "tmathutil.h"
#include "tdebugmessage.h"
#include "tfont.h"
#include "tstroke.h"
#include "tcurves.h"
#include "tconvert.h"
#include "tvectorimage.h"
using namespace std;
//----------------------------------------- structures -------------------------------------------------------------------
typedef struct {
Float32Point origin; // The origin of the current glyph
Boolean first; // Keeps track of which segment is first in a glyph
Float32Point current; // The current pen position (used to filter degenerate cases)
float adv;
TVectorImageP m_image;
std::vector<TThickPoint> m_points;
} MyCurveCallbackData;
typedef struct {
ATSGlyphRef glyphID; // The glyphID. This is simply an index into a table in the font.
Float32Point relativeOrigin; // The origin of this glyph -- relative to the origin of the line.
} MyGlyphRecord;
//----------------------------------------- callback---------------------------------------------------------------------
OSStatus MyQuadraticLineProc(const Float32Point *pt1, const Float32Point *pt2, void *callBackDataPtr)
{
/*
// Adjust the points according to the glyph origin
float x1 = ((MyCurveCallbackData *)callBackDataPtr)->origin.x + pt1->x;
float y1 = ((MyCurveCallbackData *)callBackDataPtr)->origin.y + pt1->y;
float x2 = ((MyCurveCallbackData *)callBackDataPtr)->origin.x + pt2->x;
float y2 = ((MyCurveCallbackData *)callBackDataPtr)->origin.y + pt2->y;
*/
MyCurveCallbackData *data = (MyCurveCallbackData *)callBackDataPtr;
if (data->m_points.empty())
data->m_points.push_back(TThickPoint(pt1->x, pt1->y, 0));
//else
//assert(isAlmostEqual(pt1 e back)
TThickPoint lastPoint = TThickPoint(pt2->x, pt2->y, 0);
data->m_points.push_back((data->m_points.back() + lastPoint) * 0.5);
data->m_points.push_back(lastPoint);
return noErr;
}
OSStatus MyQuadraticCurveProc(const Float32Point *pt1, const Float32Point *controlPt, const Float32Point *pt2, void *callBackDataPtr)
{
/*
// Adjust the points according to the glyph origin
float x1 = ((MyCurveCallbackData *)callBackDataPtr)->origin.x + pt1->x;
float y1 = ((MyCurveCallbackData *)callBackDataPtr)->origin.y + pt1->y;
float x2 = ((MyCurveCallbackData *)callBackDataPtr)->origin.x + pt2->x;
float y2 = ((MyCurveCallbackData *)callBackDataPtr)->origin.y + pt2->y;
float cpx = ((MyCurveCallbackData *)callBackDataPtr)->origin.x + controlPt->x;
float cpy = ((MyCurveCallbackData *)callBackDataPtr)->origin.y + controlPt->y;
*/
MyCurveCallbackData *data = (MyCurveCallbackData *)callBackDataPtr;
if (data->m_points.empty())
data->m_points.push_back(TThickPoint(pt1->x, pt1->y, 0));
//else
//assert(isAlmostEqual(pt1 e back)
data->m_points.push_back(TThickPoint(controlPt->x, controlPt->y, 0));
data->m_points.push_back(TThickPoint(pt2->x, pt2->y, 0));
return noErr;
}
OSStatus MyQuadraticNewPathProc(void *callBackDataPtr)
{
assert(((MyCurveCallbackData *)callBackDataPtr)->m_points.empty());
return noErr;
}
OSStatus MyQuadraticClosePathProc(void *callBackDataPtr)
{
MyCurveCallbackData *data = (MyCurveCallbackData *)callBackDataPtr;
assert(data->m_points.size() >= 3 && data->m_points.size() & 1); //il numero di punti di controllo devono essere dispari e >= 3
TStroke *stroke = new TStroke(data->m_points);
stroke->setSelfLoop(true);
data->m_points.clear();
data->m_image->addStroke(stroke);
return noErr;
}
//------------------------------------------------------------------------------------------------------------------
void GetGlyphIDsAndPositions(ATSUTextLayout iLayout, UniCharArrayOffset iStart, UniCharCount iLength, MyGlyphRecord **oGlyphRecordArray, ItemCount *oNumGlyphs)
{
// This block of code uses the new Direct Access APIs, which are only available on Mac OS X 10.2 and later systems
//
ATSLayoutRecord *layoutRecords;
ItemCount numRecords;
Fixed *deltaYs;
ItemCount numDeltaYs;
unsigned int i;
OSStatus status;
// Get the arrays of glyph information
status = ATSUDirectGetLayoutDataArrayPtrFromTextLayout(
iLayout, iStart,
kATSUDirectDataLayoutRecordATSLayoutRecordCurrent,
(void **)&layoutRecords, &numRecords);
assert(status == noErr);
status = ATSUDirectGetLayoutDataArrayPtrFromTextLayout(
iLayout, iStart,
kATSUDirectDataBaselineDeltaFixedArray,
(void **)&deltaYs, &numDeltaYs);
assert(status == noErr);
// Build the array of MyGlyphRecords
*oGlyphRecordArray = (MyGlyphRecord *)malloc(numRecords * sizeof(MyGlyphRecord));
*oNumGlyphs = numRecords;
for (i = 0; i < *oNumGlyphs; i++) {
// Fill in the glyphID
(*oGlyphRecordArray)[i].glyphID = layoutRecords[i].glyphID;
// Set up the relative origin of the glyph
//
// The real position is the x coordinate of the glyph, relative to the beginning of the line
// The baseline delta (deltaY), if any, is the y coordinate of the glyph, relative to the baseline
//
(*oGlyphRecordArray)[i].relativeOrigin.x = Fix2X(layoutRecords[i].realPos);
if (deltaYs == NULL) {
(*oGlyphRecordArray)[i].relativeOrigin.y = 0.0;
} else {
(*oGlyphRecordArray)[i].relativeOrigin.y = 0.0 - Fix2X(deltaYs[i]);
}
}
// Free the arrays of glyph information
if (deltaYs != NULL) {
status = ATSUDirectReleaseLayoutDataArrayPtr(NULL, kATSUDirectDataBaselineDeltaFixedArray, (void **)&deltaYs);
assert(status == noErr);
}
status = ATSUDirectReleaseLayoutDataArrayPtr(NULL, kATSUDirectDataLayoutRecordATSLayoutRecordCurrent, (void **)&layoutRecords);
assert(status == noErr);
}
void drawQuadratics(ATSUTextLayout iLayout, ATSUStyle iStyle, UniCharArrayOffset start, UniCharCount length, MyCurveCallbackData &data)
{
//boh ----------------
Fixed penX = 0;
Fixed penY = 0;
// -------------------
MyGlyphRecord *glyphRecordArray;
ItemCount numGlyphs;
ATSQuadraticNewPathUPP newPathProc;
ATSQuadraticLineUPP lineProc;
ATSQuadraticCurveUPP curveProc;
ATSQuadraticClosePathUPP closePathProc;
OSStatus status;
unsigned int i;
// Create the Quadratic callbacks
newPathProc = NewATSQuadraticNewPathUPP(MyQuadraticNewPathProc);
lineProc = NewATSQuadraticLineUPP(MyQuadraticLineProc);
curveProc = NewATSQuadraticCurveUPP(MyQuadraticCurveProc);
closePathProc = NewATSQuadraticClosePathUPP(MyQuadraticClosePathProc);
// Get the array of glyph information
GetGlyphIDsAndPositions(iLayout, start, length, &glyphRecordArray, &numGlyphs);
// Loop over all the glyphs
for (i = 0; i < numGlyphs; i++) {
// Set up the absolute origin of the glyph
data.origin.x = Fix2X(penX) + glyphRecordArray[i].relativeOrigin.x;
data.origin.y = Fix2X(penY) + glyphRecordArray[i].relativeOrigin.y;
// Reset state for quadratic drawing (the callbacks only do a MoveTo on the very first segment)
data.first = true;
// If this is a deleted glyph (-1), don't draw it. Otherwise, go ahead.
if (glyphRecordArray[i].glyphID != kATSDeletedGlyphcode) {
status = ATSUGlyphGetQuadraticPaths(iStyle, glyphRecordArray[i].glyphID, newPathProc, lineProc, curveProc, closePathProc, &data, &status);
assert(status == noErr);
}
}
// Free the array of glyph information
free(glyphRecordArray);
// Dispose of the Quadratic callbacks
DisposeATSQuadraticNewPathUPP(newPathProc);
DisposeATSQuadraticLineUPP(lineProc);
DisposeATSQuadraticCurveUPP(curveProc);
DisposeATSQuadraticClosePathUPP(closePathProc);
}
//=============================================================================
struct TFont::Impl {
bool m_hasKerning;
int m_hasVertical;
// KerningPairs m_kerningPairs;
ATSUStyle m_style;
ATSUFontID m_fontId;
ATSUTextLayout m_layout;
Fixed m_size;
int m_ascender;
int m_descender;
Impl(ATSUFontID fontId, int size);
~Impl();
//void getChar();
};
//-----------------------------------------------------------------------------
TFont::TFont(ATSUFontID fontId, int size)
{
m_pimpl = new Impl(fontId, size);
}
//-----------------------------------------------------------------------------
TFont::~TFont()
{
delete m_pimpl;
}
//-----------------------------------------------------------------------------
TFont::Impl::Impl(ATSUFontID fontId, int size)
: m_fontId(fontId), m_size(Long2Fix(size))
{
OSStatus status;
long response;
status = Gestalt(gestaltATSUFeatures, &response);
assert(response & gestaltATSUDirectAccess);
status = ATSUCreateStyle(&m_style);
assert(status == noErr);
ATSUAttributeTag tags[2];
ByteCount sizes[2];
ATSUAttributeValuePtr values[2];
tags[0] = kATSUFontTag;
sizes[0] = sizeof(ATSUFontID);
values[0] = &fontId;
tags[1] = kATSUSizeTag;
sizes[1] = sizeof(Fixed);
values[1] = &m_size;
status = ATSUSetAttributes(m_style, 2, tags, sizes, values);
//assert(status==noErr);
UniChar dummyStr[] = {'H', 'e', 'l', 'l', 'o'};
UniCharCount length = sizeof(dummyStr) / sizeof(UniChar);
status = ATSUCreateTextLayoutWithTextPtr(
dummyStr, kATSUFromTextBeginning, kATSUToTextEnd, length, 1,
&length, &m_style, &m_layout);
//assert(status==noErr);
ATSTrapezoid glyphBounds;
status = ATSUGetGlyphBounds(m_layout, 0, 0,
kATSUFromTextBeginning, kATSUToTextEnd, kATSUseFractionalOrigins,
1, &glyphBounds, NULL);
m_ascender = -FixedToInt(glyphBounds.upperLeft.y);
assert(m_ascender > 0);
m_descender = -FixedToInt(glyphBounds.lowerLeft.y);
assert(m_descender < 0);
}
//-----------------------------------------------------------------------------
TFont::Impl::~Impl()
{
}
//-----------------------------------------------------------------------------
TPoint TFont::drawChar(TVectorImageP &image, wchar_t charcode, wchar_t nextCharCode) const
{
OSStatus status;
UniChar subString[2];
subString[0] = charcode;
subString[1] = 0 /*nextCharCode*/;
UniCharCount length = sizeof(subString) / sizeof(UniChar);
status = ATSUCreateTextLayoutWithTextPtr(subString, kATSUFromTextBeginning, kATSUToTextEnd,
length, 1,
&length, &(m_pimpl->m_style), &(m_pimpl->m_layout));
assert(status == noErr);
MyCurveCallbackData data;
data.m_image = image;
drawQuadratics(m_pimpl->m_layout, m_pimpl->m_style, kATSUFromTextBeginning, kATSUToTextEnd, data);
image->transform(TScale(1, -1));
image->group(0, image->getStrokeCount());
return getDistance(charcode, nextCharCode);
}
//-----------------------------------------------------------------------------
namespace
{
void appDrawChar(TRasterGR8P &outImage, TFont::Impl *pimpl, wchar_t charcode)
{
OSStatus status;
UniChar subString[2];
subString[0] = charcode;
subString[1] = 0;
UniCharCount length = sizeof(subString) / sizeof(UniChar);
status = ATSUCreateTextLayoutWithTextPtr(subString, kATSUFromTextBeginning, kATSUToTextEnd,
length, 1,
&length, &(pimpl->m_style), &(pimpl->m_layout));
assert(status == noErr);
ATSTrapezoid glyphBounds;
status = ATSUGetGlyphBounds(pimpl->m_layout, 0, 0,
kATSUFromTextBeginning, kATSUToTextEnd, kATSUseFractionalOrigins,
1, &glyphBounds, NULL);
int height = FixedToInt(glyphBounds.lowerLeft.y) - FixedToInt(glyphBounds.upperLeft.y);
int width = tmax(FixedToInt(glyphBounds.lowerRight.x), FixedToInt(glyphBounds.upperRight.x)) -
tmin(FixedToInt(glyphBounds.lowerLeft.x), FixedToInt(glyphBounds.upperLeft.x));
outImage = TRasterGR8P(width, height);
TPixelGR8 bgp;
bgp.value = 255;
outImage->fill(bgp);
void *data = outImage->getRawData();
CGColorSpaceRef grayColorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericGray);
CGContextRef gContext = CGBitmapContextCreate(data, width, height, 8, width, grayColorSpace, kCGImageAlphaNone);
#if defined(DEBUG) || defined(_DEBUG)
int bpc = CGBitmapContextGetBitsPerComponent(gContext);
if (bpc != 8)
std::cout << "BitsPerComponent: " << bpc << std::endl;
int bpp = CGBitmapContextGetBitsPerPixel(gContext);
if (bpp != 8)
std::cout << "BitsPerPixel: " << bpp << std::endl;
int bytesPerRow = CGBitmapContextGetBytesPerRow(gContext);
int newWidth = CGBitmapContextGetWidth(gContext);
if (bytesPerRow != width || newWidth != width)
std::cout << "BytesPerRow: " << bytesPerRow
<< " Old width= " << width
<< " New width= " << newWidth << std::endl;
int newHeight = CGBitmapContextGetHeight(gContext);
if (newHeight != height)
std::cout << " Old height= " << height << " New height= " << newHeight << std::endl;
assert(CGBitmapContextGetColorSpace(gContext) == grayColorSpace);
#endif
ATSUAttributeTag tags[1];
ByteCount sizes[1];
ATSUAttributeValuePtr values[1];
tags[0] = kATSUCGContextTag;
sizes[0] = sizeof(CGContextRef);
values[0] = &gContext;
status = ATSUSetLayoutControls(pimpl->m_layout, 1, tags, sizes, values);
assert(status == noErr);
ATSUDrawText(pimpl->m_layout, kATSUFromTextBeginning, kATSUToTextEnd, 0, glyphBounds.lowerLeft.y);
}
}
//-----------------------------------------------------------------------------
TPoint TFont::drawChar(TRasterGR8P &outImage, TPoint &unused, wchar_t charcode, wchar_t nextCharCode) const
{
appDrawChar(outImage, m_pimpl, charcode);
outImage->yMirror();
return getDistance(charcode, nextCharCode);
}
//-----------------------------------------------------------------------------
TPoint TFont::drawChar(TRasterCM32P &outImage, TPoint &unused, int inkId, wchar_t charcode, wchar_t nextCharCode) const
{
TRasterGR8P grayAppImage;
appDrawChar(grayAppImage, m_pimpl, charcode);
int lx = grayAppImage->getLx();
int ly = grayAppImage->getLy();
outImage = TRasterCM32P(lx, ly);
assert(TPixelCM32::getMaxTone() == 255);
TPixelCM32 bgColor(0, 0, TPixelCM32::getMaxTone());
grayAppImage->lock();
outImage->lock();
int ty = 0;
for (int gy = ly - 1; gy >= 0; --gy, ++ty) {
TPixelGR8 *srcPix = grayAppImage->pixels(gy);
TPixelCM32 *tarPix = outImage->pixels(ty);
for (int x = 0; x < lx; ++x) {
int tone = srcPix->value;
if (tone == 255)
*tarPix = bgColor;
else
*tarPix = TPixelCM32(inkId, 0, tone);
++srcPix;
++tarPix;
}
}
grayAppImage->unlock();
outImage->unlock();
return getDistance(charcode, nextCharCode);
}
//-----------------------------------------------------------------------------
TPoint TFont::getDistance(wchar_t firstChar, wchar_t secondChar) const
{
OSStatus status;
UniChar subString[2];
subString[0] = firstChar;
subString[1] = secondChar;
UniCharCount length = sizeof(subString) / sizeof(UniChar);
status = ATSUCreateTextLayoutWithTextPtr(subString, kATSUFromTextBeginning, kATSUToTextEnd,
length, 1,
&length, &(m_pimpl->m_style), &(m_pimpl->m_layout));
assert(status == noErr);
MyGlyphRecord *glyphRecordArray;
ItemCount numGlyphs;
// Get the array of glyph information
GetGlyphIDsAndPositions(m_pimpl->m_layout, kATSUFromTextBeginning, kATSUToTextEnd, &glyphRecordArray, &numGlyphs);
assert(numGlyphs >= 2);
assert(glyphRecordArray[0].relativeOrigin.x == 0);
int advance = (int)(glyphRecordArray[1].relativeOrigin.x - glyphRecordArray[0].relativeOrigin.x);
if (advance == 0) {
subString[1] = 0;
status = ATSUCreateTextLayoutWithTextPtr(subString, kATSUFromTextBeginning, kATSUToTextEnd,
length, 1,
&length, &(m_pimpl->m_style), &(m_pimpl->m_layout));
GetGlyphIDsAndPositions(m_pimpl->m_layout, kATSUFromTextBeginning, kATSUToTextEnd, &glyphRecordArray, &numGlyphs);
advance = (int)(glyphRecordArray[1].relativeOrigin.x - glyphRecordArray[0].relativeOrigin.x);
}
return TPoint(advance, 0);
}
//-----------------------------------------------------------------------------
int TFont::getMaxHeight() const
{
return m_pimpl->m_ascender - m_pimpl->m_descender;
}
//-----------------------------------------------------------------------------
int TFont::getMaxWidth() const
{
assert(!"not implemented yet");
return 100;
}
//-----------------------------------------------------------------------------
int TFont::getLineAscender() const
{
return m_pimpl->m_ascender;
}
//-----------------------------------------------------------------------------
int TFont::getLineDescender() const
{
return m_pimpl->m_descender;
}
//-----------------------------------------------------------------------------
bool TFont::hasKerning() const
{
return true;
}
//-----------------------------------------------------------------------------
bool TFont::hasVertical() const
{
return false;
}
//-----------------------------------------------------------------------------
#include <string>
#include <map>
typedef std::map<std::string, ATSUFontID> FontFamily;
typedef std::map<std::string, FontFamily> FamilyMap;
struct TFontManager::Impl {
FamilyMap m_families;
bool m_loaded;
ATSUFontID m_currentAtsuFontId;
TFont *m_currentFont;
wstring m_currentFamily;
wstring m_currentTypeface;
int m_size;
Impl()
: m_currentAtsuFontId(0), m_currentFont(0), m_loaded(false), m_size(70)
{
}
bool setFontName(ATSUFontID fontId, int platform, int script, int lang);
bool addFont(ATSUFontID);
void loadFontNames();
bool setFont(std::wstring family, std::wstring style);
};
using namespace std;
bool TFontManager::Impl::setFontName(ATSUFontID fontId, int platform, int script, int lang)
{
ByteCount oActualNameLength;
ItemCount oFontCount;
OSStatus status;
char *buffer = 0;
char *buffer2 = 0;
// chiedo la lunhezza del Full Family Name per allocare il buffer
status = ATSUFindFontName(fontId,
kFontFullName,
platform,
script,
lang,
0, 0,
&oActualNameLength,
0);
if (status != noErr || oActualNameLength <= 1)
return false;
buffer = new char[oActualNameLength + 1];
// chiedo il Full Family Name
status = ATSUFindFontName(fontId,
kFontFullName,
platform,
script,
lang,
oActualNameLength, buffer,
&oActualNameLength,
&oFontCount);
if (status != noErr || oActualNameLength <= 1 || buffer[0] == '\0') {
delete[] buffer;
return false;
}
buffer[oActualNameLength] = '\0';
//-------------------
// chiedo la lunhezza del Typeface Name per allocare il buffer
status = ATSUFindFontName(fontId,
kFontStyleName,
platform,
script,
lang,
0, 0,
&oActualNameLength,
0);
if (status != noErr || oActualNameLength <= 1) {
delete[] buffer;
return false;
}
buffer2 = new char[oActualNameLength + 1];
// chiedo il Typeface Name
status = ATSUFindFontName(fontId,
kFontStyleName,
platform,
script,
lang,
oActualNameLength, buffer2,
&oActualNameLength,
&oFontCount);
if (status != noErr || oActualNameLength <= 1 || buffer2[0] == '\0') {
delete[] buffer;
delete[] buffer2;
return false;
} else
buffer2[oActualNameLength] = '\0';
string s_family(buffer);
FontFamily &family = m_families[s_family];
family[string(buffer2)] = fontId;
delete[] buffer;
delete[] buffer2;
return true;
}
bool TFontManager::Impl::addFont(ATSUFontID fontId)
{
int platform, script, lang;
// per ottimizzare, ciclo solo sui valori
// piu' comuni
for (lang = -1; lang <= 0; lang++)
for (platform = -1; platform <= 1; platform++)
for (script = -1; script <= 0; script++)
if (setFontName(fontId, platform, script, lang))
return true;
//poi li provo tutti
for (lang = -1; lang <= 139; lang++)
for (script = -1; script <= 32; script++)
for (platform = -1; platform <= 4; platform++) {
// escludo quelli nel tri-ciclo for precedente.
// Purtoppo si deve fare cosi:
// non si puo' fare partendo con indici piu' alti nei cicli for!
if (-1 <= lang && lang <= 0 &&
-1 <= script && script <= 0 &&
-1 <= platform && platform <= 1)
continue;
if (setFontName(fontId, platform, script, lang))
return true;
}
return false;
}
void TFontManager::Impl::loadFontNames()
{
if (m_loaded)
return;
ItemCount oFontCount, fontCount;
ATSUFontCount(&oFontCount);
fontCount = oFontCount;
ATSUFontID *oFontIDs = new ATSUFontID[fontCount];
ATSUGetFontIDs(oFontIDs, fontCount, &oFontCount);
assert(fontCount == oFontCount);
for (unsigned int i = 0; i < fontCount; i++)
addFont(oFontIDs[i]);
delete[] oFontIDs;
m_loaded = true;
}
bool TFontManager::Impl::setFont(std::wstring family, std::wstring typeface)
{
if (family == m_currentFamily && (typeface == m_currentTypeface || typeface == L""))
return false;
FamilyMap::iterator family_it = m_families.find(toString(family));
if (family_it == m_families.end())
throw TFontCreationError();
m_currentFamily = family;
FontFamily::iterator style_it;
if (typeface == L"") {
style_it = ((*family_it).second).find(toString(m_currentTypeface));
if (style_it == (*family_it).second.end())
style_it = ((*family_it).second).begin();
typeface = toWideString(style_it->first);
} else
style_it = ((*family_it).second).find(toString(typeface));
if (style_it == (*family_it).second.end())
throw TFontCreationError();
m_currentTypeface = typeface;
m_currentAtsuFontId = (*style_it).second;
return true;
}
//---------------------------------------------------------
TFontManager::TFontManager()
{
m_pimpl = new TFontManager::Impl();
}
//---------------------------------------------------------
TFontManager::~TFontManager()
{
delete m_pimpl;
}
//---------------------------------------------------------
TFontManager *TFontManager::instance()
{
static TFontManager theManager;
return &theManager;
}
//---------------------------------------------------------
void TFontManager::loadFontNames()
{
m_pimpl->loadFontNames();
}
//---------------------------------------------------------
void TFontManager::setFamily(const wstring family)
{
bool changed = m_pimpl->setFont(family, L"");
if (changed) {
delete m_pimpl->m_currentFont;
m_pimpl->m_currentFont = new TFont(m_pimpl->m_currentAtsuFontId, m_pimpl->m_size);
}
}
//---------------------------------------------------------
void TFontManager::setTypeface(const wstring typeface)
{
bool changed = m_pimpl->setFont(m_pimpl->m_currentFamily, typeface);
if (changed) {
delete m_pimpl->m_currentFont;
m_pimpl->m_currentFont = new TFont(m_pimpl->m_currentAtsuFontId, m_pimpl->m_size);
}
}
//---------------------------------------------------------
void TFontManager::setSize(int size)
{
if (m_pimpl->m_size != size) {
m_pimpl->m_size = size;
delete m_pimpl->m_currentFont;
m_pimpl->m_currentFont = new TFont(m_pimpl->m_currentAtsuFontId, m_pimpl->m_size);
}
}
//---------------------------------------------------------
wstring TFontManager::getCurrentFamily() const
{
return m_pimpl->m_currentFamily;
}
//---------------------------------------------------------
wstring TFontManager::getCurrentTypeface() const
{
return m_pimpl->m_currentTypeface;
}
//---------------------------------------------------------
TFont *TFontManager::getCurrentFont()
{
if (m_pimpl->m_currentFont)
return m_pimpl->m_currentFont;
if (!m_pimpl->m_currentFont)
loadFontNames();
assert(!m_pimpl->m_families.empty());
setFamily(toWideString(m_pimpl->m_families.begin()->first));
return m_pimpl->m_currentFont;
}
//---------------------------------------------------------
void TFontManager::getAllFamilies(vector<wstring> &families) const
{
families.clear();
families.reserve(m_pimpl->m_families.size());
FamilyMap::iterator it = m_pimpl->m_families.begin();
for (; it != m_pimpl->m_families.end(); ++it) {
families.push_back(toWideString(it->first));
}
}
//---------------------------------------------------------
void TFontManager::getAllTypefaces(vector<wstring> &typefaces) const
{
typefaces.clear();
FamilyMap::iterator it_family = m_pimpl->m_families.find(toString(m_pimpl->m_currentFamily));
if (it_family == m_pimpl->m_families.end())
return;
FontFamily &typefaceSet = it_family->second;
typefaces.reserve(typefaceSet.size());
FontFamily::iterator it_typeface = typefaceSet.begin();
for (; it_typeface != typefaceSet.end(); ++it_typeface) {
typefaces.push_back(toWideString(it_typeface->first));
}
}
//---------------------------------------------------------
void TFontManager::setVertical(bool vertical) {}
//---------------------------------------------------------
#endif