cocos2dx windows phone平台下CCLabelTTF自己主动换行的实现(2)

前几天发过一篇文章说怎样实现wp8下的CCLabelTTF怎样自己主动换行,后来发现果如预料的那般。效果非常不好。主要是非等宽字体的情况下看着非常糟心。因此再改动了一版。效果要好非常多了。

详细实现事实上就是參考initGlyphs,可是会不断的检查是否超过宽度。假设超过则自己主动换行。

详细的直接看代码就明确了

/****************************************************************************
Copyright (c) 2010 cocos2d-x.org
Copyright (c) Microsoft Open Technologies, Inc.

http://www.cocos2d-x.org

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/

#ifndef __PLATFORM_WINRT_FREETYPE_H__
#define __PLATFORM_WINRT_FREETYPE_H__

#include "platform/CCCommon.h"
#include "platform/CCImage.h"
#include <string>
#include <vector>
#include <memory>

#define generic GenericFromFreeTypeLibrary
#define internal InternalFromFreeTypeLibrary
#include <ft2build.h>
#include <freetype/freetype.h>
#include <freetype/ftglyph.h>
#include <freetype/ftoutln.h>
#include <freetype/fttrigon.h>
#undef generic
#undef internal

NS_CC_BEGIN

typedef struct TGlyph_
{
        FT_UInt    index;  // glyph index
    FT_Vector  pos;    // glyph origin on the baseline
        FT_Glyph   image;  // glyph image
} TGlyph, *PGlyph;

typedef struct FontBufferInfo
{
        unsigned char*  pBuffer;
        unsigned long  size;
} FontBufferInfo;

typedef struct FTWordInfo
{
        std::vector<TGlyph> glyphs; // glyphs for the word
        FT_BBox             bbox;   // bounding box containing all of the glyphs in the word
} FTWordInfo;

typedef struct FTLineInfo
{
        std::vector<TGlyph> glyphs;     // glyphs for the line text
        FT_BBox             bbox;       // bounding box containing all of the glyphs in the line
    unsigned int        width;      // width of the line
    FT_Vector           pen;        // current pen position
} FTLineInfo;

class CC_DLL CCFreeTypeFont
{
public:
    CCFreeTypeFont();
    ~CCFreeTypeFont();

        bool initWithString(
        const char* pText,
        const char* pFontName,
        int         nSize,
        int         width,
        int         height
    );

    unsigned char* getBitmap(
        CCImage::ETextAlign eAlignMask,
        int* outWidth,
        int* outHeight
    );

private:
        unsigned char* loadFont(const char *pFontName, unsigned long *size);

    unsigned char* CCFreeTypeFont::loadSystemFont(const char *pFontName, unsigned long *size);

    FT_Error CCFreeTypeFont::initGlyphs(const char* text);

        void compute_bbox(std::vector<TGlyph>& glyphs, FT_BBox  *abbox);

    void drawText(FTLineInfo* pInfo, unsigned char* pBuffer, FT_Vector *pen);

    void draw_bitmap(unsigned char* pBuffer, FT_Bitmap*  bitmap,FT_Int x,FT_Int y);

    void reset();

    FT_Vector getPenForAlignment(FTLineInfo* pInfo, CCImage::ETextAlign eAlignMask, int lineNumber, int totalLines);

        FT_Error addLine(const std::string& line);
    void newLine();
    void endLine();

    const std::string m_space;

        std::string             m_text;
        std::string             m_fontName;
        FT_Face                 m_face;
        std::vector<FTLineInfo*> m_lines;

    int             m_inWidth;      // requested width of text box
    int             m_inHeight;     // requested height of text box
    int             m_width;        // final bitMap width
    int             m_height;       // final bitMap height
    int             m_textWidth;    // width of text text after word wrapping and line breaks
    int             m_textHeight;   // height of text text after word wrapping and line breaks
    int             m_lineHeight;   // height of a line for the font size
    int             m_windowWidth;  // the width of the window

    FTLineInfo*     m_currentLine;  // the current line object to add words to.
};

NS_CC_END
/****************************************************************************
 Copyright (c) 2013      cocos2d-x.org   http://cocos2d-x.org
 Copyright (c) Microsoft Open Technologies, Inc.

 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 copies of the Software, and to permit persons to whom the Software is
 furnished to do so, subject to the following conditions:

 The above copyright notice and this permission notice shall be included in
 all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
 ****************************************************************************/

