| |
| |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| using namespace std; |
| |
| |
| |
| typedef struct { |
| Float32Point origin; |
| Boolean first; |
| Float32Point current; |
| |
| float adv; |
| TVectorImageP m_image; |
| std::vector<TThickPoint> m_points; |
| |
| } MyCurveCallbackData; |
| |
| typedef struct { |
| ATSGlyphRef glyphID; |
| Float32Point relativeOrigin; |
| } MyGlyphRecord; |
| |
| |
| |
| OSStatus MyQuadraticLineProc(const Float32Point *pt1, const Float32Point *pt2, void *callBackDataPtr) |
| { |
| |
| |
| |
| |
| |
| |
| |
| |
| MyCurveCallbackData *data = (MyCurveCallbackData *)callBackDataPtr; |
| |
| if (data->m_points.empty()) |
| data->m_points.push_back(TThickPoint(pt1->x, pt1->y, 0)); |
| |
| |
| |
| 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) |
| { |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| MyCurveCallbackData *data = (MyCurveCallbackData *)callBackDataPtr; |
| |
| if (data->m_points.empty()) |
| data->m_points.push_back(TThickPoint(pt1->x, pt1->y, 0)); |
| |
| |
| |
| 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); |
| |
| 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) |
| { |
| |
| |
| |
| ATSLayoutRecord *layoutRecords; |
| ItemCount numRecords; |
| Fixed *deltaYs; |
| ItemCount numDeltaYs; |
| unsigned int i; |
| OSStatus status; |
| |
| |
| status = ATSUDirectGetLayoutDataArrayPtrFromTextLayout( |
| iLayout, iStart, |
| kATSUDirectDataLayoutRecordATSLayoutRecordCurrent, |
| (void **)&layoutRecords, &numRecords); |
| assert(status == noErr); |
| |
| status = ATSUDirectGetLayoutDataArrayPtrFromTextLayout( |
| iLayout, iStart, |
| kATSUDirectDataBaselineDeltaFixedArray, |
| (void **)&deltaYs, &numDeltaYs); |
| assert(status == noErr); |
| |
| |
| *oGlyphRecordArray = (MyGlyphRecord *)malloc(numRecords * sizeof(MyGlyphRecord)); |
| *oNumGlyphs = numRecords; |
| |
| for (i = 0; i < *oNumGlyphs; i++) { |
| |
| (*oGlyphRecordArray)[i].glyphID = layoutRecords[i].glyphID; |
| |
| |
| |
| |
| |
| |
| (*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]); |
| } |
| } |
| |
| |
| 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) |
| { |
| |
| Fixed penX = 0; |
| Fixed penY = 0; |
| |
| |
| MyGlyphRecord *glyphRecordArray; |
| ItemCount numGlyphs; |
| ATSQuadraticNewPathUPP newPathProc; |
| ATSQuadraticLineUPP lineProc; |
| ATSQuadraticCurveUPP curveProc; |
| ATSQuadraticClosePathUPP closePathProc; |
| |
| OSStatus status; |
| unsigned int i; |
| |
| |
| newPathProc = NewATSQuadraticNewPathUPP(MyQuadraticNewPathProc); |
| lineProc = NewATSQuadraticLineUPP(MyQuadraticLineProc); |
| curveProc = NewATSQuadraticCurveUPP(MyQuadraticCurveProc); |
| closePathProc = NewATSQuadraticClosePathUPP(MyQuadraticClosePathProc); |
| |
| |
| GetGlyphIDsAndPositions(iLayout, start, length, &glyphRecordArray, &numGlyphs); |
| |
| |
| for (i = 0; i < numGlyphs; i++) { |
| |
| |
| data.origin.x = Fix2X(penX) + glyphRecordArray[i].relativeOrigin.x; |
| data.origin.y = Fix2X(penY) + glyphRecordArray[i].relativeOrigin.y; |
| |
| |
| data.first = true; |
| |
| |
| if (glyphRecordArray[i].glyphID != kATSDeletedGlyphcode) { |
| status = ATSUGlyphGetQuadraticPaths(iStyle, glyphRecordArray[i].glyphID, newPathProc, lineProc, curveProc, closePathProc, &data, &status); |
| assert(status == noErr); |
| } |
| } |
| |
| free(glyphRecordArray); |
| |
| |
| |
| DisposeATSQuadraticNewPathUPP(newPathProc); |
| DisposeATSQuadraticLineUPP(lineProc); |
| DisposeATSQuadraticCurveUPP(curveProc); |
| DisposeATSQuadraticClosePathUPP(closePathProc); |
| } |
| |
| |
| |
| struct TFont::Impl { |
| bool m_hasKerning; |
| int m_hasVertical; |
| |
| |
| |
| ATSUStyle m_style; |
| ATSUFontID m_fontId; |
| ATSUTextLayout m_layout; |
| Fixed m_size; |
| int m_ascender; |
| int m_descender; |
| |
| Impl(ATSUFontID fontId, int size); |
| ~Impl(); |
| |
| |
| }; |
| |
| |
| |
| 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); |
| |
| |
| 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); |
| |
| |
| 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 ; |
| 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); |
| |
| |
| |
| 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); |
| |
| |
| |
| 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; |
| |
| |
| 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; |
| } |
| |
| |
| |
| |
| |
| |
| 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; |
| |
| |
| status = ATSUFindFontName(fontId, |
| kFontFullName, |
| platform, |
| script, |
| lang, |
| 0, 0, |
| &oActualNameLength, |
| 0); |
| |
| if (status != noErr || oActualNameLength <= 1) |
| return false; |
| |
| buffer = new char[oActualNameLength + 1]; |
| |
| 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'; |
| |
| |
| |
| |
| 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]; |
| |
| |
| 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; |
| |
| |
| |
| 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; |
| |
| |
| for (lang = -1; lang <= 139; lang++) |
| for (script = -1; script <= 32; script++) |
| for (platform = -1; platform <= 4; platform++) { |
| |
| |
| |
| 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) {} |
| |
| |
| |
| |
| |