00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 #ifdef _MSC_VER
00041 # pragma warning (disable: 4786)
00042 #endif
00043
00044 #include "OSGTextMacBackend.h"
00045 #include <OSGBaseTypes.h>
00046
00047
00048 #ifdef __APPLE__
00049
00050
00051 #include "OSGTextPixmapFace.h"
00052 #include "OSGTextPixmapGlyph.h"
00053 #include "OSGTextVectorFace.h"
00054 #include "OSGTextVectorGlyph.h"
00055 #include "OSGTextTXFFace.h"
00056 #include "OSGTextTXFGlyph.h"
00057 #include "OSGTextLayoutParam.h"
00058 #include "OSGTextLayoutResult.h"
00059
00060 #include <iostream>
00061 #include <algorithm>
00062 #include <set>
00063
00064 #include <ApplicationServices/ApplicationServices.h>
00065
00066
00067 using namespace std;
00068
00069
00070 OSG_BEGIN_NAMESPACE
00071
00072
00073
00074
00075
00076
00077 class TextMacVectorFace: public TextVectorFace
00078 {
00079 public:
00080
00081
00082 TextMacVectorFace(ATSUStyle horiFontStyle);
00083
00084
00085 virtual ~TextMacVectorFace();
00086
00087
00088 virtual void layout(const wstring &text, const TextLayoutParam ¶m,
00089 TextLayoutResult &layoutResult);
00090
00091 protected:
00092
00093
00094 virtual auto_ptr<TextVectorGlyph> createGlyph(TextGlyph::Index glyphIndex);
00095
00096 private:
00097
00098
00099 ATSUStyle _horiFontStyle;
00100 ATSUStyle _vertFontStyle;
00101
00102
00103 ATSUTextLayout _horiTextLayout;
00104 ATSUTextLayout _vertTextLayout;
00105 };
00106
00107
00108
00109
00110
00111
00112 class TextMacVectorGlyph: public TextVectorGlyph
00113 {
00114 public:
00115
00116
00117 TextMacVectorGlyph(Index glyphIndex, Real32 scale, ATSUStyle horiFontStyle, ATSUStyle vertFontStyle);
00118
00119
00120 virtual ~TextMacVectorGlyph();
00121 };
00122
00123
00124
00125
00126
00127
00128 class TextMacPixmapFace: public TextPixmapFace
00129 {
00130 public:
00131
00132
00133 TextMacPixmapFace(ATSUStyle horiFontStyle);
00134
00135
00136 virtual ~TextMacPixmapFace();
00137
00138
00139 virtual void layout(const wstring &text, const TextLayoutParam ¶m,
00140 TextLayoutResult &layoutResult);
00141
00142 protected:
00143
00144
00145 virtual auto_ptr<TextPixmapGlyph> createGlyph(TextGlyph::Index glyphIndex);
00146
00147 private:
00148
00149 const TextPixmapGlyph &getPixmapGlyph(const ATSLayoutRecord &layoutRecord, bool horizontal);
00150
00151
00152 ATSUStyle _horiFontStyle;
00153 ATSUStyle _vertFontStyle;
00154
00155
00156 ATSUTextLayout _horiTextLayout;
00157 ATSUTextLayout _vertTextLayout;
00158 };
00159
00160
00161
00162
00163
00164
00165 class TextMacPixmapGlyph: public TextPixmapGlyph
00166 {
00167 public:
00168
00169
00170 TextMacPixmapGlyph(Index glyphIndex, UInt32 width, UInt32 height,
00171 Real32 horiAdvance, Int32 horiBearingX, Int32 horiBearingY,
00172 Real32 vertAdvance, Int32 vertBearingX, Int32 vertBearingY,
00173 UInt8 *pixmap);
00174
00175
00176 virtual ~TextMacPixmapGlyph();
00177 };
00178
00179
00180
00181
00182
00183
00184 class TextMacTXFFace: public TextTXFFace
00185 {
00186 public:
00187
00188
00189 TextMacTXFFace(ATSUStyle horiFontStyle, const TextTXFParam ¶m);
00190
00191
00192 virtual ~TextMacTXFFace();
00193
00194 private:
00195
00196 void createGlyphs(ATSUStyle horiFontStyle, ATSUStyle vertFontStyle,
00197 ATSUTextLayout horiTextLayout, ATSUTextLayout vertTextLayout,
00198 const TextTXFParam ¶m);
00199 };
00200
00201
00202
00203
00204
00205
00206 class TextMacTXFGlyph: public TextTXFGlyph
00207 {
00208 public:
00209
00210
00211 TextMacTXFGlyph(Index glyphIndex, Real32 scale, const ATSGlyphScreenMetrics &horiMetrics, const ATSGlyphScreenMetrics &vertMetrics);
00212
00213
00214 virtual ~TextMacTXFGlyph();
00215 };
00216
00217
00218
00219
00220
00221
00222 TextMacBackend::TextMacBackend(): TextBackend() {}
00223
00224
00225
00226
00227
00228
00229 TextMacBackend::~TextMacBackend() {}
00230
00231
00232
00233
00234
00235
00236 static string getFamilyName(ATSUFontID fontID)
00237 {
00238 ItemCount fontNameIndex;
00239 OSStatus result = ATSUFindFontName(fontID, kFontFamilyName, kFontNoPlatformCode,
00240 kFontNoScriptCode, kFontNoLanguageCode,
00241 0, 0, 0, &fontNameIndex);
00242 if (result != noErr)
00243 return string();
00244 ByteCount actualNameLength;
00245 result = ATSUGetIndFontName(fontID, fontNameIndex, 0, 0, &actualNameLength,
00246 0, 0, 0, 0);
00247 if ((result != noErr) || (actualNameLength == 0))
00248 return string();
00249 vector<char> name;
00250 name.resize(actualNameLength);
00251 FontPlatformCode fontNamePlatform;
00252 result = ATSUGetIndFontName(fontID, fontNameIndex, actualNameLength, &(name.front()), 0,
00253 0, &fontNamePlatform, 0, 0);
00254 if ((result != noErr) || (actualNameLength == 0))
00255 return string();
00256 CFStringRef str = 0;
00257 switch (fontNamePlatform)
00258 {
00259 case kFontUnicodePlatform:
00260 case kFontMicrosoftPlatform:
00261 str = CFStringCreateWithBytes(kCFAllocatorDefault, reinterpret_cast< ::UInt8*>(&(name.front())),
00262 actualNameLength, kCFStringEncodingUnicode, false);
00263 break;
00264 case kFontMacintoshPlatform:
00265 str = CFStringCreateWithBytes(kCFAllocatorDefault, reinterpret_cast< ::UInt8*>(&(name.front())),
00266 actualNameLength, kCFStringEncodingMacRoman, false);
00267 break;
00268 default:
00269 return string();
00270 }
00271 if (str == 0)
00272 return string();
00273 CFDataRef data = CFStringCreateExternalRepresentation(kCFAllocatorDefault, str, kCFStringEncodingUTF8, ' ');
00274 CFRelease(str);
00275 if (data == 0)
00276 return string();
00277 string familyName(reinterpret_cast<const char*>(CFDataGetBytePtr(data)),
00278 static_cast<string::size_type>(CFDataGetLength(data)));
00279 CFRelease(data);
00280 return familyName;
00281 }
00282
00283
00284
00285
00286
00287
00288 static ATSUStyle findFont(const string &family, TextFace::Style style, UInt32 size)
00289 {
00290
00291 string f;
00292 if (family == "SERIF")
00293 f = "Times New Roman";
00294 else if (family == "SANS")
00295 f = "Arial";
00296 else if (family == "TYPEWRITER")
00297 f = "Courier";
00298 else
00299 f = family;
00300
00301
00302 ItemCount fontCount;
00303 OSStatus result = ATSUFontCount(&fontCount);
00304 if ((result != noErr) || (fontCount == 0))
00305 return 0;
00306
00307
00308 vector<ATSUFontID> fontIDs;
00309 fontIDs.resize(fontCount);
00310 result = ATSUGetFontIDs(&(fontIDs.front()), fontCount, &fontCount);
00311 if (result != noErr)
00312 return 0;
00313
00314
00315 ItemCount i;
00316 for (i = 0; i < fontCount; ++i)
00317 {
00318 string familyName = getFamilyName(fontIDs[i]);
00319 if (familyName == f)
00320 break;
00321 }
00322 if (i >= fontCount)
00323 return 0;
00324 ATSUFontID fontID = fontIDs[i];
00325
00326 FMFontFamily fontFamily;
00327 result = FMGetFontFamilyInstanceFromFont(fontID, &fontFamily, 0);
00328 if (result != noErr)
00329 return 0;
00330 FMFontStyle fStyle;
00331 switch (style)
00332 {
00333 default:
00334 FWARNING(("Invalid font style parameter.\n"));
00335
00336 case TextFace::STYLE_PLAIN: fStyle = normal; break;
00337 case TextFace::STYLE_BOLD: fStyle = bold; break;
00338 case TextFace::STYLE_ITALIC: fStyle = italic; break;
00339 case TextFace::STYLE_BOLDITALIC: fStyle = bold | italic; break;
00340 }
00341 result = FMGetFontFromFontFamilyInstance(fontFamily, fStyle, &fontID, 0);
00342 if ((result != noErr) || (fontID == kATSUInvalidFontID))
00343 return 0;
00344
00345
00346 ATSUStyle fontStyle;
00347 result = ATSUCreateStyle(&fontStyle);
00348 if (result != noErr)
00349 return 0;
00350
00351
00352
00353
00354 Fixed fontSize = IntToFixed(size);
00355 ATSUAttributeTag attributeTags[] = { kATSUFontTag, kATSUSizeTag };
00356 ByteCount attributeSizes[] = { sizeof(fontID), sizeof(fontSize) };
00357 ATSUAttributeValuePtr attributeValues[] = { &fontID, &fontSize };
00358 result = ATSUSetAttributes(fontStyle, 2, attributeTags, attributeSizes, attributeValues);
00359 if (result != noErr)
00360 {
00361 ATSUDisposeStyle(fontStyle);
00362 return 0;
00363 }
00364
00365 return fontStyle;
00366 }
00367
00368
00369
00370
00371
00372
00373 TextVectorFace *TextMacBackend::createVectorFace(const string &family, TextFace::Style style)
00374 {
00375
00376 ATSUStyle horiFontStyle = findFont(family, style, 1000);
00377 if (horiFontStyle == 0)
00378 return 0;
00379
00380
00381 ATSStyleRenderingOptions styleRenderingOptions = kATSStyleNoHinting;
00382 ATSUAttributeTag attributeTag = kATSUStyleRenderingOptionsTag;
00383 ByteCount attributeSize = sizeof(styleRenderingOptions);
00384 ATSUAttributeValuePtr attributeValue = &styleRenderingOptions;
00385 OSStatus result = ATSUSetAttributes(horiFontStyle, 1, &attributeTag, &attributeSize, &attributeValue);
00386
00387
00388
00389 return new TextMacVectorFace(horiFontStyle);
00390 }
00391
00392
00393
00394
00395
00396
00397 TextPixmapFace *TextMacBackend::createPixmapFace(const string &family, TextFace::Style style, UInt32 size)
00398 {
00399
00400 ATSUStyle horiFontStyle = findFont(family, style, size);
00401 if (horiFontStyle == 0)
00402 return 0;
00403
00404
00405 return new TextMacPixmapFace(horiFontStyle);
00406 }
00407
00408
00409
00410
00411
00412
00413 TextTXFFace *TextMacBackend::createTXFFace(const string &family,
00414 TextFace::Style style,
00415 const TextTXFParam ¶m)
00416 {
00417
00418 ATSUStyle horiFontStyle = findFont(family, style, param.size);
00419 if (horiFontStyle == 0)
00420 return 0;
00421
00422
00423 return new TextMacTXFFace(horiFontStyle, param);
00424 }
00425
00426
00427
00428
00429
00430
00431 void TextMacBackend::getFontFamilies(vector<string> &families)
00432 {
00433 families.clear();
00434
00435
00436 ItemCount fontCount;
00437 OSStatus result = ATSUFontCount(&fontCount);
00438 if ((result != noErr) || (fontCount == 0))
00439 return;
00440
00441
00442 vector<ATSUFontID> fontIDs;
00443 fontIDs.resize(fontCount);
00444 result = ATSUGetFontIDs(&(fontIDs.front()), fontCount, &fontCount);
00445 if (result != noErr)
00446 return;
00447
00448
00449 ItemCount i;
00450 set<string> familySet;
00451 for (i = 0; i < fontCount; ++i)
00452 {
00453 string familyName = getFamilyName(fontIDs[i]);
00454 if (familyName.empty() == false)
00455 familySet.insert(familyName);
00456 }
00457 families.assign(familySet.begin(), familySet.end());
00458 }
00459
00460
00461
00462
00463
00464
00465 static void getFaceInfo(ATSUStyle horiFontStyle, ATSUStyle vertFontStyle, string &family, TextFace::Style &style,
00466 Real32 &horiAscent, Real32 &horiDescent,
00467 Real32 &vertAscent, Real32 &vertDescent)
00468 {
00469
00470 ATSUFontID fontID;
00471 OSStatus result = ATSUGetAttribute(horiFontStyle, kATSUFontTag, sizeof(fontID), &fontID, 0);
00472 if (((result == noErr) || (result == kATSUNotSetErr)) && (fontID != kATSUInvalidFontID))
00473 family = getFamilyName(fontID);
00474 else
00475 family.erase();
00476
00477
00478 Boolean bold;
00479 result = ATSUGetAttribute(horiFontStyle, kATSUQDBoldfaceTag, sizeof(bold), &bold, 0);
00480 if ((result != noErr) && (result != kATSUNotSetErr))
00481 bold = false;
00482 Boolean italic;
00483 result = ATSUGetAttribute(horiFontStyle, kATSUQDItalicTag, sizeof(italic), &italic, 0);
00484 if ((result != noErr) && (result != kATSUNotSetErr))
00485 italic = false;
00486 style = (bold == TRUE) ?
00487 (italic == TRUE ? TextFace::STYLE_BOLDITALIC : TextFace::STYLE_BOLD) :
00488 (italic == TRUE ? TextFace::STYLE_ITALIC : TextFace::STYLE_PLAIN);
00489
00490
00491 ATSUTextMeasurement measurement;
00492 result = ATSUGetAttribute(horiFontStyle, kATSUAscentTag, sizeof(measurement), &measurement, 0);
00493 horiAscent = ((result == noErr) || (result == kATSUNotSetErr)) ? FixedToFloat(measurement) : 0.f;
00494 result = ATSUGetAttribute(vertFontStyle, kATSUAscentTag, sizeof(measurement), &measurement, 0);
00495 vertAscent = ((result == noErr) || (result == kATSUNotSetErr)) ? -FixedToFloat(measurement) : 0.f;
00496
00497
00498 result = ATSUGetAttribute(horiFontStyle, kATSUDescentTag, sizeof(measurement), &measurement, 0);
00499 horiDescent = ((result == noErr) || (result == kATSUNotSetErr)) ? -FixedToFloat(measurement) : 0.f;
00500 result = ATSUGetAttribute(vertFontStyle, kATSUDescentTag, sizeof(measurement), &measurement, 0);
00501 vertDescent = ((result == noErr) || (result == kATSUNotSetErr)) ? FixedToFloat(measurement) : 0.f;
00502 }
00503
00504
00505
00506
00507
00508
00509 static void createATSUObjects(ATSUStyle horiFontStyle, ATSUStyle &vertFontStyle, ATSUTextLayout &horiTextLayout, ATSUTextLayout &vertTextLayout)
00510 {
00511
00512 OSStatus result = ATSUCreateAndCopyStyle(horiFontStyle, &vertFontStyle);
00513 if (result != noErr)
00514 vertFontStyle = 0;
00515 else
00516 {
00517 ATSUVerticalCharacterType verticalCharacterType = kATSUStronglyVertical;
00518 ATSUAttributeTag attributeTags[] = { kATSUVerticalCharacterTag };
00519 ByteCount attributeSizes[] = { sizeof(verticalCharacterType) };
00520 ATSUAttributeValuePtr attributeValues[] = { &verticalCharacterType };
00521 result = ATSUSetAttributes(vertFontStyle, 1, attributeTags, attributeSizes, attributeValues);
00522 }
00523
00524
00525 result = ATSUCreateTextLayout(&horiTextLayout);
00526 if (result != noErr)
00527 horiTextLayout = 0;
00528 result = ATSUCreateAndCopyTextLayout(horiTextLayout, &vertTextLayout);
00529 if (result != noErr)
00530 vertTextLayout = 0;
00531 else
00532 {
00533 Fixed lineRotation = IntToFixed(-90);
00534 ATSUAttributeTag layoutAttributeTags[] = { kATSULineRotationTag };
00535 ByteCount layoutAttributeSizes[] = { sizeof(lineRotation) };
00536 ATSUAttributeValuePtr layoutAttributeValues[] = { &lineRotation };
00537 result = ATSUSetLayoutControls(vertTextLayout, 1, layoutAttributeTags, layoutAttributeSizes, layoutAttributeValues);
00538 }
00539 }
00540
00541
00542
00543
00544
00545
00546 TextMacVectorFace::TextMacVectorFace(ATSUStyle horiFontStyle)
00547 : TextVectorFace(), _horiFontStyle(horiFontStyle), _vertFontStyle(0), _horiTextLayout(0), _vertTextLayout(0)
00548 {
00549
00550 createATSUObjects(_horiFontStyle, _vertFontStyle, _horiTextLayout, _vertTextLayout);
00551
00552
00553 getFaceInfo(_horiFontStyle, _vertFontStyle, _family, _style,
00554 _horiAscent, _horiDescent, _vertAscent, _vertDescent);
00555
00556
00557 _scale = 1.f / (_horiAscent - _horiDescent);
00558
00559
00560 _horiAscent *= _scale;
00561 _vertAscent = -0.5f;
00562
00563
00564 _horiDescent *= _scale;
00565 _vertDescent = 0.5f;
00566 }
00567
00568
00569
00570
00571
00572
00573 TextMacVectorFace::~TextMacVectorFace()
00574 {
00575
00576 ATSUDisposeTextLayout(_horiTextLayout);
00577 ATSUDisposeTextLayout(_vertTextLayout);
00578
00579
00580 ATSUDisposeStyle(_horiFontStyle);
00581 ATSUDisposeStyle(_vertFontStyle);
00582 }
00583
00584
00585
00586
00587
00588
00589
00590 static void convertUnicodeToUTF16(const wstring &text, vector<UniChar> &utf16Text)
00591 {
00592 UniCharCount i, textTotalLength = text.length();
00593 utf16Text.clear();
00594 utf16Text.reserve(textTotalLength);
00595 for (i = 0; i < textTotalLength; ++i)
00596 {
00597 wchar_t unicode = text[i];
00598 if (unicode < 0x10000)
00599 utf16Text.push_back(unicode);
00600 else if (unicode < 0x110000)
00601 {
00602 unsigned long u = unicode - 0x10000;
00603 utf16Text.push_back(0xd800 | (u >> 10));
00604 utf16Text.push_back(0xdc00 | (u & 0x3ff));
00605 }
00606 }
00607 }
00608
00609
00610
00611
00612
00613
00614 void TextMacVectorFace::layout(const wstring &text, const TextLayoutParam ¶m,
00615 TextLayoutResult &layoutResult)
00616 {
00617
00618 layoutResult.clear();
00619 if (param.horizontal == true)
00620 layoutResult.textBounds[1] = _horiAscent - _horiDescent;
00621 else
00622 layoutResult.textBounds[0] = _vertDescent - _vertAscent;
00623 layoutResult.lineBounds.push_back(layoutResult.textBounds);
00624
00625
00626 vector<UniChar> utf16Text;
00627 convertUnicodeToUTF16(text, utf16Text);
00628 if (utf16Text.empty() == true)
00629 return;
00630
00631
00632 ATSUStyle fontStyle;
00633 ATSUTextLayout textLayout;
00634 if (param.horizontal == true)
00635 {
00636 fontStyle = _horiFontStyle;
00637 textLayout = _horiTextLayout;
00638 }
00639 else
00640 {
00641 fontStyle = _vertFontStyle;
00642 textLayout = _vertTextLayout;
00643 }
00644
00645
00646 Real32 length = param.getLength(0);
00647 Fract justFactor = length <= 0.f ? kATSUNoJustification : kATSUFullJustification;
00648 ATSUTextMeasurement width = FloatToFixed(length <= 0.f ? 0.f : length / _scale);
00649 ATSUAttributeTag layoutAttributeTags[] = { kATSULineJustificationFactorTag, kATSULineWidthTag };
00650 ByteCount layoutAttributeSizes[] = { sizeof(justFactor), sizeof(width) };
00651 ATSUAttributeValuePtr layoutAttributeValues[] = { &justFactor, &width };
00652 ATSUSetLayoutControls(textLayout, 2, layoutAttributeTags, layoutAttributeSizes, layoutAttributeValues);
00653
00654
00655 OSStatus result = ATSUSetTextPointerLocation(textLayout, &(utf16Text[0]), kATSUFromTextBeginning, kATSUToTextEnd, utf16Text.size());
00656 if (result != noErr)
00657 return;
00658
00659
00660 result = ATSUSetRunStyle(textLayout, fontStyle, kATSUFromTextBeginning, kATSUToTextEnd);
00661 if (result != noErr)
00662 return;
00663
00664
00665 ATSLayoutRecord *layoutRecords;
00666 ItemCount numRecords;
00667 result = ATSUDirectGetLayoutDataArrayPtrFromTextLayout(textLayout, kATSUFromTextBeginning,
00668 kATSUDirectDataLayoutRecordATSLayoutRecordCurrent, (void**)&layoutRecords, &numRecords);
00669 if (result != noErr)
00670 return;
00671 Fixed *deltaYs;
00672 ItemCount numDeltaYs;
00673 result = ATSUDirectGetLayoutDataArrayPtrFromTextLayout(textLayout, kATSUFromTextBeginning,
00674 kATSUDirectDataBaselineDeltaFixedArray, (void**)&deltaYs, &numDeltaYs);
00675 if (result != noErr)
00676 deltaYs = 0;
00677
00678
00679 layoutResult.indices.reserve(numRecords);
00680 layoutResult.positions.reserve(numRecords);
00681 ItemCount j;
00682 Vec2f currPos;
00683 for (j = 0; j < numRecords; ++j)
00684 {
00685 ATSGlyphRef glyphID = layoutRecords[j].glyphID;
00686 currPos[0] = FixedToFloat(layoutRecords[j].realPos) * _scale;
00687 currPos[1] = (deltaYs != 0) && (j < numDeltaYs) ? -FixedToFloat(deltaYs[j]) * _scale: 0.f;
00688 const TextVectorGlyph &glyph = getVectorGlyph(glyphID);
00689 if (param.horizontal == true)
00690 {
00691 currPos[0] += glyph.getHoriBearingX();
00692 currPos[1] += glyph.getHoriBearingY();
00693 }
00694 else
00695 {
00696 float h = currPos.x();
00697 currPos[0] = currPos.y() + glyph.getVertBearingX();
00698 currPos[1] = -h + glyph.getVertBearingY();
00699 }
00700 if (glyphID != kATSDeletedGlyphcode)
00701 {
00702 layoutResult.indices.push_back(glyphID);
00703 layoutResult.positions.push_back(currPos);
00704 }
00705 }
00706
00707
00708 if (deltaYs != 0)
00709 ATSUDirectReleaseLayoutDataArrayPtr(0, kATSUDirectDataBaselineDeltaFixedArray, (void**)&deltaYs);
00710 ATSUDirectReleaseLayoutDataArrayPtr(0, kATSUDirectDataLayoutRecordATSLayoutRecordCurrent, (void**)&layoutRecords);
00711
00712
00713 adjustLineOrigin(param, currPos, layoutResult);
00714
00715
00716 if (param.horizontal == true)
00717 layoutResult.textBounds[0] = osgabs(currPos.x());
00718 else
00719 layoutResult.textBounds[1] = osgabs(currPos.y());
00720 assert(layoutResult.lineBounds.empty() == false);
00721 layoutResult.lineBounds.front() = layoutResult.textBounds;
00722 }
00723
00724
00725
00726
00727
00728
00729 typedef struct UserData
00730 {
00731 Real32 scale;
00732 Vec2f offset;
00733 TextVectorGlyph::Outline &outline;
00734 inline UserData(Real32 s, const Vec2f &off, TextVectorGlyph::Outline &o)
00735 : scale(s), offset(off), outline(o)
00736 {}
00737 }
00738 UserData;
00739
00740
00741
00742
00743
00744
00745 static OSStatus quadraticNewPathCallback(void *callBackDataPtr)
00746 {
00747 UserData *userData = reinterpret_cast<UserData*>(callBackDataPtr);
00748
00749
00750 userData->outline.push_back(TextVectorGlyph::Contour());
00751
00752
00753 return noErr;
00754 }
00755
00756
00757
00758
00759
00760
00761 static OSStatus quadraticLineCallback(const Float32Point *pt1, const Float32Point *pt2, void *callBackDataPtr)
00762 {
00763 UserData *userData = reinterpret_cast<UserData*>(callBackDataPtr);
00764
00765
00766 if (userData->outline.back().empty() == true)
00767 {
00768 Vec2f p(pt1->x, -pt1->y);
00769 p *= userData->scale;
00770 p -= userData->offset;
00771 userData->outline.back().push_back(TextVectorGlyph::Point(p, TextVectorGlyph::Point::PT_ON));
00772 }
00773
00774
00775 Vec2f p(pt2->x, -pt2->y);
00776 p *= userData->scale;
00777 p -= userData->offset;
00778 userData->outline.back().push_back(TextVectorGlyph::Point(p, TextVectorGlyph::Point::PT_ON));
00779
00780
00781 return noErr;
00782 }
00783
00784
00785
00786
00787
00788
00789 static OSStatus quadraticCurveCallback(const Float32Point *pt1, const Float32Point *controlPt, const Float32Point *pt2, void *callBackDataPtr)
00790 {
00791 UserData *userData = reinterpret_cast<UserData*>(callBackDataPtr);
00792
00793
00794 if (userData->outline.back().empty() == true)
00795 {
00796 Vec2f p(pt1->x, -pt1->y);
00797 p *= userData->scale;
00798 p -= userData->offset;
00799 userData->outline.back().push_back(TextVectorGlyph::Point(p, TextVectorGlyph::Point::PT_ON));
00800 }
00801
00802
00803 Vec2f p(controlPt->x, -controlPt->y);
00804 p *= userData->scale;
00805 p -= userData->offset;
00806 userData->outline.back().push_back(TextVectorGlyph::Point(p, TextVectorGlyph::Point::PT_QUAD));
00807 p.setValues(pt2->x, -pt2->y);
00808 p *= userData->scale;
00809 p -= userData->offset;
00810 userData->outline.back().push_back(TextVectorGlyph::Point(p, TextVectorGlyph::Point::PT_ON));
00811
00812
00813 return noErr;
00814 }
00815
00816
00817
00818
00819
00820
00821 OSStatus quadraticClosePathCallback(void *callBackDataPtr)
00822 {
00823 UserData *userData = reinterpret_cast<UserData*>(callBackDataPtr);
00824
00825
00826
00827 if (userData->outline.back().size() < 3)
00828 userData->outline.erase(userData->outline.end() - 1);
00829
00830
00831 return noErr;
00832 }
00833
00834
00835
00836
00837
00838
00839 static OSStatus cubicMoveToCallback(const Float32Point *pt, void *callBackDataPtr)
00840 {
00841 UserData *userData = reinterpret_cast<UserData*>(callBackDataPtr);
00842
00843
00844 userData->outline.push_back(TextVectorGlyph::Contour());
00845
00846
00847 Vec2f p(pt->x, -pt->y);
00848 p *= userData->scale;
00849 p -= userData->offset;
00850 userData->outline.back().push_back(TextVectorGlyph::Point(p, TextVectorGlyph::Point::PT_ON));
00851
00852
00853 return noErr;
00854 }
00855
00856
00857
00858
00859
00860
00861 static OSStatus cubicLineToCallback(const Float32Point *pt, void *callBackDataPtr)
00862 {
00863 UserData *userData = reinterpret_cast<UserData*>(callBackDataPtr);
00864
00865
00866 Vec2f p(pt->x, -pt->y);
00867 p *= userData->scale;
00868 p -= userData->offset;
00869 userData->outline.back().push_back(TextVectorGlyph::Point(p, TextVectorGlyph::Point::PT_ON));
00870
00871
00872 return noErr;
00873 }
00874
00875
00876
00877
00878
00879
00880 static OSStatus cubicCurveToCallback(const Float32Point *pt1, const Float32Point *pt2, const Float32Point *pt3, void *callBackDataPtr)
00881 {
00882 UserData *userData = reinterpret_cast<UserData*>(callBackDataPtr);
00883
00884
00885 Vec2f p(pt1->x, -pt1->y);
00886 p *= userData->scale;
00887 p -= userData->offset;
00888 userData->outline.back().push_back(TextVectorGlyph::Point(p, TextVectorGlyph::Point::PT_CUBIC));
00889 p.setValues(pt2->x, -pt2->y);
00890 p *= userData->scale;
00891 p -= userData->offset;
00892 userData->outline.back().push_back(TextVectorGlyph::Point(p, TextVectorGlyph::Point::PT_CUBIC));
00893 p.setValues(pt3->x, -pt3->y);
00894 p *= userData->scale;
00895 p -= userData->offset;
00896 userData->outline.back().push_back(TextVectorGlyph::Point(p, TextVectorGlyph::Point::PT_ON));
00897
00898
00899 return noErr;
00900 }
00901
00902
00903
00904
00905
00906
00907 static OSStatus cubicClosePathCallback(void *callBackDataPtr)
00908 {
00909 UserData *userData = reinterpret_cast<UserData*>(callBackDataPtr);
00910
00911
00912
00913 if (userData->outline.back().size() < 3)
00914 userData->outline.erase(userData->outline.end() - 1);
00915
00916
00917 return noErr;
00918 }
00919
00920
00921
00922
00923
00924
00925 auto_ptr<TextVectorGlyph> TextMacVectorFace::createGlyph(TextGlyph::Index glyphIndex)
00926 {
00927
00928 if (glyphIndex == TextGlyph::INVALID_INDEX)
00929 return auto_ptr<TextVectorGlyph>();
00930
00931
00932 return auto_ptr<TextVectorGlyph>(new TextMacVectorGlyph(glyphIndex, _scale, _horiFontStyle, _vertFontStyle));
00933 }
00934
00935
00936
00937
00938
00939
00940 TextMacVectorGlyph::TextMacVectorGlyph(Index glyphIndex, Real32 scale, ATSUStyle horiFontStyle, ATSUStyle vertFontStyle)
00941 : TextVectorGlyph()
00942 {
00943 _glyphIndex = glyphIndex;
00944
00945
00946 GlyphID glyphID = _glyphIndex;
00947 ATSGlyphScreenMetrics glyphScreenMetrics;
00948 OSStatus result = ATSUGlyphGetScreenMetrics(horiFontStyle, 1, &glyphID, 0, false, false, &glyphScreenMetrics);
00949 if (result == noErr)
00950 {
00951 _width = glyphScreenMetrics.width * scale;
00952 _height = glyphScreenMetrics.height * scale;
00953 _horiAdvance = glyphScreenMetrics.deviceAdvance.x * scale;
00954 _horiBearingX = glyphScreenMetrics.topLeft.x * scale;
00955 _horiBearingY = glyphScreenMetrics.topLeft.y * scale;
00956 }
00957
00958
00959 result = ATSUGlyphGetScreenMetrics(vertFontStyle, 1, &glyphID, 0, false, false, &glyphScreenMetrics);
00960 if (result == noErr)
00961 {
00962 _width = glyphScreenMetrics.width * scale;
00963 _height = glyphScreenMetrics.height * scale;
00964 _vertAdvance = glyphScreenMetrics.deviceAdvance.y * scale;
00965 _vertBearingX = glyphScreenMetrics.topLeft.x * scale;
00966 _vertBearingY = glyphScreenMetrics.topLeft.y * scale;
00967 }
00968
00969
00970 ATSCurveType curveType;
00971 result = ATSUGetNativeCurveType(horiFontStyle, &curveType);
00972 if (result != noErr)
00973 return;
00974 if (curveType == kATSQuadCurveType)
00975 {
00976
00977
00978 ATSQuadraticNewPathUPP newPathProc = NewATSQuadraticNewPathUPP(&quadraticNewPathCallback);
00979 ATSQuadraticLineUPP lineProc = NewATSQuadraticLineUPP(&quadraticLineCallback);
00980 ATSQuadraticCurveUPP curveProc = NewATSQuadraticCurveUPP(&quadraticCurveCallback);
00981 ATSQuadraticClosePathUPP closePathProc = NewATSQuadraticClosePathUPP(&quadraticClosePathCallback);
00982 UserData userData(scale, Vec2f(_horiBearingX, _horiBearingY), _outline);
00983 OSStatus callbackResult;
00984 result = ATSUGlyphGetQuadraticPaths(horiFontStyle, glyphID, newPathProc, lineProc, curveProc, closePathProc, &userData, &callbackResult);
00985 DisposeATSQuadraticClosePathUPP(closePathProc);
00986 DisposeATSQuadraticCurveUPP(curveProc);
00987 DisposeATSQuadraticLineUPP(lineProc);
00988 DisposeATSQuadraticNewPathUPP(newPathProc);
00989 }
00990 else if (curveType == kATSCubicCurveType)
00991 {
00992
00993
00994 ATSCubicMoveToUPP moveToProc = NewATSCubicMoveToUPP(&cubicMoveToCallback);
00995 ATSCubicLineToUPP lineToProc = NewATSCubicLineToUPP(&cubicLineToCallback);
00996 ATSCubicCurveToUPP curveToProc = NewATSCubicCurveToUPP(&cubicCurveToCallback);
00997 ATSCubicClosePathUPP closePathProc = NewATSCubicClosePathUPP(&cubicClosePathCallback);
00998 UserData userData(scale, Vec2f(_horiBearingX, _horiBearingY), _outline);
00999 OSStatus callbackResult;
01000 ATSUGlyphGetCubicPaths(horiFontStyle, glyphID, moveToProc, lineToProc, curveToProc, closePathProc, &userData, &callbackResult);
01001 DisposeATSCubicClosePathUPP(closePathProc);
01002 DisposeATSCubicCurveToUPP(curveToProc);
01003 DisposeATSCubicLineToUPP(lineToProc);
01004 DisposeATSCubicMoveToUPP(moveToProc);
01005 }
01006 }
01007
01008
01009
01010
01011
01012
01013 TextMacVectorGlyph::~TextMacVectorGlyph() {}
01014
01015
01016
01017
01018
01019
01020 TextMacPixmapFace::TextMacPixmapFace(ATSUStyle horiFontStyle)
01021 : TextPixmapFace(), _horiFontStyle(horiFontStyle), _vertFontStyle(0), _horiTextLayout(0), _vertTextLayout(0)
01022 {
01023
01024 createATSUObjects(_horiFontStyle, _vertFontStyle, _horiTextLayout, _vertTextLayout);
01025
01026
01027 getFaceInfo(_horiFontStyle, _vertFontStyle, _family, _style,
01028 _horiAscent, _horiDescent, _vertAscent, _vertDescent);
01029
01030
01031 Fixed size;
01032 OSStatus result = ATSUGetAttribute(_horiFontStyle, kATSUSizeTag, sizeof(size), &size, 0);
01033 _size = ((result == noErr) || (result == kATSUNotSetErr)) ? FixedToInt(size) : 0;
01034 }
01035
01036
01037
01038
01039
01040
01041 TextMacPixmapFace::~TextMacPixmapFace()
01042 {
01043
01044 ATSUDisposeTextLayout(_horiTextLayout);
01045 ATSUDisposeTextLayout(_vertTextLayout);
01046
01047
01048 ATSUDisposeStyle(_horiFontStyle);
01049 ATSUDisposeStyle(_vertFontStyle);
01050 }
01051
01052
01053
01054
01055
01056
01057 void TextMacPixmapFace::layout(const wstring &text, const TextLayoutParam ¶m,
01058 TextLayoutResult &layoutResult)
01059 {
01060
01061 layoutResult.clear();
01062 if (param.horizontal == true)
01063 layoutResult.textBounds[1] = _horiAscent - _horiDescent;
01064 else
01065 layoutResult.textBounds[0] = _vertDescent - _vertAscent;
01066 layoutResult.lineBounds.push_back(layoutResult.textBounds);
01067
01068
01069 vector<UniChar> utf16Text;
01070 convertUnicodeToUTF16(text, utf16Text);
01071 if (utf16Text.empty() == true)
01072 return;
01073
01074
01075 ATSUStyle fontStyle;
01076 ATSUTextLayout textLayout;
01077 if (param.horizontal == true)
01078 {
01079 fontStyle = _horiFontStyle;
01080 textLayout = _horiTextLayout;
01081 }
01082 else
01083 {
01084 fontStyle = _vertFontStyle;
01085 textLayout = _vertTextLayout;
01086 }
01087
01088
01089 Real32 length = param.getLength(0);
01090 Fract justFactor = length <= 0.f ? kATSUNoJustification : kATSUFullJustification;
01091 ATSUTextMeasurement width = FloatToFixed(length <= 0.f ? 0.f : length);
01092 ATSUAttributeTag layoutAttributeTags[] = { kATSULineJustificationFactorTag, kATSULineWidthTag };
01093 ByteCount layoutAttributeSizes[] = { sizeof(justFactor), sizeof(width) };
01094 ATSUAttributeValuePtr layoutAttributeValues[] = { &justFactor, &width };
01095 ATSUSetLayoutControls(textLayout, 2, layoutAttributeTags, layoutAttributeSizes, layoutAttributeValues);
01096
01097
01098 OSStatus result = ATSUSetTextPointerLocation(textLayout, &(utf16Text[0]), kATSUFromTextBeginning, kATSUToTextEnd, utf16Text.size());
01099 if (result != noErr)
01100 return;
01101
01102
01103 result = ATSUSetRunStyle(textLayout, fontStyle, kATSUFromTextBeginning, kATSUToTextEnd);
01104 if (result != noErr)
01105 return;
01106
01107
01108 ATSLayoutRecord *layoutRecords;
01109 ItemCount numRecords;
01110 result = ATSUDirectGetLayoutDataArrayPtrFromTextLayout(textLayout, kATSUFromTextBeginning,
01111 kATSUDirectDataLayoutRecordATSLayoutRecordCurrent, (void**)&layoutRecords, &numRecords);
01112 if (result != noErr)
01113 return;
01114 Fixed *deltaYs;
01115 ItemCount numDeltaYs;
01116 result = ATSUDirectGetLayoutDataArrayPtrFromTextLayout(textLayout, kATSUFromTextBeginning,
01117 kATSUDirectDataBaselineDeltaFixedArray, (void**)&deltaYs, &numDeltaYs);
01118 if (result != noErr)
01119 deltaYs = 0;
01120
01121
01122 layoutResult.indices.reserve(numRecords);
01123 layoutResult.positions.reserve(numRecords);
01124 ItemCount j;
01125 Vec2f currPos;
01126 for (j = 0; j < numRecords; ++j)
01127 {
01128 ATSGlyphRef glyphID = layoutRecords[j].glyphID;
01129 currPos[0] = FixedToFloat(layoutRecords[j].realPos);
01130 currPos[1] = (deltaYs != 0) && (j < numDeltaYs) ? -FixedToFloat(deltaYs[j]) : 0.f;
01131 const TextPixmapGlyph &glyph = getPixmapGlyph(layoutRecords[j], param.horizontal);
01132 if (param.horizontal == true)
01133 {
01134 currPos[0] += glyph.getHoriBearingX();
01135 currPos[1] += glyph.getHoriBearingY();
01136 }
01137 else
01138 {
01139 float h = currPos.x();
01140 currPos[0] = currPos.y() + glyph.getVertBearingX();
01141 currPos[1] = -h + glyph.getVertBearingY();
01142 }
01143 if (glyphID != kATSDeletedGlyphcode)
01144 {
01145 layoutResult.indices.push_back(glyphID);
01146 layoutResult.positions.push_back(currPos);
01147 }
01148 }
01149
01150
01151 if (deltaYs != 0)
01152 ATSUDirectReleaseLayoutDataArrayPtr(0, kATSUDirectDataBaselineDeltaFixedArray, (void**)&deltaYs);
01153 ATSUDirectReleaseLayoutDataArrayPtr(0, kATSUDirectDataLayoutRecordATSLayoutRecordCurrent, (void**)&layoutRecords);
01154
01155
01156 adjustLineOrigin(param, currPos, layoutResult);
01157
01158
01159 if (param.horizontal == true)
01160 layoutResult.textBounds[0] = osgabs(currPos.x());
01161 else
01162 layoutResult.textBounds[1] = osgabs(currPos.y());
01163 assert(layoutResult.lineBounds.empty() == false);
01164 layoutResult.lineBounds.front() = layoutResult.textBounds;
01165 }
01166
01167
01168
01169
01170
01171
01172 auto_ptr<TextPixmapGlyph> TextMacPixmapFace::createGlyph(TextGlyph::Index glyphIndex)
01173 {
01174 return auto_ptr<TextPixmapGlyph>();
01175 }
01176
01177
01178
01179
01180
01181
01182 static void drawGlyph(ATSUTextLayout textLayout, const ATSLayoutRecord &layoutRecord,
01183 ATSUTextMeasurement xPos, ATSUTextMeasurement yPos,
01184 UInt32 width, UInt32 height, UInt8 *dst, UInt32 pitch)
01185 {
01186
01187 if ((width == 0) || (height == 0))
01188 return;
01189
01190
01191 GWorldPtr offscreenGWorld;
01192 Rect boundsRect;
01193 SetRect(&boundsRect, 0, 0, width, height);
01194 QDErr qdResult = NewGWorld(&offscreenGWorld, 32, &boundsRect, 0, 0, 0);
01195 if (qdResult != noErr)
01196 return;
01197
01198
01199 if (LockPixels(GetGWorldPixMap(offscreenGWorld)) == FALSE)
01200 {
01201 DisposeGWorld(offscreenGWorld);
01202 return;
01203 }
01204 Ptr src = GetPixBaseAddr(GetGWorldPixMap(offscreenGWorld));
01205 if (src == 0)
01206 {
01207 UnlockPixels(GetGWorldPixMap(offscreenGWorld));
01208 DisposeGWorld(offscreenGWorld);
01209 return;
01210 }
01211
01212
01213 CGrafPtr port;
01214 GDHandle gdh;
01215 GetGWorld(&port, &gdh);
01216 SetGWorld(offscreenGWorld, 0);
01217 RGBColor gBlackColour = { 0x0000, 0x0000, 0x0000 };
01218 RGBBackColor(&gBlackColour);
01219 EraseRect(&boundsRect);
01220 RGBColor gWhiteColour = { 0xFFFF, 0xFFFF, 0xFFFF };
01221 RGBForeColor(&gWhiteColour);
01222
01223
01224 UniCharArrayOffset charOffset = layoutRecord.originalOffset >> 1;
01225 UniCharCount charCount = (layoutRecord.flags & kATSGlyphInfoByteSizeMask) >> 1;
01226 OSStatus result = ATSUDrawText(textLayout, charOffset, charCount, xPos, yPos);
01227 if (result == noErr)
01228 {
01229 long bpl = GetPixRowBytes(GetGWorldPixMap(offscreenGWorld));
01230 src += bpl * (height - 1);
01231 Ptr src2;
01232 UInt32 x, y;
01233 for (y = 0; y < height; ++y)
01234 {
01235 src2 = src + 1;
01236 for (x = 0; x < width; ++x)
01237 {
01238 *dst++ = *src2;
01239 src2+= 4;
01240 }
01241 src -= bpl;
01242 dst += pitch;
01243 }
01244 }
01245
01246
01247 SetGWorld(port, gdh);
01248 UnlockPixels(GetGWorldPixMap(offscreenGWorld));
01249 DisposeGWorld(offscreenGWorld);
01250 }
01251
01252
01253
01254
01255
01256
01257 const TextPixmapGlyph &TextMacPixmapFace::getPixmapGlyph(const ATSLayoutRecord &layoutRecord, bool horizontal)
01258 {
01259 ATSGlyphRef glyphID = layoutRecord.glyphID;
01260 if (glyphID == kATSDeletedGlyphcode)
01261 return _emptyGlyph;
01262
01263
01264 GlyphMap::const_iterator it = _glyphMap.find(glyphID);
01265 if (it != _glyphMap.end())
01266 {
01267 assert(it->second != 0);
01268 return *(it->second);
01269 }
01270
01271
01272 ATSUTextMeasurement xPos = 0, yPos = 0;
01273
01274
01275 ATSGlyphScreenMetrics glyphScreenMetrics;
01276 OSStatus result = ATSUGlyphGetScreenMetrics(_horiFontStyle, 1, &glyphID, 0, true, true, &glyphScreenMetrics);
01277 if (result != noErr)
01278 return _emptyGlyph;
01279 Real32 horiAdvance = glyphScreenMetrics.deviceAdvance.x;
01280 UInt32 width = glyphScreenMetrics.width;
01281 UInt32 height = glyphScreenMetrics.height;
01282 Int32 horiBearingX = static_cast<Int32>(glyphScreenMetrics.topLeft.x);
01283 Int32 horiBearingY = static_cast<Int32>(glyphScreenMetrics.topLeft.y);
01284 if (horizontal == true)
01285 {
01286 xPos = FloatToFixed(-glyphScreenMetrics.topLeft.x) - (layoutRecord.realPos & 0xffff0000);
01287 yPos = FloatToFixed(glyphScreenMetrics.topLeft.y);
01288 }
01289
01290
01291 result = ATSUGlyphGetScreenMetrics(_vertFontStyle, 1, &glyphID, 0, true, true, &glyphScreenMetrics);
01292 if (result != noErr)
01293 return _emptyGlyph;
01294 Real32 vertAdvance = glyphScreenMetrics.deviceAdvance.y;
01295 Int32 vertBearingX = static_cast<Int32>(glyphScreenMetrics.topLeft.x);
01296 Int32 vertBearingY = static_cast<Int32>(glyphScreenMetrics.topLeft.y);
01297 if (horizontal == false)
01298 {
01299 xPos = FloatToFixed(-glyphScreenMetrics.topLeft.x);
01300 yPos = FloatToFixed(glyphScreenMetrics.topLeft.y) - ((layoutRecord.realPos + fixed1) & 0xffff0000);
01301 }
01302
01303 UInt8 *pixmap = 0;
01304 UInt32 size = width * height;
01305 if (size != 0)
01306 {
01307
01308 ATSUTextLayout textLayout = horizontal == true ? _horiTextLayout : _vertTextLayout;
01309 pixmap = new UInt8[size];
01310 drawGlyph(textLayout, layoutRecord, xPos, yPos, width, height, pixmap, 0);
01311 }
01312
01313 auto_ptr<TextPixmapGlyph> glyph(new TextMacPixmapGlyph(glyphID, width, height, horiAdvance, horiBearingX, horiBearingY, vertAdvance, vertBearingX, vertBearingY, pixmap));
01314
01315
01316 _glyphMap.insert(GlyphMap::value_type(glyphID, glyph.get()));
01317
01318
01319 return *(glyph.release());
01320 }
01321
01322
01323
01324
01325
01326
01327 TextMacPixmapGlyph::TextMacPixmapGlyph(Index glyphIndex, UInt32 width, UInt32 height,
01328 Real32 horiAdvance, Int32 horiBearingX, Int32 horiBearingY,
01329 Real32 vertAdvance, Int32 vertBearingX, Int32 vertBearingY,
01330 UInt8 *pixmap)
01331 : TextPixmapGlyph()
01332 {
01333 _glyphIndex = glyphIndex;
01334 _width = _pitch = width;
01335 _height = height;
01336 _pixmap = pixmap;
01337
01338
01339 _horiAdvance = horiAdvance;
01340 _horiBearingX = horiBearingX;
01341 _horiBearingY = horiBearingY;
01342
01343
01344 _vertAdvance = vertAdvance;
01345 _vertBearingX = vertBearingX;
01346 _vertBearingY = vertBearingY;
01347 }
01348
01349
01350
01351
01352
01353
01354 TextMacPixmapGlyph::~TextMacPixmapGlyph() {}
01355
01356
01357
01358
01359
01360
01361 TextMacTXFFace::TextMacTXFFace(ATSUStyle horiFontStyle, const TextTXFParam ¶m)
01362 : TextTXFFace()
01363 {
01364
01365 ATSUStyle vertFontStyle;
01366 ATSUTextLayout horiTextLayout, vertTextLayout;
01367 createATSUObjects(horiFontStyle, vertFontStyle, horiTextLayout, vertTextLayout);
01368
01369
01370 getFaceInfo(horiFontStyle, vertFontStyle, _family, _style,
01371 _horiAscent, _horiDescent, _vertAscent, _vertDescent);
01372
01373
01374 _scale = 1.f / (_horiAscent - _horiDescent);
01375
01376
01377 _horiAscent *= _scale;
01378 _vertAscent = -0.5f;
01379
01380
01381 _horiDescent *= _scale;
01382 _vertDescent = 0.5f;
01383
01384
01385 _param = param;
01386
01387
01388 ATSUFontFeatureType featureType = kAllTypographicFeaturesType;
01389 ATSUFontFeatureSelector featureSelector = kAllTypeFeaturesOffSelector;
01390 ATSUSetFontFeatures(horiFontStyle, 1, &featureType, &featureSelector);
01391 ATSUSetFontFeatures(vertFontStyle, 1, &featureType, &featureSelector);
01392
01393
01394 createGlyphs(horiFontStyle, vertFontStyle, horiTextLayout, vertTextLayout, param);
01395
01396
01397 ATSUDisposeTextLayout(horiTextLayout);
01398 ATSUDisposeTextLayout(vertTextLayout);
01399
01400
01401 ATSUDisposeStyle(horiFontStyle);
01402 ATSUDisposeStyle(vertFontStyle);
01403 }
01404
01405
01406
01407
01408
01409
01410 TextMacTXFFace::~TextMacTXFFace() {}
01411
01412
01413
01414
01415
01416
01417 void TextMacTXFFace::createGlyphs(ATSUStyle horiFontStyle, ATSUStyle vertFontStyle,
01418 ATSUTextLayout horiTextLayout, ATSUTextLayout vertTextLayout,
01419 const TextTXFParam ¶m)
01420 {
01421
01422 vector<UniChar> utf16Characters;
01423 convertUnicodeToUTF16(param.getCharacters(), utf16Characters);
01424
01425
01426 OSStatus result = ATSUSetTextPointerLocation(horiTextLayout, &(utf16Characters[0]), kATSUFromTextBeginning, kATSUToTextEnd, utf16Characters.size());
01427 if (result != noErr)
01428 return;
01429
01430
01431 result = ATSUSetRunStyle(horiTextLayout, horiFontStyle, kATSUFromTextBeginning, kATSUToTextEnd);
01432 if (result != noErr)
01433 return;
01434
01435
01436 ATSLayoutRecord *layoutRecords;
01437 ItemCount numRecords;
01438 result = ATSUDirectGetLayoutDataArrayPtrFromTextLayout(horiTextLayout, kATSUFromTextBeginning,
01439 kATSUDirectDataLayoutRecordATSLayoutRecordCurrent, (void**)&layoutRecords, &numRecords);
01440 if (result != noErr)
01441 return;
01442
01443
01444 vector<ATSGlyphScreenMetrics> horiMetrics;
01445 horiMetrics.resize(numRecords);
01446 result = ATSUGlyphGetScreenMetrics(horiFontStyle, numRecords, &(layoutRecords[0].glyphID), sizeof(ATSLayoutRecord), true, true, &(horiMetrics.front()));
01447 if (result != noErr)
01448 {
01449 ATSUDirectReleaseLayoutDataArrayPtr(0, kATSUDirectDataLayoutRecordATSLayoutRecordCurrent, (void**)&layoutRecords);
01450 return;
01451 }
01452
01453
01454 vector<ATSGlyphScreenMetrics> vertMetrics;
01455 vertMetrics.resize(numRecords);
01456 result = ATSUGlyphGetScreenMetrics(vertFontStyle, numRecords, &(layoutRecords[0].glyphID), sizeof(ATSLayoutRecord), true, true, &(vertMetrics.front()));
01457 if (result != noErr)
01458 {
01459 ATSUDirectReleaseLayoutDataArrayPtr(0, kATSUDirectDataLayoutRecordATSLayoutRecordCurrent, (void**)&layoutRecords);
01460 return;
01461 }
01462
01463
01464 assert(numRecords == param.getCharacters().length() + 1);
01465 ItemCount j;
01466 for (j = 0; j < numRecords - 1; ++j)
01467 {
01468 ATSGlyphRef glyphID = layoutRecords[j].glyphID;
01469 wchar_t c = param.getCharacters()[j];
01470 _glyphMap.insert(GlyphMap::value_type(c, new TextMacTXFGlyph(c, _scale, horiMetrics[j], vertMetrics[j])));
01471 }
01472
01473
01474 prepareTexture(param);
01475 assert(_texture != NullFC);
01476 assert(_texture->getSize() == static_cast<UInt32>(_texture->getWidth() * _texture->getHeight()));
01477
01478
01479 beginEditCP(_texture);
01480 for (j = 0; j < numRecords - 1; ++j)
01481 {
01482 wchar_t c = param.getCharacters()[j];
01483 TextTXFGlyph *glyph = _glyphMap[c];
01484
01485
01486 ATSUTextMeasurement xPos = FloatToFixed(-horiMetrics[j].topLeft.x) - (layoutRecords[j].realPos & 0xffff0000);
01487 ATSUTextMeasurement yPos = FloatToFixed(horiMetrics[j].topLeft.y);
01488 UInt32 width = glyph->getPixmapWidth();
01489 UInt32 height = glyph->getPixmapHeight();
01490 UInt8 *dst = _texture->getData() + glyph->getX() + glyph->getY() * _texture->getWidth();
01491 UInt32 pitch = _texture->getWidth() - width;
01492 drawGlyph(horiTextLayout, layoutRecords[j], xPos, yPos, width, height, dst, pitch);
01493 }
01494 endEditCP(_texture);
01495
01496
01497 ATSUDirectReleaseLayoutDataArrayPtr(0, kATSUDirectDataLayoutRecordATSLayoutRecordCurrent, (void**)&layoutRecords);
01498 }
01499
01500
01501
01502
01503
01504
01505 TextMacTXFGlyph::TextMacTXFGlyph(Index glyphIndex, Real32 scale, const ATSGlyphScreenMetrics &horiMetrics, const ATSGlyphScreenMetrics &vertMetrics)
01506 : TextTXFGlyph()
01507 {
01508 _glyphIndex = glyphIndex;
01509 _scale = scale;
01510 _width = horiMetrics.width;
01511 _height = horiMetrics.height;
01512
01513
01514 _horiAdvance = horiMetrics.deviceAdvance.x * _scale;
01515 _horiBearingX = static_cast<int>(horiMetrics.topLeft.x);
01516 _horiBearingY = static_cast<int>(horiMetrics.topLeft.y);
01517
01518
01519 _vertAdvance = vertMetrics.deviceAdvance.y * _scale;
01520 _vertBearingX = static_cast<int>(vertMetrics.topLeft.x);
01521 _vertBearingY = static_cast<int>(vertMetrics.topLeft.y);
01522 }
01523
01524
01525
01526
01527
01528
01529 TextMacTXFGlyph::~TextMacTXFGlyph() {}
01530
01531
01532 OSG_END_NAMESPACE
01533
01534
01535 #endif // __APPLE__
01536
01537
01538
01539
01540
01541 #ifdef OSG_SGI_CC
01542 #pragma set woff 1174
01543 #endif
01544
01545 #ifdef OSG_LINUX_ICC
01546 #pragma warning( disable : 177 )
01547 #endif
01548
01549 namespace
01550 {
01551 static OSG::Char8 cvsid_cpp[] = "@(#)$Id: OSGTextMacBackend.cpp,v 1.4 2007/03/30 14:53:22 pdaehne Exp $";
01552 static OSG::Char8 cvsid_hpp[] = OSGTEXTMACBACKEND_HEADER_CVSID;
01553 static OSG::Char8 cvsid_inl[] = OSGTEXTMACBACKEND_INLINE_CVSID;
01554 }
01555
01556 #ifdef __sgi
01557 #pragma reset woff 1174
01558 #endif