#include "CCFreeTypeFont.h"
#include "CCDirector.h"
#include "platform/CCFileUtils.h"

#if (CC_TARGET_PLATFORM != CC_PLATFORM_WP8)
#include <dwrite.h>
#endif
#include <map>
#include <string>
#include <sstream>
#include <vector>
#include <memory>
#include <algorithm>

using namespace std;

NS_CC_BEGIN

static map<std::string, FontBufferInfo> s_fontsNames;
static FT_Library s_FreeTypeLibrary = nullptr;

CCFreeTypeFont::CCFreeTypeFont()
    :m_space(" ")
    , m_face(nullptr)
{

}

CCFreeTypeFont::~CCFreeTypeFont()
{
    reset();
}

void CCFreeTypeFont::reset()
{
    for(auto line:m_lines)
    {
        line->glyphs.clear();
        delete line;
    }

    m_lines.clear();

        if(m_face)
        {
                FT_Done_Face(m_face);
            m_face = nullptr;
        }

}

bool CCFreeTypeFont::initWithString(
        const char* pText,
        const char* pFontName,
        int         nSize,
    int         inWidth,
    int         inHeight )
{
        FT_Error error = 0;
        unsigned long size = 0;
    unsigned char* pBuffer = nullptr;
    unsigned char* data = nullptr;

    CCSize winSize = CCDirector::sharedDirector()->getWinSizeInPixels();
    m_windowWidth = (int)winSize.width;

    m_inWidth = inWidth;
    m_inHeight = inHeight;

#if 0
    // check the cache for the font file buffer
    auto ittFontNames = s_fontsNames.find(pFontName);
    if(ittFontNames != s_fontsNames.end())
    {
        pBuffer = ittFontNames->second.pBuffer;
        size = ittFontNames->second.size;
    }
#endif // 0

        if(!pBuffer)
    {
        // attempt to load font from Resources fonts folder
        pBuffer = loadFont(pFontName, &size);
            if(!pBuffer)
            {
         // attempt to load font from System fonts folder
           pBuffer = loadSystemFont(pFontName, &size);
            }
        if(!pBuffer)
        {
            // attempt to load default font from Resources fonts folder
                    pBuffer = loadFont("Arial", &size);
        }
        if(!pBuffer)
        {
            // attempt to load default font from System fonts folder
                    pBuffer = loadSystemFont("Arial", &size);
        }

        if(!pBuffer) // font not found!
            return false;

#if 0
        // cache the font file buffer
        FontBufferInfo info;
        info.pBuffer = pBuffer;
        info.size = size;
        s_fontsNames[pFontName]=info;
#endif // 0
    }

    m_fontName = pFontName;
        m_text = pText;

        if(!s_FreeTypeLibrary)
        {
                error = FT_Init_FreeType(&s_FreeTypeLibrary);
        }

        if(!error && !m_face)
        {
                error = FT_New_Memory_Face(s_FreeTypeLibrary, pBuffer, size, 0, &m_face);
        }

    if(!error)
    {
        error = FT_Select_Charmap(m_face, FT_ENCODING_UNICODE);
    }

    if(!error)
            error = FT_Set_Char_Size(m_face,nSize<<6,nSize<<6,72,72);

    if(!error)
            error = initGlyphs(pText);

    delete [] pBuffer;

        return error == 0;
}

unsigned char* CCFreeTypeFont::getBitmap(CCImage::ETextAlign eAlignMask, int* outWidth, int* outHeight)
{
    int lineNumber = 0;
    int totalLines = m_lines.size();

    m_width = m_inWidth ?

m_inWidth : m_textWidth;
    m_height = m_inHeight ? m_inHeight : m_textHeight;

    unsigned int size = m_width * m_height * 4;
    unsigned char* pBuffer = new unsigned char[size];
    if(!pBuffer)
    {
        return nullptr;
    }
    memset(pBuffer, 0, size);

    for (auto line = m_lines.begin() ; line != m_lines.end(); ++line)
    {
        FT_Vector pen = getPenForAlignment(*line, eAlignMask, lineNumber, totalLines);
        drawText(*line, pBuffer, &pen);
        lineNumber++;
    }
    *outWidth = m_width;
    *outHeight = m_height;

    reset();

    return pBuffer;
}

