📄 textsvcs.cpp
字号:
/* ***** BEGIN LICENSE BLOCK ***** * Source last modified: $Id: textsvcs.cpp,v 1.1.2.1 2004/07/09 01:50:49 hubbe Exp $ * * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved. * * The contents of this file, and the files included with this file, * are subject to the current version of the RealNetworks Public * Source License (the "RPSL") available at * http://www.helixcommunity.org/content/rpsl unless you have licensed * the file under the current version of the RealNetworks Community * Source License (the "RCSL") available at * http://www.helixcommunity.org/content/rcsl, in which case the RCSL * will apply. You may also obtain the license terms directly from * RealNetworks. You may not use this file except in compliance with * the RPSL or, if you have a valid RCSL with RealNetworks applicable * to this file, the RCSL. Please see the applicable RPSL or RCSL for * the rights, obligations and limitations governing use of the * contents of the file. * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL") in which case the provisions of the GPL are applicable * instead of those above. If you wish to allow use of your version of * this file only under the terms of the GPL, and not to allow others * to use your version of this file under the terms of either the RPSL * or RCSL, indicate your decision by deleting the provisions above * and replace them with the notice and other provisions required by * the GPL. If you do not delete the provisions above, a recipient may * use your version of this file under the terms of any one of the * RPSL, the RCSL or the GPL. * * This file is part of the Helix DNA Technology. RealNetworks is the * developer of the Original Code and owns the copyrights in the * portions it created. * * This file, and the files included with this file, is distributed * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET * ENJOYMENT OR NON-INFRINGEMENT. * * Technology Compatibility Kit Test Suite(s) Location: * http://www.helixcommunity.org/content/tck * * Contributor(s): * * ***** END LICENSE BLOCK ***** */ /**************************************************************************** * * Text Services for rendering text onto a bitmap * */#include "hxtypes.h" /*Must be included before windows.h for VC6 compiler*/#ifdef _WINDOWS#include <windows.h>#endif#include "stdlib.h"#include "hxassert.h"#include "hxstring.h"#include "textsvcs.h"#define LOW_BIT_MONOCHROME 0#define HIGH_BIT_MONOCHROME (LOW_BIT_MONOCHROME+7)HX_RESULTCTextServices::bltToBitmapFromBitmap(UCHAR* pOffscreenBitmap, LONG32 lOffscreenWidth, LONG32 lOffscreenHeight, LONG32 lOffscreenDepth, INT32 lPosX, INT32 lPosY, FT_Bitmap* pFTGlyphBitmap, UINT32 ulARGBforegroundColor){ HX_RESULT hxrslt = HXR_OK; UINT8 uBitNumForMonochrome = HIGH_BIT_MONOCHROME; UCHAR* p8SrcBits = NULL; // /XXXEH- bRowsInverted is TRUE for Windows. FALSE for others???#if defined(_WINDOWS) BOOL bRowsInverted = TRUE;#else BOOL bRowsInverted = FALSE;#endif LONG32 lGlyphHeight = (LONG32)pFTGlyphBitmap->rows; LONG32 lGlyphWidth = (LONG32)pFTGlyphBitmap->width; LONG32 lWBoundsChecked = lGlyphWidth+lPosX < lOffscreenWidth? lGlyphWidth+lPosX : lOffscreenWidth-1; INT32 lDestRow = lPosY; INT32 lSrcRow = 0; INT32 lNumPixelsPer32Bits = 4; // /XXXEH- need to handle non-32-bit destination-bitmap depths: if (32 != lOffscreenDepth) { HX_ASSERT(32 == lOffscreenDepth && "need_to_handle_other_bit-depths"); hxrslt = HXR_FAIL; goto cleanup; } if (ft_pixel_mode_grays == pFTGlyphBitmap->pixel_mode) { HX_ASSERT(256 == pFTGlyphBitmap->num_grays); lNumPixelsPer32Bits = 4; } else // /ft_pixel_mode_mono -- monochrome bitmap: { HX_ASSERT(ft_pixel_mode_mono == pFTGlyphBitmap->pixel_mode); lNumPixelsPer32Bits = 32; } if (4 != lNumPixelsPer32Bits && 32 != lNumPixelsPer32Bits) { // /We can't handle other than either 1 or 256 levels from the source // glyph bitmap. FreeType 2 doesn't allow for anything else, anyway, // but just in case that changes in the future... HX_ASSERT(4 == lNumPixelsPer32Bits || 32 == lNumPixelsPer32Bits); hxrslt = HXR_FAIL; goto cleanup; } /* /XXXEH- the FT_Bitmap struct: typedef struct FT_Bitmap_ { int rows; int width; int pitch; unsigned char* buffer; short num_grays; char pixel_mode; char palette_mode; void* palette; } FT_Bitmap; */ p8SrcBits = (UCHAR*)pFTGlyphBitmap->buffer; // /Go through and copy bits from the glyph bitmap to the offscreen one: for (uBitNumForMonochrome = HIGH_BIT_MONOCHROME, lDestRow = lPosY, lSrcRow = 0; (lDestRow < lPosY + lGlyphHeight) && (lDestRow < lOffscreenHeight) && (lSrcRow < lGlyphHeight); lDestRow++, lSrcRow++) { UINT32* p32DestBits = (UINT32*)pOffscreenBitmap + ((bRowsInverted ? lOffscreenHeight - 1 - lDestRow : lDestRow) * lOffscreenWidth) + lPosX; if (32 == lNumPixelsPer32Bits && lDestRow > lPosY) { // /This finishes fixing CROSSPLAT-TEXT-BUG-0015: // /Next byte starts the next row, so ignore pad bits: p8SrcBits++; uBitNumForMonochrome = HIGH_BIT_MONOCHROME; } else { p8SrcBits = (UCHAR*)pFTGlyphBitmap->buffer + ((lSrcRow/(lNumPixelsPer32Bits/4)) * lGlyphWidth); } UINT32 ulDestColNum = (UINT32)lWBoundsChecked; UINT32 ulSrcColNum = lGlyphWidth; while (ulDestColNum-- && ulSrcColNum--) { UINT8 u8GrayScale = (UINT8)(*p8SrcBits); if (32 == lNumPixelsPer32Bits) { // /Use the appropriate bit; this is 1 bit per pixel: u8GrayScale = (UINT8)(((*p8SrcBits)>>uBitNumForMonochrome) & 1); } if (0xFF <= u8GrayScale || (32 == lNumPixelsPer32Bits && u8GrayScale)) { // /Fixes CROSSPLAT-TEXT-BUG-0003 by using foregroundColor // instead of grayscale: *p32DestBits = ulARGBforegroundColor; } else if (u8GrayScale) { // /Fixes CROSSPLAT-TEXT-BUG-0004: // /Translate from grayscale to text color: set to gray- // adjusted color and also set transparency level to allow // background image to blend in. If background isn't 100% // transparent in the original value, then we need to blend // the original as well as the new values based on their // transparency values: if ((*p32DestBits & 0xFF000000) == 0xFF000000) { // /100% transparent bkgrnd, so just set alpha: *p32DestBits = ulARGBforegroundColor | // /Set the alpha channel: ((UINT32)(255-u8GrayScale) << 24); } else { // /Break out foreground colors: UINT16 usFGRed = (ulARGBforegroundColor & 0xFF0000) >> 16; UINT16 usFGGreen = (ulARGBforegroundColor & 0xFF00) >> 8; UINT16 usFGBlue = ulARGBforegroundColor & 0xFF; // /Break out background colors: UINT16 usBGRed = (*p32DestBits & 0xFF0000) >> 16; UINT16 usBGGreen = (*p32DestBits & 0xFF00) >> 8; UINT16 usBGBlue = *p32DestBits & 0xFF; float fFGPercentAlpha = 1.0 - ((float)u8GrayScale/255.0); // /If background is 100% opaque, leave alpha alone and // blend with existing (background) color: if (!(*p32DestBits & 0xFF000000)) { UINT32 ulBlendedRed = (UINT32)( (fFGPercentAlpha * usBGRed) + ((1.0-fFGPercentAlpha) * usFGRed) ) << 16; ulBlendedRed &= 0xFF0000; UINT32 ulBlendedGreen = (UINT32)( (fFGPercentAlpha * usBGGreen) + ((1.0-fFGPercentAlpha) * usFGGreen) ) << 8; ulBlendedGreen &= 0xFF00; UINT32 ulBlendedBlue = (UINT32)( (fFGPercentAlpha * usBGBlue) + ((1.0-fFGPercentAlpha) * usFGBlue) ); ulBlendedBlue &= 0xFF; *p32DestBits = (ulBlendedRed | ulBlendedGreen | ulBlendedBlue); } else // /Blend each, and average their alpha: { UINT32 ulBGAlpha = (*p32DestBits & 0xFF000000)>>24; float fBGPercentAlpha = (float)ulBGAlpha/255.0; float fProductFGAlphaBGAlpha = fFGPercentAlpha * fBGPercentAlpha; // /Code above should assure this (see division, below): HX_ASSERT(fFGPercentAlpha < 1.0 && fProductFGAlphaBGAlpha < 1.0); // /This is the scale factor we need to apply so that // when the vid-surface blending happens, the values // end up where they were supposed to be: float fScaleFactorToCounterNextSiteAlphaBlend = 1.0 / (1.0 - fProductFGAlphaBGAlpha); UINT32 ulBlendedRed = (UINT32)( ( ((1.0-fBGPercentAlpha) * fFGPercentAlpha * usBGRed) + ((1.0-fFGPercentAlpha) * usFGRed) ) * fScaleFactorToCounterNextSiteAlphaBlend) << 16; if (ulBlendedRed > 0xFFFFFF) { ulBlendedRed = 0xFF0000; } ulBlendedRed &= 0xFF0000; UINT32 ulBlendedGreen = (UINT32)( ( ((1.0-fBGPercentAlpha) * fFGPercentAlpha * usBGGreen) + ((1.0-fFGPercentAlpha) * usFGGreen) ) * fScaleFactorToCounterNextSiteAlphaBlend) << 8; if (ulBlendedGreen > 0xFFFF) { ulBlendedGreen = 0xFF00; } ulBlendedGreen &= 0xFF00; UINT32 ulBlendedBlue = (UINT32)( ( ((1.0-fBGPercentAlpha) * fFGPercentAlpha * usBGBlue) + ((1.0-fFGPercentAlpha) * usFGBlue) ) * fScaleFactorToCounterNextSiteAlphaBlend); if (ulBlendedBlue > 0xFF) { ulBlendedBlue = 0xFF; } ulBlendedBlue &= 0xFF; UINT32 ulNewAlpha = (UINT32)(255*fProductFGAlphaBGAlpha) << 24; *p32DestBits = (ulBlendedRed | ulBlendedGreen | ulBlendedBlue) | // /Set the alpha channel to the average of the // current bg alpha and the gray scale (right // shifting by 23 is the same as dividing by 2 // and then << by 24): ulNewAlpha; } } } else // /0 { ; // /XXXEH- finish this! Fill in bgrect if font bgcolor set. } p32DestBits++; if (32 == lNumPixelsPer32Bits) { if (LOW_BIT_MONOCHROME == uBitNumForMonochrome) { uBitNumForMonochrome = HIGH_BIT_MONOCHROME; // /Increment src ptr after every 8 bits: p8SrcBits++; } else { uBitNumForMonochrome--; } } else { p8SrcBits++; } } }cleanup: return hxrslt;}HX_RESULTCTextServices::renderTextSameFontFace(const char* pszString, UCHAR* pOffscreenBitmap, LONG32 lOffscreenWidth, LONG32 lOffscreenHeight, LONG32 lOffscreenDepth, INT32 lPosStartX, INT32 lPosStartY, BOOL bDoAntialias, FT_Encoding ftCharsetEncoding, UINT32 ulAvgCharWidthPixels /*0 to default*/, UINT32 ulCharHeightPixels, UINT32 ulARGBforegroundColor){ return renderText(pszString, pOffscreenBitmap, lOffscreenWidth, lOffscreenHeight, lOffscreenDepth, lPosStartX, lPosStartY, bDoAntialias, ftCharsetEncoding, USE_SAME_FAMILY_AS_PRIOR_CALL, USE_SAME_BOLD_AS_PRIOR_CALL, USE_SAME_ITALICS_AS_PRIOR_CALL, ulAvgCharWidthPixels /*0 to default*/, ulCharHeightPixels, ulARGBforegroundColor);}HX_RESULTCTextServices::renderText(const char* pszString, UCHAR* pOffscreenBitmap, LONG32 lOffscreenWidth, LONG32 lOffscreenHeight, LONG32 lOffscreenDepth, INT32 lPosStartX, INT32 lPosStartY, BOOL bDoAntialias, FT_Encoding ftCharsetEncoding, const char* pszFontFamily, // /NULL means use prior face BOOL bIsBold, // /-ignored if pszFontFamily==NULL BOOL bIsItalicized, // /-ignored if pszFontFamily==NULL UINT32 ulAvgCharWidthPixels /*0 to default*/, UINT32 ulCharHeightPixels, UINT32 ulARGBforegroundColor){ HX_RESULT hxrslt = HXR_OK; FT_ULong ulCharCode = 0; FT_UInt ulGlyphIndex = 0; FT_CharMap ftFound = 0; FT_CharMap ftCharmap = NULL; FT_Error ftError; INT32 lCurPenX = lPosStartX; INT32 lCurPenY = lPosStartY; INT32 lIndx = 0; FT_Render_Mode ftRenderMode = bDoAntialias ? ft_render_mode_normal : ft_render_mode_mono; // /XXXEH- use mbtrlen() if encoding is DBCS or use wcslen() for UNICODE: INT32 lStringlen = pszString? strlen(pszString):0; HX_ASSERT(NULL == USE_SAME_FAMILY_AS_PRIOR_CALL); // /If pszFontFamily is NULL, that means just re-use prior one which is // loaded in m_hFace. If m_hFace is NULL, too, then there's a problem: if (!pszFontFamily && !m_hFace) { HX_ASSERT(pszFontFamily || m_hFace); hxrslt = HXR_INVALID_PARAMETER; goto cleanup; } if (!pszString || !pOffscreenBitmap) { HX_ASSERT(pszString && pOffscreenBitmap); hxrslt = HXR_INVALID_PARAMETER; goto cleanup; } if (!m_hLibrary) { ftError = FT_Init_FreeType(&m_hLibrary); if (ftError || !m_hLibrary) { hxrslt = HXR_FAIL; goto cleanup; } } if (USE_SAME_FAMILY_AS_PRIOR_CALL != pszFontFamily) { if (m_hFace)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -