diff options
Diffstat (limited to 'src/irrlicht_changes')
-rw-r--r-- | src/irrlicht_changes/CGUITTFont.cpp | 723 | ||||
-rw-r--r-- | src/irrlicht_changes/CGUITTFont.h | 679 | ||||
-rw-r--r-- | src/irrlicht_changes/irrUString.h | 2552 | ||||
-rw-r--r-- | src/irrlicht_changes/static_text.cpp | 329 | ||||
-rw-r--r-- | src/irrlicht_changes/static_text.h | 315 |
5 files changed, 2381 insertions, 2217 deletions
diff --git a/src/irrlicht_changes/CGUITTFont.cpp b/src/irrlicht_changes/CGUITTFont.cpp index 3bd6957f5..bd4e700de 100644 --- a/src/irrlicht_changes/CGUITTFont.cpp +++ b/src/irrlicht_changes/CGUITTFont.cpp @@ -43,7 +43,7 @@ struct SGUITTFace : public virtual irr::IReferenceCounted { SGUITTFace() : face_buffer(0), face_buffer_size(0) { - memset((void *)&face, 0, sizeof(FT_Face)); + memset((void*)&face, 0, sizeof(FT_Face)); } ~SGUITTFace() @@ -53,15 +53,15 @@ struct SGUITTFace : public virtual irr::IReferenceCounted } FT_Face face; - FT_Byte *face_buffer; + FT_Byte* face_buffer; FT_Long face_buffer_size; }; // Static variables. FT_Library CGUITTFont::c_library; -core::map<io::path, SGUITTFace *> CGUITTFont::c_faces; +core::map<io::path, SGUITTFace*> CGUITTFont::c_faces; bool CGUITTFont::c_libraryLoaded = false; -scene::IMesh *CGUITTFont::shared_plane_ptr_ = 0; +scene::IMesh* CGUITTFont::shared_plane_ptr_ = 0; scene::SMesh CGUITTFont::shared_plane_; // @@ -72,14 +72,14 @@ scene::SMesh CGUITTFont::shared_plane_; inline void checkFontBitmapSize(const FT_Bitmap &bits) { if ((s32)bits.rows < 0 || (s32)bits.width < 0) { - std::cout << "Insane font glyph size. File: " << __FILE__ << " Line " - << __LINE__ << std::endl; + std::cout << "Insane font glyph size. File: " + << __FILE__ << " Line " << __LINE__ + << std::endl; abort(); } } -video::IImage *SGUITTGlyph::createGlyphImage( - const FT_Bitmap &bits, video::IVideoDriver *driver) const +video::IImage* SGUITTGlyph::createGlyphImage(const FT_Bitmap& bits, video::IVideoDriver* driver) const { // Make sure our casts to s32 in the loops below will not cause problems checkFontBitmapSize(bits); @@ -88,83 +88,76 @@ video::IImage *SGUITTGlyph::createGlyphImage( // Add 1 because textures are inclusive-exclusive. core::dimension2du d(bits.width + 1, bits.rows + 1); core::dimension2du texture_size; - // core::dimension2du texture_size(bits.width + 1, bits.rows + 1); + //core::dimension2du texture_size(bits.width + 1, bits.rows + 1); // Create and load our image now. - video::IImage *image = 0; - switch (bits.pixel_mode) { - case FT_PIXEL_MODE_MONO: { - // Create a blank image and fill it with transparent pixels. - texture_size = d.getOptimalSize(true, true); - image = driver->createImage(video::ECF_A1R5G5B5, texture_size); - image->fill(video::SColor(0, 255, 255, 255)); - - // Load the monochrome data in. - const u32 image_pitch = image->getPitch() / sizeof(u16); - u16 *image_data = (u16 *)image->lock(); - u8 *glyph_data = bits.buffer; - - for (s32 y = 0; y < (s32)bits.rows; ++y) { - u16 *row = image_data; - for (s32 x = 0; x < (s32)bits.width; ++x) { - // Monochrome bitmaps store 8 pixels per byte. The - // left-most pixel is the bit 0x80. So, we go through the - // data each bit at a time. - if ((glyph_data[y * bits.pitch + (x / 8)] & - (0x80 >> (x % 8))) != 0) - *row = 0xFFFF; - ++row; + video::IImage* image = 0; + switch (bits.pixel_mode) + { + case FT_PIXEL_MODE_MONO: + { + // Create a blank image and fill it with transparent pixels. + texture_size = d.getOptimalSize(true, true); + image = driver->createImage(video::ECF_A1R5G5B5, texture_size); + image->fill(video::SColor(0, 255, 255, 255)); + + // Load the monochrome data in. + const u32 image_pitch = image->getPitch() / sizeof(u16); + u16* image_data = (u16*)image->lock(); + u8* glyph_data = bits.buffer; + + for (s32 y = 0; y < (s32)bits.rows; ++y) + { + u16* row = image_data; + for (s32 x = 0; x < (s32)bits.width; ++x) + { + // Monochrome bitmaps store 8 pixels per byte. The left-most pixel is the bit 0x80. + // So, we go through the data each bit at a time. + if ((glyph_data[y * bits.pitch + (x / 8)] & (0x80 >> (x % 8))) != 0) + *row = 0xFFFF; + ++row; + } + image_data += image_pitch; } - image_data += image_pitch; + image->unlock(); + break; } - image->unlock(); - break; - } - case FT_PIXEL_MODE_GRAY: { - // Create our blank image. - texture_size = d.getOptimalSize( - !driver->queryFeature(video::EVDF_TEXTURE_NPOT), - !driver->queryFeature(video::EVDF_TEXTURE_NSQUARE), true, - 0); - image = driver->createImage(video::ECF_A8R8G8B8, texture_size); - image->fill(video::SColor(0, 255, 255, 255)); - - // Load the grayscale data in. - const float gray_count = static_cast<float>(bits.num_grays); - const u32 image_pitch = image->getPitch() / sizeof(u32); - u32 *image_data = (u32 *)image->lock(); - u8 *glyph_data = bits.buffer; - for (s32 y = 0; y < (s32)bits.rows; ++y) { - u8 *row = glyph_data; - for (s32 x = 0; x < (s32)bits.width; ++x) { - image_data[y * image_pitch + x] |= - static_cast<u32>( - 255.0f * - (static_cast<float>( - *row++) / - gray_count)) - << 24; - // data[y * image_pitch + x] |= ((u32)(*bitsdata++) << - // 24); + case FT_PIXEL_MODE_GRAY: + { + // Create our blank image. + texture_size = d.getOptimalSize(!driver->queryFeature(video::EVDF_TEXTURE_NPOT), !driver->queryFeature(video::EVDF_TEXTURE_NSQUARE), true, 0); + image = driver->createImage(video::ECF_A8R8G8B8, texture_size); + image->fill(video::SColor(0, 255, 255, 255)); + + // Load the grayscale data in. + const float gray_count = static_cast<float>(bits.num_grays); + const u32 image_pitch = image->getPitch() / sizeof(u32); + u32* image_data = (u32*)image->lock(); + u8* glyph_data = bits.buffer; + for (s32 y = 0; y < (s32)bits.rows; ++y) + { + u8* row = glyph_data; + for (s32 x = 0; x < (s32)bits.width; ++x) + { + image_data[y * image_pitch + x] |= static_cast<u32>(255.0f * (static_cast<float>(*row++) / gray_count)) << 24; + //data[y * image_pitch + x] |= ((u32)(*bitsdata++) << 24); + } + glyph_data += bits.pitch; } - glyph_data += bits.pitch; + image->unlock(); + break; } - image->unlock(); - break; - } - default: - // TODO: error message? - return 0; + default: + // TODO: error message? + return 0; } return image; } -void SGUITTGlyph::preload(u32 char_index, FT_Face face, video::IVideoDriver *driver, - u32 font_size, const FT_Int32 loadFlags) +void SGUITTGlyph::preload(u32 char_index, FT_Face face, video::IVideoDriver* driver, u32 font_size, const FT_Int32 loadFlags) { - if (isLoaded) - return; + if (isLoaded) return; // Set the size of the glyph. FT_Set_Pixel_Sizes(face, 0, font_size); @@ -182,10 +175,11 @@ void SGUITTGlyph::preload(u32 char_index, FT_Face face, video::IVideoDriver *dri offset = core::vector2di(glyph->bitmap_left, glyph->bitmap_top); // Try to get the last page with available slots. - CGUITTGlyphPage *page = parent->getLastGlyphPage(); + CGUITTGlyphPage* page = parent->getLastGlyphPage(); // If we need to make a new page, do that now. - if (!page) { + if (!page) + { page = parent->createGlyphPage(bits.pixel_mode); if (!page) // TODO: add error message? @@ -195,20 +189,17 @@ void SGUITTGlyph::preload(u32 char_index, FT_Face face, video::IVideoDriver *dri glyph_page = parent->getLastGlyphPageIndex(); u32 texture_side_length = page->texture->getOriginalSize().Width; core::vector2di page_position( - (page->used_slots % (texture_side_length / font_size)) * - font_size, - (page->used_slots / (texture_side_length / font_size)) * - font_size); + (page->used_slots % (texture_side_length / font_size)) * font_size, + (page->used_slots / (texture_side_length / font_size)) * font_size + ); source_rect.UpperLeftCorner = page_position; - source_rect.LowerRightCorner = core::vector2di( - page_position.X + bits.width, page_position.Y + bits.rows); + source_rect.LowerRightCorner = core::vector2di(page_position.X + bits.width, page_position.Y + bits.rows); page->dirty = true; ++page->used_slots; --page->available_slots; - // We grab the glyph bitmap here so the data won't be removed when the next glyph - // is loaded. + // We grab the glyph bitmap here so the data won't be removed when the next glyph is loaded. surface = createGlyphImage(bits, driver); // Set our glyph as loaded. @@ -217,7 +208,8 @@ void SGUITTGlyph::preload(u32 char_index, FT_Face face, video::IVideoDriver *dri void SGUITTGlyph::unload() { - if (surface) { + if (surface) + { surface->drop(); surface = 0; } @@ -226,19 +218,19 @@ void SGUITTGlyph::unload() ////////////////////// -CGUITTFont *CGUITTFont::createTTFont(IGUIEnvironment *env, const io::path &filename, - const u32 size, const bool antialias, const bool transparency, - const u32 shadow, const u32 shadow_alpha) +CGUITTFont* CGUITTFont::createTTFont(IGUIEnvironment *env, const io::path& filename, const u32 size, const bool antialias, const bool transparency, const u32 shadow, const u32 shadow_alpha) { - if (!c_libraryLoaded) { + if (!c_libraryLoaded) + { if (FT_Init_FreeType(&c_library)) return 0; c_libraryLoaded = true; } - CGUITTFont *font = new CGUITTFont(env); + CGUITTFont* font = new CGUITTFont(env); bool ret = font->load(filename, size, antialias, transparency); - if (!ret) { + if (!ret) + { font->drop(); return 0; } @@ -249,19 +241,20 @@ CGUITTFont *CGUITTFont::createTTFont(IGUIEnvironment *env, const io::path &filen return font; } -CGUITTFont *CGUITTFont::createTTFont(IrrlichtDevice *device, const io::path &filename, - const u32 size, const bool antialias, const bool transparency) +CGUITTFont* CGUITTFont::createTTFont(IrrlichtDevice *device, const io::path& filename, const u32 size, const bool antialias, const bool transparency) { - if (!c_libraryLoaded) { + if (!c_libraryLoaded) + { if (FT_Init_FreeType(&c_library)) return 0; c_libraryLoaded = true; } - CGUITTFont *font = new CGUITTFont(device->getGUIEnvironment()); + CGUITTFont* font = new CGUITTFont(device->getGUIEnvironment()); font->Device = device; bool ret = font->load(filename, size, antialias, transparency); - if (!ret) { + if (!ret) + { font->drop(); return 0; } @@ -269,14 +262,12 @@ CGUITTFont *CGUITTFont::createTTFont(IrrlichtDevice *device, const io::path &fil return font; } -CGUITTFont *CGUITTFont::create(IGUIEnvironment *env, const io::path &filename, - const u32 size, const bool antialias, const bool transparency) +CGUITTFont* CGUITTFont::create(IGUIEnvironment *env, const io::path& filename, const u32 size, const bool antialias, const bool transparency) { return CGUITTFont::createTTFont(env, filename, size, antialias, transparency); } -CGUITTFont *CGUITTFont::create(IrrlichtDevice *device, const io::path &filename, - const u32 size, const bool antialias, const bool transparency) +CGUITTFont* CGUITTFont::create(IrrlichtDevice *device, const io::path& filename, const u32 size, const bool antialias, const bool transparency) { return CGUITTFont::createTTFont(device, filename, size, antialias, transparency); } @@ -284,16 +275,16 @@ CGUITTFont *CGUITTFont::create(IrrlichtDevice *device, const io::path &filename, ////////////////////// //! Constructor. -CGUITTFont::CGUITTFont(IGUIEnvironment *env) : - use_monochrome(false), use_transparency(true), use_hinting(true), - use_auto_hinting(true), batch_load_size(1), Device(0), Environment(env), - Driver(0), GlobalKerningWidth(0), GlobalKerningHeight(0) +CGUITTFont::CGUITTFont(IGUIEnvironment *env) +: use_monochrome(false), use_transparency(true), use_hinting(true), use_auto_hinting(true), +batch_load_size(1), Device(0), Environment(env), Driver(0), GlobalKerningWidth(0), GlobalKerningHeight(0) { -#ifdef _DEBUG + #ifdef _DEBUG setDebugName("CGUITTFont"); -#endif + #endif - if (Environment) { + if (Environment) + { // don't grab environment, to avoid circular references Driver = Environment->getVideoDriver(); } @@ -303,24 +294,19 @@ CGUITTFont::CGUITTFont(IGUIEnvironment *env) : setInvisibleCharacters(L" "); - // Glyphs aren't reference counted, so don't try to delete them when we free the - // array. + // Glyphs aren't reference counted, so don't try to delete them when we free the array. Glyphs.set_free_when_destroyed(false); } -bool CGUITTFont::load(const io::path &filename, const u32 size, const bool antialias, - const bool transparency) +bool CGUITTFont::load(const io::path& filename, const u32 size, const bool antialias, const bool transparency) { // Some sanity checks. - if (Environment == 0 || Driver == 0) - return false; - if (size == 0) - return false; - if (filename.size() == 0) - return false; - - io::IFileSystem *filesystem = Environment->getFileSystem(); - irr::ILogger *logger = (Device != 0 ? Device->getLogger() : 0); + if (Environment == 0 || Driver == 0) return false; + if (size == 0) return false; + if (filename.size() == 0) return false; + + io::IFileSystem* filesystem = Environment->getFileSystem(); + irr::ILogger* logger = (Device != 0 ? Device->getLogger() : 0); this->size = size; this->filename = filename; @@ -331,32 +317,23 @@ bool CGUITTFont::load(const io::path &filename, const u32 size, const bool antia // Log. if (logger) - logger->log(L"CGUITTFont", - core::stringw(core::stringw(L"Creating new font: ") + - core::ustring(filename).toWCHAR_s() + - L" " + core::stringc(size) + L"pt " + - (antialias ? L"+antialias " - : L"-antialias ") + - (transparency ? L"+transparency" - : L"-transparency")) - .c_str(), - irr::ELL_INFORMATION); + logger->log(L"CGUITTFont", core::stringw(core::stringw(L"Creating new font: ") + core::ustring(filename).toWCHAR_s() + L" " + core::stringc(size) + L"pt " + (antialias ? L"+antialias " : L"-antialias ") + (transparency ? L"+transparency" : L"-transparency")).c_str(), irr::ELL_INFORMATION); // Grab the face. - SGUITTFace *face = 0; - core::map<io::path, SGUITTFace *>::Node *node = c_faces.find(filename); - if (node == 0) { + SGUITTFace* face = 0; + core::map<io::path, SGUITTFace*>::Node* node = c_faces.find(filename); + if (node == 0) + { face = new SGUITTFace(); c_faces.set(filename, face); - if (filesystem) { + if (filesystem) + { // Read in the file data. - io::IReadFile *file = filesystem->createAndOpenFile(filename); - if (file == 0) { - if (logger) - logger->log(L"CGUITTFont", - L"Failed to open the file.", - irr::ELL_INFORMATION); + io::IReadFile* file = filesystem->createAndOpenFile(filename); + if (file == 0) + { + if (logger) logger->log(L"CGUITTFont", L"Failed to open the file.", irr::ELL_INFORMATION); c_faces.remove(filename); delete face; @@ -369,27 +346,22 @@ bool CGUITTFont::load(const io::path &filename, const u32 size, const bool antia file->drop(); // Create the face. - if (FT_New_Memory_Face(c_library, face->face_buffer, - face->face_buffer_size, 0, &face->face)) { - if (logger) - logger->log(L"CGUITTFont", - L"FT_New_Memory_Face failed.", - irr::ELL_INFORMATION); + if (FT_New_Memory_Face(c_library, face->face_buffer, face->face_buffer_size, 0, &face->face)) + { + if (logger) logger->log(L"CGUITTFont", L"FT_New_Memory_Face failed.", irr::ELL_INFORMATION); c_faces.remove(filename); delete face; face = 0; return false; } - } else { + } + else + { core::ustring converter(filename); - if (FT_New_Face(c_library, - reinterpret_cast<const char *>( - converter.toUTF8_s().c_str()), - 0, &face->face)) { - if (logger) - logger->log(L"CGUITTFont", L"FT_New_Face failed.", - irr::ELL_INFORMATION); + if (FT_New_Face(c_library, reinterpret_cast<const char*>(converter.toUTF8_s().c_str()), 0, &face->face)) + { + if (logger) logger->log(L"CGUITTFont", L"FT_New_Face failed.", irr::ELL_INFORMATION); c_faces.remove(filename); delete face; @@ -397,7 +369,9 @@ bool CGUITTFont::load(const io::path &filename, const u32 size, const bool antia return false; } } - } else { + } + else + { // Using another instance of this face. face = node->getValue(); face->grab(); @@ -414,7 +388,8 @@ bool CGUITTFont::load(const io::path &filename, const u32 size, const bool antia Glyphs.clear(); Glyphs.reallocate(tt_face->num_glyphs); Glyphs.set_used(tt_face->num_glyphs); - for (FT_Long i = 0; i < tt_face->num_glyphs; ++i) { + for (FT_Long i = 0; i < tt_face->num_glyphs; ++i) + { Glyphs[i].isLoaded = false; Glyphs[i].glyph_page = 0; Glyphs[i].source_rect = core::recti(); @@ -438,20 +413,21 @@ CGUITTFont::~CGUITTFont() // Delete the glyphs and glyph pages. reset_images(); CGUITTAssistDelete::Delete(Glyphs); - // Glyphs.clear(); + //Glyphs.clear(); // We aren't using this face anymore. - core::map<io::path, SGUITTFace *>::Node *n = c_faces.find(filename); - if (n) { - SGUITTFace *f = n->getValue(); + core::map<io::path, SGUITTFace*>::Node* n = c_faces.find(filename); + if (n) + { + SGUITTFace* f = n->getValue(); - // Drop our face. If this was the last face, the destructor will clean - // up. + // Drop our face. If this was the last face, the destructor will clean up. if (f->drop()) c_faces.remove(filename); // If there are no more faces referenced by FreeType, clean up. - if (c_faces.size() == 0) { + if (c_faces.size() == 0) + { FT_Done_FreeType(c_library); c_libraryLoaded = false; } @@ -479,18 +455,20 @@ void CGUITTFont::reset_images() void CGUITTFont::update_glyph_pages() const { - for (u32 i = 0; i != Glyph_Pages.size(); ++i) { + for (u32 i = 0; i != Glyph_Pages.size(); ++i) + { if (Glyph_Pages[i]->dirty) Glyph_Pages[i]->updateTexture(); } } -CGUITTGlyphPage *CGUITTFont::getLastGlyphPage() const +CGUITTGlyphPage* CGUITTFont::getLastGlyphPage() const { - CGUITTGlyphPage *page = 0; + CGUITTGlyphPage* page = 0; if (Glyph_Pages.empty()) return 0; - else { + else + { page = Glyph_Pages[getLastGlyphPageIndex()]; if (page->available_slots == 0) page = 0; @@ -498,10 +476,10 @@ CGUITTGlyphPage *CGUITTFont::getLastGlyphPage() const return page; } -CGUITTGlyphPage *CGUITTFont::createGlyphPage(const u8 &pixel_mode) +CGUITTGlyphPage* CGUITTFont::createGlyphPage(const u8& pixel_mode) { - CGUITTGlyphPage *page = 0; - + CGUITTGlyphPage* page = 0; + // Name of our page. io::path name("TTFontGlyphPage_"); name += tt_face->family_name; @@ -510,8 +488,7 @@ CGUITTGlyphPage *CGUITTFont::createGlyphPage(const u8 &pixel_mode) name += "."; name += size; name += "_"; - name += Glyph_Pages.size(); // The newly created page will be at the end of the - // collection. + name += Glyph_Pages.size(); // The newly created page will be at the end of the collection. // Create the new page. page = new CGUITTGlyphPage(Driver, name); @@ -526,19 +503,13 @@ CGUITTGlyphPage *CGUITTFont::createGlyphPage(const u8 &pixel_mode) // We want to try to put at least 144 glyphs on a single texture. core::dimension2du page_texture_size; - if (size <= 21) - page_texture_size = core::dimension2du(256, 256); - else if (size <= 42) - page_texture_size = core::dimension2du(512, 512); - else if (size <= 84) - page_texture_size = core::dimension2du(1024, 1024); - else if (size <= 168) - page_texture_size = core::dimension2du(2048, 2048); - else - page_texture_size = core::dimension2du(4096, 4096); + if (size <= 21) page_texture_size = core::dimension2du(256, 256); + else if (size <= 42) page_texture_size = core::dimension2du(512, 512); + else if (size <= 84) page_texture_size = core::dimension2du(1024, 1024); + else if (size <= 168) page_texture_size = core::dimension2du(2048, 2048); + else page_texture_size = core::dimension2du(4096, 4096); - if (page_texture_size.Width > max_texture_size.Width || - page_texture_size.Height > max_texture_size.Height) + if (page_texture_size.Width > max_texture_size.Width || page_texture_size.Height > max_texture_size.Height) page_texture_size = max_texture_size; if (!page->createPageTexture(pixel_mode, page_texture_size)) { @@ -547,11 +518,10 @@ CGUITTGlyphPage *CGUITTFont::createGlyphPage(const u8 &pixel_mode) return 0; } - if (page) { - // Determine the number of glyph slots on the page and add it to the list - // of pages. - page->available_slots = (page_texture_size.Width / size) * - (page_texture_size.Height / size); + if (page) + { + // Determine the number of glyph slots on the page and add it to the list of pages. + page->available_slots = (page_texture_size.Width / size) * (page_texture_size.Height / size); Glyph_Pages.push_back(page); } return page; @@ -576,17 +546,12 @@ void CGUITTFont::setFontHinting(const bool enable, const bool enable_auto_hintin reset_images(); } -void CGUITTFont::draw(const core::stringw &text, const core::rect<s32> &position, - video::SColor color, bool hcenter, bool vcenter, - const core::rect<s32> *clip) +void CGUITTFont::draw(const core::stringw& text, const core::rect<s32>& position, video::SColor color, bool hcenter, bool vcenter, const core::rect<s32>* clip) { - draw(EnrichedString(std::wstring(text.c_str()), color), position, color, hcenter, - vcenter, clip); + draw(EnrichedString(std::wstring(text.c_str()), color), position, color, hcenter, vcenter, clip); } -void CGUITTFont::draw(const EnrichedString &text, const core::rect<s32> &position, - video::SColor color, bool hcenter, bool vcenter, - const core::rect<s32> *clip) +void CGUITTFont::draw(const EnrichedString &text, const core::rect<s32>& position, video::SColor color, bool hcenter, bool vcenter, const core::rect<s32>* clip) { std::vector<video::SColor> colors = text.getColors(); @@ -594,7 +559,8 @@ void CGUITTFont::draw(const EnrichedString &text, const core::rect<s32> &positio return; // Clear the glyph pages of their render information. - for (u32 i = 0; i < Glyph_Pages.size(); ++i) { + for (u32 i = 0; i < Glyph_Pages.size(); ++i) + { Glyph_Pages[i]->render_positions.clear(); Glyph_Pages[i]->render_source_rects.clear(); } @@ -604,60 +570,62 @@ void CGUITTFont::draw(const EnrichedString &text, const core::rect<s32> &positio core::position2d<s32> offset = position.UpperLeftCorner; // Determine offset positions. - if (hcenter || vcenter) { + if (hcenter || vcenter) + { textDimension = getDimension(text.c_str()); if (hcenter) - offset.X = ((position.getWidth() - textDimension.Width) >> 1) + - offset.X; + offset.X = ((position.getWidth() - textDimension.Width) >> 1) + offset.X; if (vcenter) - offset.Y = ((position.getHeight() - textDimension.Height) >> 1) + - offset.Y; + offset.Y = ((position.getHeight() - textDimension.Height) >> 1) + offset.Y; } // Convert to a unicode string. core::ustring utext = text.getString(); // Set up our render map. - core::map<u32, CGUITTGlyphPage *> Render_Map; + core::map<u32, CGUITTGlyphPage*> Render_Map; // Start parsing characters. u32 n; uchar32_t previousChar = 0; core::ustring::const_iterator iter(utext); std::vector<video::SColor> applied_colors; - while (!iter.atEnd()) { + while (!iter.atEnd()) + { uchar32_t currentChar = *iter; n = getGlyphIndexByChar(currentChar); bool visible = (Invisible.findFirst(currentChar) == -1); - bool lineBreak = false; + bool lineBreak=false; if (currentChar == L'\r') // Mac or Windows breaks { lineBreak = true; - if (*(iter + 1) == (uchar32_t)'\n') // Windows line breaks. + if (*(iter + 1) == (uchar32_t)'\n') // Windows line breaks. currentChar = *(++iter); - } else if (currentChar == (uchar32_t)'\n') // Unix breaks + } + else if (currentChar == (uchar32_t)'\n') // Unix breaks { lineBreak = true; } - if (lineBreak) { + if (lineBreak) + { previousChar = 0; offset.Y += font_metrics.height / 64; offset.X = position.UpperLeftCorner.X; if (hcenter) - offset.X += (position.getWidth() - textDimension.Width) >> - 1; + offset.X += (position.getWidth() - textDimension.Width) >> 1; ++iter; continue; } - if (n > 0 && visible) { + if (n > 0 && visible) + { // Calculate the glyph offset. - s32 offx = Glyphs[n - 1].offset.X; - s32 offy = (font_metrics.ascender / 64) - Glyphs[n - 1].offset.Y; + s32 offx = Glyphs[n-1].offset.X; + s32 offy = (font_metrics.ascender / 64) - Glyphs[n-1].offset.Y; // Apply kerning. core::vector2di k = getKerning(currentChar, previousChar); @@ -665,10 +633,9 @@ void CGUITTFont::draw(const EnrichedString &text, const core::rect<s32> &positio offset.Y += k.Y; // Determine rendering information. - SGUITTGlyph &glyph = Glyphs[n - 1]; - CGUITTGlyphPage *const page = Glyph_Pages[glyph.glyph_page]; - page->render_positions.push_back(core::position2di( - offset.X + offx, offset.Y + offy)); + SGUITTGlyph& glyph = Glyphs[n-1]; + CGUITTGlyphPage* const page = Glyph_Pages[glyph.glyph_page]; + page->render_positions.push_back(core::position2di(offset.X + offx, offset.Y + offy)); page->render_source_rects.push_back(glyph.source_rect); Render_Map.set(glyph.glyph_page, page); u32 current_color = iter.getPos(); @@ -683,25 +650,21 @@ void CGUITTFont::draw(const EnrichedString &text, const core::rect<s32> &positio // Draw now. update_glyph_pages(); - core::map<u32, CGUITTGlyphPage *>::Iterator j = Render_Map.getIterator(); - while (!j.atEnd()) { - core::map<u32, CGUITTGlyphPage *>::Node *n = j.getNode(); + core::map<u32, CGUITTGlyphPage*>::Iterator j = Render_Map.getIterator(); + while (!j.atEnd()) + { + core::map<u32, CGUITTGlyphPage*>::Node* n = j.getNode(); j++; - if (n == 0) - continue; + if (n == 0) continue; - CGUITTGlyphPage *page = n->getValue(); + CGUITTGlyphPage* page = n->getValue(); if (shadow_offset) { for (size_t i = 0; i < page->render_positions.size(); ++i) - page->render_positions[i] += core::vector2di( - shadow_offset, shadow_offset); - Driver->draw2DImageBatch(page->texture, page->render_positions, - page->render_source_rects, clip, - video::SColor(shadow_alpha, 0, 0, 0), true); + page->render_positions[i] += core::vector2di(shadow_offset, shadow_offset); + Driver->draw2DImageBatch(page->texture, page->render_positions, page->render_source_rects, clip, video::SColor(shadow_alpha,0,0,0), true); for (size_t i = 0; i < page->render_positions.size(); ++i) - page->render_positions[i] -= core::vector2di( - shadow_offset, shadow_offset); + page->render_positions[i] -= core::vector2di(shadow_offset, shadow_offset); } for (size_t i = 0; i < page->render_positions.size(); ++i) { irr::video::SColor col; @@ -712,24 +675,22 @@ void CGUITTFont::draw(const EnrichedString &text, const core::rect<s32> &positio } if (!use_transparency) col.color |= 0xff000000; - Driver->draw2DImage(page->texture, page->render_positions[i], - page->render_source_rects[i], clip, col, true); + Driver->draw2DImage(page->texture, page->render_positions[i], page->render_source_rects[i], clip, col, true); } } } core::dimension2d<u32> CGUITTFont::getCharDimension(const wchar_t ch) const { - return core::dimension2d<u32>( - getWidthFromCharacter(ch), getHeightFromCharacter(ch)); + return core::dimension2d<u32>(getWidthFromCharacter(ch), getHeightFromCharacter(ch)); } -core::dimension2d<u32> CGUITTFont::getDimension(const wchar_t *text) const +core::dimension2d<u32> CGUITTFont::getDimension(const wchar_t* text) const { return getDimension(core::ustring(text)); } -core::dimension2d<u32> CGUITTFont::getDimension(const core::ustring &text) const +core::dimension2d<u32> CGUITTFont::getDimension(const core::ustring& text) const { // Get the maximum font height. Unfortunately, we have to do this hack as // Irrlicht will draw things wrong. In FreeType, the font size is the @@ -748,17 +709,20 @@ core::dimension2d<u32> CGUITTFont::getDimension(const core::ustring &text) const uchar32_t previousChar = 0; core::ustring::const_iterator iter = text.begin(); - for (; !iter.atEnd(); ++iter) { + for (; !iter.atEnd(); ++iter) + { uchar32_t p = *iter; bool lineBreak = false; - if (p == '\r') // Mac or Windows line breaks. + if (p == '\r') // Mac or Windows line breaks. { lineBreak = true; - if (*(iter + 1) == '\n') { + if (*(iter + 1) == '\n') + { ++iter; p = *iter; } - } else if (p == '\n') // Unix line breaks. + } + else if (p == '\n') // Unix line breaks. { lineBreak = true; } @@ -769,7 +733,8 @@ core::dimension2d<u32> CGUITTFont::getDimension(const core::ustring &text) const previousChar = p; // Check for linebreak. - if (lineBreak) { + if (lineBreak) + { previousChar = 0; text_dimension.Height += line.Height; if (text_dimension.Width < line.Width) @@ -794,19 +759,18 @@ inline u32 CGUITTFont::getWidthFromCharacter(wchar_t c) const inline u32 CGUITTFont::getWidthFromCharacter(uchar32_t c) const { // Set the size of the face. - // This is because we cache faces and the face may have been set to a different - // size. - // FT_Set_Pixel_Sizes(tt_face, 0, size); + // This is because we cache faces and the face may have been set to a different size. + //FT_Set_Pixel_Sizes(tt_face, 0, size); u32 n = getGlyphIndexByChar(c); - if (n > 0) { - int w = Glyphs[n - 1].advance.x / 64; + if (n > 0) + { + int w = Glyphs[n-1].advance.x / 64; return w; } if (c >= 0x2000) return (font_metrics.ascender / 64); - else - return (font_metrics.ascender / 64) / 2; + else return (font_metrics.ascender / 64) / 2; } inline u32 CGUITTFont::getHeightFromCharacter(wchar_t c) const @@ -817,22 +781,19 @@ inline u32 CGUITTFont::getHeightFromCharacter(wchar_t c) const inline u32 CGUITTFont::getHeightFromCharacter(uchar32_t c) const { // Set the size of the face. - // This is because we cache faces and the face may have been set to a different - // size. - // FT_Set_Pixel_Sizes(tt_face, 0, size); + // This is because we cache faces and the face may have been set to a different size. + //FT_Set_Pixel_Sizes(tt_face, 0, size); u32 n = getGlyphIndexByChar(c); - if (n > 0) { - // Grab the true height of the character, taking into account underhanging - // glyphs. - s32 height = (font_metrics.ascender / 64) - Glyphs[n - 1].offset.Y + - Glyphs[n - 1].source_rect.getHeight(); + if (n > 0) + { + // Grab the true height of the character, taking into account underhanging glyphs. + s32 height = (font_metrics.ascender / 64) - Glyphs[n-1].offset.Y + Glyphs[n-1].source_rect.getHeight(); return height; } if (c >= 0x2000) return (font_metrics.ascender / 64); - else - return (font_metrics.ascender / 64) / 2; + else return (font_metrics.ascender / 64) / 2; } u32 CGUITTFont::getGlyphIndexByChar(wchar_t c) const @@ -845,11 +806,9 @@ u32 CGUITTFont::getGlyphIndexByChar(uchar32_t c) const // Get the glyph. u32 glyph = FT_Get_Char_Index(tt_face, c); - // Check for a valid glyph. If it is invalid, attempt to use the replacement - // character. + // Check for a valid glyph. If it is invalid, attempt to use the replacement character. if (glyph == 0) - glyph = FT_Get_Char_Index( - tt_face, core::unicode::UTF_REPLACEMENT_CHARACTER); + glyph = FT_Get_Char_Index(tt_face, core::unicode::UTF_REPLACEMENT_CHARACTER); // If our glyph is already loaded, don't bother doing any batch loading code. if (glyph != 0 && Glyphs[glyph - 1].isLoaded) @@ -858,44 +817,47 @@ u32 CGUITTFont::getGlyphIndexByChar(uchar32_t c) const // Determine our batch loading positions. u32 half_size = (batch_load_size / 2); u32 start_pos = 0; - if (c > half_size) - start_pos = c - half_size; + if (c > half_size) start_pos = c - half_size; u32 end_pos = start_pos + batch_load_size; // Load all our characters. - do { + do + { // Get the character we are going to load. u32 char_index = FT_Get_Char_Index(tt_face, start_pos); // If the glyph hasn't been loaded yet, do it now. - if (char_index) { - SGUITTGlyph &glyph = Glyphs[char_index - 1]; - if (!glyph.isLoaded) { - glyph.preload(char_index, tt_face, Driver, size, - load_flags); + if (char_index) + { + SGUITTGlyph& glyph = Glyphs[char_index - 1]; + if (!glyph.isLoaded) + { + glyph.preload(char_index, tt_face, Driver, size, load_flags); Glyph_Pages[glyph.glyph_page]->pushGlyphToBePaged(&glyph); } } - } while (++start_pos < end_pos); + } + while (++start_pos < end_pos); // Return our original character. return glyph; } -s32 CGUITTFont::getCharacterFromPos(const wchar_t *text, s32 pixel_x) const +s32 CGUITTFont::getCharacterFromPos(const wchar_t* text, s32 pixel_x) const { return getCharacterFromPos(core::ustring(text), pixel_x); } -s32 CGUITTFont::getCharacterFromPos(const core::ustring &text, s32 pixel_x) const +s32 CGUITTFont::getCharacterFromPos(const core::ustring& text, s32 pixel_x) const { s32 x = 0; - // s32 idx = 0; + //s32 idx = 0; u32 character = 0; uchar32_t previousChar = 0; core::ustring::const_iterator iter = text.begin(); - while (!iter.atEnd()) { + while (!iter.atEnd()) + { uchar32_t c = *iter; x += getWidthFromCharacter(c); @@ -924,8 +886,7 @@ void CGUITTFont::setKerningHeight(s32 kerning) GlobalKerningHeight = kerning; } -s32 CGUITTFont::getKerningWidth( - const wchar_t *thisLetter, const wchar_t *previousLetter) const +s32 CGUITTFont::getKerningWidth(const wchar_t* thisLetter, const wchar_t* previousLetter) const { if (tt_face == 0) return GlobalKerningWidth; @@ -935,8 +896,7 @@ s32 CGUITTFont::getKerningWidth( return getKerningWidth((uchar32_t)*thisLetter, (uchar32_t)*previousLetter); } -s32 CGUITTFont::getKerningWidth( - const uchar32_t thisLetter, const uchar32_t previousLetter) const +s32 CGUITTFont::getKerningWidth(const uchar32_t thisLetter, const uchar32_t previousLetter) const { // Return only the kerning width. return getKerning(thisLetter, previousLetter).X; @@ -948,21 +908,18 @@ s32 CGUITTFont::getKerningHeight() const return GlobalKerningHeight; } -core::vector2di CGUITTFont::getKerning( - const wchar_t thisLetter, const wchar_t previousLetter) const +core::vector2di CGUITTFont::getKerning(const wchar_t thisLetter, const wchar_t previousLetter) const { return getKerning((uchar32_t)thisLetter, (uchar32_t)previousLetter); } -core::vector2di CGUITTFont::getKerning( - const uchar32_t thisLetter, const uchar32_t previousLetter) const +core::vector2di CGUITTFont::getKerning(const uchar32_t thisLetter, const uchar32_t previousLetter) const { if (tt_face == 0 || thisLetter == 0 || previousLetter == 0) return core::vector2di(); // Set the size of the face. - // This is because we cache faces and the face may have been set to a different - // size. + // This is because we cache faces and the face may have been set to a different size. FT_Set_Pixel_Sizes(tt_face, 0, size); core::vector2di ret(GlobalKerningWidth, GlobalKerningHeight); @@ -973,15 +930,17 @@ core::vector2di CGUITTFont::getKerning( // Get the kerning information. FT_Vector v; - FT_Get_Kerning(tt_face, getGlyphIndexByChar(previousLetter), - getGlyphIndexByChar(thisLetter), FT_KERNING_DEFAULT, &v); + FT_Get_Kerning(tt_face, getGlyphIndexByChar(previousLetter), getGlyphIndexByChar(thisLetter), FT_KERNING_DEFAULT, &v); // If we have a scalable font, the return value will be in font points. - if (FT_IS_SCALABLE(tt_face)) { + if (FT_IS_SCALABLE(tt_face)) + { // Font points, so divide by 64. ret.X += (v.x / 64); ret.Y += (v.y / 64); - } else { + } + else + { // Pixel units. ret.X += v.x; ret.Y += v.y; @@ -995,44 +954,43 @@ void CGUITTFont::setInvisibleCharacters(const wchar_t *s) Invisible = us; } -void CGUITTFont::setInvisibleCharacters(const core::ustring &s) +void CGUITTFont::setInvisibleCharacters(const core::ustring& s) { Invisible = s; } -video::IImage *CGUITTFont::createTextureFromChar(const uchar32_t &ch) +video::IImage* CGUITTFont::createTextureFromChar(const uchar32_t& ch) { u32 n = getGlyphIndexByChar(ch); - const SGUITTGlyph &glyph = Glyphs[n - 1]; - CGUITTGlyphPage *page = Glyph_Pages[glyph.glyph_page]; + const SGUITTGlyph& glyph = Glyphs[n-1]; + CGUITTGlyphPage* page = Glyph_Pages[glyph.glyph_page]; if (page->dirty) page->updateTexture(); - video::ITexture *tex = page->texture; + video::ITexture* tex = page->texture; -// Acquire a read-only lock of the corresponding page texture. -#if IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR >= 8 - void *ptr = tex->lock(video::ETLM_READ_ONLY); -#else - void *ptr = tex->lock(true); -#endif + // Acquire a read-only lock of the corresponding page texture. + #if IRRLICHT_VERSION_MAJOR==1 && IRRLICHT_VERSION_MINOR>=8 + void* ptr = tex->lock(video::ETLM_READ_ONLY); + #else + void* ptr = tex->lock(true); + #endif video::ECOLOR_FORMAT format = tex->getColorFormat(); core::dimension2du tex_size = tex->getOriginalSize(); - video::IImage *pageholder = - Driver->createImageFromData(format, tex_size, ptr, true, false); + video::IImage* pageholder = Driver->createImageFromData(format, tex_size, ptr, true, false); // Copy the image data out of the page texture. core::dimension2du glyph_size(glyph.source_rect.getSize()); - video::IImage *image = Driver->createImage(format, glyph_size); + video::IImage* image = Driver->createImage(format, glyph_size); pageholder->copyTo(image, core::position2di(0, 0), glyph.source_rect); tex->unlock(); return image; } -video::ITexture *CGUITTFont::getPageTextureByIndex(const u32 &page_index) const +video::ITexture* CGUITTFont::getPageTextureByIndex(const u32& page_index) const { if (page_index < Glyph_Pages.size()) return Glyph_Pages[page_index]->texture; @@ -1054,71 +1012,60 @@ void CGUITTFont::createSharedPlane() using namespace video; using namespace scene; S3DVertex vertices[4]; - u16 indices[6] = {0, 2, 3, 3, 1, 0}; - vertices[0] = S3DVertex(vector3df(0, -1, 0), vector3df(0, 0, -1), - SColor(255, 255, 255, 255), vector2df(0, 1)); - vertices[1] = S3DVertex(vector3df(1, -1, 0), vector3df(0, 0, -1), - SColor(255, 255, 255, 255), vector2df(1, 1)); - vertices[2] = S3DVertex(vector3df(0, 0, 0), vector3df(0, 0, -1), - SColor(255, 255, 255, 255), vector2df(0, 0)); - vertices[3] = S3DVertex(vector3df(1, 0, 0), vector3df(0, 0, -1), - SColor(255, 255, 255, 255), vector2df(1, 0)); - - SMeshBuffer *buf = new SMeshBuffer(); + u16 indices[6] = {0,2,3,3,1,0}; + vertices[0] = S3DVertex(vector3df(0,-1,0), vector3df(0,0,-1), SColor(255,255,255,255), vector2df(0,1)); + vertices[1] = S3DVertex(vector3df(1,-1,0), vector3df(0,0,-1), SColor(255,255,255,255), vector2df(1,1)); + vertices[2] = S3DVertex(vector3df(0, 0,0), vector3df(0,0,-1), SColor(255,255,255,255), vector2df(0,0)); + vertices[3] = S3DVertex(vector3df(1, 0,0), vector3df(0,0,-1), SColor(255,255,255,255), vector2df(1,0)); + + SMeshBuffer* buf = new SMeshBuffer(); buf->append(vertices, 4, indices, 6); - shared_plane_.addMeshBuffer(buf); + shared_plane_.addMeshBuffer( buf ); shared_plane_ptr_ = &shared_plane_; - buf->drop(); // the addMeshBuffer method will grab it, so we can drop this ptr. + buf->drop(); //the addMeshBuffer method will grab it, so we can drop this ptr. } -core::dimension2d<u32> CGUITTFont::getDimensionUntilEndOfLine(const wchar_t *p) const +core::dimension2d<u32> CGUITTFont::getDimensionUntilEndOfLine(const wchar_t* p) const { core::stringw s; - for (const wchar_t *temp = p; - temp && *temp != '\0' && *temp != L'\r' && *temp != L'\n'; ++temp) + for (const wchar_t* temp = p; temp && *temp != '\0' && *temp != L'\r' && *temp != L'\n'; ++temp ) s.append(*temp); return getDimension(s.c_str()); } -core::array<scene::ISceneNode *> CGUITTFont::addTextSceneNode(const wchar_t *text, - scene::ISceneManager *smgr, scene::ISceneNode *parent, - const video::SColor &color, bool center) +core::array<scene::ISceneNode*> CGUITTFont::addTextSceneNode(const wchar_t* text, scene::ISceneManager* smgr, scene::ISceneNode* parent, const video::SColor& color, bool center) { using namespace core; using namespace video; using namespace scene; - array<scene::ISceneNode *> container; + array<scene::ISceneNode*> container; - if (!Driver || !smgr) - return container; + if (!Driver || !smgr) return container; if (!parent) parent = smgr->addEmptySceneNode(smgr->getRootSceneNode(), -1); // if you don't specify parent, then we add a empty node attached to the root node // this is generally undesirable. - if (!shared_plane_ptr_) // this points to a static mesh that contains the plane - createSharedPlane(); // if it's not initialized, we create one. + if (!shared_plane_ptr_) //this points to a static mesh that contains the plane + createSharedPlane(); //if it's not initialized, we create one. - dimension2d<s32> text_size(getDimension(text)); // convert from unsigned to - // signed. + dimension2d<s32> text_size(getDimension(text)); //convert from unsigned to signed. vector3df start_point(0, 0, 0), offset; /** NOTICE: - Because we are considering adding texts into 3D world, all Y axis vectors - are inverted. + Because we are considering adding texts into 3D world, all Y axis vectors are inverted. **/ - // There's currently no "vertical center" concept when you apply text scene node - // to the 3D world. - if (center) { + // There's currently no "vertical center" concept when you apply text scene node to the 3D world. + if (center) + { offset.X = start_point.X = -text_size.Width / 2.f; - offset.Y = start_point.Y = +text_size.Height / 2.f; - offset.X += (text_size.Width - getDimensionUntilEndOfLine(text).Width) >> - 1; + offset.Y = start_point.Y = +text_size.Height/ 2.f; + offset.X += (text_size.Width - getDimensionUntilEndOfLine(text).Width) >> 1; } // the default font material @@ -1127,8 +1074,7 @@ core::array<scene::ISceneNode *> CGUITTFont::addTextSceneNode(const wchar_t *tex mat.setFlag(video::EMF_ZWRITE_ENABLE, false); mat.setFlag(video::EMF_NORMALIZE_NORMALS, true); mat.ColorMaterial = video::ECM_NONE; - mat.MaterialType = use_transparency ? video::EMT_TRANSPARENT_ALPHA_CHANNEL - : video::EMT_SOLID; + mat.MaterialType = use_transparency ? video::EMT_TRANSPARENT_ALPHA_CHANNEL : video::EMT_SOLID; mat.MaterialTypeParam = 0.01f; mat.DiffuseColor = color; @@ -1137,36 +1083,39 @@ core::array<scene::ISceneNode *> CGUITTFont::addTextSceneNode(const wchar_t *tex array<u32> glyph_indices; - while (*text) { + while (*text) + { current_char = *text; - bool line_break = false; + bool line_break=false; if (current_char == L'\r') // Mac or Windows breaks { line_break = true; if (*(text + 1) == L'\n') // Windows line breaks. current_char = *(++text); - } else if (current_char == L'\n') // Unix breaks + } + else if (current_char == L'\n') // Unix breaks { line_break = true; } - if (line_break) { + if (line_break) + { previous_char = 0; offset.Y -= tt_face->size->metrics.ascender / 64; offset.X = start_point.X; if (center) - offset.X += (text_size.Width - getDimensionUntilEndOfLine( - text + 1) - .Width) >> - 1; + offset.X += (text_size.Width - getDimensionUntilEndOfLine(text+1).Width) >> 1; ++text; - } else { + } + else + { n = getGlyphIndexByChar(current_char); - if (n > 0) { - glyph_indices.push_back(n); + if (n > 0) + { + glyph_indices.push_back( n ); // Store glyph size and offset informations. - SGUITTGlyph const &glyph = Glyphs[n - 1]; + SGUITTGlyph const& glyph = Glyphs[n-1]; u32 texw = glyph.source_rect.getWidth(); u32 texh = glyph.source_rect.getHeight(); s32 offx = glyph.offset.X; @@ -1177,37 +1126,25 @@ core::array<scene::ISceneNode *> CGUITTFont::addTextSceneNode(const wchar_t *tex offset.X += k.X; offset.Y += k.Y; - vector3df current_pos( - offset.X + offx, offset.Y - offy, 0); - dimension2d<u32> letter_size = - dimension2d<u32>(texw, texh); + vector3df current_pos(offset.X + offx, offset.Y - offy, 0); + dimension2d<u32> letter_size = dimension2d<u32>(texw, texh); // Now we copy planes corresponding to the letter size. - IMeshManipulator *mani = smgr->getMeshManipulator(); - IMesh *meshcopy = mani->createMeshCopy(shared_plane_ptr_); -#if IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR >= 8 - mani->scale(meshcopy, - vector3df((f32)letter_size.Width, - (f32)letter_size.Height, - 1)); -#else - mani->scaleMesh(meshcopy, - vector3df((f32)letter_size.Width, - (f32)letter_size.Height, - 1)); -#endif - - ISceneNode *current_node = smgr->addMeshSceneNode( - meshcopy, parent, -1, current_pos); + IMeshManipulator* mani = smgr->getMeshManipulator(); + IMesh* meshcopy = mani->createMeshCopy(shared_plane_ptr_); + #if IRRLICHT_VERSION_MAJOR==1 && IRRLICHT_VERSION_MINOR>=8 + mani->scale(meshcopy, vector3df((f32)letter_size.Width, (f32)letter_size.Height, 1)); + #else + mani->scaleMesh(meshcopy, vector3df((f32)letter_size.Width, (f32)letter_size.Height, 1)); + #endif + + ISceneNode* current_node = smgr->addMeshSceneNode(meshcopy, parent, -1, current_pos); meshcopy->drop(); current_node->getMaterial(0) = mat; current_node->setAutomaticCulling(EAC_OFF); - current_node->setIsDebugObject( - true); // so the picking won't have any - // effect on individual letter - // current_node->setDebugDataVisible(EDS_BBOX); - // //de-comment this when debugging + current_node->setIsDebugObject(true); //so the picking won't have any effect on individual letter + //current_node->setDebugDataVisible(EDS_BBOX); //de-comment this when debugging container.push_back(current_node); } @@ -1218,37 +1155,33 @@ core::array<scene::ISceneNode *> CGUITTFont::addTextSceneNode(const wchar_t *tex } update_glyph_pages(); - // only after we update the textures can we use the glyph page textures. + //only after we update the textures can we use the glyph page textures. - for (u32 i = 0; i < glyph_indices.size(); ++i) { + for (u32 i = 0; i < glyph_indices.size(); ++i) + { u32 n = glyph_indices[i]; - SGUITTGlyph const &glyph = Glyphs[n - 1]; - ITexture *current_tex = Glyph_Pages[glyph.glyph_page]->texture; + SGUITTGlyph const& glyph = Glyphs[n-1]; + ITexture* current_tex = Glyph_Pages[glyph.glyph_page]->texture; f32 page_texture_size = (f32)current_tex->getSize().Width; - // Now we calculate the UV position according to the texture size and the - // source rect. + //Now we calculate the UV position according to the texture size and the source rect. // // 2___3 // | /| - // | / | <-- plane mesh is like this, point 2 is (0,0), point 0 is (0, - // -1) - // |/ | <-- the texture coords of point 2 is (0,0, point 0 is (0, - // 1) 0---1 + // | / | <-- plane mesh is like this, point 2 is (0,0), point 0 is (0, -1) + // |/ | <-- the texture coords of point 2 is (0,0, point 0 is (0, 1) + // 0---1 // f32 u1 = glyph.source_rect.UpperLeftCorner.X / page_texture_size; f32 u2 = u1 + (glyph.source_rect.getWidth() / page_texture_size); f32 v1 = glyph.source_rect.UpperLeftCorner.Y / page_texture_size; f32 v2 = v1 + (glyph.source_rect.getHeight() / page_texture_size); - // we can be quite sure that this is IMeshSceneNode, because we just added - // them in the above loop. - IMeshSceneNode *node = static_cast<IMeshSceneNode *>(container[i]); + //we can be quite sure that this is IMeshSceneNode, because we just added them in the above loop. + IMeshSceneNode* node = static_cast<IMeshSceneNode*>(container[i]); - S3DVertex *pv = static_cast<S3DVertex *>( - node->getMesh()->getMeshBuffer(0)->getVertices()); - // pv[0].TCoords.Y = pv[1].TCoords.Y = (letter_size.Height - 1) / - // static_cast<f32>(letter_size.Height); pv[1].TCoords.X = pv[3].TCoords.X - // = (letter_size.Width - 1) / static_cast<f32>(letter_size.Width); + S3DVertex* pv = static_cast<S3DVertex*>(node->getMesh()->getMeshBuffer(0)->getVertices()); + //pv[0].TCoords.Y = pv[1].TCoords.Y = (letter_size.Height - 1) / static_cast<f32>(letter_size.Height); + //pv[1].TCoords.X = pv[3].TCoords.X = (letter_size.Width - 1) / static_cast<f32>(letter_size.Width); pv[0].TCoords = vector2df(u1, v2); pv[1].TCoords = vector2df(u2, v2); pv[2].TCoords = vector2df(u1, v1); diff --git a/src/irrlicht_changes/CGUITTFont.h b/src/irrlicht_changes/CGUITTFont.h index bccc5b2f8..cf64934a2 100644 --- a/src/irrlicht_changes/CGUITTFont.h +++ b/src/irrlicht_changes/CGUITTFont.h @@ -42,393 +42,352 @@ namespace irr { namespace gui { -struct SGUITTFace; -class CGUITTFont; + struct SGUITTFace; + class CGUITTFont; -//! Class to assist in deleting glyphs. -class CGUITTAssistDelete -{ -public: - template <class T, typename TAlloc> static void Delete(core::array<T, TAlloc> &a) + //! Class to assist in deleting glyphs. + class CGUITTAssistDelete { - TAlloc allocator; - allocator.deallocate(a.pointer()); - } -}; + public: + template <class T, typename TAlloc> + static void Delete(core::array<T, TAlloc>& a) + { + TAlloc allocator; + allocator.deallocate(a.pointer()); + } + }; -//! Structure representing a single TrueType glyph. -struct SGUITTGlyph -{ - //! Constructor. - SGUITTGlyph() : isLoaded(false), glyph_page(0), surface(0), parent(0) {} + //! Structure representing a single TrueType glyph. + struct SGUITTGlyph + { + //! Constructor. + SGUITTGlyph() : isLoaded(false), glyph_page(0), surface(0), parent(0) {} - //! Destructor. - ~SGUITTGlyph() { unload(); } + //! Destructor. + ~SGUITTGlyph() { unload(); } - //! Preload the glyph. - //! The preload process occurs when the program tries to cache the glyph from - //!FT_Library. - //! However, it simply defines the SGUITTGlyph's properties and will only create - //! the page textures if necessary. The actual creation of the textures should - //! only occur right before the batch draw call. - void preload(u32 char_index, FT_Face face, video::IVideoDriver *driver, - u32 font_size, const FT_Int32 loadFlags); + //! Preload the glyph. + //! The preload process occurs when the program tries to cache the glyph from FT_Library. + //! However, it simply defines the SGUITTGlyph's properties and will only create the page + //! textures if necessary. The actual creation of the textures should only occur right + //! before the batch draw call. + void preload(u32 char_index, FT_Face face, video::IVideoDriver* driver, u32 font_size, const FT_Int32 loadFlags); - //! Unloads the glyph. - void unload(); + //! Unloads the glyph. + void unload(); - //! Creates the IImage object from the FT_Bitmap. - video::IImage *createGlyphImage( - const FT_Bitmap &bits, video::IVideoDriver *driver) const; + //! Creates the IImage object from the FT_Bitmap. + video::IImage* createGlyphImage(const FT_Bitmap& bits, video::IVideoDriver* driver) const; - //! If true, the glyph has been loaded. - bool isLoaded; + //! If true, the glyph has been loaded. + bool isLoaded; - //! The page the glyph is on. - u32 glyph_page; + //! The page the glyph is on. + u32 glyph_page; - //! The source rectangle for the glyph. - core::recti source_rect; + //! The source rectangle for the glyph. + core::recti source_rect; - //! The offset of glyph when drawn. - core::vector2di offset; + //! The offset of glyph when drawn. + core::vector2di offset; - //! Glyph advance information. - FT_Vector advance; + //! Glyph advance information. + FT_Vector advance; - //! This is just the temporary image holder. After this glyph is paged, - //! it will be dropped. - mutable video::IImage *surface; + //! This is just the temporary image holder. After this glyph is paged, + //! it will be dropped. + mutable video::IImage* surface; - //! The pointer pointing to the parent (CGUITTFont) - CGUITTFont *parent; -}; + //! The pointer pointing to the parent (CGUITTFont) + CGUITTFont* parent; + }; -//! Holds a sheet of glyphs. -class CGUITTGlyphPage -{ -public: - CGUITTGlyphPage(video::IVideoDriver *Driver, const io::path &texture_name) : - texture(0), available_slots(0), used_slots(0), dirty(false), - driver(Driver), name(texture_name) - { - } - ~CGUITTGlyphPage() + //! Holds a sheet of glyphs. + class CGUITTGlyphPage { - if (texture) { - if (driver) - driver->removeTexture(texture); - else - texture->drop(); - } - } - - //! Create the actual page texture, - bool createPageTexture( - const u8 &pixel_mode, const core::dimension2du &texture_size) - { - if (texture) - return false; + public: + CGUITTGlyphPage(video::IVideoDriver* Driver, const io::path& texture_name) :texture(0), available_slots(0), used_slots(0), dirty(false), driver(Driver), name(texture_name) {} + ~CGUITTGlyphPage() + { + if (texture) + { + if (driver) + driver->removeTexture(texture); + else texture->drop(); + } + } - bool flgmip = driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS); - driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false); + //! Create the actual page texture, + bool createPageTexture(const u8& pixel_mode, const core::dimension2du& texture_size) + { + if( texture ) + return false; + + bool flgmip = driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS); + driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false); #if IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR > 8 - bool flgcpy = driver->getTextureCreationFlag( - video::ETCF_ALLOW_MEMORY_COPY); - driver->setTextureCreationFlag(video::ETCF_ALLOW_MEMORY_COPY, true); + bool flgcpy = driver->getTextureCreationFlag(video::ETCF_ALLOW_MEMORY_COPY); + driver->setTextureCreationFlag(video::ETCF_ALLOW_MEMORY_COPY, true); #endif - // Set the texture color format. - switch (pixel_mode) { - case FT_PIXEL_MODE_MONO: - texture = driver->addTexture( - texture_size, name, video::ECF_A1R5G5B5); - break; - case FT_PIXEL_MODE_GRAY: - default: - texture = driver->addTexture( - texture_size, name, video::ECF_A8R8G8B8); - break; - } - - // Restore our texture creation flags. - driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, flgmip); + // Set the texture color format. + switch (pixel_mode) + { + case FT_PIXEL_MODE_MONO: + texture = driver->addTexture(texture_size, name, video::ECF_A1R5G5B5); + break; + case FT_PIXEL_MODE_GRAY: + default: + texture = driver->addTexture(texture_size, name, video::ECF_A8R8G8B8); + break; + } + + // Restore our texture creation flags. + driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, flgmip); #if IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR > 8 - driver->setTextureCreationFlag(video::ETCF_ALLOW_MEMORY_COPY, flgcpy); + driver->setTextureCreationFlag(video::ETCF_ALLOW_MEMORY_COPY, flgcpy); #endif - return texture ? true : false; - } + return texture ? true : false; + } - //! Add the glyph to a list of glyphs to be paged. - //! This collection will be cleared after updateTexture is called. - void pushGlyphToBePaged(const SGUITTGlyph *glyph) - { - glyph_to_be_paged.push_back(glyph); - } + //! Add the glyph to a list of glyphs to be paged. + //! This collection will be cleared after updateTexture is called. + void pushGlyphToBePaged(const SGUITTGlyph* glyph) + { + glyph_to_be_paged.push_back(glyph); + } - //! Updates the texture atlas with new glyphs. - void updateTexture() - { - if (!dirty) - return; - - void *ptr = texture->lock(); - video::ECOLOR_FORMAT format = texture->getColorFormat(); - core::dimension2du size = texture->getOriginalSize(); - video::IImage *pageholder = driver->createImageFromData( - format, size, ptr, true, false); - - for (u32 i = 0; i < glyph_to_be_paged.size(); ++i) { - const SGUITTGlyph *glyph = glyph_to_be_paged[i]; - if (glyph && glyph->isLoaded) { - if (glyph->surface) { - glyph->surface->copyTo(pageholder, - glyph->source_rect - .UpperLeftCorner); - glyph->surface->drop(); - glyph->surface = 0; - } else { - ; // TODO: add error message? - // currently, if we failed to create the image, - // just ignore this operation. + //! Updates the texture atlas with new glyphs. + void updateTexture() + { + if (!dirty) return; + + void* ptr = texture->lock(); + video::ECOLOR_FORMAT format = texture->getColorFormat(); + core::dimension2du size = texture->getOriginalSize(); + video::IImage* pageholder = driver->createImageFromData(format, size, ptr, true, false); + + for (u32 i = 0; i < glyph_to_be_paged.size(); ++i) + { + const SGUITTGlyph* glyph = glyph_to_be_paged[i]; + if (glyph && glyph->isLoaded) + { + if (glyph->surface) + { + glyph->surface->copyTo(pageholder, glyph->source_rect.UpperLeftCorner); + glyph->surface->drop(); + glyph->surface = 0; + } + else + { + ; // TODO: add error message? + //currently, if we failed to create the image, just ignore this operation. + } + } } + + pageholder->drop(); + texture->unlock(); + glyph_to_be_paged.clear(); + dirty = false; } - } - - pageholder->drop(); - texture->unlock(); - glyph_to_be_paged.clear(); - dirty = false; - } - - video::ITexture *texture; - u32 available_slots; - u32 used_slots; - bool dirty; - - core::array<core::vector2di> render_positions; - core::array<core::recti> render_source_rects; - -private: - core::array<const SGUITTGlyph *> glyph_to_be_paged; - video::IVideoDriver *driver; - io::path name; -}; - -//! Class representing a TrueType font. -class CGUITTFont : public IGUIFont -{ -public: - //! Creates a new TrueType font and returns a pointer to it. The pointer must be - //! drop()'ed when finished. \param env The IGUIEnvironment the font loads out of. - //! \param filename The filename of the font. - //! \param size The size of the font glyphs in pixels. Since this is the size of - //! the individual glyphs, the true height of the font may change depending on the - //! characters used. \param antialias set the use_monochrome (opposite to - //! antialias) flag \param transparency set the use_transparency flag \return - //! Returns a pointer to a CGUITTFont. Will return 0 if the font failed to load. - static CGUITTFont *createTTFont(IGUIEnvironment *env, const io::path &filename, - const u32 size, const bool antialias = true, - const bool transparency = true, const u32 shadow = 0, - const u32 shadow_alpha = 255); - static CGUITTFont *createTTFont(IrrlichtDevice *device, const io::path &filename, - const u32 size, const bool antialias = true, - const bool transparency = true); - static CGUITTFont *create(IGUIEnvironment *env, const io::path &filename, - const u32 size, const bool antialias = true, - const bool transparency = true); - static CGUITTFont *create(IrrlichtDevice *device, const io::path &filename, - const u32 size, const bool antialias = true, - const bool transparency = true); - - //! Destructor - virtual ~CGUITTFont(); - - //! Sets the amount of glyphs to batch load. - virtual void setBatchLoadSize(u32 batch_size) { batch_load_size = batch_size; } - - //! Sets the maximum texture size for a page of glyphs. - virtual void setMaxPageTextureSize(const core::dimension2du &texture_size) - { - max_page_texture_size = texture_size; - } - - //! Get the font size. - virtual u32 getFontSize() const { return size; } - - //! Check the font's transparency. - virtual bool isTransparent() const { return use_transparency; } - - //! Check if the font auto-hinting is enabled. - //! Auto-hinting is FreeType's built-in font hinting engine. - virtual bool useAutoHinting() const { return use_auto_hinting; } - - //! Check if the font hinting is enabled. - virtual bool useHinting() const { return use_hinting; } - - //! Check if the font is being loaded as a monochrome font. - //! The font can either be a 256 color grayscale font, or a 2 color monochrome - //! font. - virtual bool useMonochrome() const { return use_monochrome; } - - //! Tells the font to allow transparency when rendering. - //! Default: true. - //! \param flag If true, the font draws using transparency. - virtual void setTransparency(const bool flag); - - //! Tells the font to use monochrome rendering. - //! Default: false. - //! \param flag If true, the font draws using a monochrome image. If false, the - //! font uses a grayscale image. - virtual void setMonochrome(const bool flag); - - //! Enables or disables font hinting. - //! Default: Hinting and auto-hinting true. - //! \param enable If false, font hinting is turned off. If true, font hinting is - //! turned on. \param enable_auto_hinting If true, FreeType uses its own - //! auto-hinting algorithm. If false, it tries to use the algorithm specified by - //! the font. - virtual void setFontHinting( - const bool enable, const bool enable_auto_hinting = true); - - //! Draws some text and clips it to the specified rectangle if wanted. - virtual void draw(const core::stringw &text, const core::rect<s32> &position, - video::SColor color, bool hcenter = false, bool vcenter = false, - const core::rect<s32> *clip = 0); - - virtual void draw(const EnrichedString &text, const core::rect<s32> &position, - video::SColor color, bool hcenter = false, bool vcenter = false, - const core::rect<s32> *clip = 0); - - //! Returns the dimension of a character produced by this font. - virtual core::dimension2d<u32> getCharDimension(const wchar_t ch) const; - - //! Returns the dimension of a text string. - virtual core::dimension2d<u32> getDimension(const wchar_t *text) const; - virtual core::dimension2d<u32> getDimension(const core::ustring &text) const; - - //! Calculates the index of the character in the text which is on a specific - //! position. - virtual s32 getCharacterFromPos(const wchar_t *text, s32 pixel_x) const; - virtual s32 getCharacterFromPos(const core::ustring &text, s32 pixel_x) const; - - //! Sets global kerning width for the font. - virtual void setKerningWidth(s32 kerning); - - //! Sets global kerning height for the font. - virtual void setKerningHeight(s32 kerning); - - //! Gets kerning values (distance between letters) for the font. If no parameters - //! are provided, - virtual s32 getKerningWidth(const wchar_t *thisLetter = 0, - const wchar_t *previousLetter = 0) const; - virtual s32 getKerningWidth(const uchar32_t thisLetter = 0, - const uchar32_t previousLetter = 0) const; - - //! Returns the distance between letters - virtual s32 getKerningHeight() const; - - //! Define which characters should not be drawn by the font. - virtual void setInvisibleCharacters(const wchar_t *s); - virtual void setInvisibleCharacters(const core::ustring &s); - - //! Get the last glyph page if there's still available slots. - //! If not, it will return zero. - CGUITTGlyphPage *getLastGlyphPage() const; - - //! Create a new glyph page texture. - //! \param pixel_mode the pixel mode defined by FT_Pixel_Mode - // should be better typed. fix later. - CGUITTGlyphPage *createGlyphPage(const u8 &pixel_mode); - - //! Get the last glyph page's index. - u32 getLastGlyphPageIndex() const { return Glyph_Pages.size() - 1; } - - //! Create corresponding character's software image copy from the font, - //! so you can use this data just like any ordinary video::IImage. - //! \param ch The character you need - virtual video::IImage *createTextureFromChar(const uchar32_t &ch); - - //! This function is for debugging mostly. If the page doesn't exist it returns - //! zero. \param page_index Simply return the texture handle of a given page - //! index. - virtual video::ITexture *getPageTextureByIndex(const u32 &page_index) const; - - //! Add a list of scene nodes generated by putting font textures on the 3D planes. - virtual core::array<scene::ISceneNode *> addTextSceneNode(const wchar_t *text, - scene::ISceneManager *smgr, scene::ISceneNode *parent = 0, - const video::SColor &color = video::SColor(255, 0, 0, 0), - bool center = false); - - inline s32 getAscender() const { return font_metrics.ascender; } - -protected: - bool use_monochrome; - bool use_transparency; - bool use_hinting; - bool use_auto_hinting; - u32 size; - u32 batch_load_size; - core::dimension2du max_page_texture_size; - -private: - // Manages the FreeType library. - static FT_Library c_library; - static core::map<io::path, SGUITTFace *> c_faces; - static bool c_libraryLoaded; - static scene::IMesh *shared_plane_ptr_; - static scene::SMesh shared_plane_; - - CGUITTFont(IGUIEnvironment *env); - bool load(const io::path &filename, const u32 size, const bool antialias, - const bool transparency); - void reset_images(); - void update_glyph_pages() const; - void update_load_flags() + + video::ITexture* texture; + u32 available_slots; + u32 used_slots; + bool dirty; + + core::array<core::vector2di> render_positions; + core::array<core::recti> render_source_rects; + + private: + core::array<const SGUITTGlyph*> glyph_to_be_paged; + video::IVideoDriver* driver; + io::path name; + }; + + //! Class representing a TrueType font. + class CGUITTFont : public IGUIFont { - // Set up our loading flags. - load_flags = FT_LOAD_DEFAULT | FT_LOAD_RENDER; - if (!useHinting()) - load_flags |= FT_LOAD_NO_HINTING; - if (!useAutoHinting()) - load_flags |= FT_LOAD_NO_AUTOHINT; - if (useMonochrome()) - load_flags |= FT_LOAD_MONOCHROME | FT_LOAD_TARGET_MONO | - FT_RENDER_MODE_MONO; - else - load_flags |= FT_LOAD_TARGET_NORMAL; - } - u32 getWidthFromCharacter(wchar_t c) const; - u32 getWidthFromCharacter(uchar32_t c) const; - u32 getHeightFromCharacter(wchar_t c) const; - u32 getHeightFromCharacter(uchar32_t c) const; - u32 getGlyphIndexByChar(wchar_t c) const; - u32 getGlyphIndexByChar(uchar32_t c) const; - core::vector2di getKerning( - const wchar_t thisLetter, const wchar_t previousLetter) const; - core::vector2di getKerning( - const uchar32_t thisLetter, const uchar32_t previousLetter) const; - core::dimension2d<u32> getDimensionUntilEndOfLine(const wchar_t *p) const; - - void createSharedPlane(); - - irr::IrrlichtDevice *Device; - gui::IGUIEnvironment *Environment; - video::IVideoDriver *Driver; - io::path filename; - FT_Face tt_face; - FT_Size_Metrics font_metrics; - FT_Int32 load_flags; - - mutable core::array<CGUITTGlyphPage *> Glyph_Pages; - mutable core::array<SGUITTGlyph> Glyphs; - - s32 GlobalKerningWidth; - s32 GlobalKerningHeight; - core::ustring Invisible; - u32 shadow_offset; - u32 shadow_alpha; -}; + public: + //! Creates a new TrueType font and returns a pointer to it. The pointer must be drop()'ed when finished. + //! \param env The IGUIEnvironment the font loads out of. + //! \param filename The filename of the font. + //! \param size The size of the font glyphs in pixels. Since this is the size of the individual glyphs, the true height of the font may change depending on the characters used. + //! \param antialias set the use_monochrome (opposite to antialias) flag + //! \param transparency set the use_transparency flag + //! \return Returns a pointer to a CGUITTFont. Will return 0 if the font failed to load. + static CGUITTFont* createTTFont(IGUIEnvironment *env, const io::path& filename, const u32 size, const bool antialias = true, const bool transparency = true, const u32 shadow = 0, const u32 shadow_alpha = 255); + static CGUITTFont* createTTFont(IrrlichtDevice *device, const io::path& filename, const u32 size, const bool antialias = true, const bool transparency = true); + static CGUITTFont* create(IGUIEnvironment *env, const io::path& filename, const u32 size, const bool antialias = true, const bool transparency = true); + static CGUITTFont* create(IrrlichtDevice *device, const io::path& filename, const u32 size, const bool antialias = true, const bool transparency = true); + + //! Destructor + virtual ~CGUITTFont(); + + //! Sets the amount of glyphs to batch load. + virtual void setBatchLoadSize(u32 batch_size) { batch_load_size = batch_size; } + + //! Sets the maximum texture size for a page of glyphs. + virtual void setMaxPageTextureSize(const core::dimension2du& texture_size) { max_page_texture_size = texture_size; } + + //! Get the font size. + virtual u32 getFontSize() const { return size; } + + //! Check the font's transparency. + virtual bool isTransparent() const { return use_transparency; } + + //! Check if the font auto-hinting is enabled. + //! Auto-hinting is FreeType's built-in font hinting engine. + virtual bool useAutoHinting() const { return use_auto_hinting; } + + //! Check if the font hinting is enabled. + virtual bool useHinting() const { return use_hinting; } + + //! Check if the font is being loaded as a monochrome font. + //! The font can either be a 256 color grayscale font, or a 2 color monochrome font. + virtual bool useMonochrome() const { return use_monochrome; } + + //! Tells the font to allow transparency when rendering. + //! Default: true. + //! \param flag If true, the font draws using transparency. + virtual void setTransparency(const bool flag); + + //! Tells the font to use monochrome rendering. + //! Default: false. + //! \param flag If true, the font draws using a monochrome image. If false, the font uses a grayscale image. + virtual void setMonochrome(const bool flag); + + //! Enables or disables font hinting. + //! Default: Hinting and auto-hinting true. + //! \param enable If false, font hinting is turned off. If true, font hinting is turned on. + //! \param enable_auto_hinting If true, FreeType uses its own auto-hinting algorithm. If false, it tries to use the algorithm specified by the font. + virtual void setFontHinting(const bool enable, const bool enable_auto_hinting = true); + + //! Draws some text and clips it to the specified rectangle if wanted. + virtual void draw(const core::stringw& text, const core::rect<s32>& position, + video::SColor color, bool hcenter=false, bool vcenter=false, + const core::rect<s32>* clip=0); + + virtual void draw(const EnrichedString& text, const core::rect<s32>& position, + video::SColor color, bool hcenter=false, bool vcenter=false, + const core::rect<s32>* clip=0); + + //! Returns the dimension of a character produced by this font. + virtual core::dimension2d<u32> getCharDimension(const wchar_t ch) const; + + //! Returns the dimension of a text string. + virtual core::dimension2d<u32> getDimension(const wchar_t* text) const; + virtual core::dimension2d<u32> getDimension(const core::ustring& text) const; + + //! Calculates the index of the character in the text which is on a specific position. + virtual s32 getCharacterFromPos(const wchar_t* text, s32 pixel_x) const; + virtual s32 getCharacterFromPos(const core::ustring& text, s32 pixel_x) const; + + //! Sets global kerning width for the font. + virtual void setKerningWidth(s32 kerning); + + //! Sets global kerning height for the font. + virtual void setKerningHeight(s32 kerning); + + //! Gets kerning values (distance between letters) for the font. If no parameters are provided, + virtual s32 getKerningWidth(const wchar_t* thisLetter=0, const wchar_t* previousLetter=0) const; + virtual s32 getKerningWidth(const uchar32_t thisLetter=0, const uchar32_t previousLetter=0) const; + + //! Returns the distance between letters + virtual s32 getKerningHeight() const; + + //! Define which characters should not be drawn by the font. + virtual void setInvisibleCharacters(const wchar_t *s); + virtual void setInvisibleCharacters(const core::ustring& s); + + //! Get the last glyph page if there's still available slots. + //! If not, it will return zero. + CGUITTGlyphPage* getLastGlyphPage() const; + + //! Create a new glyph page texture. + //! \param pixel_mode the pixel mode defined by FT_Pixel_Mode + //should be better typed. fix later. + CGUITTGlyphPage* createGlyphPage(const u8& pixel_mode); + + //! Get the last glyph page's index. + u32 getLastGlyphPageIndex() const { return Glyph_Pages.size() - 1; } + + //! Create corresponding character's software image copy from the font, + //! so you can use this data just like any ordinary video::IImage. + //! \param ch The character you need + virtual video::IImage* createTextureFromChar(const uchar32_t& ch); + + //! This function is for debugging mostly. If the page doesn't exist it returns zero. + //! \param page_index Simply return the texture handle of a given page index. + virtual video::ITexture* getPageTextureByIndex(const u32& page_index) const; + + //! Add a list of scene nodes generated by putting font textures on the 3D planes. + virtual core::array<scene::ISceneNode*> addTextSceneNode + (const wchar_t* text, scene::ISceneManager* smgr, scene::ISceneNode* parent = 0, + const video::SColor& color = video::SColor(255, 0, 0, 0), bool center = false ); + + inline s32 getAscender() const { return font_metrics.ascender; } + + protected: + bool use_monochrome; + bool use_transparency; + bool use_hinting; + bool use_auto_hinting; + u32 size; + u32 batch_load_size; + core::dimension2du max_page_texture_size; + + private: + // Manages the FreeType library. + static FT_Library c_library; + static core::map<io::path, SGUITTFace*> c_faces; + static bool c_libraryLoaded; + static scene::IMesh* shared_plane_ptr_; + static scene::SMesh shared_plane_; + + CGUITTFont(IGUIEnvironment *env); + bool load(const io::path& filename, const u32 size, const bool antialias, const bool transparency); + void reset_images(); + void update_glyph_pages() const; + void update_load_flags() + { + // Set up our loading flags. + load_flags = FT_LOAD_DEFAULT | FT_LOAD_RENDER; + if (!useHinting()) load_flags |= FT_LOAD_NO_HINTING; + if (!useAutoHinting()) load_flags |= FT_LOAD_NO_AUTOHINT; + if (useMonochrome()) load_flags |= FT_LOAD_MONOCHROME | FT_LOAD_TARGET_MONO | FT_RENDER_MODE_MONO; + else load_flags |= FT_LOAD_TARGET_NORMAL; + } + u32 getWidthFromCharacter(wchar_t c) const; + u32 getWidthFromCharacter(uchar32_t c) const; + u32 getHeightFromCharacter(wchar_t c) const; + u32 getHeightFromCharacter(uchar32_t c) const; + u32 getGlyphIndexByChar(wchar_t c) const; + u32 getGlyphIndexByChar(uchar32_t c) const; + core::vector2di getKerning(const wchar_t thisLetter, const wchar_t previousLetter) const; + core::vector2di getKerning(const uchar32_t thisLetter, const uchar32_t previousLetter) const; + core::dimension2d<u32> getDimensionUntilEndOfLine(const wchar_t* p) const; + + void createSharedPlane(); + + irr::IrrlichtDevice* Device; + gui::IGUIEnvironment* Environment; + video::IVideoDriver* Driver; + io::path filename; + FT_Face tt_face; + FT_Size_Metrics font_metrics; + FT_Int32 load_flags; + + mutable core::array<CGUITTGlyphPage*> Glyph_Pages; + mutable core::array<SGUITTGlyph> Glyphs; + + s32 GlobalKerningWidth; + s32 GlobalKerningHeight; + core::ustring Invisible; + u32 shadow_offset; + u32 shadow_alpha; + }; } // end namespace gui } // end namespace irr diff --git a/src/irrlicht_changes/irrUString.h b/src/irrlicht_changes/irrUString.h index 9ff3d1b4d..b628c092c 100644 --- a/src/irrlicht_changes/irrUString.h +++ b/src/irrlicht_changes/irrUString.h @@ -31,11 +31,10 @@ #pragma once #if (__cplusplus > 199711L) || (_MSC_VER >= 1600) || defined(__GXX_EXPERIMENTAL_CXX0X__) -#define USTRING_CPP0X -#if defined(__GXX_EXPERIMENTAL_CXX0X__) && \ - ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5))) -#define USTRING_CPP0X_NEWLITERALS -#endif +# define USTRING_CPP0X +# if defined(__GXX_EXPERIMENTAL_CXX0X__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5))) +# define USTRING_CPP0X_NEWLITERALS +# endif #endif #include <stdio.h> @@ -56,13 +55,13 @@ #endif #ifdef USTRING_CPP0X -#include <utility> +# include <utility> #endif #ifndef USTRING_NO_STL -#include <string> -#include <iterator> -#include <ostream> +# include <string> +# include <iterator> +# include <ostream> #endif #include "irrTypes.h" @@ -77,22 +76,23 @@ static const irr::u16 UTF16_HI_SURROGATE = 0xD800; static const irr::u16 UTF16_LO_SURROGATE = 0xDC00; //! Is a UTF-16 code point a surrogate? -#define UTF16_IS_SURROGATE(c) (((c)&0xF800) == 0xD800) -#define UTF16_IS_SURROGATE_HI(c) (((c)&0xFC00) == 0xD800) -#define UTF16_IS_SURROGATE_LO(c) (((c)&0xFC00) == 0xDC00) +#define UTF16_IS_SURROGATE(c) (((c) & 0xF800) == 0xD800) +#define UTF16_IS_SURROGATE_HI(c) (((c) & 0xFC00) == 0xD800) +#define UTF16_IS_SURROGATE_LO(c) (((c) & 0xFC00) == 0xDC00) + namespace irr { -// Define our character types. -#ifdef USTRING_CPP0X_NEWLITERALS // C++0x -typedef char32_t uchar32_t; -typedef char16_t uchar16_t; -typedef char uchar8_t; + // Define our character types. +#ifdef USTRING_CPP0X_NEWLITERALS // C++0x + typedef char32_t uchar32_t; + typedef char16_t uchar16_t; + typedef char uchar8_t; #else -typedef u32 uchar32_t; -typedef u16 uchar16_t; -typedef u8 uchar8_t; + typedef u32 uchar32_t; + typedef u16 uchar16_t; + typedef u8 uchar8_t; #endif namespace core @@ -111,24 +111,26 @@ const irr::u16 UTF_REPLACEMENT_CHARACTER = 0xFFFD; inline uchar32_t toUTF32(uchar16_t high, uchar16_t low) { // Convert the surrogate pair into a single UTF-32 character. - uchar32_t x = ((high & ((1 << 6) - 1)) << 10) | (low & ((1 << 10) - 1)); + uchar32_t x = ((high & ((1 << 6) -1)) << 10) | (low & ((1 << 10) -1)); uchar32_t wu = ((high >> 6) & ((1 << 5) - 1)) + 1; return (wu << 16) | x; } //! Swaps the endianness of a 16-bit value. //! \return The new value. -inline uchar16_t swapEndian16(const uchar16_t &c) +inline uchar16_t swapEndian16(const uchar16_t& c) { return ((c >> 8) & 0x00FF) | ((c << 8) & 0xFF00); } //! Swaps the endianness of a 32-bit value. //! \return The new value. -inline uchar32_t swapEndian32(const uchar32_t &c) +inline uchar32_t swapEndian32(const uchar32_t& c) { - return ((c >> 24) & 0x000000FF) | ((c >> 8) & 0x0000FF00) | - ((c << 8) & 0x00FF0000) | ((c << 24) & 0xFF000000); + return ((c >> 24) & 0x000000FF) | + ((c >> 8) & 0x0000FF00) | + ((c << 8) & 0x00FF0000) | + ((c << 24) & 0xFF000000); } //! The Unicode byte order mark. @@ -140,11 +142,11 @@ const u8 BOM_UTF16_LEN = 1; const u8 BOM_UTF32_LEN = 1; //! Unicode byte order marks for file operations. -const u8 BOM_ENCODE_UTF8[3] = {0xEF, 0xBB, 0xBF}; -const u8 BOM_ENCODE_UTF16_BE[2] = {0xFE, 0xFF}; -const u8 BOM_ENCODE_UTF16_LE[2] = {0xFF, 0xFE}; -const u8 BOM_ENCODE_UTF32_BE[4] = {0x00, 0x00, 0xFE, 0xFF}; -const u8 BOM_ENCODE_UTF32_LE[4] = {0xFF, 0xFE, 0x00, 0x00}; +const u8 BOM_ENCODE_UTF8[3] = { 0xEF, 0xBB, 0xBF }; +const u8 BOM_ENCODE_UTF16_BE[2] = { 0xFE, 0xFF }; +const u8 BOM_ENCODE_UTF16_LE[2] = { 0xFF, 0xFE }; +const u8 BOM_ENCODE_UTF32_BE[4] = { 0x00, 0x00, 0xFE, 0xFF }; +const u8 BOM_ENCODE_UTF32_LE[4] = { 0xFF, 0xFE, 0x00, 0x00 }; //! The size in bytes of the Unicode byte marks for file operations. const u8 BOM_ENCODE_UTF8_LEN = 3; @@ -154,7 +156,7 @@ const u8 BOM_ENCODE_UTF32_LEN = 4; //! Unicode encoding type. enum EUTF_ENCODE { - EUTFE_NONE = 0, + EUTFE_NONE = 0, EUTFE_UTF8, EUTFE_UTF16, EUTFE_UTF16_LE, @@ -167,7 +169,7 @@ enum EUTF_ENCODE //! Unicode endianness. enum EUTF_ENDIAN { - EUTFEE_NATIVE = 0, + EUTFEE_NATIVE = 0, EUTFEE_LITTLE, EUTFEE_BIG }; @@ -175,50 +177,50 @@ enum EUTF_ENDIAN //! Returns the specified unicode byte order mark in a byte array. //! The byte order mark is the first few bytes in a text file that signifies its encoding. /** \param mode The Unicode encoding method that we want to get the byte order mark for. - If EUTFE_UTF16 or EUTFE_UTF32 is passed, it uses the native system - endianness. **/ + If EUTFE_UTF16 or EUTFE_UTF32 is passed, it uses the native system endianness. **/ //! \return An array that contains a byte order mark. inline core::array<u8> getUnicodeBOM(EUTF_ENCODE mode) { -#define COPY_ARRAY(source, size) \ - memcpy(ret.pointer(), source, size); \ +#define COPY_ARRAY(source, size) \ + memcpy(ret.pointer(), source, size); \ ret.set_used(size) core::array<u8> ret(4); - switch (mode) { - case EUTFE_UTF8: - COPY_ARRAY(BOM_ENCODE_UTF8, BOM_ENCODE_UTF8_LEN); - break; - case EUTFE_UTF16: -#ifdef __BIG_ENDIAN__ - COPY_ARRAY(BOM_ENCODE_UTF16_BE, BOM_ENCODE_UTF16_LEN); -#else - COPY_ARRAY(BOM_ENCODE_UTF16_LE, BOM_ENCODE_UTF16_LEN); -#endif - break; - case EUTFE_UTF16_BE: - COPY_ARRAY(BOM_ENCODE_UTF16_BE, BOM_ENCODE_UTF16_LEN); - break; - case EUTFE_UTF16_LE: - COPY_ARRAY(BOM_ENCODE_UTF16_LE, BOM_ENCODE_UTF16_LEN); - break; - case EUTFE_UTF32: -#ifdef __BIG_ENDIAN__ - COPY_ARRAY(BOM_ENCODE_UTF32_BE, BOM_ENCODE_UTF32_LEN); -#else - COPY_ARRAY(BOM_ENCODE_UTF32_LE, BOM_ENCODE_UTF32_LEN); -#endif - break; - case EUTFE_UTF32_BE: - COPY_ARRAY(BOM_ENCODE_UTF32_BE, BOM_ENCODE_UTF32_LEN); - break; - case EUTFE_UTF32_LE: - COPY_ARRAY(BOM_ENCODE_UTF32_LE, BOM_ENCODE_UTF32_LEN); - break; - case EUTFE_NONE: - // TODO sapier: fixed warning only, - // don't know if something needs to be done here - break; + switch (mode) + { + case EUTFE_UTF8: + COPY_ARRAY(BOM_ENCODE_UTF8, BOM_ENCODE_UTF8_LEN); + break; + case EUTFE_UTF16: + #ifdef __BIG_ENDIAN__ + COPY_ARRAY(BOM_ENCODE_UTF16_BE, BOM_ENCODE_UTF16_LEN); + #else + COPY_ARRAY(BOM_ENCODE_UTF16_LE, BOM_ENCODE_UTF16_LEN); + #endif + break; + case EUTFE_UTF16_BE: + COPY_ARRAY(BOM_ENCODE_UTF16_BE, BOM_ENCODE_UTF16_LEN); + break; + case EUTFE_UTF16_LE: + COPY_ARRAY(BOM_ENCODE_UTF16_LE, BOM_ENCODE_UTF16_LEN); + break; + case EUTFE_UTF32: + #ifdef __BIG_ENDIAN__ + COPY_ARRAY(BOM_ENCODE_UTF32_BE, BOM_ENCODE_UTF32_LEN); + #else + COPY_ARRAY(BOM_ENCODE_UTF32_LE, BOM_ENCODE_UTF32_LEN); + #endif + break; + case EUTFE_UTF32_BE: + COPY_ARRAY(BOM_ENCODE_UTF32_BE, BOM_ENCODE_UTF32_LEN); + break; + case EUTFE_UTF32_LE: + COPY_ARRAY(BOM_ENCODE_UTF32_LE, BOM_ENCODE_UTF32_LEN); + break; + case EUTFE_NONE: + // TODO sapier: fixed warning only, + // don't know if something needs to be done here + break; } return ret; @@ -227,29 +229,26 @@ inline core::array<u8> getUnicodeBOM(EUTF_ENCODE mode) //! Detects if the given data stream starts with a unicode BOM. //! \param data The data stream to check. -//! \return The unicode BOM associated with the data stream, or EUTFE_NONE if none was -//! found. -inline EUTF_ENCODE determineUnicodeBOM(const char *data) -{ - if (memcmp(data, BOM_ENCODE_UTF8, 3) == 0) - return EUTFE_UTF8; - if (memcmp(data, BOM_ENCODE_UTF16_BE, 2) == 0) - return EUTFE_UTF16_BE; - if (memcmp(data, BOM_ENCODE_UTF16_LE, 2) == 0) - return EUTFE_UTF16_LE; - if (memcmp(data, BOM_ENCODE_UTF32_BE, 4) == 0) - return EUTFE_UTF32_BE; - if (memcmp(data, BOM_ENCODE_UTF32_LE, 4) == 0) - return EUTFE_UTF32_LE; +//! \return The unicode BOM associated with the data stream, or EUTFE_NONE if none was found. +inline EUTF_ENCODE determineUnicodeBOM(const char* data) +{ + if (memcmp(data, BOM_ENCODE_UTF8, 3) == 0) return EUTFE_UTF8; + if (memcmp(data, BOM_ENCODE_UTF16_BE, 2) == 0) return EUTFE_UTF16_BE; + if (memcmp(data, BOM_ENCODE_UTF16_LE, 2) == 0) return EUTFE_UTF16_LE; + if (memcmp(data, BOM_ENCODE_UTF32_BE, 4) == 0) return EUTFE_UTF32_BE; + if (memcmp(data, BOM_ENCODE_UTF32_LE, 4) == 0) return EUTFE_UTF32_LE; return EUTFE_NONE; } } // end namespace unicode + //! UTF-16 string class. -template <typename TAlloc = irrAllocator<uchar16_t>> class ustring16 +template <typename TAlloc = irrAllocator<uchar16_t> > +class ustring16 { public: + ///------------------/// /// iterator classes /// ///------------------/// @@ -257,533 +256,555 @@ public: //! Access an element in a unicode string, allowing one to change it. class _ustring16_iterator_access { - public: - _ustring16_iterator_access(const ustring16<TAlloc> *s, u32 p) : - ref(s), pos(p) - { - } + public: + _ustring16_iterator_access(const ustring16<TAlloc>* s, u32 p) : ref(s), pos(p) {} - //! Allow the class to be interpreted as a single UTF-32 character. - operator uchar32_t() const { return _get(); } + //! Allow the class to be interpreted as a single UTF-32 character. + operator uchar32_t() const + { + return _get(); + } - //! Allow one to change the character in the unicode string. - //! \param c The new character to use. - //! \return Myself. - _ustring16_iterator_access &operator=(const uchar32_t c) - { - _set(c); - return *this; - } + //! Allow one to change the character in the unicode string. + //! \param c The new character to use. + //! \return Myself. + _ustring16_iterator_access& operator=(const uchar32_t c) + { + _set(c); + return *this; + } - //! Increments the value by 1. - //! \return Myself. - _ustring16_iterator_access &operator++() - { - _set(_get() + 1); - return *this; - } + //! Increments the value by 1. + //! \return Myself. + _ustring16_iterator_access& operator++() + { + _set(_get() + 1); + return *this; + } - //! Increments the value by 1, returning the old value. - //! \return A unicode character. - uchar32_t operator++(int) - { - uchar32_t old = _get(); - _set(old + 1); - return old; - } + //! Increments the value by 1, returning the old value. + //! \return A unicode character. + uchar32_t operator++(int) + { + uchar32_t old = _get(); + _set(old + 1); + return old; + } - //! Decrements the value by 1. - //! \return Myself. - _ustring16_iterator_access &operator--() - { - _set(_get() - 1); - return *this; - } + //! Decrements the value by 1. + //! \return Myself. + _ustring16_iterator_access& operator--() + { + _set(_get() - 1); + return *this; + } - //! Decrements the value by 1, returning the old value. - //! \return A unicode character. - uchar32_t operator--(int) - { - uchar32_t old = _get(); - _set(old - 1); - return old; - } + //! Decrements the value by 1, returning the old value. + //! \return A unicode character. + uchar32_t operator--(int) + { + uchar32_t old = _get(); + _set(old - 1); + return old; + } - //! Adds to the value by a specified amount. - //! \param val The amount to add to this character. - //! \return Myself. - _ustring16_iterator_access &operator+=(int val) - { - _set(_get() + val); - return *this; - } + //! Adds to the value by a specified amount. + //! \param val The amount to add to this character. + //! \return Myself. + _ustring16_iterator_access& operator+=(int val) + { + _set(_get() + val); + return *this; + } - //! Subtracts from the value by a specified amount. - //! \param val The amount to subtract from this character. - //! \return Myself. - _ustring16_iterator_access &operator-=(int val) - { - _set(_get() - val); - return *this; - } + //! Subtracts from the value by a specified amount. + //! \param val The amount to subtract from this character. + //! \return Myself. + _ustring16_iterator_access& operator-=(int val) + { + _set(_get() - val); + return *this; + } - //! Multiples the value by a specified amount. - //! \param val The amount to multiply this character by. - //! \return Myself. - _ustring16_iterator_access &operator*=(int val) - { - _set(_get() * val); - return *this; - } + //! Multiples the value by a specified amount. + //! \param val The amount to multiply this character by. + //! \return Myself. + _ustring16_iterator_access& operator*=(int val) + { + _set(_get() * val); + return *this; + } - //! Divides the value by a specified amount. - //! \param val The amount to divide this character by. - //! \return Myself. - _ustring16_iterator_access &operator/=(int val) - { - _set(_get() / val); - return *this; - } + //! Divides the value by a specified amount. + //! \param val The amount to divide this character by. + //! \return Myself. + _ustring16_iterator_access& operator/=(int val) + { + _set(_get() / val); + return *this; + } - //! Modulos the value by a specified amount. - //! \param val The amount to modulo this character by. - //! \return Myself. - _ustring16_iterator_access &operator%=(int val) - { - _set(_get() % val); - return *this; - } + //! Modulos the value by a specified amount. + //! \param val The amount to modulo this character by. + //! \return Myself. + _ustring16_iterator_access& operator%=(int val) + { + _set(_get() % val); + return *this; + } - //! Adds to the value by a specified amount. - //! \param val The amount to add to this character. - //! \return A unicode character. - uchar32_t operator+(int val) const { return _get() + val; } + //! Adds to the value by a specified amount. + //! \param val The amount to add to this character. + //! \return A unicode character. + uchar32_t operator+(int val) const + { + return _get() + val; + } - //! Subtracts from the value by a specified amount. - //! \param val The amount to subtract from this character. - //! \return A unicode character. - uchar32_t operator-(int val) const { return _get() - val; } + //! Subtracts from the value by a specified amount. + //! \param val The amount to subtract from this character. + //! \return A unicode character. + uchar32_t operator-(int val) const + { + return _get() - val; + } - //! Multiplies the value by a specified amount. - //! \param val The amount to multiply this character by. - //! \return A unicode character. - uchar32_t operator*(int val) const { return _get() * val; } + //! Multiplies the value by a specified amount. + //! \param val The amount to multiply this character by. + //! \return A unicode character. + uchar32_t operator*(int val) const + { + return _get() * val; + } - //! Divides the value by a specified amount. - //! \param val The amount to divide this character by. - //! \return A unicode character. - uchar32_t operator/(int val) const { return _get() / val; } + //! Divides the value by a specified amount. + //! \param val The amount to divide this character by. + //! \return A unicode character. + uchar32_t operator/(int val) const + { + return _get() / val; + } - //! Modulos the value by a specified amount. - //! \param val The amount to modulo this character by. - //! \return A unicode character. - uchar32_t operator%(int val) const { return _get() % val; } + //! Modulos the value by a specified amount. + //! \param val The amount to modulo this character by. + //! \return A unicode character. + uchar32_t operator%(int val) const + { + return _get() % val; + } - private: - //! Gets a uchar32_t from our current position. - uchar32_t _get() const - { - const uchar16_t *a = ref->c_str(); - if (!UTF16_IS_SURROGATE(a[pos])) - return static_cast<uchar32_t>(a[pos]); - else { - if (pos + 1 >= ref->size_raw()) - return 0; + private: + //! Gets a uchar32_t from our current position. + uchar32_t _get() const + { + const uchar16_t* a = ref->c_str(); + if (!UTF16_IS_SURROGATE(a[pos])) + return static_cast<uchar32_t>(a[pos]); + else + { + if (pos + 1 >= ref->size_raw()) + return 0; - return unicode::toUTF32(a[pos], a[pos + 1]); + return unicode::toUTF32(a[pos], a[pos + 1]); + } } - } - //! Sets a uchar32_t at our current position. - void _set(uchar32_t c) - { - ustring16<TAlloc> *ref2 = const_cast<ustring16<TAlloc> *>(ref); - const uchar16_t *a = ref2->c_str(); - if (c > 0xFFFF) { - // c will be multibyte, so split it up into the high and - // low surrogate pairs. - uchar16_t x = static_cast<uchar16_t>(c); - uchar16_t vh = UTF16_HI_SURROGATE | - ((((c >> 16) & ((1 << 5) - 1)) - 1) << 6) | - (x >> 10); - uchar16_t vl = UTF16_LO_SURROGATE | (x & ((1 << 10) - 1)); + //! Sets a uchar32_t at our current position. + void _set(uchar32_t c) + { + ustring16<TAlloc>* ref2 = const_cast<ustring16<TAlloc>*>(ref); + const uchar16_t* a = ref2->c_str(); + if (c > 0xFFFF) + { + // c will be multibyte, so split it up into the high and low surrogate pairs. + uchar16_t x = static_cast<uchar16_t>(c); + uchar16_t vh = UTF16_HI_SURROGATE | ((((c >> 16) & ((1 << 5) - 1)) - 1) << 6) | (x >> 10); + uchar16_t vl = UTF16_LO_SURROGATE | (x & ((1 << 10) - 1)); - // If the previous position was a surrogate pair, just - // replace them. Else, insert the low pair. - if (UTF16_IS_SURROGATE_HI(a[pos]) && - pos + 1 != ref2->size_raw()) - ref2->replace_raw(vl, static_cast<u32>(pos) + 1); - else - ref2->insert_raw(vl, static_cast<u32>(pos) + 1); + // If the previous position was a surrogate pair, just replace them. Else, insert the low pair. + if (UTF16_IS_SURROGATE_HI(a[pos]) && pos + 1 != ref2->size_raw()) + ref2->replace_raw(vl, static_cast<u32>(pos) + 1); + else ref2->insert_raw(vl, static_cast<u32>(pos) + 1); - ref2->replace_raw(vh, static_cast<u32>(pos)); - } else { - // c will be a single byte. - uchar16_t vh = static_cast<uchar16_t>(c); + ref2->replace_raw(vh, static_cast<u32>(pos)); + } + else + { + // c will be a single byte. + uchar16_t vh = static_cast<uchar16_t>(c); - // If the previous position was a surrogate pair, remove - // the extra byte. - if (UTF16_IS_SURROGATE_HI(a[pos])) - ref2->erase_raw(static_cast<u32>(pos) + 1); + // If the previous position was a surrogate pair, remove the extra byte. + if (UTF16_IS_SURROGATE_HI(a[pos])) + ref2->erase_raw(static_cast<u32>(pos) + 1); - ref2->replace_raw(vh, static_cast<u32>(pos)); + ref2->replace_raw(vh, static_cast<u32>(pos)); + } } - } - const ustring16<TAlloc> *ref; - u32 pos; + const ustring16<TAlloc>* ref; + u32 pos; }; typedef typename ustring16<TAlloc>::_ustring16_iterator_access access; + //! Iterator to iterate through a UTF-16 string. #ifndef USTRING_NO_STL - class _ustring16_const_iterator - : public std::iterator< - std::bidirectional_iterator_tag, // iterator_category - access, // value_type - ptrdiff_t, // difference_type - const access, // pointer - const access // reference - > + class _ustring16_const_iterator : public std::iterator< + std::bidirectional_iterator_tag, // iterator_category + access, // value_type + ptrdiff_t, // difference_type + const access, // pointer + const access // reference + > #else class _ustring16_const_iterator #endif { - public: - typedef _ustring16_const_iterator _Iter; - typedef std::iterator<std::bidirectional_iterator_tag, access, ptrdiff_t, - const access, const access> - _Base; - typedef const access const_pointer; - typedef const access const_reference; + public: + typedef _ustring16_const_iterator _Iter; + typedef std::iterator<std::bidirectional_iterator_tag, access, ptrdiff_t, const access, const access> _Base; + typedef const access const_pointer; + typedef const access const_reference; #ifndef USTRING_NO_STL - typedef typename _Base::value_type value_type; - typedef typename _Base::difference_type difference_type; - typedef typename _Base::difference_type distance_type; - typedef typename _Base::pointer pointer; - typedef const_reference reference; + typedef typename _Base::value_type value_type; + typedef typename _Base::difference_type difference_type; + typedef typename _Base::difference_type distance_type; + typedef typename _Base::pointer pointer; + typedef const_reference reference; #else - typedef access value_type; - typedef u32 difference_type; - typedef u32 distance_type; - typedef const_pointer pointer; - typedef const_reference reference; + typedef access value_type; + typedef u32 difference_type; + typedef u32 distance_type; + typedef const_pointer pointer; + typedef const_reference reference; #endif - //! Constructors. - _ustring16_const_iterator(const _Iter &i) : ref(i.ref), pos(i.pos) {} - _ustring16_const_iterator(const ustring16<TAlloc> &s) : ref(&s), pos(0) {} - _ustring16_const_iterator(const ustring16<TAlloc> &s, const u32 p) : - ref(&s), pos(0) - { - if (ref->size_raw() == 0 || p == 0) - return; - - // Go to the appropriate position. - u32 i = p; - u32 sr = ref->size_raw(); - const uchar16_t *a = ref->c_str(); - while (i != 0 && pos < sr) { - if (UTF16_IS_SURROGATE_HI(a[pos])) - pos += 2; - else - ++pos; - --i; + //! Constructors. + _ustring16_const_iterator(const _Iter& i) : ref(i.ref), pos(i.pos) {} + _ustring16_const_iterator(const ustring16<TAlloc>& s) : ref(&s), pos(0) {} + _ustring16_const_iterator(const ustring16<TAlloc>& s, const u32 p) : ref(&s), pos(0) + { + if (ref->size_raw() == 0 || p == 0) + return; + + // Go to the appropriate position. + u32 i = p; + u32 sr = ref->size_raw(); + const uchar16_t* a = ref->c_str(); + while (i != 0 && pos < sr) + { + if (UTF16_IS_SURROGATE_HI(a[pos])) + pos += 2; + else ++pos; + --i; + } } - } - //! Test for equalness. - bool operator==(const _Iter &iter) const - { - if (ref == iter.ref && pos == iter.pos) - return true; - return false; - } + //! Test for equalness. + bool operator==(const _Iter& iter) const + { + if (ref == iter.ref && pos == iter.pos) + return true; + return false; + } - //! Test for unequalness. - bool operator!=(const _Iter &iter) const - { - if (ref != iter.ref || pos != iter.pos) - return true; - return false; - } + //! Test for unequalness. + bool operator!=(const _Iter& iter) const + { + if (ref != iter.ref || pos != iter.pos) + return true; + return false; + } - //! Switch to the next full character in the string. - _Iter &operator++() - { // ++iterator - if (pos == ref->size_raw()) + //! Switch to the next full character in the string. + _Iter& operator++() + { // ++iterator + if (pos == ref->size_raw()) return *this; + const uchar16_t* a = ref->c_str(); + if (UTF16_IS_SURROGATE_HI(a[pos])) + pos += 2; // TODO: check for valid low surrogate? + else ++pos; + if (pos > ref->size_raw()) pos = ref->size_raw(); return *this; - const uchar16_t *a = ref->c_str(); - if (UTF16_IS_SURROGATE_HI(a[pos])) - pos += 2; // TODO: check for valid low surrogate? - else - ++pos; - if (pos > ref->size_raw()) - pos = ref->size_raw(); - return *this; - } + } - //! Switch to the next full character in the string, returning the - //! previous position. - _Iter operator++(int) - { // iterator++ - _Iter _tmp(*this); - ++*this; - return _tmp; - } + //! Switch to the next full character in the string, returning the previous position. + _Iter operator++(int) + { // iterator++ + _Iter _tmp(*this); + ++*this; + return _tmp; + } - //! Switch to the previous full character in the string. - _Iter &operator--() - { // --iterator - if (pos == 0) - return *this; - const uchar16_t *a = ref->c_str(); - --pos; - if (UTF16_IS_SURROGATE_LO(a[pos]) && - pos != 0) // low surrogate, go back one more. + //! Switch to the previous full character in the string. + _Iter& operator--() + { // --iterator + if (pos == 0) return *this; + const uchar16_t* a = ref->c_str(); --pos; - return *this; - } - - //! Switch to the previous full character in the string, returning the - //! previous position. - _Iter operator--(int) - { // iterator-- - _Iter _tmp(*this); - --*this; - return _tmp; - } - - //! Advance a specified number of full characters in the string. - //! \return Myself. - _Iter &operator+=(const difference_type v) - { - if (v == 0) - return *this; - if (v < 0) - return operator-=(v * -1); - - if (pos >= ref->size_raw()) + if (UTF16_IS_SURROGATE_LO(a[pos]) && pos != 0) // low surrogate, go back one more. + --pos; return *this; - - // Go to the appropriate position. - // TODO: Don't force u32 on an x64 OS. Make it agnostic. - u32 i = (u32)v; - u32 sr = ref->size_raw(); - const uchar16_t *a = ref->c_str(); - while (i != 0 && pos < sr) { - if (UTF16_IS_SURROGATE_HI(a[pos])) - pos += 2; - else - ++pos; - --i; } - if (pos > sr) - pos = sr; - return *this; - } + //! Switch to the previous full character in the string, returning the previous position. + _Iter operator--(int) + { // iterator-- + _Iter _tmp(*this); + --*this; + return _tmp; + } - //! Go back a specified number of full characters in the string. - //! \return Myself. - _Iter &operator-=(const difference_type v) - { - if (v == 0) - return *this; - if (v > 0) - return operator+=(v * -1); + //! Advance a specified number of full characters in the string. + //! \return Myself. + _Iter& operator+=(const difference_type v) + { + if (v == 0) return *this; + if (v < 0) return operator-=(v * -1); + + if (pos >= ref->size_raw()) + return *this; + + // Go to the appropriate position. + // TODO: Don't force u32 on an x64 OS. Make it agnostic. + u32 i = (u32)v; + u32 sr = ref->size_raw(); + const uchar16_t* a = ref->c_str(); + while (i != 0 && pos < sr) + { + if (UTF16_IS_SURROGATE_HI(a[pos])) + pos += 2; + else ++pos; + --i; + } + if (pos > sr) + pos = sr; - if (pos == 0) return *this; + } - // Go to the appropriate position. - // TODO: Don't force u32 on an x64 OS. Make it agnostic. - u32 i = (u32)v; - const uchar16_t *a = ref->c_str(); - while (i != 0 && pos != 0) { - --pos; - if (UTF16_IS_SURROGATE_LO(a[pos]) != 0 && pos != 0) + //! Go back a specified number of full characters in the string. + //! \return Myself. + _Iter& operator-=(const difference_type v) + { + if (v == 0) return *this; + if (v > 0) return operator+=(v * -1); + + if (pos == 0) + return *this; + + // Go to the appropriate position. + // TODO: Don't force u32 on an x64 OS. Make it agnostic. + u32 i = (u32)v; + const uchar16_t* a = ref->c_str(); + while (i != 0 && pos != 0) + { --pos; - --i; + if (UTF16_IS_SURROGATE_LO(a[pos]) != 0 && pos != 0) + --pos; + --i; + } + + return *this; } - return *this; - } + //! Return a new iterator that is a variable number of full characters forward from the current position. + _Iter operator+(const difference_type v) const + { + _Iter ret(*this); + ret += v; + return ret; + } - //! Return a new iterator that is a variable number of full characters - //! forward from the current position. - _Iter operator+(const difference_type v) const - { - _Iter ret(*this); - ret += v; - return ret; - } + //! Return a new iterator that is a variable number of full characters backward from the current position. + _Iter operator-(const difference_type v) const + { + _Iter ret(*this); + ret -= v; + return ret; + } - //! Return a new iterator that is a variable number of full characters - //! backward from the current position. - _Iter operator-(const difference_type v) const - { - _Iter ret(*this); - ret -= v; - return ret; - } + //! Returns the distance between two iterators. + difference_type operator-(const _Iter& iter) const + { + // Make sure we reference the same object! + if (ref != iter.ref) + return difference_type(); - //! Returns the distance between two iterators. - difference_type operator-(const _Iter &iter) const - { - // Make sure we reference the same object! - if (ref != iter.ref) - return difference_type(); + _Iter i = iter; + difference_type ret; - _Iter i = iter; - difference_type ret; + // Walk up. + if (pos > i.pos) + { + while (pos > i.pos) + { + ++i; + ++ret; + } + return ret; + } - // Walk up. - if (pos > i.pos) { - while (pos > i.pos) { - ++i; - ++ret; + // Walk down. + while (pos < i.pos) + { + --i; + --ret; } return ret; } - // Walk down. - while (pos < i.pos) { - --i; - --ret; - } - return ret; - } - - //! Accesses the full character at the iterator's position. - const_reference operator*() const - { - if (pos >= ref->size_raw()) { - const uchar16_t *a = ref->c_str(); - u32 p = ref->size_raw(); - if (UTF16_IS_SURROGATE_LO(a[p])) - --p; - reference ret(ref, p); + //! Accesses the full character at the iterator's position. + const_reference operator*() const + { + if (pos >= ref->size_raw()) + { + const uchar16_t* a = ref->c_str(); + u32 p = ref->size_raw(); + if (UTF16_IS_SURROGATE_LO(a[p])) + --p; + reference ret(ref, p); + return ret; + } + const_reference ret(ref, pos); return ret; } - const_reference ret(ref, pos); - return ret; - } - //! Accesses the full character at the iterator's position. - reference operator*() - { - if (pos >= ref->size_raw()) { - const uchar16_t *a = ref->c_str(); - u32 p = ref->size_raw(); - if (UTF16_IS_SURROGATE_LO(a[p])) - --p; - reference ret(ref, p); + //! Accesses the full character at the iterator's position. + reference operator*() + { + if (pos >= ref->size_raw()) + { + const uchar16_t* a = ref->c_str(); + u32 p = ref->size_raw(); + if (UTF16_IS_SURROGATE_LO(a[p])) + --p; + reference ret(ref, p); + return ret; + } + reference ret(ref, pos); return ret; } - reference ret(ref, pos); - return ret; - } - //! Accesses the full character at the iterator's position. - const_pointer operator->() const { return operator*(); } + //! Accesses the full character at the iterator's position. + const_pointer operator->() const + { + return operator*(); + } - //! Accesses the full character at the iterator's position. - pointer operator->() { return operator*(); } + //! Accesses the full character at the iterator's position. + pointer operator->() + { + return operator*(); + } - //! Is the iterator at the start of the string? - bool atStart() const { return pos == 0; } + //! Is the iterator at the start of the string? + bool atStart() const + { + return pos == 0; + } - //! Is the iterator at the end of the string? - bool atEnd() const - { - const uchar16_t *a = ref->c_str(); - if (UTF16_IS_SURROGATE(a[pos])) - return (pos + 1) >= ref->size_raw(); - else - return pos >= ref->size_raw(); - } + //! Is the iterator at the end of the string? + bool atEnd() const + { + const uchar16_t* a = ref->c_str(); + if (UTF16_IS_SURROGATE(a[pos])) + return (pos + 1) >= ref->size_raw(); + else return pos >= ref->size_raw(); + } - //! Moves the iterator to the start of the string. - void toStart() { pos = 0; } + //! Moves the iterator to the start of the string. + void toStart() + { + pos = 0; + } - //! Moves the iterator to the end of the string. - void toEnd() { pos = ref->size_raw(); } + //! Moves the iterator to the end of the string. + void toEnd() + { + pos = ref->size_raw(); + } - //! Returns the iterator's position. - //! \return The iterator's position. - u32 getPos() const { return pos; } + //! Returns the iterator's position. + //! \return The iterator's position. + u32 getPos() const + { + return pos; + } - protected: - const ustring16<TAlloc> *ref; - u32 pos; + protected: + const ustring16<TAlloc>* ref; + u32 pos; }; //! Iterator to iterate through a UTF-16 string. class _ustring16_iterator : public _ustring16_const_iterator { - public: - typedef _ustring16_iterator _Iter; - typedef _ustring16_const_iterator _Base; - typedef typename _Base::const_pointer const_pointer; - typedef typename _Base::const_reference const_reference; + public: + typedef _ustring16_iterator _Iter; + typedef _ustring16_const_iterator _Base; + typedef typename _Base::const_pointer const_pointer; + typedef typename _Base::const_reference const_reference; - typedef typename _Base::value_type value_type; - typedef typename _Base::difference_type difference_type; - typedef typename _Base::distance_type distance_type; - typedef access pointer; - typedef access reference; - using _Base::pos; - using _Base::ref; + typedef typename _Base::value_type value_type; + typedef typename _Base::difference_type difference_type; + typedef typename _Base::distance_type distance_type; + typedef access pointer; + typedef access reference; - //! Constructors. - _ustring16_iterator(const _Iter &i) : _ustring16_const_iterator(i) {} - _ustring16_iterator(const ustring16<TAlloc> &s) : - _ustring16_const_iterator(s) - { - } - _ustring16_iterator(const ustring16<TAlloc> &s, const u32 p) : - _ustring16_const_iterator(s, p) - { - } + using _Base::pos; + using _Base::ref; - //! Accesses the full character at the iterator's position. - reference operator*() const - { - if (pos >= ref->size_raw()) { - const uchar16_t *a = ref->c_str(); - u32 p = ref->size_raw(); - if (UTF16_IS_SURROGATE_LO(a[p])) - --p; - reference ret(ref, p); + //! Constructors. + _ustring16_iterator(const _Iter& i) : _ustring16_const_iterator(i) {} + _ustring16_iterator(const ustring16<TAlloc>& s) : _ustring16_const_iterator(s) {} + _ustring16_iterator(const ustring16<TAlloc>& s, const u32 p) : _ustring16_const_iterator(s, p) {} + + //! Accesses the full character at the iterator's position. + reference operator*() const + { + if (pos >= ref->size_raw()) + { + const uchar16_t* a = ref->c_str(); + u32 p = ref->size_raw(); + if (UTF16_IS_SURROGATE_LO(a[p])) + --p; + reference ret(ref, p); + return ret; + } + reference ret(ref, pos); return ret; } - reference ret(ref, pos); - return ret; - } - //! Accesses the full character at the iterator's position. - reference operator*() - { - if (pos >= ref->size_raw()) { - const uchar16_t *a = ref->c_str(); - u32 p = ref->size_raw(); - if (UTF16_IS_SURROGATE_LO(a[p])) - --p; - reference ret(ref, p); + //! Accesses the full character at the iterator's position. + reference operator*() + { + if (pos >= ref->size_raw()) + { + const uchar16_t* a = ref->c_str(); + u32 p = ref->size_raw(); + if (UTF16_IS_SURROGATE_LO(a[p])) + --p; + reference ret(ref, p); + return ret; + } + reference ret(ref, pos); return ret; } - reference ret(ref, pos); - return ret; - } - //! Accesses the full character at the iterator's position. - pointer operator->() const { return operator*(); } + //! Accesses the full character at the iterator's position. + pointer operator->() const + { + return operator*(); + } - //! Accesses the full character at the iterator's position. - pointer operator->() { return operator*(); } + //! Accesses the full character at the iterator's position. + pointer operator->() + { + return operator*(); + } }; typedef typename ustring16<TAlloc>::_ustring16_iterator iterator; @@ -794,7 +815,8 @@ public: ///----------------------/// //! Default constructor - ustring16() : array(0), allocated(1), used(0) + ustring16() + : array(0), allocated(1), used(0) { #if __BYTE_ORDER == __BIG_ENDIAN encoding = unicode::EUTFE_UTF16_BE; @@ -805,8 +827,10 @@ public: array[0] = 0x0; } + //! Constructor - ustring16(const ustring16<TAlloc> &other) : array(0), allocated(0), used(0) + ustring16(const ustring16<TAlloc>& other) + : array(0), allocated(0), used(0) { #if __BYTE_ORDER == __BIG_ENDIAN encoding = unicode::EUTFE_UTF16_BE; @@ -816,9 +840,11 @@ public: *this = other; } + //! Constructor from other string types template <class B, class A> - ustring16(const string<B, A> &other) : array(0), allocated(0), used(0) + ustring16(const string<B, A>& other) + : array(0), allocated(0), used(0) { #if __BYTE_ORDER == __BIG_ENDIAN encoding = unicode::EUTFE_UTF16_BE; @@ -828,11 +854,12 @@ public: *this = other; } + #ifndef USTRING_NO_STL //! Constructor from std::string template <class B, class A, typename Alloc> - ustring16(const std::basic_string<B, A, Alloc> &other) : - array(0), allocated(0), used(0) + ustring16(const std::basic_string<B, A, Alloc>& other) + : array(0), allocated(0), used(0) { #if __BYTE_ORDER == __BIG_ENDIAN encoding = unicode::EUTFE_UTF16_BE; @@ -842,9 +869,11 @@ public: *this = other.c_str(); } + //! Constructor from iterator. template <typename Itr> - ustring16(Itr first, Itr last) : array(0), allocated(0), used(0) + ustring16(Itr first, Itr last) + : array(0), allocated(0), used(0) { #if __BYTE_ORDER == __BIG_ENDIAN encoding = unicode::EUTFE_UTF16_BE; @@ -859,9 +888,11 @@ public: } #endif + #ifndef USTRING_CPP0X_NEWLITERALS //! Constructor for copying a character string from a pointer. - ustring16(const char *const c) : array(0), allocated(0), used(0) + ustring16(const char* const c) + : array(0), allocated(0), used(0) { #if __BYTE_ORDER == __BIG_ENDIAN encoding = unicode::EUTFE_UTF16_BE; @@ -870,11 +901,13 @@ public: #endif loadDataStream(c, strlen(c)); - // append((uchar8_t*)c); + //append((uchar8_t*)c); } + //! Constructor for copying a character string from a pointer with a given length. - ustring16(const char *const c, u32 length) : array(0), allocated(0), used(0) + ustring16(const char* const c, u32 length) + : array(0), allocated(0), used(0) { #if __BYTE_ORDER == __BIG_ENDIAN encoding = unicode::EUTFE_UTF16_BE; @@ -886,8 +919,10 @@ public: } #endif + //! Constructor for copying a UTF-8 string from a pointer. - ustring16(const uchar8_t *const c) : array(0), allocated(0), used(0) + ustring16(const uchar8_t* const c) + : array(0), allocated(0), used(0) { #if __BYTE_ORDER == __BIG_ENDIAN encoding = unicode::EUTFE_UTF16_BE; @@ -898,8 +933,10 @@ public: append(c); } + //! Constructor for copying a UTF-8 string from a single char. - ustring16(const char c) : array(0), allocated(0), used(0) + ustring16(const char c) + : array(0), allocated(0), used(0) { #if __BYTE_ORDER == __BIG_ENDIAN encoding = unicode::EUTFE_UTF16_BE; @@ -910,8 +947,10 @@ public: append((uchar32_t)c); } + //! Constructor for copying a UTF-8 string from a pointer with a given length. - ustring16(const uchar8_t *const c, u32 length) : array(0), allocated(0), used(0) + ustring16(const uchar8_t* const c, u32 length) + : array(0), allocated(0), used(0) { #if __BYTE_ORDER == __BIG_ENDIAN encoding = unicode::EUTFE_UTF16_BE; @@ -922,8 +961,10 @@ public: append(c, length); } + //! Constructor for copying a UTF-16 string from a pointer. - ustring16(const uchar16_t *const c) : array(0), allocated(0), used(0) + ustring16(const uchar16_t* const c) + : array(0), allocated(0), used(0) { #if __BYTE_ORDER == __BIG_ENDIAN encoding = unicode::EUTFE_UTF16_BE; @@ -934,8 +975,10 @@ public: append(c); } + //! Constructor for copying a UTF-16 string from a pointer with a given length - ustring16(const uchar16_t *const c, u32 length) : array(0), allocated(0), used(0) + ustring16(const uchar16_t* const c, u32 length) + : array(0), allocated(0), used(0) { #if __BYTE_ORDER == __BIG_ENDIAN encoding = unicode::EUTFE_UTF16_BE; @@ -946,8 +989,10 @@ public: append(c, length); } + //! Constructor for copying a UTF-32 string from a pointer. - ustring16(const uchar32_t *const c) : array(0), allocated(0), used(0) + ustring16(const uchar32_t* const c) + : array(0), allocated(0), used(0) { #if __BYTE_ORDER == __BIG_ENDIAN encoding = unicode::EUTFE_UTF16_BE; @@ -958,8 +1003,10 @@ public: append(c); } + //! Constructor for copying a UTF-32 from a pointer with a given length. - ustring16(const uchar32_t *const c, u32 length) : array(0), allocated(0), used(0) + ustring16(const uchar32_t* const c, u32 length) + : array(0), allocated(0), used(0) { #if __BYTE_ORDER == __BIG_ENDIAN encoding = unicode::EUTFE_UTF16_BE; @@ -970,8 +1017,10 @@ public: append(c, length); } + //! Constructor for copying a wchar_t string from a pointer. - ustring16(const wchar_t *const c) : array(0), allocated(0), used(0) + ustring16(const wchar_t* const c) + : array(0), allocated(0), used(0) { #if __BYTE_ORDER == __BIG_ENDIAN encoding = unicode::EUTFE_UTF16_BE; @@ -980,15 +1029,17 @@ public: #endif if (sizeof(wchar_t) == 4) - append(reinterpret_cast<const uchar32_t *const>(c)); + append(reinterpret_cast<const uchar32_t* const>(c)); else if (sizeof(wchar_t) == 2) - append(reinterpret_cast<const uchar16_t *const>(c)); + append(reinterpret_cast<const uchar16_t* const>(c)); else if (sizeof(wchar_t) == 1) - append(reinterpret_cast<const uchar8_t *const>(c)); + append(reinterpret_cast<const uchar8_t* const>(c)); } + //! Constructor for copying a wchar_t string from a pointer with a given length. - ustring16(const wchar_t *const c, u32 length) : array(0), allocated(0), used(0) + ustring16(const wchar_t* const c, u32 length) + : array(0), allocated(0), used(0) { #if __BYTE_ORDER == __BIG_ENDIAN encoding = unicode::EUTFE_UTF16_BE; @@ -997,47 +1048,50 @@ public: #endif if (sizeof(wchar_t) == 4) - append(reinterpret_cast<const uchar32_t *const>(c), length); + append(reinterpret_cast<const uchar32_t* const>(c), length); else if (sizeof(wchar_t) == 2) - append(reinterpret_cast<const uchar16_t *const>(c), length); + append(reinterpret_cast<const uchar16_t* const>(c), length); else if (sizeof(wchar_t) == 1) - append(reinterpret_cast<const uchar8_t *const>(c), length); + append(reinterpret_cast<const uchar8_t* const>(c), length); } + #ifdef USTRING_CPP0X //! Constructor for moving a ustring16 - ustring16(ustring16<TAlloc> &&other) : - array(other.array), encoding(other.encoding), - allocated(other.allocated), used(other.used) + ustring16(ustring16<TAlloc>&& other) + : array(other.array), encoding(other.encoding), allocated(other.allocated), used(other.used) { - // std::cout << "MOVE constructor" << std::endl; + //std::cout << "MOVE constructor" << std::endl; other.array = 0; other.allocated = 0; other.used = 0; } #endif + //! Destructor ~ustring16() { allocator.deallocate(array); // delete [] array; } + //! Assignment operator - ustring16 &operator=(const ustring16<TAlloc> &other) + ustring16& operator=(const ustring16<TAlloc>& other) { if (this == &other) return *this; used = other.size_raw(); - if (used >= allocated) { + if (used >= allocated) + { allocator.deallocate(array); // delete [] array; allocated = used + 1; - array = allocator.allocate(used + 1); // new u16[used]; + array = allocator.allocate(used + 1); //new u16[used]; } - const uchar16_t *p = other.c_str(); - for (u32 i = 0; i <= used; ++i, ++p) + const uchar16_t* p = other.c_str(); + for (u32 i=0; i<=used; ++i, ++p) array[i] = *p; array[used] = 0; @@ -1048,12 +1102,14 @@ public: return *this; } + #ifdef USTRING_CPP0X //! Move assignment operator - ustring16 &operator=(ustring16<TAlloc> &&other) + ustring16& operator=(ustring16<TAlloc>&& other) { - if (this != &other) { - // std::cout << "MOVE operator=" << std::endl; + if (this != &other) + { + //std::cout << "MOVE operator=" << std::endl; allocator.deallocate(array); array = other.array; @@ -1067,188 +1123,215 @@ public: } #endif + //! Assignment operator for other string types template <class B, class A> - ustring16<TAlloc> &operator=(const string<B, A> &other) + ustring16<TAlloc>& operator=(const string<B, A>& other) { *this = other.c_str(); return *this; } + //! Assignment operator for UTF-8 strings - ustring16<TAlloc> &operator=(const uchar8_t *const c) + ustring16<TAlloc>& operator=(const uchar8_t* const c) { - if (!array) { - array = allocator.allocate(1); // new u16[1]; + if (!array) + { + array = allocator.allocate(1); //new u16[1]; allocated = 1; } used = 0; array[used] = 0x0; - if (!c) - return *this; + if (!c) return *this; //! Append our string now. append(c); return *this; } + //! Assignment operator for UTF-16 strings - ustring16<TAlloc> &operator=(const uchar16_t *const c) + ustring16<TAlloc>& operator=(const uchar16_t* const c) { - if (!array) { - array = allocator.allocate(1); // new u16[1]; + if (!array) + { + array = allocator.allocate(1); //new u16[1]; allocated = 1; } used = 0; array[used] = 0x0; - if (!c) - return *this; + if (!c) return *this; //! Append our string now. append(c); return *this; } + //! Assignment operator for UTF-32 strings - ustring16<TAlloc> &operator=(const uchar32_t *const c) + ustring16<TAlloc>& operator=(const uchar32_t* const c) { - if (!array) { - array = allocator.allocate(1); // new u16[1]; + if (!array) + { + array = allocator.allocate(1); //new u16[1]; allocated = 1; } used = 0; array[used] = 0x0; - if (!c) - return *this; + if (!c) return *this; //! Append our string now. append(c); return *this; } + //! Assignment operator for wchar_t strings. - /** Note that this assumes that a correct unicode string is stored in the wchar_t - string. Since wchar_t changes depending on its platform, it could either be a - UTF-8, -16, or -32 string. This function assumes you are storing the correct - unicode encoding inside the wchar_t string. **/ - ustring16<TAlloc> &operator=(const wchar_t *const c) + /** Note that this assumes that a correct unicode string is stored in the wchar_t string. + Since wchar_t changes depending on its platform, it could either be a UTF-8, -16, or -32 string. + This function assumes you are storing the correct unicode encoding inside the wchar_t string. **/ + ustring16<TAlloc>& operator=(const wchar_t* const c) { if (sizeof(wchar_t) == 4) - *this = reinterpret_cast<const uchar32_t *const>(c); + *this = reinterpret_cast<const uchar32_t* const>(c); else if (sizeof(wchar_t) == 2) - *this = reinterpret_cast<const uchar16_t *const>(c); + *this = reinterpret_cast<const uchar16_t* const>(c); else if (sizeof(wchar_t) == 1) - *this = reinterpret_cast<const uchar8_t *const>(c); + *this = reinterpret_cast<const uchar8_t* const>(c); return *this; } + //! Assignment operator for other strings. - /** Note that this assumes that a correct unicode string is stored in the string. - * **/ - template <class B> ustring16<TAlloc> &operator=(const B *const c) + /** Note that this assumes that a correct unicode string is stored in the string. **/ + template <class B> + ustring16<TAlloc>& operator=(const B* const c) { if (sizeof(B) == 4) - *this = reinterpret_cast<const uchar32_t *const>(c); + *this = reinterpret_cast<const uchar32_t* const>(c); else if (sizeof(B) == 2) - *this = reinterpret_cast<const uchar16_t *const>(c); + *this = reinterpret_cast<const uchar16_t* const>(c); else if (sizeof(B) == 1) - *this = reinterpret_cast<const uchar8_t *const>(c); + *this = reinterpret_cast<const uchar8_t* const>(c); return *this; } + //! Direct access operator - access operator[](const u32 index) + access operator [](const u32 index) { - _IRR_DEBUG_BREAK_IF(index >= size()) // bad index + _IRR_DEBUG_BREAK_IF(index>=size()) // bad index iterator iter(*this, index); return iter.operator*(); } + //! Direct access operator - const access operator[](const u32 index) const + const access operator [](const u32 index) const { - _IRR_DEBUG_BREAK_IF(index >= size()) // bad index + _IRR_DEBUG_BREAK_IF(index>=size()) // bad index const_iterator iter(*this, index); return iter.operator*(); } + //! Equality operator - bool operator==(const uchar16_t *const str) const + bool operator ==(const uchar16_t* const str) const { if (!str) return false; u32 i; - for (i = 0; array[i] && str[i]; ++i) + for(i=0; array[i] && str[i]; ++i) if (array[i] != str[i]) return false; return !array[i] && !str[i]; } + //! Equality operator - bool operator==(const ustring16<TAlloc> &other) const + bool operator ==(const ustring16<TAlloc>& other) const { - for (u32 i = 0; array[i] && other.array[i]; ++i) + for(u32 i=0; array[i] && other.array[i]; ++i) if (array[i] != other.array[i]) return false; return used == other.used; } + //! Is smaller comparator - bool operator<(const ustring16<TAlloc> &other) const + bool operator <(const ustring16<TAlloc>& other) const { - for (u32 i = 0; array[i] && other.array[i]; ++i) { + for(u32 i=0; array[i] && other.array[i]; ++i) + { s32 diff = array[i] - other.array[i]; - if (diff) + if ( diff ) return diff < 0; } return used < other.used; } + //! Inequality operator - bool operator!=(const uchar16_t *const str) const { return !(*this == str); } + bool operator !=(const uchar16_t* const str) const + { + return !(*this == str); + } + //! Inequality operator - bool operator!=(const ustring16<TAlloc> &other) const + bool operator !=(const ustring16<TAlloc>& other) const { return !(*this == other); } + //! Returns the length of a ustring16 in full characters. //! \return Length of a ustring16 in full characters. u32 size() const { const_iterator i(*this, 0); u32 pos = 0; - while (!i.atEnd()) { + while (!i.atEnd()) + { ++i; ++pos; } return pos; } + //! Informs if the ustring is empty or not. //! \return True if the ustring is empty, false if not. - bool empty() const { return (size_raw() == 0); } + bool empty() const + { + return (size_raw() == 0); + } + //! Returns a pointer to the raw UTF-16 string data. //! \return pointer to C-style NUL terminated array of UTF-16 code points. - const uchar16_t *c_str() const { return array; } + const uchar16_t* c_str() const + { + return array; + } + //! Compares the first n characters of this string with another. //! \param other Other string to compare to. //! \param n Number of characters to compare. //! \return True if the n first characters of both strings are equal. - bool equalsn(const ustring16<TAlloc> &other, u32 n) const + bool equalsn(const ustring16<TAlloc>& other, u32 n) const { u32 i; - const uchar16_t *oa = other.c_str(); - for (i = 0; array[i] && oa[i] && i < n; ++i) + const uchar16_t* oa = other.c_str(); + for(i=0; array[i] && oa[i] && i < n; ++i) if (array[i] != oa[i]) return false; @@ -1257,16 +1340,17 @@ public: return (i == n) || (used == other.used); } + //! Compares the first n characters of this string with another. //! \param str Other string to compare to. //! \param n Number of characters to compare. //! \return True if the n first characters of both strings are equal. - bool equalsn(const uchar16_t *const str, u32 n) const + bool equalsn(const uchar16_t* const str, u32 n) const { if (!str) return false; u32 i; - for (i = 0; array[i] && str[i] && i < n; ++i) + for(i=0; array[i] && str[i] && i < n; ++i) if (array[i] != str[i]) return false; @@ -1275,62 +1359,66 @@ public: return (i == n) || (array[i] == 0 && str[i] == 0); } + //! Appends a character to this ustring16 //! \param character The character to append. //! \return A reference to our current string. - ustring16<TAlloc> &append(uchar32_t character) + ustring16<TAlloc>& append(uchar32_t character) { if (used + 2 >= allocated) reallocate(used + 2); - if (character > 0xFFFF) { + if (character > 0xFFFF) + { used += 2; - // character will be multibyte, so split it up into a surrogate - // pair. + // character will be multibyte, so split it up into a surrogate pair. uchar16_t x = static_cast<uchar16_t>(character); - uchar16_t vh = UTF16_HI_SURROGATE | - ((((character >> 16) & ((1 << 5) - 1)) - 1) << 6) | - (x >> 10); + uchar16_t vh = UTF16_HI_SURROGATE | ((((character >> 16) & ((1 << 5) - 1)) - 1) << 6) | (x >> 10); uchar16_t vl = UTF16_LO_SURROGATE | (x & ((1 << 10) - 1)); - array[used - 2] = vh; - array[used - 1] = vl; - } else { + array[used-2] = vh; + array[used-1] = vl; + } + else + { ++used; - array[used - 1] = character; + array[used-1] = character; } array[used] = 0; return *this; } + //! Appends a UTF-8 string to this ustring16 //! \param other The UTF-8 string to append. //! \param length The length of the string to append. //! \return A reference to our current string. - ustring16<TAlloc> &append(const uchar8_t *const other, u32 length = 0xffffffff) + ustring16<TAlloc>& append(const uchar8_t* const other, u32 length=0xffffffff) { if (!other) return *this; // Determine if the string is long enough for a BOM. u32 len = 0; - const uchar8_t *p = other; - do { + const uchar8_t* p = other; + do + { ++len; } while (*p++ && len < unicode::BOM_ENCODE_UTF8_LEN); // Check for BOM. unicode::EUTF_ENCODE c_bom = unicode::EUTFE_NONE; - if (len == unicode::BOM_ENCODE_UTF8_LEN) { - if (memcmp(other, unicode::BOM_ENCODE_UTF8, - unicode::BOM_ENCODE_UTF8_LEN) == 0) + if (len == unicode::BOM_ENCODE_UTF8_LEN) + { + if (memcmp(other, unicode::BOM_ENCODE_UTF8, unicode::BOM_ENCODE_UTF8_LEN) == 0) c_bom = unicode::EUTFE_UTF8; } // If a BOM was found, don't include it in the string. - const uchar8_t *c2 = other; - if (c_bom != unicode::EUTFE_NONE) { + const uchar8_t* c2 = other; + if (c_bom != unicode::EUTFE_NONE) + { c2 = other + unicode::BOM_UTF8_LEN; length -= unicode::BOM_UTF8_LEN; } @@ -1338,9 +1426,10 @@ public: // Calculate the size of the string to read in. len = 0; p = c2; - do { + do + { ++len; - } while (*p++ && len < length); + } while(*p++ && len < length); if (len > length) len = length; @@ -1351,19 +1440,24 @@ public: // Convert UTF-8 to UTF-16. u32 pos = start; - for (u32 l = 0; l < len;) { + for (u32 l = 0; l<len;) + { ++used; - if (((c2[l] >> 6) & 0x03) == 0x02) { // Invalid continuation byte. + if (((c2[l] >> 6) & 0x03) == 0x02) + { // Invalid continuation byte. array[pos++] = unicode::UTF_REPLACEMENT_CHARACTER; ++l; - } else if (c2[l] == 0xC0 || c2[l] == 0xC1) { // Invalid byte - - // overlong encoding. + } + else if (c2[l] == 0xC0 || c2[l] == 0xC1) + { // Invalid byte - overlong encoding. array[pos++] = unicode::UTF_REPLACEMENT_CHARACTER; ++l; - } else if ((c2[l] & 0xF8) == - 0xF0) { // 4 bytes UTF-8, 2 bytes UTF-16. + } + else if ((c2[l] & 0xF8) == 0xF0) + { // 4 bytes UTF-8, 2 bytes UTF-16. // Check for a full string. - if ((l + 3) >= len) { + if ((l + 3) >= len) + { array[pos++] = unicode::UTF_REPLACEMENT_CHARACTER; l += 3; break; @@ -1372,50 +1466,37 @@ public: // Validate. bool valid = true; u8 l2 = 0; - if (valid && (((c2[l + 1] >> 6) & 0x03) == 0x02)) - ++l2; - else - valid = false; - if (valid && (((c2[l + 2] >> 6) & 0x03) == 0x02)) - ++l2; - else - valid = false; - if (valid && (((c2[l + 3] >> 6) & 0x03) == 0x02)) - ++l2; - else - valid = false; - if (!valid) { + if (valid && (((c2[l+1] >> 6) & 0x03) == 0x02)) ++l2; else valid = false; + if (valid && (((c2[l+2] >> 6) & 0x03) == 0x02)) ++l2; else valid = false; + if (valid && (((c2[l+3] >> 6) & 0x03) == 0x02)) ++l2; else valid = false; + if (!valid) + { array[pos++] = unicode::UTF_REPLACEMENT_CHARACTER; l += l2; continue; } // Decode. - uchar8_t b1 = ((c2[l] & 0x7) << 2) | - ((c2[l + 1] >> 4) & 0x3); - uchar8_t b2 = ((c2[l + 1] & 0xF) << 4) | - ((c2[l + 2] >> 2) & 0xF); - uchar8_t b3 = ((c2[l + 2] & 0x3) << 6) | - (c2[l + 3] & 0x3F); - uchar32_t v = b3 | ((uchar32_t)b2 << 8) | - ((uchar32_t)b1 << 16); + uchar8_t b1 = ((c2[l] & 0x7) << 2) | ((c2[l+1] >> 4) & 0x3); + uchar8_t b2 = ((c2[l+1] & 0xF) << 4) | ((c2[l+2] >> 2) & 0xF); + uchar8_t b3 = ((c2[l+2] & 0x3) << 6) | (c2[l+3] & 0x3F); + uchar32_t v = b3 | ((uchar32_t)b2 << 8) | ((uchar32_t)b1 << 16); // Split v up into a surrogate pair. uchar16_t x = static_cast<uchar16_t>(v); - uchar16_t vh = UTF16_HI_SURROGATE | - ((((v >> 16) & ((1 << 5) - 1)) - 1) << 6) | - (x >> 10); + uchar16_t vh = UTF16_HI_SURROGATE | ((((v >> 16) & ((1 << 5) - 1)) - 1) << 6) | (x >> 10); uchar16_t vl = UTF16_LO_SURROGATE | (x & ((1 << 10) - 1)); array[pos++] = vh; array[pos++] = vl; l += 4; - ++used; // Using two shorts this time, so increase used - // by 1. - } else if ((c2[l] & 0xF0) == - 0xE0) { // 3 bytes UTF-8, 1 byte UTF-16. + ++used; // Using two shorts this time, so increase used by 1. + } + else if ((c2[l] & 0xF0) == 0xE0) + { // 3 bytes UTF-8, 1 byte UTF-16. // Check for a full string. - if ((l + 2) >= len) { + if ((l + 2) >= len) + { array[pos++] = unicode::UTF_REPLACEMENT_CHARACTER; l += 2; break; @@ -1424,39 +1505,35 @@ public: // Validate. bool valid = true; u8 l2 = 0; - if (valid && (((c2[l + 1] >> 6) & 0x03) == 0x02)) - ++l2; - else - valid = false; - if (valid && (((c2[l + 2] >> 6) & 0x03) == 0x02)) - ++l2; - else - valid = false; - if (!valid) { + if (valid && (((c2[l+1] >> 6) & 0x03) == 0x02)) ++l2; else valid = false; + if (valid && (((c2[l+2] >> 6) & 0x03) == 0x02)) ++l2; else valid = false; + if (!valid) + { array[pos++] = unicode::UTF_REPLACEMENT_CHARACTER; l += l2; continue; } // Decode. - uchar8_t b1 = ((c2[l] & 0xF) << 4) | - ((c2[l + 1] >> 2) & 0xF); - uchar8_t b2 = ((c2[l + 1] & 0x3) << 6) | - (c2[l + 2] & 0x3F); + uchar8_t b1 = ((c2[l] & 0xF) << 4) | ((c2[l+1] >> 2) & 0xF); + uchar8_t b2 = ((c2[l+1] & 0x3) << 6) | (c2[l+2] & 0x3F); uchar16_t ch = b2 | ((uchar16_t)b1 << 8); array[pos++] = ch; l += 3; - } else if ((c2[l] & 0xE0) == - 0xC0) { // 2 bytes UTF-8, 1 byte UTF-16. + } + else if ((c2[l] & 0xE0) == 0xC0) + { // 2 bytes UTF-8, 1 byte UTF-16. // Check for a full string. - if ((l + 1) >= len) { + if ((l + 1) >= len) + { array[pos++] = unicode::UTF_REPLACEMENT_CHARACTER; l += 1; break; } // Validate. - if (((c2[l + 1] >> 6) & 0x03) != 0x02) { + if (((c2[l+1] >> 6) & 0x03) != 0x02) + { array[pos++] = unicode::UTF_REPLACEMENT_CHARACTER; ++l; continue; @@ -1464,18 +1541,19 @@ public: // Decode. uchar8_t b1 = (c2[l] >> 2) & 0x7; - uchar8_t b2 = ((c2[l] & 0x3) << 6) | (c2[l + 1] & 0x3F); + uchar8_t b2 = ((c2[l] & 0x3) << 6) | (c2[l+1] & 0x3F); uchar16_t ch = b2 | ((uchar16_t)b1 << 8); array[pos++] = ch; l += 2; - } else { // 1 byte UTF-8, 1 byte UTF-16. + } + else + { // 1 byte UTF-8, 1 byte UTF-16. // Validate. - if (c2[l] > 0x7F) { // Values above 0xF4 are restricted - // and aren't used. By now, anything - // above 0x7F is invalid. + if (c2[l] > 0x7F) + { // Values above 0xF4 are restricted and aren't used. By now, anything above 0x7F is invalid. array[pos++] = unicode::UTF_REPLACEMENT_CHARACTER; - } else - array[pos++] = static_cast<uchar16_t>(c2[l]); + } + else array[pos++] = static_cast<uchar16_t>(c2[l]); ++l; } } @@ -1487,34 +1565,35 @@ public: return *this; } + //! Appends a UTF-16 string to this ustring16 //! \param other The UTF-16 string to append. //! \param length The length of the string to append. //! \return A reference to our current string. - ustring16<TAlloc> &append(const uchar16_t *const other, u32 length = 0xffffffff) + ustring16<TAlloc>& append(const uchar16_t* const other, u32 length=0xffffffff) { if (!other) return *this; // Determine if the string is long enough for a BOM. u32 len = 0; - const uchar16_t *p = other; - do { + const uchar16_t* p = other; + do + { ++len; } while (*p++ && len < unicode::BOM_ENCODE_UTF16_LEN); // Check for the BOM to determine the string's endianness. unicode::EUTF_ENDIAN c_end = unicode::EUTFEE_NATIVE; - if (memcmp(other, unicode::BOM_ENCODE_UTF16_LE, - unicode::BOM_ENCODE_UTF16_LEN) == 0) + if (memcmp(other, unicode::BOM_ENCODE_UTF16_LE, unicode::BOM_ENCODE_UTF16_LEN) == 0) c_end = unicode::EUTFEE_LITTLE; - else if (memcmp(other, unicode::BOM_ENCODE_UTF16_BE, - unicode::BOM_ENCODE_UTF16_LEN) == 0) + else if (memcmp(other, unicode::BOM_ENCODE_UTF16_BE, unicode::BOM_ENCODE_UTF16_LEN) == 0) c_end = unicode::EUTFEE_BIG; // If a BOM was found, don't include it in the string. - const uchar16_t *c2 = other; - if (c_end != unicode::EUTFEE_NATIVE) { + const uchar16_t* c2 = other; + if (c_end != unicode::EUTFEE_NATIVE) + { c2 = other + unicode::BOM_UTF16_LEN; length -= unicode::BOM_UTF16_LEN; } @@ -1522,9 +1601,10 @@ public: // Calculate the size of the string to read in. len = 0; p = c2; - do { + do + { ++len; - } while (*p++ && len < length); + } while(*p++ && len < length); if (len > length) len = length; @@ -1536,7 +1616,8 @@ public: // Copy the string now. unicode::EUTF_ENDIAN m_end = getEndianness(); - for (u32 l = start; l < start + len; ++l) { + for (u32 l = start; l < start + len; ++l) + { array[l] = (uchar16_t)c2[l]; if (c_end != unicode::EUTFEE_NATIVE && c_end != m_end) array[l] = unicode::swapEndian16(array[l]); @@ -1549,43 +1630,43 @@ public: return *this; } + //! Appends a UTF-32 string to this ustring16 //! \param other The UTF-32 string to append. //! \param length The length of the string to append. //! \return A reference to our current string. - ustring16<TAlloc> &append(const uchar32_t *const other, u32 length = 0xffffffff) + ustring16<TAlloc>& append(const uchar32_t* const other, u32 length=0xffffffff) { if (!other) return *this; // Check for the BOM to determine the string's endianness. unicode::EUTF_ENDIAN c_end = unicode::EUTFEE_NATIVE; - if (memcmp(other, unicode::BOM_ENCODE_UTF32_LE, - unicode::BOM_ENCODE_UTF32_LEN) == 0) + if (memcmp(other, unicode::BOM_ENCODE_UTF32_LE, unicode::BOM_ENCODE_UTF32_LEN) == 0) c_end = unicode::EUTFEE_LITTLE; - else if (memcmp(other, unicode::BOM_ENCODE_UTF32_BE, - unicode::BOM_ENCODE_UTF32_LEN) == 0) + else if (memcmp(other, unicode::BOM_ENCODE_UTF32_BE, unicode::BOM_ENCODE_UTF32_LEN) == 0) c_end = unicode::EUTFEE_BIG; // If a BOM was found, don't include it in the string. - const uchar32_t *c2 = other; - if (c_end != unicode::EUTFEE_NATIVE) { + const uchar32_t* c2 = other; + if (c_end != unicode::EUTFEE_NATIVE) + { c2 = other + unicode::BOM_UTF32_LEN; length -= unicode::BOM_UTF32_LEN; } // Calculate the size of the string to read in. u32 len = 0; - const uchar32_t *p = c2; - do { + const uchar32_t* p = c2; + do + { ++len; - } while (*p++ && len < length); + } while(*p++ && len < length); if (len > length) len = length; // If we need to grow the size of the array, do it now. - // In case all of the UTF-32 string is split into surrogate pairs, do len - // * 2. + // In case all of the UTF-32 string is split into surrogate pairs, do len * 2. if (used + (len * 2) >= allocated) reallocate(used + ((len * 2) * 2)); u32 start = used; @@ -1593,30 +1674,30 @@ public: // Convert UTF-32 to UTF-16. unicode::EUTF_ENDIAN m_end = getEndianness(); u32 pos = start; - for (u32 l = 0; l < len; ++l) { + for (u32 l = 0; l<len; ++l) + { ++used; uchar32_t ch = c2[l]; if (c_end != unicode::EUTFEE_NATIVE && c_end != m_end) ch = unicode::swapEndian32(ch); - if (ch > 0xFFFF) { - // Split ch up into a surrogate pair as it is over 16 bits - // long. + if (ch > 0xFFFF) + { + // Split ch up into a surrogate pair as it is over 16 bits long. uchar16_t x = static_cast<uchar16_t>(ch); - uchar16_t vh = UTF16_HI_SURROGATE | - ((((ch >> 16) & ((1 << 5) - 1)) - 1) - << 6) | - (x >> 10); + uchar16_t vh = UTF16_HI_SURROGATE | ((((ch >> 16) & ((1 << 5) - 1)) - 1) << 6) | (x >> 10); uchar16_t vl = UTF16_LO_SURROGATE | (x & ((1 << 10) - 1)); array[pos++] = vh; array[pos++] = vl; - ++used; // Using two shorts, so increased used again. - } else if (ch >= 0xD800 && ch <= 0xDFFF) { + ++used; // Using two shorts, so increased used again. + } + else if (ch >= 0xD800 && ch <= 0xDFFF) + { // Between possible UTF-16 surrogates (invalid!) array[pos++] = unicode::UTF_REPLACEMENT_CHARACTER; - } else - array[pos++] = static_cast<uchar16_t>(ch); + } + else array[pos++] = static_cast<uchar16_t>(ch); } array[used] = 0; @@ -1626,20 +1707,21 @@ public: return *this; } + //! Appends a ustring16 to this ustring16 //! \param other The string to append to this one. //! \return A reference to our current string. - ustring16<TAlloc> &append(const ustring16<TAlloc> &other) + ustring16<TAlloc>& append(const ustring16<TAlloc>& other) { - const uchar16_t *oa = other.c_str(); + const uchar16_t* oa = other.c_str(); u32 len = other.size_raw(); if (used + len >= allocated) reallocate(used + len); - for (u32 l = 0; l < len; ++l) - array[used + l] = oa[l]; + for (u32 l=0; l<len; ++l) + array[used+l] = oa[l]; used += len; array[used] = 0; @@ -1647,16 +1729,18 @@ public: return *this; } + //! Appends a certain amount of characters of a ustring16 to this ustring16. //! \param other The string to append to this one. //! \param length How many characters of the other string to add to this one. //! \return A reference to our current string. - ustring16<TAlloc> &append(const ustring16<TAlloc> &other, u32 length) + ustring16<TAlloc>& append(const ustring16<TAlloc>& other, u32 length) { if (other.size() == 0) return *this; - if (other.size() < length) { + if (other.size() < length) + { append(other); return *this; } @@ -1666,7 +1750,8 @@ public: const_iterator iter(other, 0); u32 l = length; - while (!iter.atEnd() && l) { + while (!iter.atEnd() && l) + { uchar32_t c = *iter; append(c); ++iter; @@ -1676,6 +1761,7 @@ public: return *this; } + //! Reserves some memory. //! \param count The amount of characters to reserve. void reserve(u32 count) @@ -1686,6 +1772,7 @@ public: reallocate(count); } + //! Finds first occurrence of character. //! \param c The character to search for. //! \return Position where the character has been found, or -1 if not found. @@ -1694,7 +1781,8 @@ public: const_iterator i(*this, 0); s32 pos = 0; - while (!i.atEnd()) { + while (!i.atEnd()) + { uchar32_t t = *i; if (c == t) return pos; @@ -1706,12 +1794,10 @@ public: } //! Finds first occurrence of a character of a list. - //! \param c A list of characters to find. For example if the method should find - //! the first occurrence of 'a' or 'b', this parameter should be "ab". \param - //! count The amount of characters in the list. Usually, this should be strlen(c). - //! \return Position where one of the characters has been found, or -1 if not - //! found. - s32 findFirstChar(const uchar32_t *const c, u32 count = 1) const + //! \param c A list of characters to find. For example if the method should find the first occurrence of 'a' or 'b', this parameter should be "ab". + //! \param count The amount of characters in the list. Usually, this should be strlen(c). + //! \return Position where one of the characters has been found, or -1 if not found. + s32 findFirstChar(const uchar32_t* const c, u32 count=1) const { if (!c || !count) return -1; @@ -1719,9 +1805,10 @@ public: const_iterator i(*this, 0); s32 pos = 0; - while (!i.atEnd()) { + while (!i.atEnd()) + { uchar32_t t = *i; - for (u32 j = 0; j < count; ++j) + for (u32 j=0; j<count; ++j) if (t == c[j]) return pos; ++pos; @@ -1731,13 +1818,12 @@ public: return -1; } + //! Finds first position of a character not in a given list. - //! \param c A list of characters to NOT find. For example if the method should - //! find the first occurrence of a character not 'a' or 'b', this parameter should - //! be "ab". \param count The amount of characters in the list. Usually, this - //! should be strlen(c). \return Position where the character has been found, or - //! -1 if not found. - s32 findFirstCharNotInList(const uchar32_t *const c, u32 count = 1) const + //! \param c A list of characters to NOT find. For example if the method should find the first occurrence of a character not 'a' or 'b', this parameter should be "ab". + //! \param count The amount of characters in the list. Usually, this should be strlen(c). + //! \return Position where the character has been found, or -1 if not found. + s32 findFirstCharNotInList(const uchar32_t* const c, u32 count=1) const { if (!c || !count) return -1; @@ -1745,14 +1831,15 @@ public: const_iterator i(*this, 0); s32 pos = 0; - while (!i.atEnd()) { + while (!i.atEnd()) + { uchar32_t t = *i; u32 j; - for (j = 0; j < count; ++j) + for (j=0; j<count; ++j) if (t == c[j]) break; - if (j == count) + if (j==count) return pos; ++pos; ++i; @@ -1762,12 +1849,10 @@ public: } //! Finds last position of a character not in a given list. - //! \param c A list of characters to NOT find. For example if the method should - //! find the first occurrence of a character not 'a' or 'b', this parameter should - //! be "ab". \param count The amount of characters in the list. Usually, this - //! should be strlen(c). \return Position where the character has been found, or - //! -1 if not found. - s32 findLastCharNotInList(const uchar32_t *const c, u32 count = 1) const + //! \param c A list of characters to NOT find. For example if the method should find the first occurrence of a character not 'a' or 'b', this parameter should be "ab". + //! \param count The amount of characters in the list. Usually, this should be strlen(c). + //! \return Position where the character has been found, or -1 if not found. + s32 findLastCharNotInList(const uchar32_t* const c, u32 count=1) const { if (!c || !count) return -1; @@ -1776,14 +1861,15 @@ public: --i; s32 pos = size() - 1; - while (!i.atStart()) { + while (!i.atStart()) + { uchar32_t t = *i; u32 j; - for (j = 0; j < count; ++j) + for (j=0; j<count; ++j) if (t == c[j]) break; - if (j == count) + if (j==count) return pos; --pos; --i; @@ -1801,7 +1887,8 @@ public: const_iterator i(*this, startPos); s32 pos = startPos; - while (!i.atEnd()) { + while (!i.atEnd()) + { uchar32_t t = *i; if (t == c) return pos; @@ -1812,18 +1899,20 @@ public: return -1; } + //! Finds last occurrence of character. //! \param c The character to search for. - //! \param start The start position of the reverse search ( default = -1, on end - //! ). \return Position where the character has been found, or -1 if not found. + //! \param start The start position of the reverse search ( default = -1, on end ). + //! \return Position where the character has been found, or -1 if not found. s32 findLast(uchar32_t c, s32 start = -1) const { u32 s = size(); - start = core::clamp(start < 0 ? (s32)s : start, 0, (s32)s) - 1; + start = core::clamp ( start < 0 ? (s32)s : start, 0, (s32)s ) - 1; const_iterator i(*this, start); u32 pos = start; - while (!i.atStart()) { + while (!i.atStart()) + { uchar32_t t = *i; if (t == c) return pos; @@ -1835,11 +1924,10 @@ public: } //! Finds last occurrence of a character in a list. - //! \param c A list of strings to find. For example if the method should find the - //! last occurrence of 'a' or 'b', this parameter should be "ab". \param count The - //! amount of characters in the list. Usually, this should be strlen(c). \return - //! Position where one of the characters has been found, or -1 if not found. - s32 findLastChar(const uchar32_t *const c, u32 count = 1) const + //! \param c A list of strings to find. For example if the method should find the last occurrence of 'a' or 'b', this parameter should be "ab". + //! \param count The amount of characters in the list. Usually, this should be strlen(c). + //! \return Position where one of the characters has been found, or -1 if not found. + s32 findLastChar(const uchar32_t* const c, u32 count=1) const { if (!c || !count) return -1; @@ -1848,9 +1936,10 @@ public: --i; s32 pos = size(); - while (!i.atStart()) { + while (!i.atStart()) + { uchar32_t t = *i; - for (u32 j = 0; j < count; ++j) + for (u32 j=0; j<count; ++j) if (t == c[j]) return pos; --pos; @@ -1860,11 +1949,12 @@ public: return -1; } + //! Finds another ustring16 in this ustring16. //! \param str The string to find. //! \param start The start position of the search. //! \return Positions where the ustring16 has been found, or -1 if not found. - s32 find(const ustring16<TAlloc> &str, const u32 start = 0) const + s32 find(const ustring16<TAlloc>& str, const u32 start = 0) const { u32 my_size = size(); u32 their_size = str.size(); @@ -1875,12 +1965,14 @@ public: const_iterator i(*this, start); s32 pos = start; - while (!i.atEnd()) { + while (!i.atEnd()) + { const_iterator i2(i); const_iterator j(str, 0); uchar32_t t1 = (uchar32_t)*i2; uchar32_t t2 = (uchar32_t)*j; - while (t1 == t2) { + while (t1 == t2) + { ++i2; ++j; if (j.atEnd()) @@ -1895,14 +1987,16 @@ public: return -1; } + //! Finds another ustring16 in this ustring16. //! \param str The string to find. //! \param start The start position of the search. //! \return Positions where the string has been found, or -1 if not found. - s32 find_raw(const ustring16<TAlloc> &str, const u32 start = 0) const + s32 find_raw(const ustring16<TAlloc>& str, const u32 start = 0) const { - const uchar16_t *data = str.c_str(); - if (data && *data) { + const uchar16_t* data = str.c_str(); + if (data && *data) + { u32 len = 0; while (data[len]) @@ -1911,10 +2005,11 @@ public: if (len > used) return -1; - for (u32 i = start; i <= used - len; ++i) { - u32 j = 0; + for (u32 i=start; i<=used-len; ++i) + { + u32 j=0; - while (data[j] && array[i + j] == data[j]) + while(data[j] && array[i+j] == data[j]) ++j; if (!data[j]) @@ -1925,6 +2020,7 @@ public: return -1; } + //! Returns a substring. //! \param begin: Start of substring. //! \param length: Length of substring. @@ -1934,17 +2030,18 @@ public: u32 len = size(); // if start after ustring16 // or no proper substring length - if ((length <= 0) || (begin >= len)) + if ((length <= 0) || (begin>=len)) return ustring16<TAlloc>(""); // clamp length to maximal value - if ((length + begin) > len) - length = len - begin; + if ((length+begin) > len) + length = len-begin; ustring16<TAlloc> o; - o.reserve((length + 1) * 2); + o.reserve((length+1) * 2); const_iterator i(*this, begin); - while (!i.atEnd() && length) { + while (!i.atEnd() && length) + { o.append(*i); ++i; --length; @@ -1953,115 +2050,128 @@ public: return o; } + //! Appends a character to this ustring16. //! \param c Character to append. //! \return A reference to our current string. - ustring16<TAlloc> &operator+=(char c) + ustring16<TAlloc>& operator += (char c) { append((uchar32_t)c); return *this; } + //! Appends a character to this ustring16. //! \param c Character to append. //! \return A reference to our current string. - ustring16<TAlloc> &operator+=(uchar32_t c) + ustring16<TAlloc>& operator += (uchar32_t c) { append(c); return *this; } + //! Appends a number to this ustring16. //! \param c Number to append. //! \return A reference to our current string. - ustring16<TAlloc> &operator+=(short c) + ustring16<TAlloc>& operator += (short c) { append(core::stringc(c)); return *this; } + //! Appends a number to this ustring16. //! \param c Number to append. //! \return A reference to our current string. - ustring16<TAlloc> &operator+=(unsigned short c) + ustring16<TAlloc>& operator += (unsigned short c) { append(core::stringc(c)); return *this; } + #ifdef USTRING_CPP0X_NEWLITERALS //! Appends a number to this ustring16. //! \param c Number to append. //! \return A reference to our current string. - ustring16<TAlloc> &operator+=(int c) + ustring16<TAlloc>& operator += (int c) { append(core::stringc(c)); return *this; } + //! Appends a number to this ustring16. //! \param c Number to append. //! \return A reference to our current string. - ustring16<TAlloc> &operator+=(unsigned int c) + ustring16<TAlloc>& operator += (unsigned int c) { append(core::stringc(c)); return *this; } #endif + //! Appends a number to this ustring16. //! \param c Number to append. //! \return A reference to our current string. - ustring16<TAlloc> &operator+=(long c) + ustring16<TAlloc>& operator += (long c) { append(core::stringc(c)); return *this; } + //! Appends a number to this ustring16. //! \param c Number to append. //! \return A reference to our current string. - ustring16<TAlloc> &operator+=(unsigned long c) + ustring16<TAlloc>& operator += (unsigned long c) { append(core::stringc(c)); return *this; } + //! Appends a number to this ustring16. //! \param c Number to append. //! \return A reference to our current string. - ustring16<TAlloc> &operator+=(double c) + ustring16<TAlloc>& operator += (double c) { append(core::stringc(c)); return *this; } + //! Appends a char ustring16 to this ustring16. //! \param c Char ustring16 to append. //! \return A reference to our current string. - ustring16<TAlloc> &operator+=(const uchar16_t *const c) + ustring16<TAlloc>& operator += (const uchar16_t* const c) { append(c); return *this; } + //! Appends a ustring16 to this ustring16. //! \param other ustring16 to append. //! \return A reference to our current string. - ustring16<TAlloc> &operator+=(const ustring16<TAlloc> &other) + ustring16<TAlloc>& operator += (const ustring16<TAlloc>& other) { append(other); return *this; } + //! Replaces all characters of a given type with another one. //! \param toReplace Character to replace. //! \param replaceWith Character replacing the old one. //! \return A reference to our current string. - ustring16<TAlloc> &replace(uchar32_t toReplace, uchar32_t replaceWith) + ustring16<TAlloc>& replace(uchar32_t toReplace, uchar32_t replaceWith) { iterator i(*this, 0); - while (!i.atEnd()) { + while (!i.atEnd()) + { typename ustring16<TAlloc>::access a = *i; if ((uchar32_t)a == toReplace) a = replaceWith; @@ -2070,18 +2180,18 @@ public: return *this; } + //! Replaces all instances of a string with another one. //! \param toReplace The string to replace. //! \param replaceWith The string replacing the old one. //! \return A reference to our current string. - ustring16<TAlloc> &replace(const ustring16<TAlloc> &toReplace, - const ustring16<TAlloc> &replaceWith) + ustring16<TAlloc>& replace(const ustring16<TAlloc>& toReplace, const ustring16<TAlloc>& replaceWith) { if (toReplace.size() == 0) return *this; - const uchar16_t *other = toReplace.c_str(); - const uchar16_t *replace = replaceWith.c_str(); + const uchar16_t* other = toReplace.c_str(); + const uchar16_t* replace = replaceWith.c_str(); const u32 other_size = toReplace.size_raw(); const u32 replace_size = replaceWith.size_raw(); @@ -2089,9 +2199,11 @@ public: s32 delta = replace_size - other_size; // A character for character replace. The string will not shrink or grow. - if (delta == 0) { + if (delta == 0) + { s32 pos = 0; - while ((pos = find_raw(other, pos)) != -1) { + while ((pos = find_raw(other, pos)) != -1) + { for (u32 i = 0; i < replace_size; ++i) array[pos + i] = replace[i]; ++pos; @@ -2100,20 +2212,25 @@ public: } // We are going to be removing some characters. The string will shrink. - if (delta < 0) { + if (delta < 0) + { u32 i = 0; - for (u32 pos = 0; pos <= used; ++i, ++pos) { + for (u32 pos = 0; pos <= used; ++i, ++pos) + { // Is this potentially a match? - if (array[pos] == *other) { + if (array[pos] == *other) + { // Check to see if we have a match. u32 j; - for (j = 0; j < other_size; ++j) { + for (j = 0; j < other_size; ++j) + { if (array[pos + j] != other[j]) break; } // If we have a match, replace characters. - if (j == other_size) { + if (j == other_size) + { for (j = 0; j < replace_size; ++j) array[i + j] = replace[j]; i += replace_size - 1; @@ -2132,11 +2249,11 @@ public: } // We are going to be adding characters, so the string size will increase. - // Count the number of times toReplace exists in the string so we can - // allocate the new size. + // Count the number of times toReplace exists in the string so we can allocate the new size. u32 find_count = 0; s32 pos = 0; - while ((pos = find_raw(other, pos)) != -1) { + while ((pos = find_raw(other, pos)) != -1) + { ++find_count; ++pos; } @@ -2148,13 +2265,15 @@ public: // Start replacing. pos = 0; - while ((pos = find_raw(other, pos)) != -1) { - uchar16_t *start = array + pos + other_size - 1; - uchar16_t *ptr = array + used; - uchar16_t *end = array + used + delta; + while ((pos = find_raw(other, pos)) != -1) + { + uchar16_t* start = array + pos + other_size - 1; + uchar16_t* ptr = array + used; + uchar16_t* end = array + used + delta; // Shift characters to make room for the string. - while (ptr != start) { + while (ptr != start) + { *end = *ptr; --ptr; --end; @@ -2173,27 +2292,29 @@ public: return *this; } + //! Removes characters from a ustring16.. //! \param c The character to remove. //! \return A reference to our current string. - ustring16<TAlloc> &remove(uchar32_t c) + ustring16<TAlloc>& remove(uchar32_t c) { u32 pos = 0; u32 found = 0; - u32 len = (c > 0xFFFF ? 2 : 1); // Remove characters equal to the size of - // c as a UTF-16 character. - for (u32 i = 0; i <= used; ++i) { + u32 len = (c > 0xFFFF ? 2 : 1); // Remove characters equal to the size of c as a UTF-16 character. + for (u32 i=0; i<=used; ++i) + { uchar32_t uc32 = 0; if (!UTF16_IS_SURROGATE_HI(array[i])) uc32 |= array[i]; - else if (i + 1 <= used) { - // Convert the surrogate pair into a single UTF-32 - // character. + else if (i + 1 <= used) + { + // Convert the surrogate pair into a single UTF-32 character. uc32 = unicode::toUTF32(array[i], array[i + 1]); } u32 len2 = (uc32 > 0xFFFF ? 2 : 1); - if (uc32 == c) { + if (uc32 == c) + { found += len; continue; } @@ -2207,26 +2328,29 @@ public: return *this; } + //! Removes a ustring16 from the ustring16. //! \param toRemove The string to remove. //! \return A reference to our current string. - ustring16<TAlloc> &remove(const ustring16<TAlloc> &toRemove) + ustring16<TAlloc>& remove(const ustring16<TAlloc>& toRemove) { u32 size = toRemove.size_raw(); - if (size == 0) - return *this; + if (size == 0) return *this; - const uchar16_t *tra = toRemove.c_str(); + const uchar16_t* tra = toRemove.c_str(); u32 pos = 0; u32 found = 0; - for (u32 i = 0; i <= used; ++i) { + for (u32 i=0; i<=used; ++i) + { u32 j = 0; - while (j < size) { + while (j < size) + { if (array[i + j] != tra[j]) break; ++j; } - if (j == size) { + if (j == size) + { found += size; i += size - 1; continue; @@ -2239,10 +2363,11 @@ public: return *this; } + //! Removes characters from the ustring16. //! \param characters The characters to remove. //! \return A reference to our current string. - ustring16<TAlloc> &removeChars(const ustring16<TAlloc> &characters) + ustring16<TAlloc>& removeChars(const ustring16<TAlloc>& characters) { if (characters.size_raw() == 0) return *this; @@ -2250,35 +2375,33 @@ public: u32 pos = 0; u32 found = 0; const_iterator iter(characters); - for (u32 i = 0; i <= used; ++i) { + for (u32 i=0; i<=used; ++i) + { uchar32_t uc32 = 0; if (!UTF16_IS_SURROGATE_HI(array[i])) uc32 |= array[i]; - else if (i + 1 <= used) { - // Convert the surrogate pair into a single UTF-32 - // character. - uc32 = unicode::toUTF32(array[i], array[i + 1]); + else if (i + 1 <= used) + { + // Convert the surrogate pair into a single UTF-32 character. + uc32 = unicode::toUTF32(array[i], array[i+1]); } u32 len2 = (uc32 > 0xFFFF ? 2 : 1); bool cont = false; iter.toStart(); - while (!iter.atEnd()) { + while (!iter.atEnd()) + { uchar32_t c = *iter; - if (uc32 == c) { - found += (c > 0xFFFF ? 2 - : 1); // Remove characters - // equal to the size of - // c as a UTF-16 - // character. + if (uc32 == c) + { + found += (c > 0xFFFF ? 2 : 1); // Remove characters equal to the size of c as a UTF-16 character. ++i; cont = true; break; } ++iter; } - if (cont) - continue; + if (cont) continue; array[pos++] = array[i]; if (len2 == 2) @@ -2289,33 +2412,33 @@ public: return *this; } + //! Trims the ustring16. - //! Removes the specified characters (by default, Latin-1 whitespace) from the - //! begining and the end of the ustring16. \param whitespace The characters that - //! are to be considered as whitespace. \return A reference to our current string. - ustring16<TAlloc> &trim(const ustring16<TAlloc> &whitespace = " \t\n\r") + //! Removes the specified characters (by default, Latin-1 whitespace) from the begining and the end of the ustring16. + //! \param whitespace The characters that are to be considered as whitespace. + //! \return A reference to our current string. + ustring16<TAlloc>& trim(const ustring16<TAlloc>& whitespace = " \t\n\r") { core::array<uchar32_t> utf32white = whitespace.toUTF32(); // find start and end of the substring without the specified characters - const s32 begin = findFirstCharNotInList( - utf32white.const_pointer(), whitespace.used + 1); + const s32 begin = findFirstCharNotInList(utf32white.const_pointer(), whitespace.used + 1); if (begin == -1) - return (*this = ""); + return (*this=""); - const s32 end = findLastCharNotInList( - utf32white.const_pointer(), whitespace.used + 1); + const s32 end = findLastCharNotInList(utf32white.const_pointer(), whitespace.used + 1); - return (*this = subString(begin, (end + 1) - begin)); + return (*this = subString(begin, (end +1) - begin)); } + //! Erases a character from the ustring16. - //! May be slow, because all elements following after the erased element have to - //! be copied. \param index Index of element to be erased. \return A reference to - //! our current string. - ustring16<TAlloc> &erase(u32 index) + //! May be slow, because all elements following after the erased element have to be copied. + //! \param index Index of element to be erased. + //! \return A reference to our current string. + ustring16<TAlloc>& erase(u32 index) { - _IRR_DEBUG_BREAK_IF(index > used) // access violation + _IRR_DEBUG_BREAK_IF(index>used) // access violation iterator i(*this, index); @@ -2331,23 +2454,25 @@ public: return *this; } - //! Validate the existing ustring16, checking for valid surrogate pairs and - //! checking for proper termination. \return A reference to our current string. - ustring16<TAlloc> &validate() + + //! Validate the existing ustring16, checking for valid surrogate pairs and checking for proper termination. + //! \return A reference to our current string. + ustring16<TAlloc>& validate() { // Validate all unicode characters. - for (u32 i = 0; i < allocated; ++i) { + for (u32 i=0; i<allocated; ++i) + { // Terminate on existing null. - if (array[i] == 0) { + if (array[i] == 0) + { used = i; return *this; } - if (UTF16_IS_SURROGATE(array[i])) { - if (((i + 1) >= allocated) || - UTF16_IS_SURROGATE_LO(array[i])) + if (UTF16_IS_SURROGATE(array[i])) + { + if (((i+1) >= allocated) || UTF16_IS_SURROGATE_LO(array[i])) array[i] = unicode::UTF_REPLACEMENT_CHARACTER; - else if (UTF16_IS_SURROGATE_HI(array[i]) && - !UTF16_IS_SURROGATE_LO(array[i + 1])) + else if (UTF16_IS_SURROGATE_HI(array[i]) && !UTF16_IS_SURROGATE_LO(array[i+1])) array[i] = unicode::UTF_REPLACEMENT_CHARACTER; ++i; } @@ -2357,13 +2482,15 @@ public: // terminate used = 0; - if (allocated > 0) { + if (allocated > 0) + { used = allocated - 1; array[used] = 0; } return *this; } + //! Gets the last char of the ustring16, or 0. //! \return The last char of the ustring16, or 0. uchar32_t lastChar() const @@ -2371,22 +2498,26 @@ public: if (used < 1) return 0; - if (UTF16_IS_SURROGATE_LO(array[used - 1])) { + if (UTF16_IS_SURROGATE_LO(array[used-1])) + { // Make sure we have a paired surrogate. if (used < 2) return 0; // Check for an invalid surrogate. - if (!UTF16_IS_SURROGATE_HI(array[used - 2])) + if (!UTF16_IS_SURROGATE_HI(array[used-2])) return 0; // Convert the surrogate pair into a single UTF-32 character. - return unicode::toUTF32(array[used - 2], array[used - 1]); - } else { - return array[used - 1]; + return unicode::toUTF32(array[used-2], array[used-1]); + } + else + { + return array[used-1]; } } + //! Split the ustring16 into parts. /** This method will split a ustring16 at certain delimiter characters into the container passed in as reference. The type of the container @@ -2405,33 +2536,32 @@ public: characters between the delimiters are returned. \return The number of resulting substrings */ - template <class container> - u32 split(container &ret, const uchar32_t *const c, u32 count = 1, - bool ignoreEmptyTokens = true, bool keepSeparators = false) const + template<class container> + u32 split(container& ret, const uchar32_t* const c, u32 count=1, bool ignoreEmptyTokens=true, bool keepSeparators=false) const { if (!c) return 0; const_iterator i(*this); - const u32 oldSize = ret.size(); + const u32 oldSize=ret.size(); u32 pos = 0; u32 lastpos = 0; u32 lastpospos = 0; bool lastWasSeparator = false; - while (!i.atEnd()) { + while (!i.atEnd()) + { uchar32_t ch = *i; bool foundSeparator = false; - for (u32 j = 0; j < count; ++j) { - if (ch == c[j]) { + for (u32 j=0; j<count; ++j) + { + if (ch == c[j]) + { if ((!ignoreEmptyTokens || pos - lastpos != 0) && !lastWasSeparator) - ret.push_back(ustring16<TAlloc>( - &array[lastpospos], - pos - lastpos)); + ret.push_back(ustring16<TAlloc>(&array[lastpospos], pos - lastpos)); foundSeparator = true; lastpos = (keepSeparators ? pos : pos + 1); - lastpospos = (keepSeparators ? i.getPos() - : i.getPos() + 1); + lastpospos = (keepSeparators ? i.getPos() : i.getPos() + 1); break; } } @@ -2442,9 +2572,10 @@ public: u32 s = size() + 1; if (s > lastpos) ret.push_back(ustring16<TAlloc>(&array[lastpospos], s - lastpos)); - return ret.size() - oldSize; + return ret.size()-oldSize; } + //! Split the ustring16 into parts. /** This method will split a ustring16 at certain delimiter characters into the container passed in as reference. The type of the container @@ -2462,29 +2593,35 @@ public: characters between the delimiters are returned. \return The number of resulting substrings */ - template <class container> - u32 split(container &ret, const ustring16<TAlloc> &c, - bool ignoreEmptyTokens = true, bool keepSeparators = false) const + template<class container> + u32 split(container& ret, const ustring16<TAlloc>& c, bool ignoreEmptyTokens=true, bool keepSeparators=false) const { core::array<uchar32_t> v = c.toUTF32(); - return split(ret, v.pointer(), v.size(), ignoreEmptyTokens, - keepSeparators); + return split(ret, v.pointer(), v.size(), ignoreEmptyTokens, keepSeparators); } + //! Gets the size of the allocated memory buffer for the string. //! \return The size of the allocated memory buffer. - u32 capacity() const { return allocated; } + u32 capacity() const + { + return allocated; + } + + + //! Returns the raw number of UTF-16 code points in the string which includes the individual surrogates. + //! \return The raw number of UTF-16 code points, excluding the trialing NUL. + u32 size_raw() const + { + return used; + } - //! Returns the raw number of UTF-16 code points in the string which includes the - //! individual surrogates. \return The raw number of UTF-16 code points, excluding - //! the trialing NUL. - u32 size_raw() const { return used; } //! Inserts a character into the string. //! \param c The character to insert. //! \param pos The position to insert the character. //! \return A reference to our current string. - ustring16<TAlloc> &insert(uchar32_t c, u32 pos) + ustring16<TAlloc>& insert(uchar32_t c, u32 pos) { u8 len = (c > 0xFFFF ? 2 : 1); @@ -2497,31 +2634,32 @@ public: for (u32 i = used - 2; i > iter.getPos(); --i) array[i] = array[i - len]; - if (c > 0xFFFF) { + if (c > 0xFFFF) + { // c will be multibyte, so split it up into a surrogate pair. uchar16_t x = static_cast<uchar16_t>(c); - uchar16_t vh = UTF16_HI_SURROGATE | - ((((c >> 16) & ((1 << 5) - 1)) - 1) << 6) | - (x >> 10); + uchar16_t vh = UTF16_HI_SURROGATE | ((((c >> 16) & ((1 << 5) - 1)) - 1) << 6) | (x >> 10); uchar16_t vl = UTF16_LO_SURROGATE | (x & ((1 << 10) - 1)); array[iter.getPos()] = vh; - array[iter.getPos() + 1] = vl; - } else { + array[iter.getPos()+1] = vl; + } + else + { array[iter.getPos()] = static_cast<uchar16_t>(c); } array[used] = 0; return *this; } + //! Inserts a string into the string. //! \param c The string to insert. //! \param pos The position to insert the string. //! \return A reference to our current string. - ustring16<TAlloc> &insert(const ustring16<TAlloc> &c, u32 pos) + ustring16<TAlloc>& insert(const ustring16<TAlloc>& c, u32 pos) { u32 len = c.size_raw(); - if (len == 0) - return *this; + if (len == 0) return *this; if (used + len >= allocated) reallocate(used + len); @@ -2532,8 +2670,9 @@ public: for (u32 i = used - 2; i > iter.getPos() + len; --i) array[i] = array[i - len]; - const uchar16_t *s = c.c_str(); - for (u32 i = 0; i < len; ++i) { + const uchar16_t* s = c.c_str(); + for (u32 i = 0; i < len; ++i) + { array[pos++] = *s; ++s; } @@ -2542,11 +2681,12 @@ public: return *this; } + //! Inserts a character into the string. //! \param c The character to insert. //! \param pos The position to insert the character. //! \return A reference to our current string. - ustring16<TAlloc> &insert_raw(uchar16_t c, u32 pos) + ustring16<TAlloc>& insert_raw(uchar16_t c, u32 pos) { if (used + 1 >= allocated) reallocate(used + 1); @@ -2561,12 +2701,14 @@ public: return *this; } + //! Removes a character from string. //! \param pos Position of the character to remove. //! \return A reference to our current string. - ustring16<TAlloc> &erase_raw(u32 pos) + ustring16<TAlloc>& erase_raw(u32 pos) { - for (u32 i = pos; i <= used; ++i) { + for (u32 i=pos; i<=used; ++i) + { array[i] = array[i + 1]; } --used; @@ -2574,16 +2716,18 @@ public: return *this; } + //! Replaces a character in the string. //! \param c The new character. //! \param pos The position of the character to replace. //! \return A reference to our current string. - ustring16<TAlloc> &replace_raw(uchar16_t c, u32 pos) + ustring16<TAlloc>& replace_raw(uchar16_t c, u32 pos) { array[pos] = c; return *this; } + //! Returns an iterator to the beginning of the string. //! \return An iterator to the beginning of the string. iterator begin() @@ -2592,6 +2736,7 @@ public: return i; } + //! Returns an iterator to the beginning of the string. //! \return An iterator to the beginning of the string. const_iterator begin() const @@ -2600,6 +2745,7 @@ public: return i; } + //! Returns an iterator to the beginning of the string. //! \return An iterator to the beginning of the string. const_iterator cbegin() const @@ -2608,6 +2754,7 @@ public: return i; } + //! Returns an iterator to the end of the string. //! \return An iterator to the end of the string. iterator end() @@ -2617,6 +2764,7 @@ public: return i; } + //! Returns an iterator to the end of the string. //! \return An iterator to the end of the string. const_iterator end() const @@ -2626,6 +2774,7 @@ public: return i; } + //! Returns an iterator to the end of the string. //! \return An iterator to the end of the string. const_iterator cend() const @@ -2635,9 +2784,10 @@ public: return i; } + //! Converts the string to a UTF-8 encoded string. - //! \param addBOM If true, the proper unicode byte-order mark will be prefixed to - //! the string. \return A string containing the UTF-8 encoded string. + //! \param addBOM If true, the proper unicode byte-order mark will be prefixed to the string. + //! \return A string containing the UTF-8 encoded string. core::string<uchar8_t> toUTF8_s(const bool addBOM = false) const { core::string<uchar8_t> ret; @@ -2645,15 +2795,18 @@ public: const_iterator iter(*this, 0); // Add the byte order mark if the user wants it. - if (addBOM) { + if (addBOM) + { ret.append(unicode::BOM_ENCODE_UTF8[0]); ret.append(unicode::BOM_ENCODE_UTF8[1]); ret.append(unicode::BOM_ENCODE_UTF8[2]); } - while (!iter.atEnd()) { + while (!iter.atEnd()) + { uchar32_t c = *iter; - if (c > 0xFFFF) { // 4 bytes + if (c > 0xFFFF) + { // 4 bytes uchar8_t b1 = (0x1E << 3) | ((c >> 18) & 0x7); uchar8_t b2 = (0x2 << 6) | ((c >> 12) & 0x3F); uchar8_t b3 = (0x2 << 6) | ((c >> 6) & 0x3F); @@ -2662,19 +2815,25 @@ public: ret.append(b2); ret.append(b3); ret.append(b4); - } else if (c > 0x7FF) { // 3 bytes + } + else if (c > 0x7FF) + { // 3 bytes uchar8_t b1 = (0xE << 4) | ((c >> 12) & 0xF); uchar8_t b2 = (0x2 << 6) | ((c >> 6) & 0x3F); uchar8_t b3 = (0x2 << 6) | (c & 0x3F); ret.append(b1); ret.append(b2); ret.append(b3); - } else if (c > 0x7F) { // 2 bytes + } + else if (c > 0x7F) + { // 2 bytes uchar8_t b1 = (0x6 << 5) | ((c >> 6) & 0x1F); uchar8_t b2 = (0x2 << 6) | (c & 0x3F); ret.append(b1); ret.append(b2); - } else { // 1 byte + } + else + { // 1 byte ret.append(static_cast<uchar8_t>(c)); } ++iter; @@ -2682,25 +2841,28 @@ public: return ret; } + //! Converts the string to a UTF-8 encoded string array. - //! \param addBOM If true, the proper unicode byte-order mark will be prefixed to - //! the string. \return An array containing the UTF-8 encoded string. + //! \param addBOM If true, the proper unicode byte-order mark will be prefixed to the string. + //! \return An array containing the UTF-8 encoded string. core::array<uchar8_t> toUTF8(const bool addBOM = false) const { - core::array<uchar8_t> ret( - used * 4 + (addBOM ? unicode::BOM_UTF8_LEN : 0) + 1); + core::array<uchar8_t> ret(used * 4 + (addBOM ? unicode::BOM_UTF8_LEN : 0) + 1); const_iterator iter(*this, 0); // Add the byte order mark if the user wants it. - if (addBOM) { + if (addBOM) + { ret.push_back(unicode::BOM_ENCODE_UTF8[0]); ret.push_back(unicode::BOM_ENCODE_UTF8[1]); ret.push_back(unicode::BOM_ENCODE_UTF8[2]); } - while (!iter.atEnd()) { + while (!iter.atEnd()) + { uchar32_t c = *iter; - if (c > 0xFFFF) { // 4 bytes + if (c > 0xFFFF) + { // 4 bytes uchar8_t b1 = (0x1E << 3) | ((c >> 18) & 0x7); uchar8_t b2 = (0x2 << 6) | ((c >> 12) & 0x3F); uchar8_t b3 = (0x2 << 6) | ((c >> 6) & 0x3F); @@ -2709,19 +2871,25 @@ public: ret.push_back(b2); ret.push_back(b3); ret.push_back(b4); - } else if (c > 0x7FF) { // 3 bytes + } + else if (c > 0x7FF) + { // 3 bytes uchar8_t b1 = (0xE << 4) | ((c >> 12) & 0xF); uchar8_t b2 = (0x2 << 6) | ((c >> 6) & 0x3F); uchar8_t b3 = (0x2 << 6) | (c & 0x3F); ret.push_back(b1); ret.push_back(b2); ret.push_back(b3); - } else if (c > 0x7F) { // 2 bytes + } + else if (c > 0x7F) + { // 2 bytes uchar8_t b1 = (0x6 << 5) | ((c >> 6) & 0x1F); uchar8_t b2 = (0x2 << 6) | (c & 0x3F); ret.push_back(b1); ret.push_back(b2); - } else { // 1 byte + } + else + { // 1 byte ret.push_back(static_cast<uchar8_t>(c)); } ++iter; @@ -2730,36 +2898,40 @@ public: return ret; } -#ifdef USTRING_CPP0X_NEWLITERALS // C++0x + +#ifdef USTRING_CPP0X_NEWLITERALS // C++0x //! Converts the string to a UTF-16 encoded string. //! \param endian The desired endianness of the string. - //! \param addBOM If true, the proper unicode byte-order mark will be prefixed to - //! the string. \return A string containing the UTF-16 encoded string. - core::string<char16_t> toUTF16_s( - const unicode::EUTF_ENDIAN endian = unicode::EUTFEE_NATIVE, - const bool addBOM = false) const + //! \param addBOM If true, the proper unicode byte-order mark will be prefixed to the string. + //! \return A string containing the UTF-16 encoded string. + core::string<char16_t> toUTF16_s(const unicode::EUTF_ENDIAN endian = unicode::EUTFEE_NATIVE, const bool addBOM = false) const { core::string<char16_t> ret; ret.reserve(used + (addBOM ? unicode::BOM_UTF16_LEN : 0) + 1); // Add the BOM if specified. - if (addBOM) { + if (addBOM) + { if (endian == unicode::EUTFEE_NATIVE) ret[0] = unicode::BOM; - else if (endian == unicode::EUTFEE_LITTLE) { - uchar8_t *ptr8 = reinterpret_cast<uchar8_t *>(&ret[0]); + else if (endian == unicode::EUTFEE_LITTLE) + { + uchar8_t* ptr8 = reinterpret_cast<uchar8_t*>(&ret[0]); *ptr8++ = unicode::BOM_ENCODE_UTF16_LE[0]; *ptr8 = unicode::BOM_ENCODE_UTF16_LE[1]; - } else { - uchar8_t *ptr8 = reinterpret_cast<uchar8_t *>(&ret[0]); + } + else + { + uchar8_t* ptr8 = reinterpret_cast<uchar8_t*>(&ret[0]); *ptr8++ = unicode::BOM_ENCODE_UTF16_BE[0]; *ptr8 = unicode::BOM_ENCODE_UTF16_BE[1]; } } ret.append(array); - if (endian != unicode::EUTFEE_NATIVE && getEndianness() != endian) { - char16_t *ptr = ret.c_str(); + if (endian != unicode::EUTFEE_NATIVE && getEndianness() != endian) + { + char16_t* ptr = ret.c_str(); for (u32 i = 0; i < ret.size(); ++i) *ptr++ = unicode::swapEndian16(*ptr); } @@ -2767,37 +2939,40 @@ public: } #endif + //! Converts the string to a UTF-16 encoded string array. - //! Unfortunately, no toUTF16_s() version exists due to limitations with - //! Irrlicht's string class. \param endian The desired endianness of the string. - //! \param addBOM If true, the proper unicode byte-order mark will be prefixed to - //! the string. \return An array containing the UTF-16 encoded string. - core::array<uchar16_t> toUTF16( - const unicode::EUTF_ENDIAN endian = unicode::EUTFEE_NATIVE, - const bool addBOM = false) const - { - core::array<uchar16_t> ret( - used + (addBOM ? unicode::BOM_UTF16_LEN : 0) + 1); - uchar16_t *ptr = ret.pointer(); + //! Unfortunately, no toUTF16_s() version exists due to limitations with Irrlicht's string class. + //! \param endian The desired endianness of the string. + //! \param addBOM If true, the proper unicode byte-order mark will be prefixed to the string. + //! \return An array containing the UTF-16 encoded string. + core::array<uchar16_t> toUTF16(const unicode::EUTF_ENDIAN endian = unicode::EUTFEE_NATIVE, const bool addBOM = false) const + { + core::array<uchar16_t> ret(used + (addBOM ? unicode::BOM_UTF16_LEN : 0) + 1); + uchar16_t* ptr = ret.pointer(); // Add the BOM if specified. - if (addBOM) { + if (addBOM) + { if (endian == unicode::EUTFEE_NATIVE) *ptr = unicode::BOM; - else if (endian == unicode::EUTFEE_LITTLE) { - uchar8_t *ptr8 = reinterpret_cast<uchar8_t *>(ptr); + else if (endian == unicode::EUTFEE_LITTLE) + { + uchar8_t* ptr8 = reinterpret_cast<uchar8_t*>(ptr); *ptr8++ = unicode::BOM_ENCODE_UTF16_LE[0]; *ptr8 = unicode::BOM_ENCODE_UTF16_LE[1]; - } else { - uchar8_t *ptr8 = reinterpret_cast<uchar8_t *>(ptr); + } + else + { + uchar8_t* ptr8 = reinterpret_cast<uchar8_t*>(ptr); *ptr8++ = unicode::BOM_ENCODE_UTF16_BE[0]; *ptr8 = unicode::BOM_ENCODE_UTF16_BE[1]; } ++ptr; } - memcpy((void *)ptr, (void *)array, used * sizeof(uchar16_t)); - if (endian != unicode::EUTFEE_NATIVE && getEndianness() != endian) { + memcpy((void*)ptr, (void*)array, used * sizeof(uchar16_t)); + if (endian != unicode::EUTFEE_NATIVE && getEndianness() != endian) + { for (u32 i = 0; i <= used; ++i) ptr[i] = unicode::swapEndian16(ptr[i]); } @@ -2806,36 +2981,40 @@ public: return ret; } -#ifdef USTRING_CPP0X_NEWLITERALS // C++0x + +#ifdef USTRING_CPP0X_NEWLITERALS // C++0x //! Converts the string to a UTF-32 encoded string. //! \param endian The desired endianness of the string. - //! \param addBOM If true, the proper unicode byte-order mark will be prefixed to - //! the string. \return A string containing the UTF-32 encoded string. - core::string<char32_t> toUTF32_s( - const unicode::EUTF_ENDIAN endian = unicode::EUTFEE_NATIVE, - const bool addBOM = false) const + //! \param addBOM If true, the proper unicode byte-order mark will be prefixed to the string. + //! \return A string containing the UTF-32 encoded string. + core::string<char32_t> toUTF32_s(const unicode::EUTF_ENDIAN endian = unicode::EUTFEE_NATIVE, const bool addBOM = false) const { core::string<char32_t> ret; ret.reserve(size() + 1 + (addBOM ? unicode::BOM_UTF32_LEN : 0)); const_iterator iter(*this, 0); // Add the BOM if specified. - if (addBOM) { + if (addBOM) + { if (endian == unicode::EUTFEE_NATIVE) ret.append(unicode::BOM); - else { + else + { union { uchar32_t full; u8 chunk[4]; } t; - if (endian == unicode::EUTFEE_LITTLE) { + if (endian == unicode::EUTFEE_LITTLE) + { t.chunk[0] = unicode::BOM_ENCODE_UTF32_LE[0]; t.chunk[1] = unicode::BOM_ENCODE_UTF32_LE[1]; t.chunk[2] = unicode::BOM_ENCODE_UTF32_LE[2]; t.chunk[3] = unicode::BOM_ENCODE_UTF32_LE[3]; - } else { + } + else + { t.chunk[0] = unicode::BOM_ENCODE_UTF32_BE[0]; t.chunk[1] = unicode::BOM_ENCODE_UTF32_BE[1]; t.chunk[2] = unicode::BOM_ENCODE_UTF32_BE[2]; @@ -2845,7 +3024,8 @@ public: } } - while (!iter.atEnd()) { + while (!iter.atEnd()) + { uchar32_t c = *iter; if (endian != unicode::EUTFEE_NATIVE && getEndianness() != endian) c = unicode::swapEndian32(c); @@ -2856,36 +3036,39 @@ public: } #endif + //! Converts the string to a UTF-32 encoded string array. - //! Unfortunately, no toUTF32_s() version exists due to limitations with - //! Irrlicht's string class. \param endian The desired endianness of the string. - //! \param addBOM If true, the proper unicode byte-order mark will be prefixed to - //! the string. \return An array containing the UTF-32 encoded string. - core::array<uchar32_t> toUTF32( - const unicode::EUTF_ENDIAN endian = unicode::EUTFEE_NATIVE, - const bool addBOM = false) const - { - core::array<uchar32_t> ret( - size() + (addBOM ? unicode::BOM_UTF32_LEN : 0) + 1); + //! Unfortunately, no toUTF32_s() version exists due to limitations with Irrlicht's string class. + //! \param endian The desired endianness of the string. + //! \param addBOM If true, the proper unicode byte-order mark will be prefixed to the string. + //! \return An array containing the UTF-32 encoded string. + core::array<uchar32_t> toUTF32(const unicode::EUTF_ENDIAN endian = unicode::EUTFEE_NATIVE, const bool addBOM = false) const + { + core::array<uchar32_t> ret(size() + (addBOM ? unicode::BOM_UTF32_LEN : 0) + 1); const_iterator iter(*this, 0); // Add the BOM if specified. - if (addBOM) { + if (addBOM) + { if (endian == unicode::EUTFEE_NATIVE) ret.push_back(unicode::BOM); - else { + else + { union { uchar32_t full; u8 chunk[4]; } t; - if (endian == unicode::EUTFEE_LITTLE) { + if (endian == unicode::EUTFEE_LITTLE) + { t.chunk[0] = unicode::BOM_ENCODE_UTF32_LE[0]; t.chunk[1] = unicode::BOM_ENCODE_UTF32_LE[1]; t.chunk[2] = unicode::BOM_ENCODE_UTF32_LE[2]; t.chunk[3] = unicode::BOM_ENCODE_UTF32_LE[3]; - } else { + } + else + { t.chunk[0] = unicode::BOM_ENCODE_UTF32_BE[0]; t.chunk[1] = unicode::BOM_ENCODE_UTF32_BE[1]; t.chunk[2] = unicode::BOM_ENCODE_UTF32_BE[2]; @@ -2896,7 +3079,8 @@ public: } ret.push_back(0); - while (!iter.atEnd()) { + while (!iter.atEnd()) + { uchar32_t c = *iter; if (endian != unicode::EUTFEE_NATIVE && getEndianness() != endian) c = unicode::swapEndian32(c); @@ -2906,31 +3090,37 @@ public: return ret; } + //! Converts the string to a wchar_t encoded string. - /** The size of a wchar_t changes depending on the platform. This function will - store a correct UTF-8, -16, or -32 encoded string depending on the size of a - wchar_t. **/ + /** The size of a wchar_t changes depending on the platform. This function will store a + correct UTF-8, -16, or -32 encoded string depending on the size of a wchar_t. **/ //! \param endian The desired endianness of the string. - //! \param addBOM If true, the proper unicode byte-order mark will be prefixed to - //! the string. \return A string containing the wchar_t encoded string. - core::string<wchar_t> toWCHAR_s( - const unicode::EUTF_ENDIAN endian = unicode::EUTFEE_NATIVE, - const bool addBOM = false) const + //! \param addBOM If true, the proper unicode byte-order mark will be prefixed to the string. + //! \return A string containing the wchar_t encoded string. + core::string<wchar_t> toWCHAR_s(const unicode::EUTF_ENDIAN endian = unicode::EUTFEE_NATIVE, const bool addBOM = false) const { - if (sizeof(wchar_t) == 4) { + if (sizeof(wchar_t) == 4) + { core::array<uchar32_t> a(toUTF32(endian, addBOM)); core::stringw ret(a.pointer()); return ret; - } else if (sizeof(wchar_t) == 2) { - if (endian == unicode::EUTFEE_NATIVE && addBOM == false) { + } + else if (sizeof(wchar_t) == 2) + { + if (endian == unicode::EUTFEE_NATIVE && addBOM == false) + { core::stringw ret(array); return ret; - } else { + } + else + { core::array<uchar16_t> a(toUTF16(endian, addBOM)); core::stringw ret(a.pointer()); return ret; } - } else if (sizeof(wchar_t) == 1) { + } + else if (sizeof(wchar_t) == 1) + { core::array<uchar8_t> a(toUTF8(addBOM)); core::stringw ret(a.pointer()); return ret; @@ -2940,47 +3130,47 @@ public: return core::stringw(); } + //! Converts the string to a wchar_t encoded string array. - /** The size of a wchar_t changes depending on the platform. This function will - store a correct UTF-8, -16, or -32 encoded string depending on the size of a - wchar_t. **/ + /** The size of a wchar_t changes depending on the platform. This function will store a + correct UTF-8, -16, or -32 encoded string depending on the size of a wchar_t. **/ //! \param endian The desired endianness of the string. - //! \param addBOM If true, the proper unicode byte-order mark will be prefixed to - //! the string. \return An array containing the wchar_t encoded string. - core::array<wchar_t> toWCHAR( - const unicode::EUTF_ENDIAN endian = unicode::EUTFEE_NATIVE, - const bool addBOM = false) const + //! \param addBOM If true, the proper unicode byte-order mark will be prefixed to the string. + //! \return An array containing the wchar_t encoded string. + core::array<wchar_t> toWCHAR(const unicode::EUTF_ENDIAN endian = unicode::EUTFEE_NATIVE, const bool addBOM = false) const { - if (sizeof(wchar_t) == 4) { + if (sizeof(wchar_t) == 4) + { core::array<uchar32_t> a(toUTF32(endian, addBOM)); core::array<wchar_t> ret(a.size()); ret.set_used(a.size()); - memcpy((void *)ret.pointer(), (void *)a.pointer(), - a.size() * sizeof(uchar32_t)); + memcpy((void*)ret.pointer(), (void*)a.pointer(), a.size() * sizeof(uchar32_t)); return ret; } - if (sizeof(wchar_t) == 2) { - if (endian == unicode::EUTFEE_NATIVE && addBOM == false) { + if (sizeof(wchar_t) == 2) + { + if (endian == unicode::EUTFEE_NATIVE && addBOM == false) + { core::array<wchar_t> ret(used); ret.set_used(used); - memcpy((void *)ret.pointer(), (void *)array, - used * sizeof(uchar16_t)); + memcpy((void*)ret.pointer(), (void*)array, used * sizeof(uchar16_t)); return ret; - } else { + } + else + { core::array<uchar16_t> a(toUTF16(endian, addBOM)); core::array<wchar_t> ret(a.size()); ret.set_used(a.size()); - memcpy((void *)ret.pointer(), (void *)a.pointer(), - a.size() * sizeof(uchar16_t)); + memcpy((void*)ret.pointer(), (void*)a.pointer(), a.size() * sizeof(uchar16_t)); return ret; } } - if (sizeof(wchar_t) == 1) { + if (sizeof(wchar_t) == 1) + { core::array<uchar8_t> a(toUTF8(addBOM)); core::array<wchar_t> ret(a.size()); ret.set_used(a.size()); - memcpy((void *)ret.pointer(), (void *)a.pointer(), - a.size() * sizeof(uchar8_t)); + memcpy((void*)ret.pointer(), (void*)a.pointer(), a.size() * sizeof(uchar8_t)); return ret; } @@ -2990,10 +3180,9 @@ public: //! Converts the string to a properly encoded io::path string. //! \param endian The desired endianness of the string. - //! \param addBOM If true, the proper unicode byte-order mark will be prefixed to - //! the string. \return An io::path string containing the properly encoded string. - io::path toPATH_s(const unicode::EUTF_ENDIAN endian = unicode::EUTFEE_NATIVE, - const bool addBOM = false) const + //! \param addBOM If true, the proper unicode byte-order mark will be prefixed to the string. + //! \return An io::path string containing the properly encoded string. + io::path toPATH_s(const unicode::EUTF_ENDIAN endian = unicode::EUTFEE_NATIVE, const bool addBOM = false) const { #if defined(_IRR_WCHAR_FILESYSTEM) return toWCHAR_s(endian, addBOM); @@ -3003,10 +3192,11 @@ public: } //! Loads an unknown stream of data. - //! Will attempt to determine if the stream is unicode data. Useful for loading - //! from files. \param data The data stream to load from. \param data_size The - //! length of the data string. \return A reference to our current string. - ustring16<TAlloc> &loadDataStream(const char *data, size_t data_size) + //! Will attempt to determine if the stream is unicode data. Useful for loading from files. + //! \param data The data stream to load from. + //! \param data_size The length of the data string. + //! \return A reference to our current string. + ustring16<TAlloc>& loadDataStream(const char* data, size_t data_size) { // Clear our string. *this = ""; @@ -3014,23 +3204,24 @@ public: return *this; unicode::EUTF_ENCODE e = unicode::determineUnicodeBOM(data); - switch (e) { - default: - case unicode::EUTFE_UTF8: - append((uchar8_t *)data, data_size); - break; + switch (e) + { + default: + case unicode::EUTFE_UTF8: + append((uchar8_t*)data, data_size); + break; - case unicode::EUTFE_UTF16: - case unicode::EUTFE_UTF16_BE: - case unicode::EUTFE_UTF16_LE: - append((uchar16_t *)data, data_size / 2); - break; + case unicode::EUTFE_UTF16: + case unicode::EUTFE_UTF16_BE: + case unicode::EUTFE_UTF16_LE: + append((uchar16_t*)data, data_size / 2); + break; - case unicode::EUTFE_UTF32: - case unicode::EUTFE_UTF32_BE: - case unicode::EUTFE_UTF32_LE: - append((uchar32_t *)data, data_size / 4); - break; + case unicode::EUTFE_UTF32: + case unicode::EUTFE_UTF32_BE: + case unicode::EUTFE_UTF32_LE: + append((uchar32_t*)data, data_size / 4); + break; } return *this; @@ -3038,33 +3229,35 @@ public: //! Gets the encoding of the Unicode string this class contains. //! \return An enum describing the current encoding of this string. - const unicode::EUTF_ENCODE getEncoding() const { return encoding; } + const unicode::EUTF_ENCODE getEncoding() const + { + return encoding; + } //! Gets the endianness of the Unicode string this class contains. //! \return An enum describing the endianness of this string. const unicode::EUTF_ENDIAN getEndianness() const { if (encoding == unicode::EUTFE_UTF16_LE || - encoding == unicode::EUTFE_UTF32_LE) + encoding == unicode::EUTFE_UTF32_LE) return unicode::EUTFEE_LITTLE; - else - return unicode::EUTFEE_BIG; + else return unicode::EUTFEE_BIG; } private: + //! Reallocate the string, making it bigger or smaller. //! \param new_size The new size of the string. void reallocate(u32 new_size) { - uchar16_t *old_array = array; + uchar16_t* old_array = array; - array = allocator.allocate(new_size + 1); // new u16[new_size]; + array = allocator.allocate(new_size + 1); //new u16[new_size]; allocated = new_size + 1; - if (old_array == 0) - return; + if (old_array == 0) return; u32 amount = used < new_size ? used : new_size; - for (u32 i = 0; i <= amount; ++i) + for (u32 i=0; i<=amount; ++i) array[i] = old_array[i]; if (allocated <= used) @@ -3077,115 +3270,121 @@ private: //--- member variables - uchar16_t *array; + uchar16_t* array; unicode::EUTF_ENCODE encoding; u32 allocated; u32 used; TAlloc allocator; - // irrAllocator<uchar16_t> allocator; + //irrAllocator<uchar16_t> allocator; }; -typedef ustring16<irrAllocator<uchar16_t>> ustring; +typedef ustring16<irrAllocator<uchar16_t> > ustring; + //! Appends two ustring16s. template <typename TAlloc> -inline ustring16<TAlloc> operator+( - const ustring16<TAlloc> &left, const ustring16<TAlloc> &right) +inline ustring16<TAlloc> operator+(const ustring16<TAlloc>& left, const ustring16<TAlloc>& right) { ustring16<TAlloc> ret(left); ret += right; return ret; } + //! Appends a ustring16 and a null-terminated unicode string. template <typename TAlloc, class B> -inline ustring16<TAlloc> operator+(const ustring16<TAlloc> &left, const B *const right) +inline ustring16<TAlloc> operator+(const ustring16<TAlloc>& left, const B* const right) { ustring16<TAlloc> ret(left); ret += right; return ret; } + //! Appends a ustring16 and a null-terminated unicode string. template <class B, typename TAlloc> -inline ustring16<TAlloc> operator+(const B *const left, const ustring16<TAlloc> &right) +inline ustring16<TAlloc> operator+(const B* const left, const ustring16<TAlloc>& right) { ustring16<TAlloc> ret(left); ret += right; return ret; } + //! Appends a ustring16 and an Irrlicht string. template <typename TAlloc, typename B, typename BAlloc> -inline ustring16<TAlloc> operator+( - const ustring16<TAlloc> &left, const string<B, BAlloc> &right) +inline ustring16<TAlloc> operator+(const ustring16<TAlloc>& left, const string<B, BAlloc>& right) { ustring16<TAlloc> ret(left); ret += right; return ret; } + //! Appends a ustring16 and an Irrlicht string. template <typename TAlloc, typename B, typename BAlloc> -inline ustring16<TAlloc> operator+( - const string<B, BAlloc> &left, const ustring16<TAlloc> &right) +inline ustring16<TAlloc> operator+(const string<B, BAlloc>& left, const ustring16<TAlloc>& right) { ustring16<TAlloc> ret(left); ret += right; return ret; } + //! Appends a ustring16 and a std::basic_string. template <typename TAlloc, typename B, typename A, typename BAlloc> -inline ustring16<TAlloc> operator+(const ustring16<TAlloc> &left, - const std::basic_string<B, A, BAlloc> &right) +inline ustring16<TAlloc> operator+(const ustring16<TAlloc>& left, const std::basic_string<B, A, BAlloc>& right) { ustring16<TAlloc> ret(left); ret += right; return ret; } + //! Appends a ustring16 and a std::basic_string. template <typename TAlloc, typename B, typename A, typename BAlloc> -inline ustring16<TAlloc> operator+(const std::basic_string<B, A, BAlloc> &left, - const ustring16<TAlloc> &right) +inline ustring16<TAlloc> operator+(const std::basic_string<B, A, BAlloc>& left, const ustring16<TAlloc>& right) { ustring16<TAlloc> ret(left); ret += right; return ret; } + //! Appends a ustring16 and a char. template <typename TAlloc> -inline ustring16<TAlloc> operator+(const ustring16<TAlloc> &left, const char right) +inline ustring16<TAlloc> operator+(const ustring16<TAlloc>& left, const char right) { ustring16<TAlloc> ret(left); ret += right; return ret; } + //! Appends a ustring16 and a char. template <typename TAlloc> -inline ustring16<TAlloc> operator+(const char left, const ustring16<TAlloc> &right) +inline ustring16<TAlloc> operator+(const char left, const ustring16<TAlloc>& right) { ustring16<TAlloc> ret(left); ret += right; return ret; } + #ifdef USTRING_CPP0X_NEWLITERALS //! Appends a ustring16 and a uchar32_t. template <typename TAlloc> -inline ustring16<TAlloc> operator+(const ustring16<TAlloc> &left, const uchar32_t right) +inline ustring16<TAlloc> operator+(const ustring16<TAlloc>& left, const uchar32_t right) { ustring16<TAlloc> ret(left); ret += right; return ret; } + //! Appends a ustring16 and a uchar32_t. template <typename TAlloc> -inline ustring16<TAlloc> operator+(const uchar32_t left, const ustring16<TAlloc> &right) +inline ustring16<TAlloc> operator+(const uchar32_t left, const ustring16<TAlloc>& right) { ustring16<TAlloc> ret(left); ret += right; @@ -3193,417 +3392,454 @@ inline ustring16<TAlloc> operator+(const uchar32_t left, const ustring16<TAlloc> } #endif + //! Appends a ustring16 and a short. template <typename TAlloc> -inline ustring16<TAlloc> operator+(const ustring16<TAlloc> &left, const short right) +inline ustring16<TAlloc> operator+(const ustring16<TAlloc>& left, const short right) { ustring16<TAlloc> ret(left); ret += core::stringc(right); return ret; } + //! Appends a ustring16 and a short. template <typename TAlloc> -inline ustring16<TAlloc> operator+(const short left, const ustring16<TAlloc> &right) +inline ustring16<TAlloc> operator+(const short left, const ustring16<TAlloc>& right) { ustring16<TAlloc> ret((core::stringc(left))); ret += right; return ret; } + //! Appends a ustring16 and an unsigned short. template <typename TAlloc> -inline ustring16<TAlloc> operator+( - const ustring16<TAlloc> &left, const unsigned short right) +inline ustring16<TAlloc> operator+(const ustring16<TAlloc>& left, const unsigned short right) { ustring16<TAlloc> ret(left); ret += core::stringc(right); return ret; } + //! Appends a ustring16 and an unsigned short. template <typename TAlloc> -inline ustring16<TAlloc> operator+( - const unsigned short left, const ustring16<TAlloc> &right) +inline ustring16<TAlloc> operator+(const unsigned short left, const ustring16<TAlloc>& right) { ustring16<TAlloc> ret((core::stringc(left))); ret += right; return ret; } + //! Appends a ustring16 and an int. template <typename TAlloc> -inline ustring16<TAlloc> operator+(const ustring16<TAlloc> &left, const int right) +inline ustring16<TAlloc> operator+(const ustring16<TAlloc>& left, const int right) { ustring16<TAlloc> ret(left); ret += core::stringc(right); return ret; } + //! Appends a ustring16 and an int. template <typename TAlloc> -inline ustring16<TAlloc> operator+(const int left, const ustring16<TAlloc> &right) +inline ustring16<TAlloc> operator+(const int left, const ustring16<TAlloc>& right) { ustring16<TAlloc> ret((core::stringc(left))); ret += right; return ret; } + //! Appends a ustring16 and an unsigned int. template <typename TAlloc> -inline ustring16<TAlloc> operator+( - const ustring16<TAlloc> &left, const unsigned int right) +inline ustring16<TAlloc> operator+(const ustring16<TAlloc>& left, const unsigned int right) { ustring16<TAlloc> ret(left); ret += core::stringc(right); return ret; } + //! Appends a ustring16 and an unsigned int. template <typename TAlloc> -inline ustring16<TAlloc> operator+( - const unsigned int left, const ustring16<TAlloc> &right) +inline ustring16<TAlloc> operator+(const unsigned int left, const ustring16<TAlloc>& right) { ustring16<TAlloc> ret((core::stringc(left))); ret += right; return ret; } + //! Appends a ustring16 and a long. template <typename TAlloc> -inline ustring16<TAlloc> operator+(const ustring16<TAlloc> &left, const long right) +inline ustring16<TAlloc> operator+(const ustring16<TAlloc>& left, const long right) { ustring16<TAlloc> ret(left); ret += core::stringc(right); return ret; } + //! Appends a ustring16 and a long. template <typename TAlloc> -inline ustring16<TAlloc> operator+(const long left, const ustring16<TAlloc> &right) +inline ustring16<TAlloc> operator+(const long left, const ustring16<TAlloc>& right) { ustring16<TAlloc> ret((core::stringc(left))); ret += right; return ret; } + //! Appends a ustring16 and an unsigned long. template <typename TAlloc> -inline ustring16<TAlloc> operator+( - const ustring16<TAlloc> &left, const unsigned long right) +inline ustring16<TAlloc> operator+(const ustring16<TAlloc>& left, const unsigned long right) { ustring16<TAlloc> ret(left); ret += core::stringc(right); return ret; } + //! Appends a ustring16 and an unsigned long. template <typename TAlloc> -inline ustring16<TAlloc> operator+( - const unsigned long left, const ustring16<TAlloc> &right) +inline ustring16<TAlloc> operator+(const unsigned long left, const ustring16<TAlloc>& right) { ustring16<TAlloc> ret((core::stringc(left))); ret += right; return ret; } + //! Appends a ustring16 and a float. template <typename TAlloc> -inline ustring16<TAlloc> operator+(const ustring16<TAlloc> &left, const float right) +inline ustring16<TAlloc> operator+(const ustring16<TAlloc>& left, const float right) { ustring16<TAlloc> ret(left); ret += core::stringc(right); return ret; } + //! Appends a ustring16 and a float. template <typename TAlloc> -inline ustring16<TAlloc> operator+(const float left, const ustring16<TAlloc> &right) +inline ustring16<TAlloc> operator+(const float left, const ustring16<TAlloc>& right) { ustring16<TAlloc> ret((core::stringc(left))); ret += right; return ret; } + //! Appends a ustring16 and a double. template <typename TAlloc> -inline ustring16<TAlloc> operator+(const ustring16<TAlloc> &left, const double right) +inline ustring16<TAlloc> operator+(const ustring16<TAlloc>& left, const double right) { ustring16<TAlloc> ret(left); ret += core::stringc(right); return ret; } + //! Appends a ustring16 and a double. template <typename TAlloc> -inline ustring16<TAlloc> operator+(const double left, const ustring16<TAlloc> &right) +inline ustring16<TAlloc> operator+(const double left, const ustring16<TAlloc>& right) { ustring16<TAlloc> ret((core::stringc(left))); ret += right; return ret; } + #ifdef USTRING_CPP0X //! Appends two ustring16s. template <typename TAlloc> -inline ustring16<TAlloc> &&operator+( - const ustring16<TAlloc> &left, ustring16<TAlloc> &&right) +inline ustring16<TAlloc>&& operator+(const ustring16<TAlloc>& left, ustring16<TAlloc>&& right) { - // std::cout << "MOVE operator+(&, &&)" << std::endl; + //std::cout << "MOVE operator+(&, &&)" << std::endl; right.insert(left, 0); return std::move(right); } + //! Appends two ustring16s. template <typename TAlloc> -inline ustring16<TAlloc> &&operator+( - ustring16<TAlloc> &&left, const ustring16<TAlloc> &right) +inline ustring16<TAlloc>&& operator+(ustring16<TAlloc>&& left, const ustring16<TAlloc>& right) { - // std::cout << "MOVE operator+(&&, &)" << std::endl; + //std::cout << "MOVE operator+(&&, &)" << std::endl; left.append(right); return std::move(left); } + //! Appends two ustring16s. template <typename TAlloc> -inline ustring16<TAlloc> &&operator+(ustring16<TAlloc> &&left, ustring16<TAlloc> &&right) +inline ustring16<TAlloc>&& operator+(ustring16<TAlloc>&& left, ustring16<TAlloc>&& right) { - // std::cout << "MOVE operator+(&&, &&)" << std::endl; + //std::cout << "MOVE operator+(&&, &&)" << std::endl; if ((right.size_raw() <= left.capacity() - left.size_raw()) || - (right.capacity() - right.size_raw() < left.size_raw())) { + (right.capacity() - right.size_raw() < left.size_raw())) + { left.append(right); return std::move(left); - } else { + } + else + { right.insert(left, 0); return std::move(right); } } + //! Appends a ustring16 and a null-terminated unicode string. template <typename TAlloc, class B> -inline ustring16<TAlloc> &&operator+(ustring16<TAlloc> &&left, const B *const right) +inline ustring16<TAlloc>&& operator+(ustring16<TAlloc>&& left, const B* const right) { - // std::cout << "MOVE operator+(&&, B*)" << std::endl; + //std::cout << "MOVE operator+(&&, B*)" << std::endl; left.append(right); return std::move(left); } + //! Appends a ustring16 and a null-terminated unicode string. template <class B, typename TAlloc> -inline ustring16<TAlloc> &&operator+(const B *const left, ustring16<TAlloc> &&right) +inline ustring16<TAlloc>&& operator+(const B* const left, ustring16<TAlloc>&& right) { - // std::cout << "MOVE operator+(B*, &&)" << std::endl; + //std::cout << "MOVE operator+(B*, &&)" << std::endl; right.insert(left, 0); return std::move(right); } + //! Appends a ustring16 and an Irrlicht string. template <typename TAlloc, typename B, typename BAlloc> -inline ustring16<TAlloc> &&operator+( - const string<B, BAlloc> &left, ustring16<TAlloc> &&right) +inline ustring16<TAlloc>&& operator+(const string<B, BAlloc>& left, ustring16<TAlloc>&& right) { - // std::cout << "MOVE operator+(&, &&)" << std::endl; + //std::cout << "MOVE operator+(&, &&)" << std::endl; right.insert(left, 0); return std::move(right); } + //! Appends a ustring16 and an Irrlicht string. template <typename TAlloc, typename B, typename BAlloc> -inline ustring16<TAlloc> &&operator+( - ustring16<TAlloc> &&left, const string<B, BAlloc> &right) +inline ustring16<TAlloc>&& operator+(ustring16<TAlloc>&& left, const string<B, BAlloc>& right) { - // std::cout << "MOVE operator+(&&, &)" << std::endl; + //std::cout << "MOVE operator+(&&, &)" << std::endl; left.append(right); return std::move(left); } + //! Appends a ustring16 and a std::basic_string. template <typename TAlloc, typename B, typename A, typename BAlloc> -inline ustring16<TAlloc> &&operator+( - const std::basic_string<B, A, BAlloc> &left, ustring16<TAlloc> &&right) +inline ustring16<TAlloc>&& operator+(const std::basic_string<B, A, BAlloc>& left, ustring16<TAlloc>&& right) { - // std::cout << "MOVE operator+(&, &&)" << std::endl; + //std::cout << "MOVE operator+(&, &&)" << std::endl; right.insert(core::ustring16<TAlloc>(left), 0); return std::move(right); } + //! Appends a ustring16 and a std::basic_string. template <typename TAlloc, typename B, typename A, typename BAlloc> -inline ustring16<TAlloc> &&operator+( - ustring16<TAlloc> &&left, const std::basic_string<B, A, BAlloc> &right) +inline ustring16<TAlloc>&& operator+(ustring16<TAlloc>&& left, const std::basic_string<B, A, BAlloc>& right) { - // std::cout << "MOVE operator+(&&, &)" << std::endl; + //std::cout << "MOVE operator+(&&, &)" << std::endl; left.append(right); return std::move(left); } + //! Appends a ustring16 and a char. template <typename TAlloc> -inline ustring16<TAlloc> operator+(ustring16<TAlloc> &&left, const char right) +inline ustring16<TAlloc> operator+(ustring16<TAlloc>&& left, const char right) { left.append((uchar32_t)right); return std::move(left); } + //! Appends a ustring16 and a char. template <typename TAlloc> -inline ustring16<TAlloc> operator+(const char left, ustring16<TAlloc> &&right) +inline ustring16<TAlloc> operator+(const char left, ustring16<TAlloc>&& right) { right.insert((uchar32_t)left, 0); return std::move(right); } + #ifdef USTRING_CPP0X_NEWLITERALS //! Appends a ustring16 and a uchar32_t. template <typename TAlloc> -inline ustring16<TAlloc> operator+(ustring16<TAlloc> &&left, const uchar32_t right) +inline ustring16<TAlloc> operator+(ustring16<TAlloc>&& left, const uchar32_t right) { left.append(right); return std::move(left); } + //! Appends a ustring16 and a uchar32_t. template <typename TAlloc> -inline ustring16<TAlloc> operator+(const uchar32_t left, ustring16<TAlloc> &&right) +inline ustring16<TAlloc> operator+(const uchar32_t left, ustring16<TAlloc>&& right) { right.insert(left, 0); return std::move(right); } #endif + //! Appends a ustring16 and a short. template <typename TAlloc> -inline ustring16<TAlloc> operator+(ustring16<TAlloc> &&left, const short right) +inline ustring16<TAlloc> operator+(ustring16<TAlloc>&& left, const short right) { left.append(core::stringc(right)); return std::move(left); } + //! Appends a ustring16 and a short. template <typename TAlloc> -inline ustring16<TAlloc> operator+(const short left, ustring16<TAlloc> &&right) +inline ustring16<TAlloc> operator+(const short left, ustring16<TAlloc>&& right) { right.insert(core::stringc(left), 0); return std::move(right); } + //! Appends a ustring16 and an unsigned short. template <typename TAlloc> -inline ustring16<TAlloc> operator+(ustring16<TAlloc> &&left, const unsigned short right) +inline ustring16<TAlloc> operator+(ustring16<TAlloc>&& left, const unsigned short right) { left.append(core::stringc(right)); return std::move(left); } + //! Appends a ustring16 and an unsigned short. template <typename TAlloc> -inline ustring16<TAlloc> operator+(const unsigned short left, ustring16<TAlloc> &&right) +inline ustring16<TAlloc> operator+(const unsigned short left, ustring16<TAlloc>&& right) { right.insert(core::stringc(left), 0); return std::move(right); } + //! Appends a ustring16 and an int. template <typename TAlloc> -inline ustring16<TAlloc> operator+(ustring16<TAlloc> &&left, const int right) +inline ustring16<TAlloc> operator+(ustring16<TAlloc>&& left, const int right) { left.append(core::stringc(right)); return std::move(left); } + //! Appends a ustring16 and an int. template <typename TAlloc> -inline ustring16<TAlloc> operator+(const int left, ustring16<TAlloc> &&right) +inline ustring16<TAlloc> operator+(const int left, ustring16<TAlloc>&& right) { right.insert(core::stringc(left), 0); return std::move(right); } + //! Appends a ustring16 and an unsigned int. template <typename TAlloc> -inline ustring16<TAlloc> operator+(ustring16<TAlloc> &&left, const unsigned int right) +inline ustring16<TAlloc> operator+(ustring16<TAlloc>&& left, const unsigned int right) { left.append(core::stringc(right)); return std::move(left); } + //! Appends a ustring16 and an unsigned int. template <typename TAlloc> -inline ustring16<TAlloc> operator+(const unsigned int left, ustring16<TAlloc> &&right) +inline ustring16<TAlloc> operator+(const unsigned int left, ustring16<TAlloc>&& right) { right.insert(core::stringc(left), 0); return std::move(right); } + //! Appends a ustring16 and a long. template <typename TAlloc> -inline ustring16<TAlloc> operator+(ustring16<TAlloc> &&left, const long right) +inline ustring16<TAlloc> operator+(ustring16<TAlloc>&& left, const long right) { left.append(core::stringc(right)); return std::move(left); } + //! Appends a ustring16 and a long. template <typename TAlloc> -inline ustring16<TAlloc> operator+(const long left, ustring16<TAlloc> &&right) +inline ustring16<TAlloc> operator+(const long left, ustring16<TAlloc>&& right) { right.insert(core::stringc(left), 0); return std::move(right); } + //! Appends a ustring16 and an unsigned long. template <typename TAlloc> -inline ustring16<TAlloc> operator+(ustring16<TAlloc> &&left, const unsigned long right) +inline ustring16<TAlloc> operator+(ustring16<TAlloc>&& left, const unsigned long right) { left.append(core::stringc(right)); return std::move(left); } + //! Appends a ustring16 and an unsigned long. template <typename TAlloc> -inline ustring16<TAlloc> operator+(const unsigned long left, ustring16<TAlloc> &&right) +inline ustring16<TAlloc> operator+(const unsigned long left, ustring16<TAlloc>&& right) { right.insert(core::stringc(left), 0); return std::move(right); } + //! Appends a ustring16 and a float. template <typename TAlloc> -inline ustring16<TAlloc> operator+(ustring16<TAlloc> &&left, const float right) +inline ustring16<TAlloc> operator+(ustring16<TAlloc>&& left, const float right) { left.append(core::stringc(right)); return std::move(left); } + //! Appends a ustring16 and a float. template <typename TAlloc> -inline ustring16<TAlloc> operator+(const float left, ustring16<TAlloc> &&right) +inline ustring16<TAlloc> operator+(const float left, ustring16<TAlloc>&& right) { right.insert(core::stringc(left), 0); return std::move(right); } + //! Appends a ustring16 and a double. template <typename TAlloc> -inline ustring16<TAlloc> operator+(ustring16<TAlloc> &&left, const double right) +inline ustring16<TAlloc> operator+(ustring16<TAlloc>&& left, const double right) { left.append(core::stringc(right)); return std::move(left); } + //! Appends a ustring16 and a double. template <typename TAlloc> -inline ustring16<TAlloc> operator+(const double left, ustring16<TAlloc> &&right) +inline ustring16<TAlloc> operator+(const double left, ustring16<TAlloc>&& right) { right.insert(core::stringc(left), 0); return std::move(right); } #endif + #ifndef USTRING_NO_STL //! Writes a ustring16 to an ostream. template <typename TAlloc> -inline std::ostream &operator<<(std::ostream &out, const ustring16<TAlloc> &in) +inline std::ostream& operator<<(std::ostream& out, const ustring16<TAlloc>& in) { out << in.toUTF8_s().c_str(); return out; @@ -3611,13 +3847,14 @@ inline std::ostream &operator<<(std::ostream &out, const ustring16<TAlloc> &in) //! Writes a ustring16 to a wostream. template <typename TAlloc> -inline std::wostream &operator<<(std::wostream &out, const ustring16<TAlloc> &in) +inline std::wostream& operator<<(std::wostream& out, const ustring16<TAlloc>& in) { out << in.toWCHAR_s().c_str(); return out; } #endif + #ifndef USTRING_NO_STL namespace unicode @@ -3627,22 +3864,23 @@ namespace unicode //! Algorithm taken from std::hash<std::string>. class hash : public std::unary_function<core::ustring, size_t> { -public: - size_t operator()(const core::ustring &s) const - { - size_t ret = 2166136261U; - size_t index = 0; - size_t stride = 1 + s.size_raw() / 10; - - core::ustring::const_iterator i = s.begin(); - while (i != s.end()) { - // TODO: Don't force u32 on an x64 OS. Make it agnostic. - ret = 16777619U * ret ^ (size_t)s[(u32)index]; - index += stride; - i += stride; + public: + size_t operator()(const core::ustring& s) const + { + size_t ret = 2166136261U; + size_t index = 0; + size_t stride = 1 + s.size_raw() / 10; + + core::ustring::const_iterator i = s.begin(); + while (i != s.end()) + { + // TODO: Don't force u32 on an x64 OS. Make it agnostic. + ret = 16777619U * ret ^ (size_t)s[(u32)index]; + index += stride; + i += stride; + } + return (ret); } - return (ret); - } }; } // end namespace unicode diff --git a/src/irrlicht_changes/static_text.cpp b/src/irrlicht_changes/static_text.cpp index eb1d338dc..bf61cd64e 100644 --- a/src/irrlicht_changes/static_text.cpp +++ b/src/irrlicht_changes/static_text.cpp @@ -13,7 +13,7 @@ #include <SColor.h> #if USE_FREETYPE -#include "CGUITTFont.h" + #include "CGUITTFont.h" #endif #include "util/string.h" @@ -27,20 +27,23 @@ namespace gui { //! constructor StaticText::StaticText(const EnrichedString &text, bool border, - IGUIEnvironment *environment, IGUIElement *parent, s32 id, - const core::rect<s32> &rectangle, bool background) : - IGUIStaticText(environment, parent, id, rectangle), - HAlign(EGUIA_UPPERLEFT), VAlign(EGUIA_UPPERLEFT), Border(border), - WordWrap(false), Background(background), RestrainTextInside(true), - RightToLeft(false), OverrideFont(0), LastBreakFont(0) -{ -#ifdef _DEBUG + IGUIEnvironment* environment, IGUIElement* parent, + s32 id, const core::rect<s32>& rectangle, + bool background) +: IGUIStaticText(environment, parent, id, rectangle), + HAlign(EGUIA_UPPERLEFT), VAlign(EGUIA_UPPERLEFT), + Border(border), WordWrap(false), Background(background), + RestrainTextInside(true), RightToLeft(false), + OverrideFont(0), LastBreakFont(0) +{ + #ifdef _DEBUG setDebugName("StaticText"); -#endif + #endif setText(text); } + //! destructor StaticText::~StaticText() { @@ -54,24 +57,23 @@ void StaticText::draw() if (!IsVisible) return; - IGUISkin *skin = Environment->getSkin(); + IGUISkin* skin = Environment->getSkin(); if (!skin) return; - video::IVideoDriver *driver = Environment->getVideoDriver(); + video::IVideoDriver* driver = Environment->getVideoDriver(); core::rect<s32> frameRect(AbsoluteRect); // draw background if (Background) - driver->draw2DRectangle( - getBackgroundColor(), frameRect, &AbsoluteClippingRect); + driver->draw2DRectangle(getBackgroundColor(), frameRect, &AbsoluteClippingRect); // draw the border - if (Border) { - skin->draw3DSunkenPane( - this, 0, true, false, frameRect, &AbsoluteClippingRect); + if (Border) + { + skin->draw3DSunkenPane(this, 0, true, false, frameRect, &AbsoluteClippingRect); frameRect.UpperLeftCorner.X += skin->getSize(EGDS_TEXT_DISTANCE_X); } @@ -82,52 +84,52 @@ void StaticText::draw() updateText(); core::rect<s32> r = frameRect; - s32 height_line = font->getDimension(L"A").Height + - font->getKerningHeight(); + s32 height_line = font->getDimension(L"A").Height + font->getKerningHeight(); s32 height_total = height_line * BrokenText.size(); - if (VAlign == EGUIA_CENTER && WordWrap) { + if (VAlign == EGUIA_CENTER && WordWrap) + { r.UpperLeftCorner.Y = r.getCenter().Y - (height_total / 2); - } else if (VAlign == EGUIA_LOWERRIGHT) { + } + else if (VAlign == EGUIA_LOWERRIGHT) + { r.UpperLeftCorner.Y = r.LowerRightCorner.Y - height_total; } - if (HAlign == EGUIA_LOWERRIGHT) { - r.UpperLeftCorner.X = r.LowerRightCorner.X - getTextWidth(); + if (HAlign == EGUIA_LOWERRIGHT) + { + r.UpperLeftCorner.X = r.LowerRightCorner.X - + getTextWidth(); } irr::video::SColor previous_color(255, 255, 255, 255); for (const EnrichedString &str : BrokenText) { - if (HAlign == EGUIA_LOWERRIGHT) { - r.UpperLeftCorner.X = - frameRect.LowerRightCorner.X - - font->getDimension(str.c_str()).Width; + if (HAlign == EGUIA_LOWERRIGHT) + { + r.UpperLeftCorner.X = frameRect.LowerRightCorner.X - + font->getDimension(str.c_str()).Width; } - // str = colorizeText(BrokenText[i].c_str(), colors, - // previous_color); if (!colors.empty()) previous_color = - //colors[colors.size() - 1]; + //str = colorizeText(BrokenText[i].c_str(), colors, previous_color); + //if (!colors.empty()) + // previous_color = colors[colors.size() - 1]; #if USE_FREETYPE if (font->getType() == irr::gui::EGFT_CUSTOM) { - irr::gui::CGUITTFont *tmp = - static_cast<irr::gui::CGUITTFont *>(font); - tmp->draw(str, r, previous_color, // FIXME - HAlign == EGUIA_CENTER, - VAlign == EGUIA_CENTER, - (RestrainTextInside ? &AbsoluteClippingRect - : NULL)); + irr::gui::CGUITTFont *tmp = static_cast<irr::gui::CGUITTFont*>(font); + tmp->draw(str, + r, previous_color, // FIXME + HAlign == EGUIA_CENTER, VAlign == EGUIA_CENTER, + (RestrainTextInside ? &AbsoluteClippingRect : NULL)); } else #endif { // Draw non-colored text - font->draw(str.c_str(), r, - str.getDefaultColor(), // TODO: Implement - // colorization - HAlign == EGUIA_CENTER, - VAlign == EGUIA_CENTER, - (RestrainTextInside ? &AbsoluteClippingRect - : NULL)); + font->draw(str.c_str(), + r, str.getDefaultColor(), // TODO: Implement colorization + HAlign == EGUIA_CENTER, VAlign == EGUIA_CENTER, + (RestrainTextInside ? &AbsoluteClippingRect : NULL)); } + r.LowerRightCorner.Y += height_line; r.UpperLeftCorner.Y += height_line; } @@ -136,8 +138,9 @@ void StaticText::draw() IGUIElement::draw(); } + //! Sets another skin independent font. -void StaticText::setOverrideFont(IGUIFont *font) +void StaticText::setOverrideFont(IGUIFont* font) { if (OverrideFont == font) return; @@ -154,17 +157,17 @@ void StaticText::setOverrideFont(IGUIFont *font) } //! Gets the override font (if any) -IGUIFont *StaticText::getOverrideFont() const +IGUIFont * StaticText::getOverrideFont() const { return OverrideFont; } //! Get the font which is used right now for drawing -IGUIFont *StaticText::getActiveFont() const +IGUIFont* StaticText::getActiveFont() const { - if (OverrideFont) + if ( OverrideFont ) return OverrideFont; - IGUISkin *skin = Environment->getSkin(); + IGUISkin* skin = Environment->getSkin(); if (skin) return skin->getFont(); return 0; @@ -177,6 +180,7 @@ void StaticText::setOverrideColor(video::SColor color) updateText(); } + //! Sets another color for the text. void StaticText::setBackgroundColor(video::SColor color) { @@ -184,57 +188,66 @@ void StaticText::setBackgroundColor(video::SColor color) Background = true; } + //! Sets whether to draw the background void StaticText::setDrawBackground(bool draw) { Background = draw; } + //! Gets the background color video::SColor StaticText::getBackgroundColor() const { IGUISkin *skin = Environment->getSkin(); - return (ColoredText.hasBackground() || !skin) ? ColoredText.getBackground() - : skin->getColor(gui::EGDC_3D_FACE); + return (ColoredText.hasBackground() || !skin) ? + ColoredText.getBackground() : skin->getColor(gui::EGDC_3D_FACE); } + //! Checks if background drawing is enabled bool StaticText::isDrawBackgroundEnabled() const { return Background; } + //! Sets whether to draw the border void StaticText::setDrawBorder(bool draw) { Border = draw; } + //! Checks if border drawing is enabled bool StaticText::isDrawBorderEnabled() const { return Border; } + void StaticText::setTextRestrainedInside(bool restrainTextInside) { RestrainTextInside = restrainTextInside; } + bool StaticText::isTextRestrainedInside() const { return RestrainTextInside; } + void StaticText::setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical) { HAlign = horizontal; VAlign = vertical; } + #if IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR <= 7 -const video::SColor &StaticText::getOverrideColor() const +const video::SColor& StaticText::getOverrideColor() const #else video::SColor StaticText::getOverrideColor() const #endif @@ -242,6 +255,7 @@ video::SColor StaticText::getOverrideColor() const return ColoredText.getDefaultColor(); } + //! Sets if the static text should use the overide color or the //! color in the gui skin. void StaticText::enableOverrideColor(bool enable) @@ -249,11 +263,13 @@ void StaticText::enableOverrideColor(bool enable) // TODO } + bool StaticText::isOverrideColorEnabled() const { return true; } + //! Enables or disables word wrap for using the static text as //! multiline text control. void StaticText::setWordWrap(bool enable) @@ -262,24 +278,29 @@ void StaticText::setWordWrap(bool enable) updateText(); } + bool StaticText::isWordWrapEnabled() const { return WordWrap; } + void StaticText::setRightToLeft(bool rtl) { - if (RightToLeft != rtl) { + if (RightToLeft != rtl) + { RightToLeft = rtl; updateText(); } } + bool StaticText::isRightToLeft() const { return RightToLeft; } + //! Breaks the single text line. // Updates the font colors void StaticText::updateText() @@ -299,8 +320,8 @@ void StaticText::updateText() // Update word wrap - IGUISkin *skin = Environment->getSkin(); - IGUIFont *font = getActiveFont(); + IGUISkin* skin = Environment->getSkin(); + IGUIFont* font = getActiveFont(); if (!font) return; @@ -313,96 +334,92 @@ void StaticText::updateText() s32 length = 0; s32 elWidth = RelativeRect.getWidth(); if (Border) - elWidth -= 2 * skin->getSize(EGDS_TEXT_DISTANCE_X); + elWidth -= 2*skin->getSize(EGDS_TEXT_DISTANCE_X); wchar_t c; - // std::vector<irr::video::SColor> colors; + //std::vector<irr::video::SColor> colors; // We have to deal with right-to-left and left-to-right differently // However, most parts of the following code is the same, it's just // some order and boundaries which change. - if (!RightToLeft) { + if (!RightToLeft) + { // regular (left-to-right) - for (s32 i = 0; i < size; ++i) { + for (s32 i=0; i<size; ++i) + { c = cText.getString()[i]; bool lineBreak = false; if (c == L'\r') // Mac or Windows breaks { lineBreak = true; - // if (Text[i+1] == L'\n') // Windows breaks + //if (Text[i+1] == L'\n') // Windows breaks //{ // Text.erase(i+1); // --size; //} c = '\0'; - } else if (c == L'\n') // Unix breaks + } + else if (c == L'\n') // Unix breaks { lineBreak = true; c = '\0'; } bool isWhitespace = (c == L' ' || c == 0); - if (!isWhitespace) { + if ( !isWhitespace ) + { // part of a word - // word += c; + //word += c; word.addChar(cText, i); } - if (isWhitespace || i == (size - 1)) { - if (word.size()) { + if ( isWhitespace || i == (size-1)) + { + if (word.size()) + { // here comes the next whitespace, look if // we must break the last word to the next line. - const s32 whitelgth = - font->getDimension(whitespace.c_str()) - .Width; - // const std::wstring sanitized = - // removeEscapes(word.c_str()); - const s32 wordlgth = - font->getDimension(word.c_str()) - .Width; - - if (wordlgth > elWidth) { - // This word is too long to fit in the - // available space, look for the Unicode - // Soft HYphen (SHY / 00AD) character for - // a place to break the word at - int where = core::stringw(word.c_str()) - .findFirst(wchar_t( - 0x00AD)); - if (where != -1) { - EnrichedString first = word.substr( - 0, where); - EnrichedString second = word.substr( - where, - word.size() - where); + const s32 whitelgth = font->getDimension(whitespace.c_str()).Width; + //const std::wstring sanitized = removeEscapes(word.c_str()); + const s32 wordlgth = font->getDimension(word.c_str()).Width; + + if (wordlgth > elWidth) + { + // This word is too long to fit in the available space, look for + // the Unicode Soft HYphen (SHY / 00AD) character for a place to + // break the word at + int where = core::stringw(word.c_str()).findFirst( wchar_t(0x00AD) ); + if (where != -1) + { + EnrichedString first = word.substr(0, where); + EnrichedString second = word.substr(where, word.size() - where); first.addCharNoColor(L'-'); - BrokenText.push_back( - line + first); - const s32 secondLength = - font->getDimension(second.c_str()) - .Width; + BrokenText.push_back(line + first); + const s32 secondLength = font->getDimension(second.c_str()).Width; length = secondLength; line = second; - } else { - // No soft hyphen found, so - // there's nothing more we can do + } + else + { + // No soft hyphen found, so there's nothing more we can do // break to next line if (length) - BrokenText.push_back( - line); + BrokenText.push_back(line); length = wordlgth; line = word; } - } else if (length && - (length + wordlgth + whitelgth > - elWidth)) { + } + else if (length && (length + wordlgth + whitelgth > elWidth)) + { // break to next line BrokenText.push_back(line); length = wordlgth; line = word; - } else { + } + else + { // add word to line line += whitespace; line += word; @@ -413,12 +430,14 @@ void StaticText::updateText() whitespace.clear(); } - if (isWhitespace && c != 0) { + if ( isWhitespace && c != 0) + { whitespace.addChar(cText, i); } // compute line break - if (lineBreak) { + if (lineBreak) + { line += whitespace; line += word; BrokenText.push_back(line); @@ -433,45 +452,49 @@ void StaticText::updateText() line += whitespace; line += word; BrokenText.push_back(line); - } else { + } + else + { // right-to-left - for (s32 i = size; i >= 0; --i) { + for (s32 i=size; i>=0; --i) + { c = cText.getString()[i]; bool lineBreak = false; if (c == L'\r') // Mac or Windows breaks { lineBreak = true; - // if ((i>0) && Text[i-1] == L'\n') // Windows breaks + //if ((i>0) && Text[i-1] == L'\n') // Windows breaks //{ // Text.erase(i-1); // --size; //} c = '\0'; - } else if (c == L'\n') // Unix breaks + } + else if (c == L'\n') // Unix breaks { lineBreak = true; c = '\0'; } - if (c == L' ' || c == 0 || i == 0) { - if (word.size()) { + if (c==L' ' || c==0 || i==0) + { + if (word.size()) + { // here comes the next whitespace, look if // we must break the last word to the next line. - const s32 whitelgth = - font->getDimension(whitespace.c_str()) - .Width; - const s32 wordlgth = - font->getDimension(word.c_str()) - .Width; - - if (length && (length + wordlgth + whitelgth > - elWidth)) { + const s32 whitelgth = font->getDimension(whitespace.c_str()).Width; + const s32 wordlgth = font->getDimension(word.c_str()).Width; + + if (length && (length + wordlgth + whitelgth > elWidth)) + { // break to next line BrokenText.push_back(line); length = wordlgth; line = word; - } else { + } + else + { // add word to line line = whitespace + line; line = word + line; @@ -483,12 +506,12 @@ void StaticText::updateText() } if (c != 0) - // whitespace = core::stringw(&c, 1) + - //whitespace; - whitespace = cText.substr(i, 1) + whitespace; + // whitespace = core::stringw(&c, 1) + whitespace; + whitespace = cText.substr(i, 1) + whitespace; // compute line break - if (lineBreak) { + if (lineBreak) + { line = whitespace + line; line = word + line; BrokenText.push_back(line); @@ -497,9 +520,11 @@ void StaticText::updateText() whitespace.clear(); length = 0; } - } else { + } + else + { // yippee this is a word.. - // word = core::stringw(&c, 1) + word; + //word = core::stringw(&c, 1) + word; word = cText.substr(i, 1) + word; } } @@ -510,8 +535,9 @@ void StaticText::updateText() } } + //! Sets the new caption of this element. -void StaticText::setText(const wchar_t *text) +void StaticText::setText(const wchar_t* text) { setText(EnrichedString(text, getOverrideColor())); } @@ -529,10 +555,11 @@ void StaticText::updateAbsolutePosition() updateText(); } + //! Returns the height of the text in pixels when it is drawn. s32 StaticText::getTextHeight() const { - IGUIFont *font = getActiveFont(); + IGUIFont* font = getActiveFont(); if (!font) return 0; @@ -544,6 +571,7 @@ s32 StaticText::getTextHeight() const return font->getDimension(BrokenText[0].c_str()).Height; } + s32 StaticText::getTextWidth() const { IGUIFont *font = getActiveFont(); @@ -562,34 +590,34 @@ s32 StaticText::getTextWidth() const return widest; } + //! Writes attributes of the element. //! Implement this to expose the attributes of your element for //! scripting languages, editors, debuggers or xml serialization purposes. -void StaticText::serializeAttributes( - io::IAttributes *out, io::SAttributeReadWriteOptions *options = 0) const -{ - IGUIStaticText::serializeAttributes(out, options); - - out->addBool("Border", Border); - out->addBool("OverrideColorEnabled", true); - out->addBool("OverrideBGColorEnabled", ColoredText.hasBackground()); - out->addBool("WordWrap", WordWrap); - out->addBool("Background", Background); - out->addBool("RightToLeft", RightToLeft); - out->addBool("RestrainTextInside", RestrainTextInside); - out->addColor("OverrideColor", ColoredText.getDefaultColor()); - out->addColor("BGColor", ColoredText.getBackground()); - out->addEnum("HTextAlign", HAlign, GUIAlignmentNames); - out->addEnum("VTextAlign", VAlign, GUIAlignmentNames); +void StaticText::serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options=0) const +{ + IGUIStaticText::serializeAttributes(out,options); + + out->addBool ("Border", Border); + out->addBool ("OverrideColorEnabled",true); + out->addBool ("OverrideBGColorEnabled",ColoredText.hasBackground()); + out->addBool ("WordWrap", WordWrap); + out->addBool ("Background", Background); + out->addBool ("RightToLeft", RightToLeft); + out->addBool ("RestrainTextInside", RestrainTextInside); + out->addColor ("OverrideColor", ColoredText.getDefaultColor()); + out->addColor ("BGColor", ColoredText.getBackground()); + out->addEnum ("HTextAlign", HAlign, GUIAlignmentNames); + out->addEnum ("VTextAlign", VAlign, GUIAlignmentNames); // out->addFont ("OverrideFont", OverrideFont); } + //! Reads attributes of the element -void StaticText::deserializeAttributes( - io::IAttributes *in, io::SAttributeReadWriteOptions *options = 0) +void StaticText::deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options=0) { - IGUIStaticText::deserializeAttributes(in, options); + IGUIStaticText::deserializeAttributes(in,options); Border = in->getAttributeAsBool("Border"); setWordWrap(in->getAttributeAsBool("WordWrap")); @@ -601,10 +629,8 @@ void StaticText::deserializeAttributes( if (in->getAttributeAsBool("OverrideBGColorEnabled")) ColoredText.setBackground(in->getAttributeAsColor("BGColor")); - setTextAlignment((EGUI_ALIGNMENT)in->getAttributeAsEnumeration( - "HTextAlign", GUIAlignmentNames), - (EGUI_ALIGNMENT)in->getAttributeAsEnumeration( - "VTextAlign", GUIAlignmentNames)); + setTextAlignment( (EGUI_ALIGNMENT) in->getAttributeAsEnumeration("HTextAlign", GUIAlignmentNames), + (EGUI_ALIGNMENT) in->getAttributeAsEnumeration("VTextAlign", GUIAlignmentNames)); // OverrideFont = in->getAttributeAsFont("OverrideFont"); } @@ -615,4 +641,5 @@ void StaticText::deserializeAttributes( } // end namespace irr + #endif // _IRR_COMPILE_WITH_GUI_ diff --git a/src/irrlicht_changes/static_text.h b/src/irrlicht_changes/static_text.h index 5c4db3e95..1f111ea56 100644 --- a/src/irrlicht_changes/static_text.h +++ b/src/irrlicht_changes/static_text.h @@ -28,202 +28,207 @@ namespace irr namespace gui { -const EGUI_ELEMENT_TYPE EGUIET_ENRICHED_STATIC_TEXT = (EGUI_ELEMENT_TYPE)(0x1000); + const EGUI_ELEMENT_TYPE EGUIET_ENRICHED_STATIC_TEXT = (EGUI_ELEMENT_TYPE)(0x1000); -class StaticText : public IGUIStaticText -{ -public: - // StaticText is translated by EnrichedString. - // No need to use translate_string() - StaticText(const EnrichedString &text, bool border, IGUIEnvironment *environment, - IGUIElement *parent, s32 id, const core::rect<s32> &rectangle, + class StaticText : public IGUIStaticText + { + public: + + // StaticText is translated by EnrichedString. + // No need to use translate_string() + StaticText(const EnrichedString &text, bool border, IGUIEnvironment* environment, + IGUIElement* parent, s32 id, const core::rect<s32>& rectangle, bool background = false); - //! destructor - virtual ~StaticText(); + //! destructor + virtual ~StaticText(); + + static irr::gui::IGUIStaticText *add( + irr::gui::IGUIEnvironment *guienv, + const EnrichedString &text, + const core::rect< s32 > &rectangle, + bool border = false, + bool wordWrap = true, + irr::gui::IGUIElement *parent = NULL, + s32 id = -1, + bool fillBackground = false) + { + if (parent == NULL) { + // parent is NULL, so we must find one, or we need not to drop + // result, but then there will be a memory leak. + // + // What Irrlicht does is to use guienv as a parent, but the problem + // is that guienv is here only an IGUIEnvironment, while it is a + // CGUIEnvironment in Irrlicht, which inherits from both IGUIElement + // and IGUIEnvironment. + // + // A solution would be to dynamic_cast guienv to a + // IGUIElement*, but Irrlicht is shipped without rtti support + // in some distributions, causing the dymanic_cast to segfault. + // + // Thus, to find the parent, we create a dummy StaticText and ask + // for its parent, and then remove it. + irr::gui::IGUIStaticText *dummy_text = + guienv->addStaticText(L"", rectangle, border, wordWrap, + parent, id, fillBackground); + parent = dummy_text->getParent(); + dummy_text->remove(); + } + irr::gui::IGUIStaticText *result = new irr::gui::StaticText( + text, border, guienv, parent, + id, rectangle, fillBackground); + + result->setWordWrap(wordWrap); + result->drop(); + return result; + } - static irr::gui::IGUIStaticText *add(irr::gui::IGUIEnvironment *guienv, - const EnrichedString &text, const core::rect<s32> &rectangle, - bool border = false, bool wordWrap = true, - irr::gui::IGUIElement *parent = NULL, s32 id = -1, + static irr::gui::IGUIStaticText *add( + irr::gui::IGUIEnvironment *guienv, + const wchar_t *text, + const core::rect< s32 > &rectangle, + bool border = false, + bool wordWrap = true, + irr::gui::IGUIElement *parent = NULL, + s32 id = -1, bool fillBackground = false) - { - if (parent == NULL) { - // parent is NULL, so we must find one, or we need not to drop - // result, but then there will be a memory leak. - // - // What Irrlicht does is to use guienv as a parent, but the - // problem is that guienv is here only an IGUIEnvironment, while - // it is a CGUIEnvironment in Irrlicht, which inherits from both - // IGUIElement and IGUIEnvironment. - // - // A solution would be to dynamic_cast guienv to a - // IGUIElement*, but Irrlicht is shipped without rtti support - // in some distributions, causing the dymanic_cast to segfault. - // - // Thus, to find the parent, we create a dummy StaticText and ask - // for its parent, and then remove it. - irr::gui::IGUIStaticText *dummy_text = guienv->addStaticText(L"", - rectangle, border, wordWrap, parent, id, - fillBackground); - parent = dummy_text->getParent(); - dummy_text->remove(); + { + return add(guienv, EnrichedString(text), rectangle, border, wordWrap, parent, + id, fillBackground); } - irr::gui::IGUIStaticText *result = new irr::gui::StaticText(text, border, - guienv, parent, id, rectangle, fillBackground); - result->setWordWrap(wordWrap); - result->drop(); - return result; - } + //! draws the element and its children + virtual void draw(); - static irr::gui::IGUIStaticText *add(irr::gui::IGUIEnvironment *guienv, - const wchar_t *text, const core::rect<s32> &rectangle, - bool border = false, bool wordWrap = true, - irr::gui::IGUIElement *parent = NULL, s32 id = -1, - bool fillBackground = false) - { - return add(guienv, EnrichedString(text), rectangle, border, wordWrap, - parent, id, fillBackground); - } + //! Sets another skin independent font. + virtual void setOverrideFont(IGUIFont* font=0); - //! draws the element and its children - virtual void draw(); + //! Gets the override font (if any) + virtual IGUIFont* getOverrideFont() const; - //! Sets another skin independent font. - virtual void setOverrideFont(IGUIFont *font = 0); + //! Get the font which is used right now for drawing + virtual IGUIFont* getActiveFont() const; - //! Gets the override font (if any) - virtual IGUIFont *getOverrideFont() const; + //! Sets another color for the text. + virtual void setOverrideColor(video::SColor color); - //! Get the font which is used right now for drawing - virtual IGUIFont *getActiveFont() const; + //! Sets another color for the background. + virtual void setBackgroundColor(video::SColor color); - //! Sets another color for the text. - virtual void setOverrideColor(video::SColor color); + //! Sets whether to draw the background + virtual void setDrawBackground(bool draw); - //! Sets another color for the background. - virtual void setBackgroundColor(video::SColor color); + //! Gets the background color + virtual video::SColor getBackgroundColor() const; - //! Sets whether to draw the background - virtual void setDrawBackground(bool draw); + //! Checks if background drawing is enabled + virtual bool isDrawBackgroundEnabled() const; - //! Gets the background color - virtual video::SColor getBackgroundColor() const; + //! Sets whether to draw the border + virtual void setDrawBorder(bool draw); - //! Checks if background drawing is enabled - virtual bool isDrawBackgroundEnabled() const; + //! Checks if border drawing is enabled + virtual bool isDrawBorderEnabled() const; - //! Sets whether to draw the border - virtual void setDrawBorder(bool draw); + //! Sets alignment mode for text + virtual void setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical); - //! Checks if border drawing is enabled - virtual bool isDrawBorderEnabled() const; + //! Gets the override color + #if IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR <= 7 + virtual const video::SColor& getOverrideColor() const; + #else + virtual video::SColor getOverrideColor() const; + #endif - //! Sets alignment mode for text - virtual void setTextAlignment(EGUI_ALIGNMENT horizontal, EGUI_ALIGNMENT vertical); + //! Sets if the static text should use the overide color or the + //! color in the gui skin. + virtual void enableOverrideColor(bool enable); -//! Gets the override color -#if IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR <= 7 - virtual const video::SColor &getOverrideColor() const; -#else - virtual video::SColor getOverrideColor() const; -#endif + //! Checks if an override color is enabled + virtual bool isOverrideColorEnabled() const; - //! Sets if the static text should use the overide color or the - //! color in the gui skin. - virtual void enableOverrideColor(bool enable); + //! Set whether the text in this label should be clipped if it goes outside bounds + virtual void setTextRestrainedInside(bool restrainedInside); - //! Checks if an override color is enabled - virtual bool isOverrideColorEnabled() const; + //! Checks if the text in this label should be clipped if it goes outside bounds + virtual bool isTextRestrainedInside() const; - //! Set whether the text in this label should be clipped if it goes outside bounds - virtual void setTextRestrainedInside(bool restrainedInside); + //! Enables or disables word wrap for using the static text as + //! multiline text control. + virtual void setWordWrap(bool enable); - //! Checks if the text in this label should be clipped if it goes outside bounds - virtual bool isTextRestrainedInside() const; + //! Checks if word wrap is enabled + virtual bool isWordWrapEnabled() const; - //! Enables or disables word wrap for using the static text as - //! multiline text control. - virtual void setWordWrap(bool enable); + //! Sets the new caption of this element. + virtual void setText(const wchar_t* text); - //! Checks if word wrap is enabled - virtual bool isWordWrapEnabled() const; + //! Returns the height of the text in pixels when it is drawn. + virtual s32 getTextHeight() const; - //! Sets the new caption of this element. - virtual void setText(const wchar_t *text); + //! Returns the width of the current text, in the current font + virtual s32 getTextWidth() const; - //! Returns the height of the text in pixels when it is drawn. - virtual s32 getTextHeight() const; + //! Updates the absolute position, splits text if word wrap is enabled + virtual void updateAbsolutePosition(); - //! Returns the width of the current text, in the current font - virtual s32 getTextWidth() const; + //! Set whether the string should be interpreted as right-to-left (RTL) text + /** \note This component does not implement the Unicode bidi standard, the + text of the component should be already RTL if you call this. The + main difference when RTL is enabled is that the linebreaks for multiline + elements are performed starting from the end. + */ + virtual void setRightToLeft(bool rtl); - //! Updates the absolute position, splits text if word wrap is enabled - virtual void updateAbsolutePosition(); + //! Checks if the text should be interpreted as right-to-left text + virtual bool isRightToLeft() const; - //! Set whether the string should be interpreted as right-to-left (RTL) text - /** \note This component does not implement the Unicode bidi standard, the - text of the component should be already RTL if you call this. The - main difference when RTL is enabled is that the linebreaks for multiline - elements are performed starting from the end. - */ - virtual void setRightToLeft(bool rtl); + //! Writes attributes of the element. + virtual void serializeAttributes(io::IAttributes* out, io::SAttributeReadWriteOptions* options) const; - //! Checks if the text should be interpreted as right-to-left text - virtual bool isRightToLeft() const; + //! Reads attributes of the element + virtual void deserializeAttributes(io::IAttributes* in, io::SAttributeReadWriteOptions* options); - //! Writes attributes of the element. - virtual void serializeAttributes(io::IAttributes *out, - io::SAttributeReadWriteOptions *options) const; + virtual bool hasType(EGUI_ELEMENT_TYPE t) const { + return (t == EGUIET_ENRICHED_STATIC_TEXT) || (t == EGUIET_STATIC_TEXT); + }; - //! Reads attributes of the element - virtual void deserializeAttributes( - io::IAttributes *in, io::SAttributeReadWriteOptions *options); + virtual bool hasType(EGUI_ELEMENT_TYPE t) { + return (t == EGUIET_ENRICHED_STATIC_TEXT) || (t == EGUIET_STATIC_TEXT); + }; - virtual bool hasType(EGUI_ELEMENT_TYPE t) const - { - return (t == EGUIET_ENRICHED_STATIC_TEXT) || (t == EGUIET_STATIC_TEXT); - }; + void setText(const EnrichedString &text); - virtual bool hasType(EGUI_ELEMENT_TYPE t) - { - return (t == EGUIET_ENRICHED_STATIC_TEXT) || (t == EGUIET_STATIC_TEXT); - }; + private: - void setText(const EnrichedString &text); + //! Breaks the single text line. + void updateText(); -private: - //! Breaks the single text line. - void updateText(); + EGUI_ALIGNMENT HAlign, VAlign; + bool Border; + bool WordWrap; + bool Background; + bool RestrainTextInside; + bool RightToLeft; - EGUI_ALIGNMENT HAlign, VAlign; - bool Border; - bool WordWrap; - bool Background; - bool RestrainTextInside; - bool RightToLeft; + gui::IGUIFont* OverrideFont; + gui::IGUIFont* LastBreakFont; // stored because: if skin changes, line break must be recalculated. - gui::IGUIFont *OverrideFont; - gui::IGUIFont *LastBreakFont; // stored because: if skin changes, line break must - // be recalculated. + EnrichedString ColoredText; + std::vector<EnrichedString> BrokenText; + }; - EnrichedString ColoredText; - std::vector<EnrichedString> BrokenText; -}; } // end namespace gui } // end namespace irr -inline void setStaticText( - irr::gui::IGUIStaticText *static_text, const EnrichedString &text) +inline void setStaticText(irr::gui::IGUIStaticText *static_text, const EnrichedString &text) { // dynamic_cast not possible due to some distributions shipped // without rtti support in irrlicht if (static_text->hasType(irr::gui::EGUIET_ENRICHED_STATIC_TEXT)) { - irr::gui::StaticText *stext = - static_cast<irr::gui::StaticText *>(static_text); + irr::gui::StaticText* stext = static_cast<irr::gui::StaticText*>(static_text); stext->setText(text); } else { static_text->setText(text.c_str()); @@ -240,14 +245,17 @@ namespace gui class StaticText { public: - static irr::gui::IGUIStaticText *add(irr::gui::IGUIEnvironment *guienv, - const EnrichedString &text, const core::rect<s32> &rectangle, - bool border = false, bool wordWrap = true, - irr::gui::IGUIElement *parent = NULL, s32 id = -1, - bool fillBackground = false) + static irr::gui::IGUIStaticText *add( + irr::gui::IGUIEnvironment *guienv, + const EnrichedString &text, + const core::rect< s32 > &rectangle, + bool border = false, + bool wordWrap = true, + irr::gui::IGUIElement *parent = NULL, + s32 id = -1, + bool fillBackground = false) { - return guienv->addStaticText(text.c_str(), rectangle, border, wordWrap, - parent, id, fillBackground); + return guienv->addStaticText(text.c_str(), rectangle, border, wordWrap, parent, id, fillBackground); } }; @@ -255,8 +263,7 @@ public: } // end namespace irr -inline void setStaticText( - irr::gui::IGUIStaticText *static_text, const EnrichedString &text) +inline void setStaticText(irr::gui::IGUIStaticText *static_text, const EnrichedString &text) { static_text->setText(text.c_str()); } |