FT_Vector CCFreeTypeFont::getPenForAlignment(FTLineInfo* pInfo, CCImage::ETextAlign eAlignMask,int lineNumber, int totalLines)
{
    FT_Error error = 0;
    FT_Vector pen;

    int top;
    int stringWidth  = pInfo->bbox.xMax - pInfo->bbox.xMin;
    int maxLineNumber = totalLines - 1;
    pen.x = 0;
    pen.y = 0;

    switch(eAlignMask)
    {
        case CCImage::ETextAlign::kAlignTop: // Horizontal center and vertical top.
            pen.x = ((m_width  - stringWidth) / 2) - pInfo->bbox.xMin;
            pen.y = pInfo->bbox.yMax + (lineNumber * m_lineHeight);
                    break;

        case CCImage::ETextAlign::kAlignTopLeft: // Horizontal left and vertical top.
            pen.x -=pInfo->bbox.xMin;
            pen.y = pInfo->bbox.yMax + (lineNumber * m_lineHeight);
                    break;

            case CCImage::ETextAlign::kAlignTopRight: // Horizontal right and vertical top.
            pen.x = m_width - stringWidth - pInfo->bbox.xMin;
            pen.y = pInfo->bbox.yMax + (lineNumber * m_lineHeight);
                    break;

            case CCImage::ETextAlign::kAlignBottomRight: // Horizontal right and vertical bottom.
            pen.x = m_width - stringWidth - pInfo->bbox.xMin;
            pen.y = m_height + pInfo->bbox.yMin - ((maxLineNumber - lineNumber) * m_lineHeight);
                    break;

            case CCImage::ETextAlign::kAlignBottom: // Horizontal center and vertical bottom.
            pen.x = ((m_width  - stringWidth) / 2) - pInfo->bbox.xMin;
            pen.y = m_height + pInfo->bbox.yMin - ((maxLineNumber - lineNumber) * m_lineHeight);
                    break;

            case CCImage::ETextAlign::kAlignBottomLeft: // Horizontal left and vertical bottom.
            pen.x -=pInfo->bbox.xMin;
            top = (m_height - m_textHeight) / 2;
            pen.y = m_height + pInfo->bbox.yMin - ((maxLineNumber - lineNumber) * m_lineHeight);
                    break;

            case CCImage::ETextAlign::kAlignCenter: // Horizontal center and vertical center
            pen.x = ((m_width  - stringWidth) / 2) - pInfo->bbox.xMin;
            top = (m_height - m_textHeight) / 2;
            pen.y = top + (lineNumber * m_lineHeight) + pInfo->bbox.yMax;
            break;

            case CCImage::ETextAlign::kAlignRight: // Horizontal right and vertical center.
            pen.x = m_width - stringWidth - pInfo->bbox.xMin;
            top = (m_height - m_textHeight) / 2;
            pen.y = top + (lineNumber * m_lineHeight) + pInfo->bbox.yMax;
                    break;

            case CCImage::ETextAlign::kAlignLeft: // Horizontal left and vertical center.
            default:
            pen.x -=pInfo->bbox.xMin;
            top = (m_height - m_textHeight) / 2;
            pen.y = top + (lineNumber * m_lineHeight) + pInfo->bbox.yMax;
                    break;
    }

    return pen;
}

void  CCFreeTypeFont::drawText(FTLineInfo* pInfo, unsigned char* pBuffer, FT_Vector *pen)
{

    auto glyphs = pInfo->glyphs;
    for (auto glyph = glyphs.begin() ; glyph != glyphs.end(); ++glyph)
    {
        FT_Glyph image = glyph->image;
        FT_Error error = FT_Glyph_To_Bitmap(&image, FT_RENDER_MODE_NORMAL, 0, 1);
        if (!error)
        {
            FT_BitmapGlyph  bit = (FT_BitmapGlyph)image;
            draw_bitmap(pBuffer, &bit->bitmap, pen->x + glyph->pos.x + bit->left,pen->y - bit->top);
            FT_Done_Glyph(image);
        }
    }
}

