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 #ifdef _MSC_VER
00040 # pragma warning (disable: 4786)
00041 #endif
00042
00043 #include "OSGTextTXFFace.h"
00044 #include "OSGTextTXFGlyph.h"
00045 #include "OSGTextLayoutParam.h"
00046 #include "OSGTextLayoutResult.h"
00047 #include "OSGTextFaceFactory.h"
00048
00049 #include <fstream>
00050 #ifdef __sgi
00051 # include <assert.h>
00052 #else
00053 # include <cassert>
00054 #endif
00055
00056
00057 using namespace std;
00058
00059
00060 OSG_BEGIN_NAMESPACE
00061
00062
00063
00064
00065
00066
00067 TextTXFGlyph TextTXFFace::_emptyGlyph;
00068
00069
00070
00071
00072
00073
00074 TextTXFFace::~TextTXFFace()
00075 {
00076
00077 GlyphMap::iterator it;
00078 for (it = _glyphMap.begin(); it != _glyphMap.end(); ++it)
00079 {
00080 assert(it->second != 0);
00081 delete it->second;
00082 }
00083
00084
00085 subRefCP(_texture);
00086 }
00087
00088
00089
00090
00091
00092
00093 const TextGlyph &TextTXFFace::getGlyph(TextGlyph::Index glyphIndex)
00094 {
00095 return getTXFGlyph(glyphIndex);
00096 }
00097
00098
00099
00100
00101
00102
00103 const TextTXFGlyph &TextTXFFace::getTXFGlyph(TextGlyph::Index glyphIndex)
00104 {
00105
00106 GlyphMap::const_iterator it = _glyphMap.find(glyphIndex);
00107 if (it != _glyphMap.end())
00108 {
00109 assert(it->second != 0);
00110 return *(it->second);
00111 }
00112
00113
00114
00115
00116 if (glyphIndex > 255)
00117 glyphIndex = TextGlyph::INVALID_INDEX;
00118 else if (isupper(glyphIndex))
00119 glyphIndex = tolower(glyphIndex);
00120 else if (islower(glyphIndex))
00121 glyphIndex = toupper(glyphIndex);
00122 else
00123 glyphIndex = TextGlyph::INVALID_INDEX;
00124 it = _glyphMap.find(glyphIndex);
00125 if (it != _glyphMap.end())
00126 {
00127 assert(it->second != 0);
00128 return *(it->second);
00129 }
00130
00131 return _emptyGlyph;
00132 }
00133
00134
00135
00136
00137
00138
00139 void TextTXFFace::fillGeo(GeometryPtr &geoPtr, const TextLayoutResult &layoutResult, Real32 scale,
00140 Vec2f offset, Color3f color)
00141 {
00142
00143
00144 GeoPositions3fPtr posPtr = GeoPositions3fPtr::dcast(geoPtr->getPositions());
00145 if (posPtr != NullFC)
00146 posPtr->clear();
00147
00148
00149 GeoNormals3fPtr normalPtr = GeoNormals3fPtr::dcast(geoPtr->getNormals());
00150 if (normalPtr != NullFC)
00151 normalPtr->clear();
00152
00153 GeoTexCoords2fPtr texPtr = GeoTexCoords2fPtr::dcast(geoPtr->getTexCoords());
00154 if (texPtr != NullFC)
00155 texPtr->clear();
00156
00157 GeoColors3fPtr colorPtr = GeoColors3fPtr::dcast(geoPtr->getColors());
00158 if (NullFC != colorPtr)
00159 colorPtr->clear();
00160
00161 GeoPLengthsUI32Ptr lensPtr = GeoPLengthsUI32Ptr::dcast(geoPtr->getLengths());
00162 if (lensPtr != NullFC)
00163 lensPtr->clear();
00164
00165 GeoPTypesUI8Ptr typesPtr = GeoPTypesUI8Ptr::dcast(geoPtr->getTypes());
00166 if (typesPtr != NullFC)
00167 typesPtr->clear();
00168
00169 geoPtr->setIndices(NullFC);
00170 geoPtr->setSecondaryColors(NullFC);
00171 geoPtr->setTexCoords1(NullFC);
00172 geoPtr->setTexCoords2(NullFC);
00173 geoPtr->setTexCoords3(NullFC);
00174 geoPtr->getIndexMapping().clear();
00175
00176 addToGeom(geoPtr,layoutResult,scale,offset,color);
00177 }
00178
00179 void TextTXFFace::addToGeom(GeometryPtr &geoPtr, const TextLayoutResult &layoutResult, Real32 scale,
00180 Vec2f offset, Color3f color)
00181 {
00182 beginEditCP(geoPtr);
00183
00184
00185
00186 GeoPositions3fPtr posPtr = GeoPositions3fPtr::dcast(geoPtr->getPositions());
00187 GeoNormals3fPtr normalPtr = GeoNormals3fPtr::dcast(geoPtr->getNormals());
00188 GeoTexCoords2fPtr texPtr = GeoTexCoords2fPtr::dcast(geoPtr->getTexCoords());
00189 GeoColors3fPtr colorPtr = GeoColors3fPtr::dcast(geoPtr->getColors());
00190 GeoPLengthsUI32Ptr lensPtr = GeoPLengthsUI32Ptr::dcast(geoPtr->getLengths());
00191 GeoPTypesUI8Ptr typesPtr = GeoPTypesUI8Ptr::dcast(geoPtr->getTypes());
00192
00193
00194 if ((NullFC == colorPtr) && (color != OSG::Color3f(-1,-1,-1)) &&
00195 ((NullFC == posPtr) && (NullFC == texPtr)) )
00196 {
00197 colorPtr = GeoColors3f::create();
00198 geoPtr->setColors(colorPtr);
00199 }
00200 bool use_colors(NullFC != colorPtr);
00201
00202 if (posPtr == NullFC)
00203 {
00204 posPtr = GeoPositions3f::create();
00205 geoPtr->setPositions(posPtr);
00206 }
00207
00208 if (normalPtr == NullFC)
00209 {
00210 normalPtr = GeoNormals3f::create();
00211 geoPtr->setNormals(normalPtr);
00212 }
00213
00214 if (texPtr == NullFC)
00215 {
00216 texPtr = GeoTexCoords2f::create();
00217 geoPtr->setTexCoords(texPtr);
00218 }
00219
00220 if (lensPtr == NullFC)
00221 {
00222 lensPtr = GeoPLengthsUI32::create();
00223 geoPtr->setLengths(lensPtr);
00224 }
00225
00226 if (typesPtr == NullFC)
00227 {
00228 typesPtr = GeoPTypesUI8::create();
00229 geoPtr->setTypes(typesPtr);
00230 }
00231
00232 UInt32 numGlyphs = layoutResult.getNumGlyphs();
00233 if (numGlyphs == 0)
00234 {
00235 endEditCP(geoPtr);
00236 return;
00237 }
00238
00239 beginEditCP(posPtr, GeoPositions3f::GeoPropDataFieldMask);
00240 beginEditCP(normalPtr, GeoNormals3f::GeoPropDataFieldMask);
00241 beginEditCP(texPtr, GeoTexCoords2f::GeoPropDataFieldMask);
00242 if(NullFC != colorPtr)
00243 { beginEditCP(colorPtr, GeoIndicesUI32::GeoPropDataFieldMask); }
00244 beginEditCP(lensPtr, GeoPLengthsUI32::GeoPropDataFieldMask);
00245 beginEditCP(typesPtr, GeoPTypesUI8::GeoPropDataFieldMask);
00246
00247 OSG::Vec3f normal(0.0, 0.0, 0.0);
00248
00249 typesPtr->push_back(GL_QUADS);
00250 unsigned num_glyphs_added(0);
00251
00252 for (UInt32 i = 0; i < numGlyphs; ++i)
00253 {
00254 TextGlyph::Index glyphIndex = layoutResult.indices[i];
00255 const TextTXFGlyph &glyph = getTXFGlyph(glyphIndex);
00256 Real32 width = glyph.getWidth();
00257 Real32 height = glyph.getHeight();
00258
00259 if ((width <= 0.f) || (height <= 0.f))
00260 continue;
00261 else
00262 num_glyphs_added += 1;
00263
00264
00265 Vec2f pos = layoutResult.positions[i];
00266 Real32 posLeft = (pos.x() * scale) + offset.x();
00267 Real32 posTop = (pos.y() * scale) + offset.y();
00268 Real32 posRight = ((pos.x() + width) * scale) + offset.x();
00269 Real32 posBottom = ((pos.y() - height) * scale) + offset.y();
00270
00271
00272 Real32 texCoordLeft = glyph.getTexCoord(TextTXFGlyph::COORD_LEFT);
00273 Real32 texCoordTop = glyph.getTexCoord(TextTXFGlyph::COORD_TOP);
00274 Real32 texCoordRight = glyph.getTexCoord(TextTXFGlyph::COORD_RIGHT);
00275 Real32 texCoordBottom = glyph.getTexCoord(TextTXFGlyph::COORD_BOTTOM);
00276
00277
00278 posPtr->push_back(Vec3f(posLeft, posBottom, 0.f));
00279 texPtr->push_back(Vec2f(texCoordLeft, texCoordBottom));
00280 normalPtr->push_back(normal);
00281 if(use_colors) colorPtr->push_back(color);
00282
00283
00284 posPtr->push_back(Vec3f(posRight, posBottom, 0.f));
00285 texPtr->push_back(Vec2f(texCoordRight, texCoordBottom));
00286 normalPtr->push_back(normal);
00287 if(use_colors) colorPtr->push_back(color);
00288
00289
00290 posPtr->push_back(Vec3f(posRight, posTop, 0.f));
00291 texPtr->push_back(Vec2f(texCoordRight, texCoordTop));
00292 normalPtr->push_back(normal);
00293 if(use_colors) colorPtr->push_back(color);
00294
00295
00296 posPtr->push_back(Vec3f(posLeft, posTop, 0.f));
00297 texPtr->push_back(Vec2f(texCoordLeft, texCoordTop));
00298 normalPtr->push_back(normal);
00299 if(use_colors) colorPtr->push_back(color);
00300 }
00301 lensPtr->push_back(num_glyphs_added*4);
00302
00303 endEditCP(typesPtr, GeoPTypesUI8::GeoPropDataFieldMask);
00304 endEditCP(lensPtr, GeoPLengthsUI32::GeoPropDataFieldMask);
00305 endEditCP(texPtr, GeoTexCoords2f::GeoPropDataFieldMask);
00306 endEditCP(normalPtr, GeoNormals3f::GeoPropDataFieldMask);
00307 endEditCP(posPtr, GeoPositions3f::GeoPropDataFieldMask);
00308 if(NullFC != colorPtr)
00309 { endEditCP(colorPtr, GeoIndicesUI32::GeoPropDataFieldMask); }
00310
00311 endEditCP(geoPtr);
00312 }
00313
00314
00315
00316
00317
00318
00319 GeometryPtr TextTXFFace::makeGeo(const TextLayoutResult &layoutResult, Real32 scale,
00320 Vec2f offset, Color3f color)
00321 {
00322 GeometryPtr geo = Geometry::create();
00323 fillGeo(geo, layoutResult, scale, offset, color);
00324 return geo;
00325 }
00326
00327
00328
00329
00330
00331
00332 NodePtr TextTXFFace::makeNode(const TextLayoutResult &layoutResult, Real32 scale,
00333 Vec2f offset, Color3f color)
00334 {
00335 GeometryPtr geo = makeGeo(layoutResult, scale, offset, color);
00336 NodePtr node = Node::create();
00337 beginEditCP(node, Node::CoreFieldMask);
00338 node->setCore(geo);
00339 endEditCP(node, Node::CoreFieldMask);
00340 return node;
00341 }
00342
00343
00344
00345
00346
00347
00348 TextTXFFace *TextTXFFace::create(const string &family, Style style, const TextTXFParam ¶m)
00349 { return TextFaceFactory::the().createTXFFace(family, style, param); }
00350
00351
00352
00353
00354
00355
00356 static UInt32 readLong(istream &is, bool swap)
00357 {
00358 UInt8 bytes[4];
00359 is.read((istream::char_type*)(bytes), 4);
00360 return swap ?
00361 (bytes[3] << 24) |
00362 (bytes[2] << 16) |
00363 (bytes[1] << 8) |
00364 bytes[0]
00365 :
00366 (bytes[0] << 24) |
00367 (bytes[1] << 16) |
00368 (bytes[2] << 8) |
00369 bytes[3];
00370 }
00371
00372
00373
00374
00375
00376
00377 static UInt16 readShort(istream &is, bool swap)
00378 {
00379 UInt8 bytes[2];
00380 is.read((istream::char_type*)(bytes), 2);
00381 return swap ?
00382 (bytes[1] << 8) |
00383 bytes[0]
00384 :
00385 (bytes[0] << 8) |
00386 bytes[1];
00387 }
00388
00389
00390
00391
00392
00393
00394 TextTXFFace *TextTXFFace::createFromStream(istream &is, const string &family, Style style)
00395 {
00396
00397 istream::char_type magicBytes[4];
00398 is.read(magicBytes, 4);
00399 if ((is.good() == false) || (strncmp(magicBytes, "\xfftxf", 4) != 0))
00400 return 0;
00401
00402
00403 UInt32 endianness = readLong(is, false);
00404 bool swap;
00405 if (endianness == 0x12345678)
00406 swap = false;
00407 else if (endianness == 0x78563412)
00408 swap = true;
00409 else
00410 return 0;
00411
00412 TextTXFFace *face = new TextTXFFace();
00413 face->_family = family;
00414 face->_style = style;
00415
00416
00417 UInt32 format = readLong(is, swap);
00418 UInt32 textureWidth = readLong(is, swap);
00419 UInt32 textureHeight = readLong(is, swap);
00420 Int32 max_ascent = readLong(is, swap);
00421 Int32 max_descent = readLong(is, swap);
00422 if (max_descent < 0)
00423 max_descent = -max_descent;
00424 UInt32 num_glyphs = readLong(is, swap);
00425 if (is.good() == false)
00426 {
00427 subRefP(face);
00428 return 0;
00429 }
00430
00431
00432 face->_param.size = max_ascent + max_descent;
00433 face->_param.gap = 0;
00434 face->_param.textureWidth = textureWidth;
00435
00436
00437 face->_scale = 1.f / static_cast<Real32>(max_ascent + max_descent);
00438
00439
00440 face->_horiAscent = static_cast<Real32>(max_ascent) * face->_scale;
00441 face->_vertAscent = -0.5f;
00442
00443
00444 face->_horiDescent = static_cast<Real32>(-max_descent) * face->_scale;
00445 face->_vertDescent = 0.5f;
00446
00447
00448 Int32 vertBearingY = -(max_ascent + max_descent) / 20;
00449 if (vertBearingY > -1)
00450 vertBearingY = -1;
00451 Real32 vertAdvanceOffset = static_cast<Real32>(vertBearingY) * 2.f * face->_scale;
00452 wstring characters;
00453 characters.reserve(num_glyphs);
00454 UInt32 i;
00455 for (i = 0; i < num_glyphs; ++i)
00456 {
00457
00458 TextTXFGlyph *glyph = new TextTXFGlyph();
00459 UInt16 glyphIndex = readShort(is, swap);
00460 characters.append(static_cast<wchar_t>(glyphIndex), 1);
00461 glyph->_glyphIndex = glyphIndex;
00462 glyph->_scale = face->_scale;
00463 glyph->_width = (unsigned char)is.get();
00464 glyph->_height = (unsigned char)is.get();
00465 glyph->_horiBearingX = (signed char)is.get();
00466 glyph->_horiBearingY = (signed char)is.get() + glyph->_height;
00467 glyph->_horiAdvance = ((signed char)is.get()) * face->_scale;
00468 is.ignore();
00469 glyph->_x = readShort(is, swap);
00470 glyph->_y = readShort(is, swap);
00471
00472
00473
00474 glyph->_vertBearingX = -static_cast<Int32>(glyph->_width >> 1);
00475 if (glyphIndex == 32)
00476 {
00477 glyph->_vertBearingY = -glyph->_horiBearingX;
00478 glyph->_vertAdvance = -glyph->_horiAdvance;
00479 }
00480 else
00481 {
00482 glyph->_vertBearingY = vertBearingY;
00483 glyph->_vertAdvance = -static_cast<Real32>(glyph->_height) * face->_scale + vertAdvanceOffset;
00484 }
00485
00486 glyph->calculateCoordinates(textureWidth, textureHeight);
00487 face->_glyphMap[glyphIndex] = glyph;
00488
00489 if (is.good() == false)
00490 {
00491 subRefP(face);
00492 return 0;
00493 }
00494 }
00495 face->_param.setCharacters(characters);
00496
00497
00498 face->_texture = Image::create();
00499 addRefCP(face->_texture);
00500 beginEditCP(face->_texture);
00501 face->_texture->set(Image::OSG_I_PF, textureWidth, textureHeight);
00502 face->_texture->clear();
00503
00504
00505 switch (format)
00506 {
00507 case 0:
00508 {
00509 UInt32 size = textureWidth * textureHeight;
00510 assert(face->_texture->getSize() == size);
00511 is.read((istream::char_type*)face->_texture->getData(), size);
00512 endEditCP(face->_texture);
00513 if (is.good() == false)
00514 {
00515 subRefP(face);
00516 return 0;
00517 }
00518 }
00519 break;
00520 case 1:
00521 {
00522 UInt32 stride = (textureWidth + 7) >> 3;
00523 UInt32 size = stride * textureHeight;
00524 UInt8 *buffer = new UInt8[size];
00525 is.read((istream::char_type*)buffer, size);
00526 if (is.good() == false)
00527 {
00528 delete [] buffer;
00529 endEditCP(face->_texture);
00530 subRefP(face);
00531 return 0;
00532 }
00533 assert(face->_texture->getSize() == textureWidth * textureHeight);
00534 UInt8 *dst = face->_texture->getData();
00535 UInt32 x, y;
00536 for (y = 0; y < textureHeight; ++y)
00537 for (x = 0; x < textureWidth; ++x)
00538 dst[y * textureWidth + x] = buffer[y * stride + (x >> 3)] & (1 << (x & 7)) ? 255 : 0;
00539 delete [] buffer;
00540 endEditCP(face->_texture);
00541 }
00542 break;
00543 default:
00544 endEditCP(face->_texture);
00545 subRefP(face);
00546 return 0;
00547 }
00548
00549 return face;
00550 }
00551
00552
00553
00554
00555
00556
00557 TextTXFFace *TextTXFFace::createFromFile(const string &filename)
00558 {
00559
00560 ifstream is(filename.c_str(), ios_base::in | ios_base::binary);
00561 if (is.good() == false)
00562 return 0;
00563
00564
00565
00566 string::size_type pos = filename.find_last_of("/\\");
00567 string family = pos != string::npos ? filename.substr(pos + 1) : filename;
00568 pos = family.rfind('.');
00569 if (pos != string::npos)
00570 family.erase(pos);
00571
00572
00573 TextTXFFace *face = createFromStream(is, family);
00574 if (face == 0)
00575 return 0;
00576
00577 return face;
00578 }
00579
00580
00581
00582
00583
00584
00585 static void writeLong(ostream &os, UInt32 value)
00586 {
00587 UInt8 bytes[4];
00588 bytes[0] = static_cast<UInt8>((value >> 24) & 0xff);
00589 bytes[1] = static_cast<UInt8>((value >> 16) & 0xff);
00590 bytes[2] = static_cast<UInt8>((value >> 8) & 0xff);
00591 bytes[3] = static_cast<UInt8>(value & 0xff);
00592 os.write(reinterpret_cast<ostream::char_type*>(bytes), 4);
00593 }
00594
00595
00596
00597
00598
00599
00600 static void writeShort(ostream &os, UInt16 value)
00601 {
00602 UInt8 bytes[2];
00603 bytes[0] = static_cast<UInt8>((value >> 8) & 0xff);
00604 bytes[1] = static_cast<UInt8>(value & 0xff);
00605 os.write(reinterpret_cast<ostream::char_type*>(bytes), 2);
00606 }
00607
00608
00609
00610
00611
00612
00613 bool TextTXFFace::writeToStream(ostream &os) const
00614 {
00615
00616 const ostream::char_type *magicBytes = "\xfftxf";
00617 os.write(magicBytes, 4);
00618
00619
00620 assert(_texture != NullFC);
00621 writeLong(os, 0x12345678);
00622 writeLong(os, 0);
00623 writeLong(os, _texture->getWidth());
00624 writeLong(os, _texture->getHeight());
00625 writeLong(os, static_cast<UInt32>(_horiAscent / _scale));
00626 writeLong(os, static_cast<UInt32>(_horiDescent / _scale));
00627 writeLong(os, _glyphMap.size());
00628 if (os.good() == false)
00629 return false;
00630
00631
00632 GlyphMap::const_iterator it;
00633 for (it = _glyphMap.begin(); it != _glyphMap.end(); ++it)
00634 {
00635 assert(it->second != 0);
00636 writeShort(os, static_cast<UInt16>(it->second->getGlyphIndex()));
00637 os.put(it->second->getPixmapWidth());
00638 os.put(it->second->getPixmapHeight());
00639 os.put(it->second->getPixmapHoriBearingX());
00640 os.put(it->second->getPixmapHoriBearingY() - it->second->getPixmapHeight());
00641 os.put(static_cast<ostream::char_type>(it->second->getHoriAdvance() / _scale));
00642 os.put(0);
00643 writeShort(os, it->second->getX());
00644 writeShort(os, it->second->getY());
00645 if (os.good() == false)
00646 return false;
00647 }
00648
00649
00650 assert(_texture->getSize() == static_cast<UInt32>(_texture->getWidth() * _texture->getHeight()));
00651 os.write((ostream::char_type*)_texture->getData(), _texture->getWidth() * _texture->getHeight());
00652
00653 return os.good();
00654 }
00655
00656
00657
00658
00659
00660
00661 bool TextTXFFace::writeToFile(const string &filename) const
00662 {
00663 ofstream os(filename.c_str(), ios_base::out | ios_base::trunc | ios_base::binary);
00664 if (os.good() == false)
00665 return false;
00666 return writeToStream(os);
00667 }
00668
00669
00670
00671
00672
00673
00674 void TextTXFFace::layout(const string &utf8Text,
00675 const TextLayoutParam ¶m,
00676 TextLayoutResult &result)
00677 {
00678 TextFace::layout(utf8Text, param, result);
00679 }
00680
00681
00682
00683
00684
00685
00686 void TextTXFFace::layout(const wstring &text,
00687 const TextLayoutParam ¶m,
00688 TextLayoutResult &result)
00689 {
00690
00691 result.clear();
00692
00693
00694 Vec2f currPos;
00695 size_t i, len = text.length();
00696 result.indices.reserve(len);
00697 result.positions.reserve(len);
00698 vector<UInt32> spaceIndices;
00699 bool justify = param.getLength(0) > 0.f;
00700 for (i = 0; i < len; ++i)
00701 {
00702
00703 const TextGlyph &glyph = getGlyph(text[i]);
00704 if ((justify == true) && (text[i] == ' '))
00705 spaceIndices.push_back(result.indices.size());
00706
00707
00708 Vec2f pos;
00709 if (param.horizontal == true)
00710 {
00711 if (param.leftToRight == true)
00712 {
00713 pos = currPos;
00714 pos[0] += glyph.getHoriBearingX();
00715 pos[1] += glyph.getHoriBearingY();
00716 currPos[0] += glyph.getHoriAdvance();
00717 }
00718 else
00719 {
00720 currPos[0] -= glyph.getHoriAdvance();
00721 pos = currPos;
00722 pos[0] += glyph.getHoriBearingX();
00723 pos[1] += glyph.getHoriBearingY();
00724 }
00725 }
00726 else
00727 {
00728 if (param.topToBottom == true)
00729 {
00730 pos = currPos;
00731 pos[0] += glyph.getVertBearingX();
00732 pos[1] += glyph.getVertBearingY();
00733 currPos[1] += glyph.getVertAdvance();
00734 }
00735 else
00736 {
00737 currPos[1] -= glyph.getVertAdvance();
00738 pos = currPos;
00739 pos[0] += glyph.getVertBearingX();
00740 pos[1] += glyph.getVertBearingY();
00741 }
00742 }
00743
00744 result.indices.push_back(glyph.getGlyphIndex());
00745 result.positions.push_back(pos);
00746 }
00747
00748
00749 if (justify == true)
00750 justifyLine(param, spaceIndices, currPos, result);
00751
00752
00753 adjustLineOrigin(param, currPos, result);
00754
00755
00756 if (param.horizontal == true)
00757 result.textBounds.setValues(osgabs(currPos.x()), _horiAscent - _horiDescent);
00758 else
00759 result.textBounds.setValues(_vertDescent - _vertAscent, osgabs(currPos.y()));
00760 result.lineBounds.push_back(result.textBounds);
00761 }
00762
00763
00764
00765
00766
00767
00768 void TextTXFFace::layout(const vector<string> &lines,
00769 const TextLayoutParam ¶m,
00770 TextLayoutResult &result)
00771 {
00772 TextFace::layout(lines, param, result);
00773 }
00774
00775
00776
00777
00778
00779
00780 void TextTXFFace::layout(const vector<wstring> &lines,
00781 const TextLayoutParam ¶m,
00782 TextLayoutResult &result)
00783 {
00784 TextFace::layout(lines, param, result);
00785 }
00786
00787
00788
00789
00790
00791
00792 void TextTXFFace::prepareTexture(const TextTXFParam ¶m)
00793 {
00794
00795
00796 typedef multimap<UInt32, TextTXFGlyph*, greater<UInt32> > HeightMap;
00797 HeightMap heightMap;
00798 UInt32 area = 0, maxWidth = 0;
00799 GlyphMap::iterator gmIt;
00800 for (gmIt = _glyphMap.begin(); gmIt != _glyphMap.end(); ++gmIt)
00801 {
00802 TextTXFGlyph *glyph = gmIt->second;
00803 heightMap.insert(HeightMap::value_type(glyph->getPixmapHeight(), glyph));
00804 if (maxWidth < glyph->getPixmapWidth())
00805 maxWidth = glyph->getPixmapWidth();
00806 area += (glyph->getPixmapWidth() + param.gap) * (glyph->getPixmapHeight() + param.gap);
00807 }
00808
00809 UInt32 textureSize;
00810 if (param.textureWidth == 0)
00811 {
00812
00813 textureSize = static_cast<UInt32>(ceil(sqrt(static_cast<Real32>(area))));
00814 }
00815 else
00816 textureSize = param.textureWidth;
00817 maxWidth += param.gap << 1;
00818 if (textureSize < maxWidth)
00819 textureSize = maxWidth;
00820 UInt32 textureWidth = osgnextpower2(textureSize);
00821
00822
00823 HeightMap::iterator hmIt = heightMap.begin();
00824 UInt32 xpos = param.gap, ypos = param.gap, heightOfRow = 0;
00825 while (hmIt != heightMap.end())
00826 {
00827 HeightMap::iterator hmIt3;
00828
00829 if (xpos + hmIt->second->getPixmapWidth() + param.gap > textureWidth)
00830 {
00831
00832 HeightMap::iterator hmIt2 = hmIt;
00833 ++hmIt2;
00834 for (++hmIt2; hmIt2 != heightMap.end(); ++hmIt2)
00835 {
00836 if (xpos + hmIt2->second->getPixmapWidth() + param.gap <= textureWidth)
00837 break;
00838 }
00839 if (hmIt2 == heightMap.end())
00840 {
00841
00842 xpos = param.gap;
00843 ypos += heightOfRow + param.gap;
00844 heightOfRow = 0;
00845 hmIt3 = hmIt;
00846 ++hmIt;
00847 }
00848 else
00849 hmIt3 = hmIt2;
00850 }
00851 else
00852 {
00853
00854 hmIt3 = hmIt;
00855 ++hmIt;
00856 }
00857 hmIt3->second->_x = xpos;
00858 hmIt3->second->_y = ypos;
00859 xpos += hmIt3->second->getPixmapWidth() + param.gap;
00860 if (hmIt3->second->getPixmapHeight() > heightOfRow)
00861 heightOfRow = hmIt3->second->getPixmapHeight();
00862 heightMap.erase(hmIt3);
00863 }
00864 ypos += heightOfRow;
00865
00866
00867 UInt32 textureHeight = osgnextpower2(static_cast<UInt32>(ypos));
00868
00869
00870 _texture = Image::create();
00871 addRefCP(_texture);
00872 beginEditCP(_texture);
00873 {
00874 _texture->set(Image::OSG_I_PF, textureWidth, textureHeight);
00875 _texture->clear();
00876 }
00877 endEditCP(_texture);
00878
00879
00880 for (gmIt = _glyphMap.begin(); gmIt != _glyphMap.end(); ++gmIt)
00881 gmIt->second->calculateCoordinates(textureWidth, textureHeight);
00882 }
00883
00884
00885 OSG_END_NAMESPACE
00886
00887
00888
00889
00890
00891 #ifdef OSG_SGI_CC
00892 #pragma set woff 1174
00893 #endif
00894
00895 #ifdef OSG_LINUX_ICC
00896 #pragma warning( disable : 177 )
00897 #endif
00898
00899 namespace
00900 {
00901 static OSG::Char8 cvsid_cpp[] = "@(#)$Id: OSGTextTXFFace.cpp,v 1.5 2005/07/05 16:25:15 dirk Exp $";
00902 static OSG::Char8 cvsid_hpp[] = OSGTEXTTXFFACE_HEADER_CVSID;
00903 static OSG::Char8 cvsid_inl[] = OSGTEXTTXFFACE_INLINE_CVSID;
00904 }
00905
00906 #ifdef __sgi
00907 #pragma reset woff 1174
00908 #endif