diff --git a/Sources/Plasma/PubUtilLib/plPipeline/plTextFont.cpp b/Sources/Plasma/PubUtilLib/plPipeline/plTextFont.cpp index 84a3a883d2..bad650cb1f 100644 --- a/Sources/Plasma/PubUtilLib/plPipeline/plTextFont.cpp +++ b/Sources/Plasma/PubUtilLib/plPipeline/plTextFont.cpp @@ -68,8 +68,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #import #endif -#define DisplayableChar(c) (c >= 0 && c <= 128) - //// Constructor & Destructor ///////////////////////////////////////////////// plTextFont::plTextFont( plPipeline *pipe ) @@ -88,16 +86,9 @@ plTextFont::~plTextFont() uint16_t *plTextFont::IInitFontTexture() { -#ifdef HS_BUILD_FOR_WIN32 - int nHeight, x, y, c; + int x, y, c; char myChar[ 2 ] = "x"; - BITMAPINFO bmi; - HDC hDC; - HFONT hFont; - SIZE size; - BYTE bAlpha; - // Figure out our texture size if( fSize > 40 ) @@ -109,38 +100,67 @@ uint16_t *plTextFont::IInitFontTexture() /// Now create the data block uint16_t* data = new uint16_t[fTextureWidth * fTextureHeight](); - - hDC = CreateCompatibleDC(nullptr); - SetMapMode( hDC, MM_TEXT ); - - nHeight = -MulDiv( fSize, GetDeviceCaps(hDC, LOGPIXELSY), 72 ); - fFontHeight = -nHeight; FT_Library library; FT_Face face; FT_Error ftError = FT_Init_FreeType(&library); hsAssert(ftError == FT_Err_Ok, "FreeType did not initialize"); +#ifdef HS_BUILD_FOR_WIN32 + + HDC hDC; + HFONT hFont; + BYTE bAlpha; + + hDC = CreateCompatibleDC(nullptr); + SetMapMode( hDC, MM_TEXT ); + // Get the font data + + int nHeight = -MulDiv( fSize, GetDeviceCaps(hDC, LOGPIXELSY), 72 ); + hFont = CreateFont( nHeight, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY, VARIABLE_PITCH, fFace ); hsAssert(hFont != nullptr, "Cannot create Windows font"); - SelectObject( hDC, hFont ); - // Get the font data - + SelectObject(hDC, hFont); + DWORD fontDataSize = GetFontData( hDC, 0, 0, 0, 0 ); void* fontData = std::malloc( fontDataSize ); GetFontData(hDC, 0, 0, fontData, fontDataSize); ftError = FT_New_Memory_Face(library, (FT_Byte *) fontData, fontDataSize, 0, &face); - FT_UInt freeTypeResolution = GetDeviceCaps(hDC, LOGPIXELSY); - ftError = FT_Set_Char_Size(face, 0, fSize * 64, freeTypeResolution, freeTypeResolution); - // Set text colors - SetTextColor( hDC, RGB( 255, 255, 255 ) ); - SetBkColor( hDC, 0 ); - SetTextAlign( hDC, TA_TOP ); + DeleteDC( hDC ); + DeleteObject( hFont ); + +#elif defined(HS_BUILD_FOR_APPLE) + + CFStringRef fontName = CFStringCreateWithCString(nullptr, fFace, kCFStringEncodingUTF8); + CTFontDescriptorRef fontDescriptor = CTFontDescriptorCreateWithNameAndSize( fontName, 0.0f ); + CTFontDescriptorRef fulfilledFontDescriptor = CTFontDescriptorCreateMatchingFontDescriptor(fontDescriptor, nullptr); + hsAssert(fulfilledFontDescriptor != nullptr, "Cannot create Mac font"); + CFRelease(fontName); + CFRelease(fontDescriptor); + + CFURLRef fontURL = (CFURLRef) CTFontDescriptorCopyAttribute(fulfilledFontDescriptor, kCTFontURLAttribute); + CFStringRef fileSystemPath = CFURLCopyFileSystemPath(fontURL, kCFURLPOSIXPathStyle); + char cPath[PATH_MAX]; + CFStringGetCString(fileSystemPath, cPath, PATH_MAX, kCFStringEncodingUTF8); + + ftError = FT_New_Face(library, cPath, 0, &face); + + CFRelease(fulfilledFontDescriptor); + CFRelease(fontURL); + CFRelease(fileSystemPath); + + FT_UInt freeTypeResolution = 192; +#else + FT_Done_FreeType(library); + FT_UInt freeTypeResolution = 0; + return nullptr; +#endif + ftError = FT_Set_Char_Size(face, 0, fSize * 64, freeTypeResolution, freeTypeResolution); FT_Size_Metrics fontMetrics = face->size->metrics; fFontHeight = int(fontMetrics.height / 64.f); @@ -148,6 +168,10 @@ uint16_t *plTextFont::IInitFontTexture() data[0] = 0xffff; int maxDescent = abs(int(fontMetrics.descender / 64.f)); + struct { + long cx; + long cy; + } size; // Loop through characters, drawing them one at a time for( c = 32, x = 1, y = 0; c < 127; c++ ) @@ -173,7 +197,7 @@ uint16_t *plTextFont::IInitFontTexture() x = 0; y += size.cy + 1; } - int offset = fFontHeight - cBox.yMax; + int offset = int( fFontHeight - cBox.yMax ); //blit the bitmap into place for (int glyphY = bitmap.rows - 1; glyphY >= 0 ; glyphY--) { @@ -218,134 +242,7 @@ uint16_t *plTextFont::IInitFontTexture() FT_Done_Face(face); FT_Done_FreeType(library); - // Cleanup and return - DeleteDC( hDC ); - DeleteObject( hFont ); - - return data; -#elif defined(HS_BUILD_FOR_APPLE) - int nHeight, x, y, c; - char myChar[ 2 ] = "x"; - uint16_t *tBits; - - uint32_t *bitmapBits; - uint32_t bAlpha; - - - // Figure out our texture size - if( fSize * 2 > 40 ) - fTextureWidth = fTextureHeight = 1024; - else if( fSize * 2 > 20 ) - fTextureWidth = fTextureHeight = 512; - else - fTextureWidth = fTextureHeight = 256; - - - // Create a new DC and bitmap that we can draw characters to - CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); - CGContextRef bitmapContext = CGBitmapContextCreate(nullptr, - fTextureWidth, - fTextureHeight, - 8, - 4 * fTextureWidth, - colorSpace, - kCGImageAlphaPremultipliedLast); - CFRelease(colorSpace); - CGContextSetTextMatrix(bitmapContext, CGAffineTransformMakeScale(1, -1)); - CGContextTranslateCTM(bitmapContext, 0, fTextureHeight); - CGContextScaleCTM(bitmapContext, 1, -1); - CGContextScaleCTM(bitmapContext, 2.0, 2.0); - - bitmapBits = (uint32_t *)CGBitmapContextGetData(bitmapContext); - - //TEMPORARY: Mac client should vend through better data to make this decision - nHeight = fSize; - fFontHeight = (fSize * 144.0f) / 72.0f; - - CFStringRef fontName = CFStringCreateWithCString(nullptr, fFace, kCFStringEncodingUTF8); - CTFontRef font = CTFontCreateWithName(fontName, nHeight, nullptr); - hsAssert(font != nullptr, "Cannot create Mac font"); - CFRelease(fontName); - - // Set text colors - CGFloat color[4] = { 255.0f, 255.0f, 255.0f, 255.0f }; - CGContextSetFillColor(bitmapContext, color); - CGContextSetShouldAntialias(bitmapContext, false); - - // Loop through characters, drawing them one at a time - CGRect r = CGRectMake(0, 0, 10, 10); - - fTextureWidth /= 2; - fTextureHeight /= 2; - - // (Make first character a black dot, for filling rectangles) - bitmapBits[0] = UINT32_MAX; - for( c = 32, x = 1, y = 0; c < 127; c++ ) - { - myChar[ 0 ] = c; - CGGlyph glpyh; - CTFontGetGlyphsForCharacters(font, (UniChar *)myChar, &glpyh, 1); - CGRect rect; - CTFontGetOpticalBoundsForGlyphs(font, &glpyh, &rect, 1, 0); - CGSize size = rect.size; - - if( (uint32_t)( x + size.width + 1 ) > fTextureWidth ) - { - x = 0; - y += size.height + 1; - } - - CGPoint position = CGPointMake(x, -y - size.height - rect.origin.y); - CTFontDrawGlyphs(font, &glpyh, &position, 1, bitmapContext); - - fCharInfo[ c ].fW = (uint16_t)size.width * 2.0f; - fCharInfo[ c ].fH = (uint16_t)size.height * 2.0f; - fCharInfo[ c ].fUVs[ 0 ].fX = (float)x / (float)fTextureWidth; - fCharInfo[ c ].fUVs[ 0 ].fY = (float)y / (float)fTextureHeight; - fCharInfo[ c ].fUVs[ 1 ].fX = (float)( x + size.width ) / (float)fTextureWidth; - fCharInfo[ c ].fUVs[ 1 ].fY = (float)( y + size.height ) / (float)fTextureHeight; - fCharInfo[ c ].fUVs[ 0 ].fZ = fCharInfo[ c ].fUVs[ 1 ].fZ = 0; - - x += ceil(size.width) + 1; - } - fCharInfo[ 32 ].fUVs[ 1 ].fX = fCharInfo[ 32 ].fUVs[ 0 ].fX; - - // Special case the tab key - fCharInfo[ '\t' ].fUVs[ 1 ].fX = fCharInfo[ '\t' ].fUVs[ 0 ].fX = fCharInfo[ 32 ].fUVs[ 0 ].fX; - fCharInfo[ '\t' ].fUVs[ 1 ].fY = fCharInfo[ '\t' ].fUVs[ 0 ].fY = 0; - fCharInfo[ '\t' ].fUVs[ 0 ].fZ = fCharInfo[ '\t' ].fUVs[ 1 ].fZ = 0; - fCharInfo[ '\t' ].fW = fCharInfo[ 32 ].fW * 4; - fCharInfo[ '\t' ].fH = fCharInfo[ 32 ].fH; - - fTextureWidth *= 2; - fTextureHeight *= 2; - - /// Now create the data block - uint16_t *data = new uint16_t[ fTextureWidth * fTextureHeight ]; - tBits = data; - for( y = 0; y < fTextureHeight; y++ ) - { - for( x = 0; x < fTextureWidth; x++ ) - { - bAlpha = (char)( ( bitmapBits[ fTextureWidth * y + x ] & 0xff ) >> 4 ); - - if( bitmapBits[ fTextureWidth * y + x ] ) - *tBits = 0xffff; - else - *tBits = 0; - - tBits++; - } - } - - // Cleanup and return - CFRelease(font); - CFRelease(bitmapContext); - return data; -#else - return nullptr; -#endif } //// Create /////////////////////////////////////////////////////////////////// @@ -384,7 +281,8 @@ void plTextFont::DrawString( const char *string, int sX, int sY, uint32_t hex { static std::vector verts; - int i, j, width, height, count, thisCount, italOffset; + size_t i, j, width, height, count, thisCount; + uint32_t italOffset; float x = (float)sX; char c, *strPtr; @@ -414,49 +312,45 @@ void plTextFont::DrawString( const char *string, int sX, int sY, uint32_t hex for( i = 0, j = 0; i < thisCount; i++, j += 6 ) { c = strPtr[ i ]; - // make sure its a character we will display - if ( DisplayableChar(c) ) + width = fCharInfo[uint8_t(c)].fW + 1; + height = fCharInfo[uint8_t(c)].fH + 1; + + if( rightEdge > 0 && x + width + italOffset >= rightEdge ) { - width = fCharInfo[uint8_t(c)].fW + 1; - height = fCharInfo[uint8_t(c)].fH + 1; - - if( rightEdge > 0 && x + width + italOffset >= rightEdge ) - { - count = 0; - thisCount = i; - break; - } + count = 0; + thisCount = i; + break; + } - verts[ j ].fPoint.fX = x + italOffset; - verts[ j ].fPoint.fY = (float)sY; - verts[ j ].fUV = fCharInfo[uint8_t(c)].fUVs[ 0 ]; + verts[ j ].fPoint.fX = x + italOffset; + verts[ j ].fPoint.fY = (float)sY; + verts[ j ].fUV = fCharInfo[uint8_t(c)].fUVs[ 0 ]; - verts[ j + 1 ].fPoint.fX = x + width + italOffset; - verts[ j + 1 ].fPoint.fY = (float)sY; - verts[ j + 1 ].fUV = fCharInfo[uint8_t(c)].fUVs[ 0 ]; - verts[ j + 1 ].fUV.fX = fCharInfo[uint8_t(c)].fUVs[ 1 ].fX; + verts[ j + 1 ].fPoint.fX = x + width + italOffset; + verts[ j + 1 ].fPoint.fY = (float)sY; + verts[ j + 1 ].fUV = fCharInfo[uint8_t(c)].fUVs[ 0 ]; + verts[ j + 1 ].fUV.fX = fCharInfo[uint8_t(c)].fUVs[ 1 ].fX; - verts[ j + 2 ].fPoint.fX = x; - verts[ j + 2 ].fPoint.fY = (float)sY + height; - verts[ j + 2 ].fUV = fCharInfo[uint8_t(c)].fUVs[ 0 ]; - verts[ j + 2 ].fUV.fY = fCharInfo[uint8_t(c)].fUVs[ 1 ].fY; + verts[ j + 2 ].fPoint.fX = x; + verts[ j + 2 ].fPoint.fY = (float)sY + height; + verts[ j + 2 ].fUV = fCharInfo[uint8_t(c)].fUVs[ 0 ]; + verts[ j + 2 ].fUV.fY = fCharInfo[uint8_t(c)].fUVs[ 1 ].fY; - verts[ j + 3 ].fPoint.fX = x; - verts[ j + 3 ].fPoint.fY = (float)sY + height; - verts[ j + 3 ].fUV = fCharInfo[uint8_t(c)].fUVs[ 0 ]; - verts[ j + 3 ].fUV.fY = fCharInfo[uint8_t(c)].fUVs[ 1 ].fY; + verts[ j + 3 ].fPoint.fX = x; + verts[ j + 3 ].fPoint.fY = (float)sY + height; + verts[ j + 3 ].fUV = fCharInfo[uint8_t(c)].fUVs[ 0 ]; + verts[ j + 3 ].fUV.fY = fCharInfo[uint8_t(c)].fUVs[ 1 ].fY; - verts[ j + 4 ].fPoint.fX = x + width + italOffset; - verts[ j + 4 ].fPoint.fY = (float)sY; - verts[ j + 4 ].fUV = fCharInfo[uint8_t(c)].fUVs[ 0 ]; - verts[ j + 4 ].fUV.fX = fCharInfo[uint8_t(c)].fUVs[ 1 ].fX; + verts[ j + 4 ].fPoint.fX = x + width + italOffset; + verts[ j + 4 ].fPoint.fY = (float)sY; + verts[ j + 4 ].fUV = fCharInfo[uint8_t(c)].fUVs[ 0 ]; + verts[ j + 4 ].fUV.fX = fCharInfo[uint8_t(c)].fUVs[ 1 ].fX; - verts[ j + 5 ].fPoint.fX = x + width; - verts[ j + 5 ].fPoint.fY = (float)sY + height; - verts[ j + 5 ].fUV = fCharInfo[uint8_t(c)].fUVs[ 1 ]; + verts[ j + 5 ].fPoint.fX = x + width; + verts[ j + 5 ].fPoint.fY = (float)sY + height; + verts[ j + 5 ].fUV = fCharInfo[uint8_t(c)].fUVs[ 1 ]; - x += width + 1; - } + x += width + 1; } if( thisCount == 0 ) @@ -502,7 +396,7 @@ void plTextFont::DrawString( const char *string, int sX, int sY, uint32_t hex /// Draw a set of tris now - IDrawPrimitive(thisCount * ((style & plDebugText::kStyleBold) ? 4 : 2), verts.data()); + IDrawPrimitive(thisCount * uint32_t((style & plDebugText::kStyleBold) ? 4 : 2), verts.data()); strPtr += thisCount; } @@ -522,9 +416,7 @@ uint32_t plTextFont::CalcStringWidth( const char *string ) for( i = 0; i < strlen( string ); i++ ) { - // make sure its a character we will display - if ( DisplayableChar(string[i]) ) - width += fCharInfo[uint8_t(string[i])].fW + 2; + width += fCharInfo[uint8_t(string[i])].fW + 2; } return width;