void CCFreeTypeFont::draw_bitmap(unsigned char* pBuffer, FT_Bitmap*  bitmap, FT_Int x, FT_Int y)
{
    FT_Int  i, j, p, q;
    FT_Int  x_max = x + bitmap->width;
    FT_Int  y_max = y + bitmap->rows;

    for (i = x, p = 0; i < x_max; i++, p++)
    {
        for ( j = y, q = 0; j < y_max; j++, q++ )
        {
            if (i < 0 || j < 0 || i >= m_width || j >= m_height)
                continue;

            unsigned char value =  bitmap->buffer[q * bitmap->width + p];

            if(value > 0)
            {
                FT_Int index = (j * m_width * 4) + (i * 4);
                pBuffer[index++] = 0xff;
                pBuffer[index++] = 0xff;
                pBuffer[index++] = 0xff;
                pBuffer[index++] = value;
           }
        }
    }
}

void CCFreeTypeFont::endLine()
{
    if(m_currentLine)
    {
        m_lines.push_back(m_currentLine);
                compute_bbox(m_currentLine->glyphs, &m_currentLine->bbox);
                m_currentLine->width = m_currentLine->bbox.xMax - m_currentLine->bbox.xMin;
        m_textWidth = max(m_textWidth,m_currentLine->bbox.xMax - m_currentLine->bbox.xMin);
        m_textHeight += m_lineHeight;
                m_currentLine = NULL;
    }
}

void CCFreeTypeFont::newLine()
{
    m_currentLine = new FTLineInfo();
    m_currentLine->width = 0;
    m_currentLine->pen.x = 0;
    m_currentLine->pen.y = 0;
}

FT_Error CCFreeTypeFont::addLine(const std::string& line)
{
        wchar_t *       pwszBuffer = nullptr;

        int num_chars = line.size();
        int nBufLen = num_chars + 1;
        pwszBuffer = new wchar_t[nBufLen];
        if (!pwszBuffer)
        {
                return -1;
        }

        memset(pwszBuffer, 0, nBufLen);
        num_chars = MultiByteToWideChar(CP_UTF8, 0, line.c_str(), num_chars, pwszBuffer, nBufLen);
        pwszBuffer[num_chars] = '\0';

        int maxWidth = m_inWidth ? m_inWidth : m_windowWidth;

        newLine();
        FT_Vector pen = m_currentLine->pen;
        FT_GlyphSlot    slot = m_face->glyph;
        FT_UInt                 glyph_index;
        FT_UInt                 previous = 0;
        FT_Error                error = 0;
        unsigned int    numGlyphs = 0;

        FT_Bool useKerning = FT_HAS_KERNING(m_face);

        int n = 0;
        while (n < num_chars)
        {
                TGlyph glyph;

                /* convert character code to glyph index */
                FT_ULong c = pwszBuffer[n++];
                glyph_index = FT_Get_Char_Index(m_face, c);

                if (useKerning && previous && glyph_index)
                {
                        FT_Vector  delta;
                        FT_Get_Kerning(m_face, previous, glyph_index,
                                FT_KERNING_DEFAULT, &delta);
                        pen.x += delta.x >> 6;
                }

                /* store current pen position */
                glyph.pos = pen;
                glyph.index = glyph_index;

                /* load glyph image into the slot without rendering */
                error = FT_Load_Glyph(m_face, glyph_index, FT_LOAD_DEFAULT);
                if (error)
                        continue;  /* ignore errors, jump to next glyph */

                /* extract glyph image and store it in our table */
                error = FT_Get_Glyph(m_face->glyph, &glyph.image);
                if (error)
                        continue;  /* ignore errors, jump to next glyph */

                /* translate the glyph image now */
                FT_Glyph_Transform(glyph.image, 0, &glyph.pos);

                /* increment pen position */
                pen.x += slot->advance.x >> 6;

                if (pen.x > maxWidth)
                {
                        m_currentLine->pen = pen;
                        endLine();

                        newLine();
                        pen = m_currentLine->pen;
                        previous = 0;
                        n--;
                }
                else
                {
                        m_currentLine->glyphs.push_back(glyph);
                        /* record current glyph index */
                        previous = glyph_index;
                }
        }

        if (m_currentLine)
        {
                m_currentLine->pen = pen;
                endLine();
        }

        CC_SAFE_DELETE_ARRAY(pwszBuffer);
        return error;
}

