/** * Returns 1 (true) if the font object type 1 passed as a parameter * exists and is added successfully to the manager loading the font directly from * ::IND_Image object and a configuration file, both generated with MudFont * (modified version for IndieLib can be found in the section tools). * * The posibility of changing the font from an ::IND_Image object is offered in case * that you want to change the original font with any modification or filter from * ::IND_ImageManager. * * @param pNewFont Pointer to a new object type 1 font. * @param pImage Pointer to an object ::IND_Image that contains a previously loaded font from a graphic file generated by MudFont (see tools section). * @param pFile Name of the configuration file of the font generated by MudFont (see tools section). * @param pType Font type (see ::IND_Type). * @param pQuality Font quality (see ::IND_Quality). */ bool IND_FontManager::addMudFont(IND_Font *pNewFont, IND_Image *pImage, const char *pFile, IND_Type pType, IND_Quality pQuality) { g_debug->header("Parsing and loading MudFont font", DebugApi::LogHeaderBegin); g_debug->header("File name:", DebugApi::LogHeaderInfo); g_debug->dataChar(pFile, 1); if (!_ok) { writeMessage(); return 0; } // ----- Width and height of the bitmap font MUST be power of two ----- IND_Math mMath; if (!mMath.isPowerOfTwo(pImage->getWidth()) || !mMath.isPowerOfTwo(pImage->getHeight())) { g_debug->header("This operation can not be done", DebugApi::LogHeaderInfo); g_debug->dataChar("", 1); g_debug->header("The height and width of the MudFont font must be power of 2", DebugApi::LogHeaderError); return 0; } // ----- XML font parsing ----- if (!parseMudFont(pNewFont, pFile)) { g_debug->header("Fatal error, cannot load the MudFont font xml file", DebugApi::LogHeaderError); return 0; } pNewFont->setFileName(pFile); // ----- Bitmap (IND_Surface object) creation ----- IND_Surface *mNewSurface = IND_Surface::newSurface(); if (!_surfaceManager->add(mNewSurface, pImage, pType, pQuality)) return 0; // IND_Surface object MUST have one block ONLY if (mNewSurface->getNumBlocks() > 1) { _surfaceManager->remove(mNewSurface); return 0; } pNewFont->setSurface(mNewSurface); // ----- Puts the object into the manager ----- addToList(pNewFont); // ----- g_debug ----- g_debug->header("MudFont font parsed and loaded", DebugApi::LogHeaderEnd); return 1; }
/* ================== Parses an Angelcode XML font file Uses Tinyxml ================== */ bool IND_FontManager::parseAngelCodeFont(IND_Font *pNewFont,const char *pFileName, IND_Type pType, IND_Quality pQuality) { TiXmlDocument *mXmlDoc = new TiXmlDocument(pFileName); // Fatal error, cannot load if (!mXmlDoc->LoadFile()) { DISPOSE(mXmlDoc); return 0; } // Setting font filename pNewFont->setFileName(pFileName); // Setting the type of the font pNewFont->setFontType(IND_Font::FONTTYPE_AngelCode); // Document root TiXmlElement *mXFont = 0; mXFont = mXmlDoc->FirstChildElement("font"); if (!mXFont) { g_debug->header("Invalid name for document root, should be <font>", DebugApi::LogHeaderError); mXmlDoc->Clear(); delete mXmlDoc; return 0; } //TODO : info element variables ... maybe //TODO : common element variables ... maybe //TODO : pages, this one needs to be done ... MudFont have (allways?) just one page .. Angelcode can have multiple // Image loading // Pages element TiXmlElement *mXPages = 0; mXPages = mXFont->FirstChildElement("pages"); if (!mXPages) { g_debug->header("The <font> element doesn't have a <pages> child element", DebugApi::LogHeaderError); mXmlDoc->Clear(); delete mXmlDoc; return 0; } // Page element TiXmlElement *mXPage = 0; mXPage = mXPages->FirstChildElement("page"); if (!mXPage) { g_debug->header("There are no <page> elements to parse", DebugApi::LogHeaderError); mXmlDoc->Clear(); delete mXmlDoc; return 0; } // Parse each page int mPageCount = 0; while (mXPage) { // Id if (mXPage->Attribute("id")) { //pNewFont->getLetters() [mCharCount]._letter = static_cast<unsigned char>(atoi(mXChar->Attribute("id"))); //TODO : FIXME !! id refers to font image, starting from 0 -> } else { g_debug->header("The <page> element doesn't have a \"id\" attribute", DebugApi::LogHeaderError); mXmlDoc->Clear(); delete mXmlDoc; return 0; } // File if (mXPage->Attribute("file")) { IND_Image *mNewImage = IND_Image::newImage(); bool noImgError = _imageManager->add(mNewImage, mXPage->Attribute("file")); if (!noImgError) { DISPOSEMANAGED(mNewImage); g_debug->header("Failed at adding page image for Angelcode font", DebugApi::LogHeaderError); mXmlDoc->Clear(); delete mXmlDoc; return 0; } // ----- Width and height of the bitmap font MUST be power of two ----- IND_Math mMath; if (!mMath.isPowerOfTwo(mNewImage->getWidth()) || !mMath.isPowerOfTwo(mNewImage->getHeight())) { g_debug->header("This operation can not be done", DebugApi::LogHeaderInfo); g_debug->dataChar("", 1); g_debug->header("The height and width of the AngelCode font font must be power of 2", DebugApi::LogHeaderError); mXmlDoc->Clear(); delete mXmlDoc; return 0; } // ----- Bitmap (IND_Surface object) creation ----- IND_Surface *mNewSurface = IND_Surface::newSurface(); if (!_surfaceManager->add(mNewSurface, mNewImage, pType, pQuality)) { mXmlDoc->Clear(); delete mXmlDoc; return 0; } // IND_Surface object MUST have one block ONLY if (mNewSurface->getNumBlocks() > 1) { mXmlDoc->Clear(); delete mXmlDoc; _surfaceManager->remove(mNewSurface); return 0; } pNewFont->setSurface(mNewSurface); // TODO: somehow handle more than one font surface, - this relates to the "id" attribute parsed.. } else { g_debug->header("The <page> element doesn't have a \"file\" attribute", DebugApi::LogHeaderError); mXmlDoc->Clear(); delete mXmlDoc; return 0; } // Move to the next char declaration mXPage = mXPage->NextSiblingElement("page"); mPageCount++; } // Chars element TiXmlElement *mXChars = 0; mXChars = mXFont->FirstChildElement("chars"); if (!mXChars) { g_debug->header("The <font> element doesn't have a <chars> child element", DebugApi::LogHeaderError); mXmlDoc->Clear(); delete mXmlDoc; return 0; } if (mXChars->Attribute("count")) { pNewFont->setNumChars(atoi(mXChars->Attribute("count"))); pNewFont->setLetters(new IND_Font::LETTER [pNewFont->getNumChars()]); } else { g_debug->header("The <chars> element doesn't have a \"count\" attribute", DebugApi::LogHeaderError); mXmlDoc->Clear(); delete mXmlDoc; return 0; } // Char element TiXmlElement *mXChar = 0; mXChar = mXChars->FirstChildElement("char"); if (!mXChar) { g_debug->header("There are no <char> elements to parse", DebugApi::LogHeaderError); mXmlDoc->Clear(); delete mXmlDoc; return 0; } // Parse each char int mCharCount = 0; while (mXChar) { // Id if (mXChar->Attribute("id")) { pNewFont->getLetters() [mCharCount]._letter = static_cast<unsigned char>(atoi(mXChar->Attribute("id"))); } else { g_debug->header("The <char> element doesn't have a \"id\" attribute", DebugApi::LogHeaderError); mXmlDoc->Clear(); delete mXmlDoc; return 0; } // x if (mXChar->Attribute("x")) { pNewFont->getLetters() [mCharCount]._x = atoi(mXChar->Attribute("x")); } else { g_debug->header("The <char> element doesn't have a \"x\" attribute", DebugApi::LogHeaderError); mXmlDoc->Clear(); delete mXmlDoc; return 0; } // y if (mXChar->Attribute("y")) { pNewFont->getLetters() [mCharCount]._y = atoi(mXChar->Attribute("y")); } else { g_debug->header("The <char> element doesn't have a \"y\" attribute", DebugApi::LogHeaderError); mXmlDoc->Clear(); delete mXmlDoc; return 0; } // width if (mXChar->Attribute("width")) { pNewFont->getLetters() [mCharCount]._width = atoi(mXChar->Attribute("width")); } else { g_debug->header("The <char> element doesn't have a \"width\" attribute", DebugApi::LogHeaderError); mXmlDoc->Clear(); delete mXmlDoc; return 0; } // height if (mXChar->Attribute("height")) { pNewFont->getLetters() [mCharCount]._height = atoi(mXChar->Attribute("height")); } else { g_debug->header("The <char> element doesn't have a \"height\" attribute", DebugApi::LogHeaderError); mXmlDoc->Clear(); delete mXmlDoc; return 0; } // xoffset if (mXChar->Attribute("xoffset")) { pNewFont->getLetters() [mCharCount]._xOffset = atoi(mXChar->Attribute("xoffset")); } else { g_debug->header("The char doesn't have a \"xoffset\" attribute", DebugApi::LogHeaderError); mXmlDoc->Clear(); delete mXmlDoc; return 0; } // yoffset if (mXChar->Attribute("yoffset")) { pNewFont->getLetters() [mCharCount]._yOffset = atoi(mXChar->Attribute("yoffset")); } else { g_debug->header("The <char> element doesn't have a \"yoffset\" attribute", DebugApi::LogHeaderError); mXmlDoc->Clear(); delete mXmlDoc; return 0; } // xadvance if (mXChar->Attribute("xadvance")) { pNewFont->getLetters() [mCharCount]._xAdvance = atoi(mXChar->Attribute("xadvance")); } else { g_debug->header("The <char> element doesn't have a \"xadvance\" attribute", DebugApi::LogHeaderError); mXmlDoc->Clear(); delete mXmlDoc; return 0; } // page if (mXChar->Attribute("page")) { pNewFont->getLetters() [mCharCount]._page = atoi(mXChar->Attribute("page")); } else { g_debug->header("The <char> element doesn't have a \"page\" attribute", DebugApi::LogHeaderError); mXmlDoc->Clear(); delete mXmlDoc; return 0; } // chnl if (mXChar->Attribute("chnl")) { pNewFont->getLetters() [mCharCount]._chnl = atoi(mXChar->Attribute("chnl")); } else { g_debug->header("The <char> element doesn't have a \"chnl\" attribute", DebugApi::LogHeaderError); mXmlDoc->Clear(); delete mXmlDoc; return 0; } // Move to the next char declaration mXChar = mXChar->NextSiblingElement("char"); mCharCount++; } // Kernings element TiXmlElement *mXKernings = 0; mXKernings = mXFont->FirstChildElement("kernings"); if (!mXKernings) { g_debug->header("The <font> element doesn't have a <kernings> child element", DebugApi::LogHeaderError); mXmlDoc->Clear(); delete mXmlDoc; return 0; } if (mXKernings->Attribute("count")) { pNewFont->setNumKernings(atoi(mXKernings->Attribute("count"))); pNewFont->setKernings(new IND_Font::KERNING [pNewFont->getNumKernings()]); } else { g_debug->header("The <kernings> element doesn't have a \"count\" attribute", DebugApi::LogHeaderError); mXmlDoc->Clear(); delete mXmlDoc; return 0; } // Kerning element TiXmlElement *mXKerning = 0; mXKerning = mXKernings->FirstChildElement("kerning"); if (!mXKerning) { g_debug->header("There are no <kerning> elements to parse", DebugApi::LogHeaderError); mXmlDoc->Clear(); delete mXmlDoc; return 0; } // Parse each kerning int mKerCount = 0; while (mXKerning) { // First if (mXKerning->Attribute("first")) { pNewFont->getKernings()[mKerCount]._first = atoi(mXKerning->Attribute("first")); } else { g_debug->header("The <kerning> element doesn't have a \"first\" attribute", DebugApi::LogHeaderError); mXmlDoc->Clear(); delete mXmlDoc; return 0; } // Second if (mXKerning->Attribute("second")) { pNewFont->getKernings()[mKerCount]._second = atoi(mXKerning->Attribute("second")); } else { g_debug->header("The <kerning> element doesn't have a \"second\" attribute", DebugApi::LogHeaderError); mXmlDoc->Clear(); delete mXmlDoc; return 0; } // Amount if (mXKerning->Attribute("amount")) { pNewFont->getKernings()[mKerCount]._amount = atoi(mXKerning->Attribute("amount")); } else { g_debug->header("The <kerning> element doesn't have a \"second\" attribute", DebugApi::LogHeaderError); mXmlDoc->Clear(); delete mXmlDoc; return 0; } // Move to the next kerning declaration mXKerning = mXKerning->NextSiblingElement("kerning"); mKerCount++; } mXmlDoc->Clear(); delete mXmlDoc; return 1; }