FT_Error CCFreeTypeFont::initGlyphs(const char* text)
{
    FT_Error error = 0;
    std::stringstream stringStream(text);
    std::string line;

    m_textWidth = 0;
    m_textHeight = 0;
    // the height of a line of text based on the max height of a glyph in the font size
    m_lineHeight = ((m_face->size->metrics.ascender) >> 6) - ((m_face->size->metrics.descender) >> 6);

    m_lines.clear();

    while(std::getline(stringStream, line) && !error)
    {
                addLine(line);
    }

    return error;
}

void  CCFreeTypeFont::compute_bbox(std::vector<TGlyph>& glyphs, FT_BBox  *abbox)
{
    FT_BBox bbox;
    FT_BBox glyph_bbox;

    /* initialize string bbox to "empty" values */
    bbox.xMin = 32000;
    bbox.xMax = -32000;

    // use the max and min values for the entire font face
    bbox.yMin = (m_face->size->metrics.descender) >> 6;
    bbox.yMax = (m_face->size->metrics.ascender) >> 6;

    /* for each glyph image, compute its bounding box, */
    /* translate it, and grow the string bbox          */
    for (auto glyph = glyphs.begin() ; glyph != glyphs.end(); ++glyph)
    {
        FT_Glyph_Get_CBox(glyph->image, ft_glyph_bbox_pixels, &glyph_bbox);

        glyph_bbox.xMin += glyph->pos.x;
        glyph_bbox.xMax += glyph->pos.x;
        glyph_bbox.yMin += glyph->pos.y;
        glyph_bbox.yMax += glyph->pos.y;

        if (glyph_bbox.xMin < bbox.xMin)
            bbox.xMin = glyph_bbox.xMin;

        if (glyph_bbox.yMin < bbox.yMin)
            bbox.yMin = glyph_bbox.yMin;

        if (glyph_bbox.xMax > bbox.xMax)
            bbox.xMax = glyph_bbox.xMax;

        if (glyph_bbox.yMax > bbox.yMax)
            bbox.yMax = glyph_bbox.yMax;
    }

    /* check that we really grew the string bbox */
    if (bbox.xMin > bbox.xMax)
    {
        bbox.xMin = 0;
        bbox.yMin = 0;
        bbox.xMax = 0;
        bbox.yMax = 0;
    }

    /* return string bbox */
    *abbox = bbox;
}

unsigned char* CCFreeTypeFont::loadFont(const char *pFontName, unsigned long *size)
{
        std::string lowerCase(pFontName);
        std::string path(pFontName);

    for (unsigned int i = 0; i < lowerCase.length(); ++i)
    {
        lowerCase[i] = tolower(lowerCase[i]);
    }

    if (std::string::npos == lowerCase.find("fonts/"))
    {
        path = "fonts/";
        path += pFontName;
    }

    if (std::string::npos == lowerCase.find(".ttf"))
    {
        path += ".ttf";
    }

        std::string fullpath  = CCFileUtils::sharedFileUtils()->fullPathForFilename(path.c_str());
        return CCFileUtils::sharedFileUtils()->getFileData(fullpath.c_str(), "rb", size);
}

unsigned char* CCFreeTypeFont::loadSystemFont(const char *pFontName, unsigned long *size)
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8)
        return nullptr;
#else
    std::string aName(pFontName);
    unsigned char* pBuffer = nullptr;
    HRESULT hr = S_OK;
        IDWriteFactory *writeFactory = nullptr;
        IDWriteFontCollection *fontCollection = nullptr;
        IDWriteFontFamily *fontFamily = nullptr;
        IDWriteFont *matchingFont = nullptr;
        IDWriteFontFace *fontFace = nullptr;
        IDWriteFontFile *fontFile = nullptr;
        IDWriteFontFileLoader *fontFileLoader = nullptr;
        IDWriteFontFileStream *fontFileStream = nullptr;
        UINT32 index;
        BOOL exists;
        std::wstring fontNameW;
    const void *fontFileReferenceKey = nullptr;
    UINT32 fontFileReferenceKeySize;
    void *fragmentContext = nullptr;

    for (unsigned int i = 0; i < aName.length(); ++i)
    {
        aName[i] = tolower(aName[i]);
    }
    fontNameW.assign(aName.begin(), aName.end());

        //create the factory
        hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), reinterpret_cast<IUnknown**>(&writeFactory));

    if(SUCCEEDED(hr))
    {
            //obtain the fonts owned by the machine
            hr  = writeFactory->GetSystemFontCollection(&fontCollection, TRUE);
    }

        //get the font
    if(SUCCEEDED(hr))
    {
            hr = fontCollection->FindFamilyName(fontNameW.c_str(), &index, &exists);
        if(SUCCEEDED(hr) && exists)
        {
                hr = fontCollection->GetFontFamily(index, &fontFamily);

            if(SUCCEEDED(hr))
            {
                    hr = fontFamily->GetFirstMatchingFont(DWRITE_FONT_WEIGHT_REGULAR, DWRITE_FONT_STRETCH_NORMAL, DWRITE_FONT_STYLE_NORMAL, &matchingFont);
            }

            if(SUCCEEDED(hr))
            {
                    hr = matchingFont->CreateFontFace(&fontFace);
            }

            if(SUCCEEDED(hr))
            {
                    UINT32 numberOfFiles = 1;
                    hr = fontFace->GetFiles(&numberOfFiles, &fontFile);
            }

            if(SUCCEEDED(hr))
            {
                    //create the font file stream
               hr = fontFile->GetReferenceKey(&fontFileReferenceKey, &fontFileReferenceKeySize);
            }

            if(SUCCEEDED(hr))
            {
                hr = fontFile->GetLoader(&fontFileLoader);
            }

            if(SUCCEEDED(hr))
            {
                hr = fontFileLoader->CreateStreamFromKey(fontFileReferenceKey, fontFileReferenceKeySize, &fontFileStream);
            }

            if(SUCCEEDED(hr))
            {
                    //finally get the font file dat
                    UINT64 fileSize;
                        const void *fragmentStart = nullptr;
                hr = fontFileStream->GetFileSize(&fileSize);

                if(SUCCEEDED(hr))
                {
                        hr = fontFileStream->ReadFileFragment(&fragmentStart, 0, fileSize, &fragmentContext);
                }

                if(SUCCEEDED(hr))
                {
                        pBuffer = (unsigned char*)malloc((size_t)fileSize);
                        memcpy(pBuffer, fragmentStart, (size_t)fileSize);
                    *size = (unsigned long)fileSize;
                }
            }
        }
    }

        //clean up all the DWrite stuff
    if(fontFileStream)
    {
            fontFileStream->ReleaseFileFragment(fragmentContext);
            fontFileStream->Release();
    }
    if(fontFileLoader)
    {
            fontFileLoader->Release();
    }
    if(fontFile)
    {
            fontFile->Release();
    }
    if(fontFace)
    {
            fontFace->Release();
    }
    if(matchingFont)
    {
            matchingFont->Release();
    }
    if(fontFamily)
    {
            fontFamily->Release();
    }
    if(fontCollection)
    {
            fontCollection->Release();
    }
    if(writeFactory)
    {
            writeFactory->Release();
    }

    return pBuffer;
#endif
}

NS_CC_END
时间: 2024-10-02 08:39:04

cocos2dx windows phone平台下CCLabelTTF自己主动换行的实现(2)的相关文章

cocos2dx windows phone平台下CCLabelTTF自动换行的实现

先吐个槽,刚准备发这条博客的时候居然发现账号被盗了,真是有人闲得蛋疼,顺便赞一个csdn的客服,处理的很快. 好了,言归正转.看了一下,自动换行的实现在CCFreeType这个类里,这个类的实现只是针对英文的,它采用空格断句的方式来进行操作,一个word一个word的加,如果发现超过规定的范围就会换行,但是对于中文来说,这个实现简直弱爆了,所以就会出现不能自动换行的情况.参考它的实现,做一点小的修改,基本原理如下 1.读一行文本出来,参考它的实现,算出这个文本的宽度 2.如果这个宽度没有超过,则

cocos2dx windows phone平台下CCLabelTTF自动换行的实现(2)

前几天发过一篇文章说如何实现wp8下的CCLabelTTF如何自动换行,后来发现果如预料的那般,效果很不好,主要是非等宽字体的情况下看着很糟心,因此再修改了一版,效果要好很多了. 具体实现其实就是参考initGlyphs,但是会不断的检查是否超过宽度,如果超过则自动换行. 具体的直接看代码就明白了 /**************************************************************************** Copyright (c) 2010 coc

在Windows 10平台下的MySQL-5.7.15-winx64安装

白发渔樵江渚上,惯看秋月春风. 一壶浊酒喜相逢,古今多少事,都付笑谈中. --<临江仙> 一.下载 1.在官网上下载MySQL对应的版本:https://downloads.mysql.com/archives/community/ 2.下载完成解压到指定路径: 二.配置MySQL 在mysql-5.7.15-winx64目录下,复制my-default.ini命名为my.ini. 配置my.ini文件 [mysql] # 设置mysql客户端默认字符集 default-character-s

windows平台下的oracle ORA-01031的解决方法

今天下午遇到一个很怪异的问题,在windows平台下sqlplus  / as sysdba登陆数据库,提示权限不足, 当时就纳闷了,sys用户登陆数据库还能权限不足,问题出现了,就开始寻找解决方法呗 首先查看$ORACLE_HOME/network/admin/sqlnet.ora中SQLNET.AUTHENTICATION_SERVICES项的配置信息, 网上的大多数帖子一致结论为: 在windows平台上,SQLNET.AUTHENTICATION_SERVICES必须设置为NTS或者AL

Windows平台下Oracle监听服务启动过程中日志输出

Windows平台下Oracle监听服务启动过程中日志输出记录. 日志目录:D:\app\Administrator\diag\tnslsnr\WIN-RU03CB21QGA\listener\trace\listener.log 日志输出内容: Sat Aug 06 20:38:44 2016 系统参数文件为D:\app\Administrator\product\11.2.0\dbhome_1\network\admin\listener.ora 写入d:\app\administrator

Windows平台下Oracle实例启动过程中日志输出

Windows平台下Oracle实例启动过程中日志输出记录. 路径:D:\app\Administrator\diag\rdbms\orcl\orcl\trace\alert_orcl.log 输出内容: Sat Aug 06 20:39:55 2016 Starting ORACLE instance (normal) LICENSE_MAX_SESSION = 0 LICENSE_SESSIONS_WARNING = 0 Picked latch-free SCN scheme 3 Usin

wchar_t内置还是别名(wchar_t在windows下是16整数的别名,在linux等平台下是32位整数的别名。MSVC2008开始默认是/Zc:wchar_t)

接前一篇C++ ABI之名字改编(以Qt为例),继续看看C++名字改编相关的问题. 问题 MSVC 有一对选项/Zc:wchar_t- 与 /Zc:wchar_t控制wchar_t 于是 wchar_t 可以是 unsigned short 或 __wchar_t(称为原生类型?) 的别名 两个东西混用会怎么样? 首先考虑,会混用么?,是杞人忧天么? 由于 Qt 为 MSVC 提供的二进制包采用的前者/Zc:wchar_t-.考虑: 如果你编译自己的Qt程序时,启用了后者,会怎么样? 如果Qt程

Windows 平台下Git 服务器搭建

由于项目中一直在使用git作为版本管理,自己对git的理解.使用都还不是怎么的熟悉,所以准备深入了解一下git及一些常用命令的使用,于是干脆把服务端架上,通过自己的PC作为服务端同时作为客户端的角色进行折腾了...本文主要介绍在Windows平台下Git服务器的搭建,如下: 一:下载java,地址:http://www.java.com/zh_CN/ 二:安装Java.安装步骤不再详述. 三:配置Java环境变量. 右键 计算机->属性->高级系统设置->高级->环境变量->

Windows平台下Git服务器搭建

该文章转自:http://www.codeceo.com/article/windows-git-server.html 第一步:下载Java,下载地址:http://www.java.com/zh_CN/ 第二步:安装Java.安装步骤不再详述. 第三步:配置Java环境变量. 右键”计算机” => ”属性” => ”高级系统设置” => ”高级” => “环境变量” => “系统变量”. 新建: 变量名:JAVA_HOME 变量值:D:\Program Files (x8