diff options
Diffstat (limited to 'core/src/fxge/ge')
-rw-r--r-- | core/src/fxge/ge/fx_ge.cpp | 102 | ||||
-rw-r--r-- | core/src/fxge/ge/fx_ge_device.cpp | 759 | ||||
-rw-r--r-- | core/src/fxge/ge/fx_ge_font.cpp | 768 | ||||
-rw-r--r-- | core/src/fxge/ge/fx_ge_fontmap.cpp | 2516 | ||||
-rw-r--r-- | core/src/fxge/ge/fx_ge_linux.cpp | 376 | ||||
-rw-r--r-- | core/src/fxge/ge/fx_ge_path.cpp | 1236 | ||||
-rw-r--r-- | core/src/fxge/ge/fx_ge_ps.cpp | 1240 | ||||
-rw-r--r-- | core/src/fxge/ge/fx_ge_text.cpp | 3438 | ||||
-rw-r--r-- | core/src/fxge/ge/text_int.h | 162 |
9 files changed, 5521 insertions, 5076 deletions
diff --git a/core/src/fxge/ge/fx_ge.cpp b/core/src/fxge/ge/fx_ge.cpp index 6ba6cf5979..d37ed5c714 100644 --- a/core/src/fxge/ge/fx_ge.cpp +++ b/core/src/fxge/ge/fx_ge.cpp @@ -7,59 +7,51 @@ #include "../../../include/fxge/fx_ge.h" #include "text_int.h" static CFX_GEModule* g_pGEModule = NULL; -CFX_GEModule::CFX_GEModule() -{ - m_pFontCache = NULL; - m_pFontMgr = NULL; - m_FTLibrary = NULL; - m_pCodecModule = NULL; - m_pPlatformData = NULL; -} -CFX_GEModule::~CFX_GEModule() -{ - delete m_pFontCache; - m_pFontCache = NULL; - delete m_pFontMgr; - m_pFontMgr = NULL; - DestroyPlatform(); -} -CFX_GEModule* CFX_GEModule::Get() -{ - return g_pGEModule; -} -void CFX_GEModule::Create() -{ - g_pGEModule = new CFX_GEModule; - g_pGEModule->m_pFontMgr = new CFX_FontMgr; - g_pGEModule->InitPlatform(); - g_pGEModule->SetTextGamma(2.2f); -} -void CFX_GEModule::Use(CFX_GEModule* pModule) -{ - g_pGEModule = pModule; -} -void CFX_GEModule::Destroy() -{ - delete g_pGEModule; - g_pGEModule = NULL; -} -CFX_FontCache* CFX_GEModule::GetFontCache() -{ - if (m_pFontCache == NULL) { - m_pFontCache = new CFX_FontCache(); - } - return m_pFontCache; -} -void CFX_GEModule::SetTextGamma(FX_FLOAT gammaValue) -{ - gammaValue /= 2.2f; - int i = 0; - while (i < 256) { - m_GammaValue[i] = (uint8_t)(FXSYS_pow((FX_FLOAT)i / 255, gammaValue) * 255.0f + 0.5f); - i++; - } -} -const uint8_t* CFX_GEModule::GetTextGammaTable() -{ - return m_GammaValue; +CFX_GEModule::CFX_GEModule() { + m_pFontCache = NULL; + m_pFontMgr = NULL; + m_FTLibrary = NULL; + m_pCodecModule = NULL; + m_pPlatformData = NULL; +} +CFX_GEModule::~CFX_GEModule() { + delete m_pFontCache; + m_pFontCache = NULL; + delete m_pFontMgr; + m_pFontMgr = NULL; + DestroyPlatform(); +} +CFX_GEModule* CFX_GEModule::Get() { + return g_pGEModule; +} +void CFX_GEModule::Create() { + g_pGEModule = new CFX_GEModule; + g_pGEModule->m_pFontMgr = new CFX_FontMgr; + g_pGEModule->InitPlatform(); + g_pGEModule->SetTextGamma(2.2f); +} +void CFX_GEModule::Use(CFX_GEModule* pModule) { + g_pGEModule = pModule; +} +void CFX_GEModule::Destroy() { + delete g_pGEModule; + g_pGEModule = NULL; +} +CFX_FontCache* CFX_GEModule::GetFontCache() { + if (m_pFontCache == NULL) { + m_pFontCache = new CFX_FontCache(); + } + return m_pFontCache; +} +void CFX_GEModule::SetTextGamma(FX_FLOAT gammaValue) { + gammaValue /= 2.2f; + int i = 0; + while (i < 256) { + m_GammaValue[i] = + (uint8_t)(FXSYS_pow((FX_FLOAT)i / 255, gammaValue) * 255.0f + 0.5f); + i++; + } +} +const uint8_t* CFX_GEModule::GetTextGammaTable() { + return m_GammaValue; } diff --git a/core/src/fxge/ge/fx_ge_device.cpp b/core/src/fxge/ge/fx_ge_device.cpp index 0baa99cdc7..7ab399a3bd 100644 --- a/core/src/fxge/ge/fx_ge_device.cpp +++ b/core/src/fxge/ge/fx_ge_device.cpp @@ -5,398 +5,471 @@ // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com #include "../../../include/fxge/fx_ge.h" -CFX_RenderDevice::CFX_RenderDevice() -{ - m_pDeviceDriver = NULL; - m_pBitmap = NULL; +CFX_RenderDevice::CFX_RenderDevice() { + m_pDeviceDriver = NULL; + m_pBitmap = NULL; } -CFX_RenderDevice::~CFX_RenderDevice() -{ - delete m_pDeviceDriver; +CFX_RenderDevice::~CFX_RenderDevice() { + delete m_pDeviceDriver; } -void CFX_RenderDevice::SetDeviceDriver(IFX_RenderDeviceDriver* pDriver) -{ - delete m_pDeviceDriver; - m_pDeviceDriver = pDriver; - InitDeviceInfo(); +void CFX_RenderDevice::SetDeviceDriver(IFX_RenderDeviceDriver* pDriver) { + delete m_pDeviceDriver; + m_pDeviceDriver = pDriver; + InitDeviceInfo(); } -void CFX_RenderDevice::InitDeviceInfo() -{ - ASSERT(m_pDeviceDriver != NULL); - m_Width = m_pDeviceDriver->GetDeviceCaps(FXDC_PIXEL_WIDTH); - m_Height = m_pDeviceDriver->GetDeviceCaps(FXDC_PIXEL_HEIGHT); - m_bpp = m_pDeviceDriver->GetDeviceCaps(FXDC_BITS_PIXEL); - m_RenderCaps = m_pDeviceDriver->GetDeviceCaps(FXDC_RENDER_CAPS); - m_DeviceClass = m_pDeviceDriver->GetDeviceCaps(FXDC_DEVICE_CLASS); - if (!m_pDeviceDriver->GetClipBox(&m_ClipBox)) { - m_ClipBox.left = 0; - m_ClipBox.top = 0; - m_ClipBox.right = m_Width; - m_ClipBox.bottom = m_Height; - } +void CFX_RenderDevice::InitDeviceInfo() { + ASSERT(m_pDeviceDriver != NULL); + m_Width = m_pDeviceDriver->GetDeviceCaps(FXDC_PIXEL_WIDTH); + m_Height = m_pDeviceDriver->GetDeviceCaps(FXDC_PIXEL_HEIGHT); + m_bpp = m_pDeviceDriver->GetDeviceCaps(FXDC_BITS_PIXEL); + m_RenderCaps = m_pDeviceDriver->GetDeviceCaps(FXDC_RENDER_CAPS); + m_DeviceClass = m_pDeviceDriver->GetDeviceCaps(FXDC_DEVICE_CLASS); + if (!m_pDeviceDriver->GetClipBox(&m_ClipBox)) { + m_ClipBox.left = 0; + m_ClipBox.top = 0; + m_ClipBox.right = m_Width; + m_ClipBox.bottom = m_Height; + } } -FX_BOOL CFX_RenderDevice::StartRendering() -{ - return m_pDeviceDriver->StartRendering(); +FX_BOOL CFX_RenderDevice::StartRendering() { + return m_pDeviceDriver->StartRendering(); } -void CFX_RenderDevice::EndRendering() -{ - m_pDeviceDriver->EndRendering(); +void CFX_RenderDevice::EndRendering() { + m_pDeviceDriver->EndRendering(); } -void CFX_RenderDevice::SaveState() -{ - m_pDeviceDriver->SaveState(); +void CFX_RenderDevice::SaveState() { + m_pDeviceDriver->SaveState(); } -void CFX_RenderDevice::RestoreState(FX_BOOL bKeepSaved) -{ - m_pDeviceDriver->RestoreState(bKeepSaved); - UpdateClipBox(); +void CFX_RenderDevice::RestoreState(FX_BOOL bKeepSaved) { + m_pDeviceDriver->RestoreState(bKeepSaved); + UpdateClipBox(); } -int CFX_RenderDevice::GetDeviceCaps(int caps_id) const -{ - return m_pDeviceDriver->GetDeviceCaps(caps_id); +int CFX_RenderDevice::GetDeviceCaps(int caps_id) const { + return m_pDeviceDriver->GetDeviceCaps(caps_id); } -CFX_Matrix CFX_RenderDevice::GetCTM() const -{ - return m_pDeviceDriver->GetCTM(); +CFX_Matrix CFX_RenderDevice::GetCTM() const { + return m_pDeviceDriver->GetCTM(); } -FX_BOOL CFX_RenderDevice::CreateCompatibleBitmap(CFX_DIBitmap* pDIB, int width, int height) const -{ - if (m_RenderCaps & FXRC_CMYK_OUTPUT) { - return pDIB->Create(width, height, m_RenderCaps & FXRC_ALPHA_OUTPUT ? FXDIB_Cmyka : FXDIB_Cmyk); - } - if (m_RenderCaps & FXRC_BYTEMASK_OUTPUT) { - return pDIB->Create(width, height, FXDIB_8bppMask); - } -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ - return pDIB->Create(width, height, m_RenderCaps & FXRC_ALPHA_OUTPUT ? FXDIB_Argb : FXDIB_Rgb32); +FX_BOOL CFX_RenderDevice::CreateCompatibleBitmap(CFX_DIBitmap* pDIB, + int width, + int height) const { + if (m_RenderCaps & FXRC_CMYK_OUTPUT) { + return pDIB->Create(width, height, m_RenderCaps & FXRC_ALPHA_OUTPUT + ? FXDIB_Cmyka + : FXDIB_Cmyk); + } + if (m_RenderCaps & FXRC_BYTEMASK_OUTPUT) { + return pDIB->Create(width, height, FXDIB_8bppMask); + } +#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ + return pDIB->Create(width, height, m_RenderCaps & FXRC_ALPHA_OUTPUT + ? FXDIB_Argb + : FXDIB_Rgb32); #else - return pDIB->Create(width, height, m_RenderCaps & FXRC_ALPHA_OUTPUT ? FXDIB_Argb : FXDIB_Rgb); + return pDIB->Create( + width, height, m_RenderCaps & FXRC_ALPHA_OUTPUT ? FXDIB_Argb : FXDIB_Rgb); #endif } -FX_BOOL CFX_RenderDevice::SetClip_PathFill(const CFX_PathData* pPathData, - const CFX_AffineMatrix* pObject2Device, - int fill_mode - ) -{ - if (!m_pDeviceDriver->SetClip_PathFill(pPathData, pObject2Device, fill_mode)) { - return FALSE; - } - UpdateClipBox(); - return TRUE; +FX_BOOL CFX_RenderDevice::SetClip_PathFill( + const CFX_PathData* pPathData, + const CFX_AffineMatrix* pObject2Device, + int fill_mode) { + if (!m_pDeviceDriver->SetClip_PathFill(pPathData, pObject2Device, + fill_mode)) { + return FALSE; + } + UpdateClipBox(); + return TRUE; } -FX_BOOL CFX_RenderDevice::SetClip_PathStroke(const CFX_PathData* pPathData, - const CFX_AffineMatrix* pObject2Device, - const CFX_GraphStateData* pGraphState - ) -{ - if (!m_pDeviceDriver->SetClip_PathStroke(pPathData, pObject2Device, pGraphState)) { - return FALSE; - } - UpdateClipBox(); - return TRUE; +FX_BOOL CFX_RenderDevice::SetClip_PathStroke( + const CFX_PathData* pPathData, + const CFX_AffineMatrix* pObject2Device, + const CFX_GraphStateData* pGraphState) { + if (!m_pDeviceDriver->SetClip_PathStroke(pPathData, pObject2Device, + pGraphState)) { + return FALSE; + } + UpdateClipBox(); + return TRUE; } -FX_BOOL CFX_RenderDevice::SetClip_Rect(const FX_RECT* pRect) -{ - CFX_PathData path; - path.AppendRect((FX_FLOAT)(pRect->left), (FX_FLOAT)(pRect->bottom), (FX_FLOAT)(pRect->right), (FX_FLOAT)(pRect->top)); - if (!SetClip_PathFill(&path, NULL, FXFILL_WINDING)) { - return FALSE; - } - UpdateClipBox(); - return TRUE; +FX_BOOL CFX_RenderDevice::SetClip_Rect(const FX_RECT* pRect) { + CFX_PathData path; + path.AppendRect((FX_FLOAT)(pRect->left), (FX_FLOAT)(pRect->bottom), + (FX_FLOAT)(pRect->right), (FX_FLOAT)(pRect->top)); + if (!SetClip_PathFill(&path, NULL, FXFILL_WINDING)) { + return FALSE; + } + UpdateClipBox(); + return TRUE; } -void CFX_RenderDevice::UpdateClipBox() -{ - if (m_pDeviceDriver->GetClipBox(&m_ClipBox)) { - return; - } - m_ClipBox.left = 0; - m_ClipBox.top = 0; - m_ClipBox.right = m_Width; - m_ClipBox.bottom = m_Height; +void CFX_RenderDevice::UpdateClipBox() { + if (m_pDeviceDriver->GetClipBox(&m_ClipBox)) { + return; + } + m_ClipBox.left = 0; + m_ClipBox.top = 0; + m_ClipBox.right = m_Width; + m_ClipBox.bottom = m_Height; } FX_BOOL CFX_RenderDevice::DrawPath(const CFX_PathData* pPathData, const CFX_AffineMatrix* pObject2Device, const CFX_GraphStateData* pGraphState, - FX_DWORD fill_color, FX_DWORD stroke_color, int fill_mode, - int alpha_flag, void* pIccTransform, int blend_type) -{ - uint8_t fill_alpha, stroke_alpha; - if (FXGETFLAG_COLORTYPE(alpha_flag)) { - fill_alpha = FXGETFLAG_ALPHA_FILL(alpha_flag); - stroke_alpha = FXGETFLAG_ALPHA_STROKE(alpha_flag); + FX_DWORD fill_color, + FX_DWORD stroke_color, + int fill_mode, + int alpha_flag, + void* pIccTransform, + int blend_type) { + uint8_t fill_alpha, stroke_alpha; + if (FXGETFLAG_COLORTYPE(alpha_flag)) { + fill_alpha = FXGETFLAG_ALPHA_FILL(alpha_flag); + stroke_alpha = FXGETFLAG_ALPHA_STROKE(alpha_flag); + } else { + fill_alpha = FXARGB_A(fill_color); + stroke_alpha = FXARGB_A(stroke_color); + } + if ((fill_mode & 3) == 0) { + fill_alpha = 0; + } + if (pGraphState == NULL) { + stroke_alpha = 0; + } + if (stroke_alpha == 0 && pPathData->GetPointCount() == 2) { + FX_PATHPOINT* pPoints = pPathData->GetPoints(); + FX_FLOAT x1, x2, y1, y2; + if (pObject2Device) { + pObject2Device->Transform(pPoints[0].m_PointX, pPoints[0].m_PointY, x1, + y1); + pObject2Device->Transform(pPoints[1].m_PointX, pPoints[1].m_PointY, x2, + y2); } else { - fill_alpha = FXARGB_A(fill_color); - stroke_alpha = FXARGB_A(stroke_color); - } - if ((fill_mode & 3) == 0) { - fill_alpha = 0; - } - if (pGraphState == NULL) { - stroke_alpha = 0; - } - if (stroke_alpha == 0 && pPathData->GetPointCount() == 2) { - FX_PATHPOINT* pPoints = pPathData->GetPoints(); - FX_FLOAT x1, x2, y1, y2; - if (pObject2Device) { - pObject2Device->Transform(pPoints[0].m_PointX, pPoints[0].m_PointY, x1, y1); - pObject2Device->Transform(pPoints[1].m_PointX, pPoints[1].m_PointY, x2, y2); - } else { - x1 = pPoints[0].m_PointX; - y1 = pPoints[0].m_PointY; - x2 = pPoints[1].m_PointX; - y2 = pPoints[1].m_PointY; - } - DrawCosmeticLine(x1, y1, x2, y2, fill_color, fill_mode, alpha_flag, pIccTransform, blend_type); - return TRUE; + x1 = pPoints[0].m_PointX; + y1 = pPoints[0].m_PointY; + x2 = pPoints[1].m_PointX; + y2 = pPoints[1].m_PointY; } - if ((pPathData->GetPointCount() == 5 || pPathData->GetPointCount() == 4) && stroke_alpha == 0) { - CFX_FloatRect rect_f; - if (!(fill_mode & FXFILL_RECT_AA) && pPathData->IsRect(pObject2Device, &rect_f)) { - FX_RECT rect_i = rect_f.GetOutterRect(); - int width = (int)FXSYS_ceil(rect_f.right - rect_f.left); - if (width < 1) { - width = 1; - if (rect_i.left == rect_i.right) { - rect_i.right ++; - } - } - int height = (int)FXSYS_ceil(rect_f.top - rect_f.bottom); - if (height < 1) { - height = 1; - if (rect_i.bottom == rect_i.top) { - rect_i.bottom ++; - } - } - if (rect_i.Width() >= width + 1) { - if (rect_f.left - (FX_FLOAT)(rect_i.left) > (FX_FLOAT)(rect_i.right) - rect_f.right) { - rect_i.left ++; - } else { - rect_i.right --; - } - } - if (rect_i.Height() >= height + 1) { - if (rect_f.top - (FX_FLOAT)(rect_i.top) > (FX_FLOAT)(rect_i.bottom) - rect_f.bottom) { - rect_i.top ++; - } else { - rect_i.bottom --; - } - } - if (FillRect(&rect_i, fill_color, alpha_flag, pIccTransform, blend_type)) { - return TRUE; - } + DrawCosmeticLine(x1, y1, x2, y2, fill_color, fill_mode, alpha_flag, + pIccTransform, blend_type); + return TRUE; + } + if ((pPathData->GetPointCount() == 5 || pPathData->GetPointCount() == 4) && + stroke_alpha == 0) { + CFX_FloatRect rect_f; + if (!(fill_mode & FXFILL_RECT_AA) && + pPathData->IsRect(pObject2Device, &rect_f)) { + FX_RECT rect_i = rect_f.GetOutterRect(); + int width = (int)FXSYS_ceil(rect_f.right - rect_f.left); + if (width < 1) { + width = 1; + if (rect_i.left == rect_i.right) { + rect_i.right++; } - } - if((fill_mode & 3) && stroke_alpha == 0 && !(fill_mode & FX_FILL_STROKE) && !(fill_mode & FX_FILL_TEXT_MODE)) { - CFX_PathData newPath; - FX_BOOL bThin = FALSE; - if (pPathData->GetZeroAreaPath(newPath, (CFX_Matrix*)pObject2Device, bThin, m_pDeviceDriver->GetDriverType())) { - CFX_GraphStateData graphState; - graphState.m_LineWidth = 0.0f; - FX_DWORD strokecolor = fill_color; - if (bThin) { - if (FXGETFLAG_COLORTYPE(alpha_flag)) { - FXSETFLAG_ALPHA_STROKE(alpha_flag, fill_alpha >> 2); - } else { - strokecolor = (((fill_alpha >> 2) << 24) | (strokecolor & 0x00ffffff)); - } - } - CFX_AffineMatrix* pMatrix = NULL; - if (pObject2Device && !pObject2Device->IsIdentity()) { - pMatrix = (CFX_AffineMatrix*)pObject2Device; - } - int smooth_path = FX_ZEROAREA_FILL; - if (fill_mode & FXFILL_NOPATHSMOOTH) { - smooth_path |= FXFILL_NOPATHSMOOTH; - } - m_pDeviceDriver->DrawPath(&newPath, pMatrix, &graphState, 0, strokecolor, smooth_path, alpha_flag, pIccTransform, blend_type); + } + int height = (int)FXSYS_ceil(rect_f.top - rect_f.bottom); + if (height < 1) { + height = 1; + if (rect_i.bottom == rect_i.top) { + rect_i.bottom++; } - } - if ((fill_mode & 3) && fill_alpha && stroke_alpha < 0xff && (fill_mode & FX_FILL_STROKE)) { - if (!(m_RenderCaps & FXRC_GET_BITS)) { - return FALSE; - } - CFX_FloatRect bbox; - if (pGraphState) { - bbox = pPathData->GetBoundingBox(pGraphState->m_LineWidth, pGraphState->m_MiterLimit); + } + if (rect_i.Width() >= width + 1) { + if (rect_f.left - (FX_FLOAT)(rect_i.left) > + (FX_FLOAT)(rect_i.right) - rect_f.right) { + rect_i.left++; } else { - bbox = pPathData->GetBoundingBox(); - } - if (pObject2Device) { - bbox.Transform(pObject2Device); + rect_i.right--; } - CFX_Matrix ctm = GetCTM(); - FX_FLOAT fScaleX = FXSYS_fabs(ctm.a); - FX_FLOAT fScaleY = FXSYS_fabs(ctm.d); - FX_RECT rect = bbox.GetOutterRect(); - CFX_DIBitmap bitmap, Backdrop; - if (!CreateCompatibleBitmap(&bitmap, FXSYS_round(rect.Width() * fScaleX), FXSYS_round(rect.Height() * fScaleY))) { - return FALSE; - } - if (bitmap.HasAlpha()) { - bitmap.Clear(0); - Backdrop.Copy(&bitmap); + } + if (rect_i.Height() >= height + 1) { + if (rect_f.top - (FX_FLOAT)(rect_i.top) > + (FX_FLOAT)(rect_i.bottom) - rect_f.bottom) { + rect_i.top++; } else { - if (!m_pDeviceDriver->GetDIBits(&bitmap, rect.left, rect.top, NULL)) { - return FALSE; - } - Backdrop.Copy(&bitmap); - } - CFX_FxgeDevice bitmap_device; - bitmap_device.Attach(&bitmap, 0, FALSE, &Backdrop, TRUE); - CFX_AffineMatrix matrix; - if (pObject2Device) { - matrix = *pObject2Device; + rect_i.bottom--; } - matrix.TranslateI(-rect.left, -rect.top); - matrix.Concat(fScaleX, 0, 0, fScaleY, 0, 0); - if (!bitmap_device.GetDeviceDriver()->DrawPath(pPathData, &matrix, pGraphState, fill_color, stroke_color, fill_mode, alpha_flag, pIccTransform, blend_type)) { - return FALSE; - } - FX_RECT src_rect(0, 0, FXSYS_round(rect.Width() * fScaleX), FXSYS_round(rect.Height() * fScaleY)); - return m_pDeviceDriver->SetDIBits(&bitmap, 0, &src_rect, rect.left, rect.top, FXDIB_BLEND_NORMAL); - } - return m_pDeviceDriver->DrawPath(pPathData, pObject2Device, pGraphState, fill_color, stroke_color, fill_mode, alpha_flag, pIccTransform, blend_type); -} -FX_BOOL CFX_RenderDevice::SetPixel(int x, int y, FX_DWORD color, int alpha_flag, void* pIccTransform) -{ - if (m_pDeviceDriver->SetPixel(x, y, color, alpha_flag, pIccTransform)) { + } + if (FillRect(&rect_i, fill_color, alpha_flag, pIccTransform, + blend_type)) { return TRUE; + } } - FX_RECT rect(x, y, x + 1, y + 1); - return FillRect(&rect, color, alpha_flag, pIccTransform); -} -FX_BOOL CFX_RenderDevice::FillRect(const FX_RECT* pRect, FX_DWORD fill_color, int alpha_flag, void* pIccTransform, int blend_type) -{ - if (m_pDeviceDriver->FillRect(pRect, fill_color, alpha_flag, pIccTransform, blend_type)) { - return TRUE; + } + if ((fill_mode & 3) && stroke_alpha == 0 && !(fill_mode & FX_FILL_STROKE) && + !(fill_mode & FX_FILL_TEXT_MODE)) { + CFX_PathData newPath; + FX_BOOL bThin = FALSE; + if (pPathData->GetZeroAreaPath(newPath, (CFX_Matrix*)pObject2Device, bThin, + m_pDeviceDriver->GetDriverType())) { + CFX_GraphStateData graphState; + graphState.m_LineWidth = 0.0f; + FX_DWORD strokecolor = fill_color; + if (bThin) { + if (FXGETFLAG_COLORTYPE(alpha_flag)) { + FXSETFLAG_ALPHA_STROKE(alpha_flag, fill_alpha >> 2); + } else { + strokecolor = + (((fill_alpha >> 2) << 24) | (strokecolor & 0x00ffffff)); + } + } + CFX_AffineMatrix* pMatrix = NULL; + if (pObject2Device && !pObject2Device->IsIdentity()) { + pMatrix = (CFX_AffineMatrix*)pObject2Device; + } + int smooth_path = FX_ZEROAREA_FILL; + if (fill_mode & FXFILL_NOPATHSMOOTH) { + smooth_path |= FXFILL_NOPATHSMOOTH; + } + m_pDeviceDriver->DrawPath(&newPath, pMatrix, &graphState, 0, strokecolor, + smooth_path, alpha_flag, pIccTransform, + blend_type); } + } + if ((fill_mode & 3) && fill_alpha && stroke_alpha < 0xff && + (fill_mode & FX_FILL_STROKE)) { if (!(m_RenderCaps & FXRC_GET_BITS)) { - return FALSE; + return FALSE; } - CFX_DIBitmap bitmap; - if (!CreateCompatibleBitmap(&bitmap, pRect->Width(), pRect->Height())) { - return FALSE; + CFX_FloatRect bbox; + if (pGraphState) { + bbox = pPathData->GetBoundingBox(pGraphState->m_LineWidth, + pGraphState->m_MiterLimit); + } else { + bbox = pPathData->GetBoundingBox(); } - if (!m_pDeviceDriver->GetDIBits(&bitmap, pRect->left, pRect->top)) { - return FALSE; + if (pObject2Device) { + bbox.Transform(pObject2Device); } - if (!bitmap.CompositeRect(0, 0, pRect->Width(), pRect->Height(), fill_color, alpha_flag, pIccTransform)) { + CFX_Matrix ctm = GetCTM(); + FX_FLOAT fScaleX = FXSYS_fabs(ctm.a); + FX_FLOAT fScaleY = FXSYS_fabs(ctm.d); + FX_RECT rect = bbox.GetOutterRect(); + CFX_DIBitmap bitmap, Backdrop; + if (!CreateCompatibleBitmap(&bitmap, FXSYS_round(rect.Width() * fScaleX), + FXSYS_round(rect.Height() * fScaleY))) { + return FALSE; + } + if (bitmap.HasAlpha()) { + bitmap.Clear(0); + Backdrop.Copy(&bitmap); + } else { + if (!m_pDeviceDriver->GetDIBits(&bitmap, rect.left, rect.top, NULL)) { return FALSE; + } + Backdrop.Copy(&bitmap); + } + CFX_FxgeDevice bitmap_device; + bitmap_device.Attach(&bitmap, 0, FALSE, &Backdrop, TRUE); + CFX_AffineMatrix matrix; + if (pObject2Device) { + matrix = *pObject2Device; } - FX_RECT src_rect(0, 0, pRect->Width(), pRect->Height()); - m_pDeviceDriver->SetDIBits(&bitmap, 0, &src_rect, pRect->left, pRect->top, FXDIB_BLEND_NORMAL); + matrix.TranslateI(-rect.left, -rect.top); + matrix.Concat(fScaleX, 0, 0, fScaleY, 0, 0); + if (!bitmap_device.GetDeviceDriver()->DrawPath( + pPathData, &matrix, pGraphState, fill_color, stroke_color, + fill_mode, alpha_flag, pIccTransform, blend_type)) { + return FALSE; + } + FX_RECT src_rect(0, 0, FXSYS_round(rect.Width() * fScaleX), + FXSYS_round(rect.Height() * fScaleY)); + return m_pDeviceDriver->SetDIBits(&bitmap, 0, &src_rect, rect.left, + rect.top, FXDIB_BLEND_NORMAL); + } + return m_pDeviceDriver->DrawPath(pPathData, pObject2Device, pGraphState, + fill_color, stroke_color, fill_mode, + alpha_flag, pIccTransform, blend_type); +} +FX_BOOL CFX_RenderDevice::SetPixel(int x, + int y, + FX_DWORD color, + int alpha_flag, + void* pIccTransform) { + if (m_pDeviceDriver->SetPixel(x, y, color, alpha_flag, pIccTransform)) { return TRUE; + } + FX_RECT rect(x, y, x + 1, y + 1); + return FillRect(&rect, color, alpha_flag, pIccTransform); } -FX_BOOL CFX_RenderDevice::DrawCosmeticLine(FX_FLOAT x1, FX_FLOAT y1, FX_FLOAT x2, FX_FLOAT y2, FX_DWORD color, - int fill_mode, int alpha_flag, void* pIccTransform, int blend_type) -{ - if (((m_RenderCaps & FXRC_ALPHA_PATH) && - (FXGETFLAG_COLORTYPE(alpha_flag) && FXGETFLAG_ALPHA_FILL(alpha_flag) == 0xff)) || - color >= 0xff000000) - if (m_pDeviceDriver->DrawCosmeticLine(x1, y1, x2, y2, color, alpha_flag, pIccTransform, blend_type)) { - return TRUE; - } - CFX_GraphStateData graph_state; - CFX_PathData path; - path.SetPointCount(2); - path.SetPoint(0, x1, y1, FXPT_MOVETO); - path.SetPoint(1, x2, y2, FXPT_LINETO); - return m_pDeviceDriver->DrawPath(&path, NULL, &graph_state, 0, color, fill_mode, alpha_flag, pIccTransform, blend_type); +FX_BOOL CFX_RenderDevice::FillRect(const FX_RECT* pRect, + FX_DWORD fill_color, + int alpha_flag, + void* pIccTransform, + int blend_type) { + if (m_pDeviceDriver->FillRect(pRect, fill_color, alpha_flag, pIccTransform, + blend_type)) { + return TRUE; + } + if (!(m_RenderCaps & FXRC_GET_BITS)) { + return FALSE; + } + CFX_DIBitmap bitmap; + if (!CreateCompatibleBitmap(&bitmap, pRect->Width(), pRect->Height())) { + return FALSE; + } + if (!m_pDeviceDriver->GetDIBits(&bitmap, pRect->left, pRect->top)) { + return FALSE; + } + if (!bitmap.CompositeRect(0, 0, pRect->Width(), pRect->Height(), fill_color, + alpha_flag, pIccTransform)) { + return FALSE; + } + FX_RECT src_rect(0, 0, pRect->Width(), pRect->Height()); + m_pDeviceDriver->SetDIBits(&bitmap, 0, &src_rect, pRect->left, pRect->top, + FXDIB_BLEND_NORMAL); + return TRUE; } -FX_BOOL CFX_RenderDevice::GetDIBits(CFX_DIBitmap* pBitmap, int left, int top, void* pIccTransform) -{ - if (!(m_RenderCaps & FXRC_GET_BITS)) { - return FALSE; +FX_BOOL CFX_RenderDevice::DrawCosmeticLine(FX_FLOAT x1, + FX_FLOAT y1, + FX_FLOAT x2, + FX_FLOAT y2, + FX_DWORD color, + int fill_mode, + int alpha_flag, + void* pIccTransform, + int blend_type) { + if (((m_RenderCaps & FXRC_ALPHA_PATH) && + (FXGETFLAG_COLORTYPE(alpha_flag) && + FXGETFLAG_ALPHA_FILL(alpha_flag) == 0xff)) || + color >= 0xff000000) + if (m_pDeviceDriver->DrawCosmeticLine(x1, y1, x2, y2, color, alpha_flag, + pIccTransform, blend_type)) { + return TRUE; } - return m_pDeviceDriver->GetDIBits(pBitmap, left, top, pIccTransform); + CFX_GraphStateData graph_state; + CFX_PathData path; + path.SetPointCount(2); + path.SetPoint(0, x1, y1, FXPT_MOVETO); + path.SetPoint(1, x2, y2, FXPT_LINETO); + return m_pDeviceDriver->DrawPath(&path, NULL, &graph_state, 0, color, + fill_mode, alpha_flag, pIccTransform, + blend_type); } -CFX_DIBitmap* CFX_RenderDevice::GetBackDrop() -{ - return m_pDeviceDriver->GetBackDrop(); +FX_BOOL CFX_RenderDevice::GetDIBits(CFX_DIBitmap* pBitmap, + int left, + int top, + void* pIccTransform) { + if (!(m_RenderCaps & FXRC_GET_BITS)) { + return FALSE; + } + return m_pDeviceDriver->GetDIBits(pBitmap, left, top, pIccTransform); } -FX_BOOL CFX_RenderDevice::SetDIBits(const CFX_DIBSource* pBitmap, int left, int top, int blend_mode, - void* pIccTransform) -{ - ASSERT(!pBitmap->IsAlphaMask()); - CFX_AffineMatrix ctm = GetCTM(); - FX_FLOAT fScaleX = FXSYS_fabs(ctm.a); - FX_FLOAT fScaleY = FXSYS_fabs(ctm.d); - FX_RECT dest_rect(left, top, FXSYS_round(left + pBitmap->GetWidth() / fScaleX), FXSYS_round(top + pBitmap->GetHeight() / fScaleY)); - dest_rect.Intersect(m_ClipBox); - if (dest_rect.IsEmpty()) { - return TRUE; +CFX_DIBitmap* CFX_RenderDevice::GetBackDrop() { + return m_pDeviceDriver->GetBackDrop(); +} +FX_BOOL CFX_RenderDevice::SetDIBits(const CFX_DIBSource* pBitmap, + int left, + int top, + int blend_mode, + void* pIccTransform) { + ASSERT(!pBitmap->IsAlphaMask()); + CFX_AffineMatrix ctm = GetCTM(); + FX_FLOAT fScaleX = FXSYS_fabs(ctm.a); + FX_FLOAT fScaleY = FXSYS_fabs(ctm.d); + FX_RECT dest_rect(left, top, + FXSYS_round(left + pBitmap->GetWidth() / fScaleX), + FXSYS_round(top + pBitmap->GetHeight() / fScaleY)); + dest_rect.Intersect(m_ClipBox); + if (dest_rect.IsEmpty()) { + return TRUE; + } + FX_RECT src_rect(dest_rect.left - left, dest_rect.top - top, + dest_rect.left - left + dest_rect.Width(), + dest_rect.top - top + dest_rect.Height()); + src_rect.left = FXSYS_round(src_rect.left * fScaleX); + src_rect.top = FXSYS_round(src_rect.top * fScaleY); + src_rect.right = FXSYS_round(src_rect.right * fScaleX); + src_rect.bottom = FXSYS_round(src_rect.bottom * fScaleY); + if ((blend_mode != FXDIB_BLEND_NORMAL && !(m_RenderCaps & FXRC_BLEND_MODE)) || + (pBitmap->HasAlpha() && !(m_RenderCaps & FXRC_ALPHA_IMAGE))) { + if (!(m_RenderCaps & FXRC_GET_BITS)) { + return FALSE; } - FX_RECT src_rect(dest_rect.left - left, dest_rect.top - top, - dest_rect.left - left + dest_rect.Width(), dest_rect.top - top + dest_rect.Height()); - src_rect.left = FXSYS_round(src_rect.left * fScaleX); - src_rect.top = FXSYS_round(src_rect.top * fScaleY); - src_rect.right = FXSYS_round(src_rect.right * fScaleX); - src_rect.bottom = FXSYS_round(src_rect.bottom * fScaleY); - if ((blend_mode != FXDIB_BLEND_NORMAL && !(m_RenderCaps & FXRC_BLEND_MODE)) || - (pBitmap->HasAlpha() && !(m_RenderCaps & FXRC_ALPHA_IMAGE))) { - if (!(m_RenderCaps & FXRC_GET_BITS)) { - return FALSE; - } - int bg_pixel_width = FXSYS_round(dest_rect.Width() * fScaleX); - int bg_pixel_height = FXSYS_round(dest_rect.Height() * fScaleY); - CFX_DIBitmap background; - if (!background.Create(bg_pixel_width, bg_pixel_height, - (m_RenderCaps & FXRC_CMYK_OUTPUT) ? FXDIB_Cmyk : FXDIB_Rgb32)) { - return FALSE; - } - if (!m_pDeviceDriver->GetDIBits(&background, dest_rect.left, dest_rect.top)) { - return FALSE; - } - if (!background.CompositeBitmap(0, 0, bg_pixel_width, bg_pixel_height, - pBitmap, src_rect.left, src_rect.top, - blend_mode, NULL, FALSE, pIccTransform)) { - return FALSE; - } - FX_RECT src_rect(0, 0, bg_pixel_width, bg_pixel_height); - return m_pDeviceDriver->SetDIBits(&background, 0, &src_rect, dest_rect.left, dest_rect.top, FXDIB_BLEND_NORMAL); + int bg_pixel_width = FXSYS_round(dest_rect.Width() * fScaleX); + int bg_pixel_height = FXSYS_round(dest_rect.Height() * fScaleY); + CFX_DIBitmap background; + if (!background.Create( + bg_pixel_width, bg_pixel_height, + (m_RenderCaps & FXRC_CMYK_OUTPUT) ? FXDIB_Cmyk : FXDIB_Rgb32)) { + return FALSE; } - return m_pDeviceDriver->SetDIBits(pBitmap, 0, &src_rect, dest_rect.left, dest_rect.top, blend_mode, 0, pIccTransform); -} -FX_BOOL CFX_RenderDevice::StretchDIBits(const CFX_DIBSource* pBitmap, int left, int top, - int dest_width, int dest_height, FX_DWORD flags, - void* pIccTransform, int blend_mode) -{ - FX_RECT dest_rect(left, top, left + dest_width, top + dest_height); - FX_RECT clip_box = m_ClipBox; - clip_box.Intersect(dest_rect); - if (clip_box.IsEmpty()) { - return TRUE; + if (!m_pDeviceDriver->GetDIBits(&background, dest_rect.left, + dest_rect.top)) { + return FALSE; + } + if (!background.CompositeBitmap(0, 0, bg_pixel_width, bg_pixel_height, + pBitmap, src_rect.left, src_rect.top, + blend_mode, NULL, FALSE, pIccTransform)) { + return FALSE; } - return m_pDeviceDriver->StretchDIBits(pBitmap, 0, left, top, dest_width, dest_height, &clip_box, flags, 0, pIccTransform, blend_mode); + FX_RECT src_rect(0, 0, bg_pixel_width, bg_pixel_height); + return m_pDeviceDriver->SetDIBits(&background, 0, &src_rect, dest_rect.left, + dest_rect.top, FXDIB_BLEND_NORMAL); + } + return m_pDeviceDriver->SetDIBits(pBitmap, 0, &src_rect, dest_rect.left, + dest_rect.top, blend_mode, 0, + pIccTransform); +} +FX_BOOL CFX_RenderDevice::StretchDIBits(const CFX_DIBSource* pBitmap, + int left, + int top, + int dest_width, + int dest_height, + FX_DWORD flags, + void* pIccTransform, + int blend_mode) { + FX_RECT dest_rect(left, top, left + dest_width, top + dest_height); + FX_RECT clip_box = m_ClipBox; + clip_box.Intersect(dest_rect); + if (clip_box.IsEmpty()) { + return TRUE; + } + return m_pDeviceDriver->StretchDIBits(pBitmap, 0, left, top, dest_width, + dest_height, &clip_box, flags, 0, + pIccTransform, blend_mode); } -FX_BOOL CFX_RenderDevice::SetBitMask(const CFX_DIBSource* pBitmap, int left, int top, FX_DWORD argb, - int alpha_flag, void* pIccTransform) -{ - FX_RECT src_rect(0, 0, pBitmap->GetWidth(), pBitmap->GetHeight()); - return m_pDeviceDriver->SetDIBits(pBitmap, argb, &src_rect, left, top, FXDIB_BLEND_NORMAL, alpha_flag, pIccTransform); +FX_BOOL CFX_RenderDevice::SetBitMask(const CFX_DIBSource* pBitmap, + int left, + int top, + FX_DWORD argb, + int alpha_flag, + void* pIccTransform) { + FX_RECT src_rect(0, 0, pBitmap->GetWidth(), pBitmap->GetHeight()); + return m_pDeviceDriver->SetDIBits(pBitmap, argb, &src_rect, left, top, + FXDIB_BLEND_NORMAL, alpha_flag, + pIccTransform); } -FX_BOOL CFX_RenderDevice::StretchBitMask(const CFX_DIBSource* pBitmap, int left, int top, - int dest_width, int dest_height, FX_DWORD argb, FX_DWORD flags, - int alpha_flag, void* pIccTransform) -{ - FX_RECT dest_rect(left, top, left + dest_width, top + dest_height); - FX_RECT clip_box = m_ClipBox; - clip_box.Intersect(dest_rect); - return m_pDeviceDriver->StretchDIBits(pBitmap, argb, left, top, dest_width, dest_height, &clip_box, flags, alpha_flag, pIccTransform); +FX_BOOL CFX_RenderDevice::StretchBitMask(const CFX_DIBSource* pBitmap, + int left, + int top, + int dest_width, + int dest_height, + FX_DWORD argb, + FX_DWORD flags, + int alpha_flag, + void* pIccTransform) { + FX_RECT dest_rect(left, top, left + dest_width, top + dest_height); + FX_RECT clip_box = m_ClipBox; + clip_box.Intersect(dest_rect); + return m_pDeviceDriver->StretchDIBits(pBitmap, argb, left, top, dest_width, + dest_height, &clip_box, flags, + alpha_flag, pIccTransform); } -FX_BOOL CFX_RenderDevice::StartDIBits(const CFX_DIBSource* pBitmap, int bitmap_alpha, FX_DWORD argb, - const CFX_AffineMatrix* pMatrix, FX_DWORD flags, void*& handle, - int alpha_flag, void* pIccTransform, int blend_mode) -{ - return m_pDeviceDriver->StartDIBits(pBitmap, bitmap_alpha, argb, pMatrix, flags, handle, alpha_flag, pIccTransform, blend_mode); +FX_BOOL CFX_RenderDevice::StartDIBits(const CFX_DIBSource* pBitmap, + int bitmap_alpha, + FX_DWORD argb, + const CFX_AffineMatrix* pMatrix, + FX_DWORD flags, + void*& handle, + int alpha_flag, + void* pIccTransform, + int blend_mode) { + return m_pDeviceDriver->StartDIBits(pBitmap, bitmap_alpha, argb, pMatrix, + flags, handle, alpha_flag, pIccTransform, + blend_mode); } -FX_BOOL CFX_RenderDevice::ContinueDIBits(void* handle, IFX_Pause* pPause) -{ - return m_pDeviceDriver->ContinueDIBits(handle, pPause); +FX_BOOL CFX_RenderDevice::ContinueDIBits(void* handle, IFX_Pause* pPause) { + return m_pDeviceDriver->ContinueDIBits(handle, pPause); } -void CFX_RenderDevice::CancelDIBits(void* handle) -{ - m_pDeviceDriver->CancelDIBits(handle); +void CFX_RenderDevice::CancelDIBits(void* handle) { + m_pDeviceDriver->CancelDIBits(handle); } diff --git a/core/src/fxge/ge/fx_ge_font.cpp b/core/src/fxge/ge/fx_ge_font.cpp index 6a950bf20b..e701ee9492 100644 --- a/core/src/fxge/ge/fx_ge_font.cpp +++ b/core/src/fxge/ge/fx_ge_font.cpp @@ -7,426 +7,426 @@ #include "../../../include/fxge/fx_ge.h" #include "../../../include/fxge/fx_freetype.h" #include "text_int.h" -#define EM_ADJUST(em, a) (em == 0?(a): (a)*1000/em) -extern void _FPDFAPI_GetInternalFontData(int id1, const uint8_t*& data, FX_DWORD& size); -CFX_Font::CFX_Font() -{ - m_pSubstFont = NULL; - m_Face = NULL; - m_bEmbedded = FALSE; - m_bVertical = FALSE; - m_pFontData = NULL; - m_pFontDataAllocation = NULL; - m_dwSize = 0; - m_pOwnedStream = NULL; - m_pGsubData = NULL; - m_pPlatformFont = NULL; - m_pPlatformFontCollection = NULL; - m_pDwFont = NULL; - m_hHandle = NULL; - m_bDwLoaded = FALSE; +#define EM_ADJUST(em, a) (em == 0 ? (a) : (a)*1000 / em) +extern void _FPDFAPI_GetInternalFontData(int id1, + const uint8_t*& data, + FX_DWORD& size); +CFX_Font::CFX_Font() { + m_pSubstFont = NULL; + m_Face = NULL; + m_bEmbedded = FALSE; + m_bVertical = FALSE; + m_pFontData = NULL; + m_pFontDataAllocation = NULL; + m_dwSize = 0; + m_pOwnedStream = NULL; + m_pGsubData = NULL; + m_pPlatformFont = NULL; + m_pPlatformFontCollection = NULL; + m_pDwFont = NULL; + m_hHandle = NULL; + m_bDwLoaded = FALSE; } -CFX_Font::~CFX_Font() -{ - delete m_pSubstFont; - m_pSubstFont = NULL; - if (m_pFontDataAllocation) { - FX_Free(m_pFontDataAllocation); - m_pFontDataAllocation = NULL; - } - if (m_Face) { - if (FXFT_Get_Face_External_Stream(m_Face)) { - FXFT_Clear_Face_External_Stream(m_Face); - } - if(m_bEmbedded) { - DeleteFace(); - } else { - CFX_GEModule::Get()->GetFontMgr()->ReleaseFace(m_Face); - } - } - if (m_pOwnedStream) { - FX_Free(m_pOwnedStream); - m_pOwnedStream = NULL; +CFX_Font::~CFX_Font() { + delete m_pSubstFont; + m_pSubstFont = NULL; + if (m_pFontDataAllocation) { + FX_Free(m_pFontDataAllocation); + m_pFontDataAllocation = NULL; + } + if (m_Face) { + if (FXFT_Get_Face_External_Stream(m_Face)) { + FXFT_Clear_Face_External_Stream(m_Face); } - if (m_pGsubData) { - FX_Free(m_pGsubData); - m_pGsubData = NULL; + if (m_bEmbedded) { + DeleteFace(); + } else { + CFX_GEModule::Get()->GetFontMgr()->ReleaseFace(m_Face); } -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ - ReleasePlatformResource(); + } + if (m_pOwnedStream) { + FX_Free(m_pOwnedStream); + m_pOwnedStream = NULL; + } + if (m_pGsubData) { + FX_Free(m_pGsubData); + m_pGsubData = NULL; + } +#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ + ReleasePlatformResource(); #endif } -void CFX_Font::DeleteFace() -{ - FXFT_Done_Face(m_Face); - m_Face = NULL; +void CFX_Font::DeleteFace() { + FXFT_Done_Face(m_Face); + m_Face = NULL; } -FX_BOOL CFX_Font::LoadSubst(const CFX_ByteString& face_name, FX_BOOL bTrueType, FX_DWORD flags, - int weight, int italic_angle, int CharsetCP, FX_BOOL bVertical) -{ - m_bEmbedded = FALSE; - m_bVertical = bVertical; - m_pSubstFont = new CFX_SubstFont; - m_Face = CFX_GEModule::Get()->GetFontMgr()->FindSubstFont(face_name, bTrueType, flags, weight, italic_angle, - CharsetCP, m_pSubstFont); -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ - if(m_pSubstFont->m_ExtHandle) { - m_pPlatformFont = m_pSubstFont->m_ExtHandle; - m_pSubstFont->m_ExtHandle = NULL; - } +FX_BOOL CFX_Font::LoadSubst(const CFX_ByteString& face_name, + FX_BOOL bTrueType, + FX_DWORD flags, + int weight, + int italic_angle, + int CharsetCP, + FX_BOOL bVertical) { + m_bEmbedded = FALSE; + m_bVertical = bVertical; + m_pSubstFont = new CFX_SubstFont; + m_Face = CFX_GEModule::Get()->GetFontMgr()->FindSubstFont( + face_name, bTrueType, flags, weight, italic_angle, CharsetCP, + m_pSubstFont); +#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ + if (m_pSubstFont->m_ExtHandle) { + m_pPlatformFont = m_pSubstFont->m_ExtHandle; + m_pSubstFont->m_ExtHandle = NULL; + } #endif - if (m_Face) { - m_pFontData = FXFT_Get_Face_Stream_Base(m_Face); - m_dwSize = FXFT_Get_Face_Stream_Size(m_Face); - } - return TRUE; + if (m_Face) { + m_pFontData = FXFT_Get_Face_Stream_Base(m_Face); + m_dwSize = FXFT_Get_Face_Stream_Size(m_Face); + } + return TRUE; } extern "C" { - unsigned long _FTStreamRead(FXFT_Stream stream, unsigned long offset, - unsigned char* buffer, unsigned long count) - { - if (count == 0) { - return 0; - } - IFX_FileRead* pFile = (IFX_FileRead*)stream->descriptor.pointer; - int res = pFile->ReadBlock(buffer, offset, count); - if (res) { - return count; - } - return 0; - } - void _FTStreamClose(FXFT_Stream stream) - { - } +unsigned long _FTStreamRead(FXFT_Stream stream, + unsigned long offset, + unsigned char* buffer, + unsigned long count) { + if (count == 0) { + return 0; + } + IFX_FileRead* pFile = (IFX_FileRead*)stream->descriptor.pointer; + int res = pFile->ReadBlock(buffer, offset, count); + if (res) { + return count; + } + return 0; +} +void _FTStreamClose(FXFT_Stream stream) {} }; -FX_BOOL _LoadFile(FXFT_Library library, FXFT_Face* Face, IFX_FileRead* pFile, FXFT_Stream* stream) -{ - FXFT_Stream stream1 = (FXFT_Stream)FX_Alloc(uint8_t, sizeof (FXFT_StreamRec)); - stream1->base = NULL; - stream1->size = (unsigned long)pFile->GetSize(); - stream1->pos = 0; - stream1->descriptor.pointer = pFile; - stream1->close = _FTStreamClose; - stream1->read = _FTStreamRead; - FXFT_Open_Args args; - args.flags = FT_OPEN_STREAM; - args.stream = stream1; - if (FXFT_Open_Face(library, &args, 0, Face)) { - FX_Free(stream1); - return FALSE; - } - if (stream) { - *stream = stream1; - } - return TRUE; +FX_BOOL _LoadFile(FXFT_Library library, + FXFT_Face* Face, + IFX_FileRead* pFile, + FXFT_Stream* stream) { + FXFT_Stream stream1 = (FXFT_Stream)FX_Alloc(uint8_t, sizeof(FXFT_StreamRec)); + stream1->base = NULL; + stream1->size = (unsigned long)pFile->GetSize(); + stream1->pos = 0; + stream1->descriptor.pointer = pFile; + stream1->close = _FTStreamClose; + stream1->read = _FTStreamRead; + FXFT_Open_Args args; + args.flags = FT_OPEN_STREAM; + args.stream = stream1; + if (FXFT_Open_Face(library, &args, 0, Face)) { + FX_Free(stream1); + return FALSE; + } + if (stream) { + *stream = stream1; + } + return TRUE; } -FX_BOOL CFX_Font::LoadFile(IFX_FileRead* pFile) -{ - m_bEmbedded = FALSE; - FXFT_Library library; - if (CFX_GEModule::Get()->GetFontMgr()->m_FTLibrary == NULL) { - FXFT_Init_FreeType(&CFX_GEModule::Get()->GetFontMgr()->m_FTLibrary); - } - library = CFX_GEModule::Get()->GetFontMgr()->m_FTLibrary; - FXFT_Stream stream = NULL; - if (!_LoadFile(library, &m_Face, pFile, &stream)) { - return FALSE; - } - m_pOwnedStream = stream; - FXFT_Set_Pixel_Sizes(m_Face, 0, 64); - return TRUE; +FX_BOOL CFX_Font::LoadFile(IFX_FileRead* pFile) { + m_bEmbedded = FALSE; + FXFT_Library library; + if (CFX_GEModule::Get()->GetFontMgr()->m_FTLibrary == NULL) { + FXFT_Init_FreeType(&CFX_GEModule::Get()->GetFontMgr()->m_FTLibrary); + } + library = CFX_GEModule::Get()->GetFontMgr()->m_FTLibrary; + FXFT_Stream stream = NULL; + if (!_LoadFile(library, &m_Face, pFile, &stream)) { + return FALSE; + } + m_pOwnedStream = stream; + FXFT_Set_Pixel_Sizes(m_Face, 0, 64); + return TRUE; } -int CFX_Font::GetGlyphWidth(FX_DWORD glyph_index) -{ - if (!m_Face) { - return 0; - } - if (m_pSubstFont && (m_pSubstFont->m_SubstFlags & FXFONT_SUBST_MM)) { - AdjustMMParams(glyph_index, 0, 0); - } - int err = FXFT_Load_Glyph(m_Face, glyph_index, FXFT_LOAD_NO_SCALE | FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH); - if (err) { - return 0; - } - int width = EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face), FXFT_Get_Glyph_HoriAdvance(m_Face)); - return width; +int CFX_Font::GetGlyphWidth(FX_DWORD glyph_index) { + if (!m_Face) { + return 0; + } + if (m_pSubstFont && (m_pSubstFont->m_SubstFlags & FXFONT_SUBST_MM)) { + AdjustMMParams(glyph_index, 0, 0); + } + int err = FXFT_Load_Glyph( + m_Face, glyph_index, + FXFT_LOAD_NO_SCALE | FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH); + if (err) { + return 0; + } + int width = EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face), + FXFT_Get_Glyph_HoriAdvance(m_Face)); + return width; } -static FXFT_Face FT_LoadFont(uint8_t* pData, int size) -{ - FXFT_Library library; - if (CFX_GEModule::Get()->GetFontMgr()->m_FTLibrary == NULL) { - FXFT_Init_FreeType(&CFX_GEModule::Get()->GetFontMgr()->m_FTLibrary); - } - library = CFX_GEModule::Get()->GetFontMgr()->m_FTLibrary; - FXFT_Face face = NULL; - int error = FXFT_New_Memory_Face(library, pData, size, 0, &face); - if (error) { - return NULL; - } - error = FXFT_Set_Pixel_Sizes(face, 64, 64); - if (error) { - return NULL; - } - return face; +static FXFT_Face FT_LoadFont(uint8_t* pData, int size) { + FXFT_Library library; + if (CFX_GEModule::Get()->GetFontMgr()->m_FTLibrary == NULL) { + FXFT_Init_FreeType(&CFX_GEModule::Get()->GetFontMgr()->m_FTLibrary); + } + library = CFX_GEModule::Get()->GetFontMgr()->m_FTLibrary; + FXFT_Face face = NULL; + int error = FXFT_New_Memory_Face(library, pData, size, 0, &face); + if (error) { + return NULL; + } + error = FXFT_Set_Pixel_Sizes(face, 64, 64); + if (error) { + return NULL; + } + return face; } -FX_BOOL CFX_Font::LoadEmbedded(const uint8_t* data, FX_DWORD size) -{ - m_pFontDataAllocation = FX_Alloc(uint8_t, size); - FXSYS_memcpy(m_pFontDataAllocation, data, size); - m_Face = FT_LoadFont((uint8_t*)m_pFontDataAllocation, size); - m_pFontData = (uint8_t*)m_pFontDataAllocation; - m_bEmbedded = TRUE; - m_dwSize = size; - return m_Face != NULL; +FX_BOOL CFX_Font::LoadEmbedded(const uint8_t* data, FX_DWORD size) { + m_pFontDataAllocation = FX_Alloc(uint8_t, size); + FXSYS_memcpy(m_pFontDataAllocation, data, size); + m_Face = FT_LoadFont((uint8_t*)m_pFontDataAllocation, size); + m_pFontData = (uint8_t*)m_pFontDataAllocation; + m_bEmbedded = TRUE; + m_dwSize = size; + return m_Face != NULL; } -FX_BOOL CFX_Font::IsTTFont() -{ - if (m_Face == NULL) { - return FALSE; - } - return FXFT_Is_Face_TT_OT(m_Face) == FXFT_FACE_FLAG_SFNT; +FX_BOOL CFX_Font::IsTTFont() { + if (m_Face == NULL) { + return FALSE; + } + return FXFT_Is_Face_TT_OT(m_Face) == FXFT_FACE_FLAG_SFNT; } -int CFX_Font::GetAscent() const -{ - if (m_Face == NULL) { - return 0; - } - int ascent = EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face), FXFT_Get_Face_Ascender(m_Face)); - return ascent; +int CFX_Font::GetAscent() const { + if (m_Face == NULL) { + return 0; + } + int ascent = EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face), + FXFT_Get_Face_Ascender(m_Face)); + return ascent; } -int CFX_Font::GetDescent() const -{ - if (m_Face == NULL) { - return 0; - } - int descent = EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face), FXFT_Get_Face_Descender(m_Face)); - return descent; +int CFX_Font::GetDescent() const { + if (m_Face == NULL) { + return 0; + } + int descent = EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face), + FXFT_Get_Face_Descender(m_Face)); + return descent; } -FX_BOOL CFX_Font::GetGlyphBBox(FX_DWORD glyph_index, FX_RECT &bbox) -{ - if (m_Face == NULL) { - return FALSE; - } - if (FXFT_Is_Face_Tricky(m_Face)) { - int error = FXFT_Set_Char_Size(m_Face, 0, 1000 * 64, 72, 72); - if (error) { - return FALSE; - } - error = FXFT_Load_Glyph(m_Face, glyph_index, FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH); - if (error) { - return FALSE; - } - FXFT_BBox cbox; - FT_Glyph glyph; - error = FXFT_Get_Glyph(((FXFT_Face)m_Face)->glyph, &glyph); - if (error) { - return FALSE; - } - FXFT_Glyph_Get_CBox(glyph, FXFT_GLYPH_BBOX_PIXELS, &cbox); - int pixel_size_x = ((FXFT_Face)m_Face)->size->metrics.x_ppem, - pixel_size_y = ((FXFT_Face)m_Face)->size->metrics.y_ppem; - if (pixel_size_x == 0 || pixel_size_y == 0) { - bbox.left = cbox.xMin; - bbox.right = cbox.xMax; - bbox.top = cbox.yMax; - bbox.bottom = cbox.yMin; - } else { - bbox.left = cbox.xMin * 1000 / pixel_size_x; - bbox.right = cbox.xMax * 1000 / pixel_size_x; - bbox.top = cbox.yMax * 1000 / pixel_size_y; - bbox.bottom = cbox.yMin * 1000 / pixel_size_y; - } - if (bbox.top > FXFT_Get_Face_Ascender(m_Face)) { - bbox.top = FXFT_Get_Face_Ascender(m_Face); - } - if (bbox.bottom < FXFT_Get_Face_Descender(m_Face)) { - bbox.bottom = FXFT_Get_Face_Descender(m_Face); - } - FT_Done_Glyph(glyph); - return FXFT_Set_Pixel_Sizes(m_Face, 0, 64) == 0; +FX_BOOL CFX_Font::GetGlyphBBox(FX_DWORD glyph_index, FX_RECT& bbox) { + if (m_Face == NULL) { + return FALSE; + } + if (FXFT_Is_Face_Tricky(m_Face)) { + int error = FXFT_Set_Char_Size(m_Face, 0, 1000 * 64, 72, 72); + if (error) { + return FALSE; } - if (FXFT_Load_Glyph(m_Face, glyph_index, FXFT_LOAD_NO_SCALE | FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH)) { - return FALSE; + error = FXFT_Load_Glyph(m_Face, glyph_index, + FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH); + if (error) { + return FALSE; } - int em = FXFT_Get_Face_UnitsPerEM(m_Face); - if (em == 0) { - bbox.left = FXFT_Get_Glyph_HoriBearingX(m_Face); - bbox.bottom = FXFT_Get_Glyph_HoriBearingY(m_Face); - bbox.top = bbox.bottom - FXFT_Get_Glyph_Height(m_Face); - bbox.right = bbox.left + FXFT_Get_Glyph_Width(m_Face); + FXFT_BBox cbox; + FT_Glyph glyph; + error = FXFT_Get_Glyph(((FXFT_Face)m_Face)->glyph, &glyph); + if (error) { + return FALSE; + } + FXFT_Glyph_Get_CBox(glyph, FXFT_GLYPH_BBOX_PIXELS, &cbox); + int pixel_size_x = ((FXFT_Face)m_Face)->size->metrics.x_ppem, + pixel_size_y = ((FXFT_Face)m_Face)->size->metrics.y_ppem; + if (pixel_size_x == 0 || pixel_size_y == 0) { + bbox.left = cbox.xMin; + bbox.right = cbox.xMax; + bbox.top = cbox.yMax; + bbox.bottom = cbox.yMin; } else { - bbox.left = FXFT_Get_Glyph_HoriBearingX(m_Face) * 1000 / em; - bbox.top = (FXFT_Get_Glyph_HoriBearingY(m_Face) - FXFT_Get_Glyph_Height(m_Face)) * 1000 / em; - bbox.right = (FXFT_Get_Glyph_HoriBearingX(m_Face) + FXFT_Get_Glyph_Width(m_Face)) * 1000 / em; - bbox.bottom = (FXFT_Get_Glyph_HoriBearingY(m_Face)) * 1000 / em; - } - return TRUE; + bbox.left = cbox.xMin * 1000 / pixel_size_x; + bbox.right = cbox.xMax * 1000 / pixel_size_x; + bbox.top = cbox.yMax * 1000 / pixel_size_y; + bbox.bottom = cbox.yMin * 1000 / pixel_size_y; + } + if (bbox.top > FXFT_Get_Face_Ascender(m_Face)) { + bbox.top = FXFT_Get_Face_Ascender(m_Face); + } + if (bbox.bottom < FXFT_Get_Face_Descender(m_Face)) { + bbox.bottom = FXFT_Get_Face_Descender(m_Face); + } + FT_Done_Glyph(glyph); + return FXFT_Set_Pixel_Sizes(m_Face, 0, 64) == 0; + } + if (FXFT_Load_Glyph( + m_Face, glyph_index, + FXFT_LOAD_NO_SCALE | FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH)) { + return FALSE; + } + int em = FXFT_Get_Face_UnitsPerEM(m_Face); + if (em == 0) { + bbox.left = FXFT_Get_Glyph_HoriBearingX(m_Face); + bbox.bottom = FXFT_Get_Glyph_HoriBearingY(m_Face); + bbox.top = bbox.bottom - FXFT_Get_Glyph_Height(m_Face); + bbox.right = bbox.left + FXFT_Get_Glyph_Width(m_Face); + } else { + bbox.left = FXFT_Get_Glyph_HoriBearingX(m_Face) * 1000 / em; + bbox.top = + (FXFT_Get_Glyph_HoriBearingY(m_Face) - FXFT_Get_Glyph_Height(m_Face)) * + 1000 / em; + bbox.right = + (FXFT_Get_Glyph_HoriBearingX(m_Face) + FXFT_Get_Glyph_Width(m_Face)) * + 1000 / em; + bbox.bottom = (FXFT_Get_Glyph_HoriBearingY(m_Face)) * 1000 / em; + } + return TRUE; } -FX_BOOL CFX_Font::IsItalic() -{ - if (m_Face == NULL) { - return FALSE; - } - FX_BOOL ret = FXFT_Is_Face_Italic(m_Face) == FXFT_STYLE_FLAG_ITALIC; - if (!ret) { - CFX_ByteString str(FXFT_Get_Face_Style_Name(m_Face)); - str.MakeLower(); - if (str.Find("italic") != -1) { - ret = TRUE; - } - } - return ret; +FX_BOOL CFX_Font::IsItalic() { + if (m_Face == NULL) { + return FALSE; + } + FX_BOOL ret = FXFT_Is_Face_Italic(m_Face) == FXFT_STYLE_FLAG_ITALIC; + if (!ret) { + CFX_ByteString str(FXFT_Get_Face_Style_Name(m_Face)); + str.MakeLower(); + if (str.Find("italic") != -1) { + ret = TRUE; + } + } + return ret; } -FX_BOOL CFX_Font::IsBold() -{ - if (m_Face == NULL) { - return FALSE; - } - return FXFT_Is_Face_Bold(m_Face) == FXFT_STYLE_FLAG_BOLD; +FX_BOOL CFX_Font::IsBold() { + if (m_Face == NULL) { + return FALSE; + } + return FXFT_Is_Face_Bold(m_Face) == FXFT_STYLE_FLAG_BOLD; } -FX_BOOL CFX_Font::IsFixedWidth() -{ - if (m_Face == NULL) { - return FALSE; - } - return FXFT_Is_Face_fixedwidth(m_Face); +FX_BOOL CFX_Font::IsFixedWidth() { + if (m_Face == NULL) { + return FALSE; + } + return FXFT_Is_Face_fixedwidth(m_Face); } -CFX_WideString CFX_Font::GetPsName() const -{ - if (m_Face == NULL) { - return CFX_WideString(); - } - CFX_WideString psName = CFX_WideString::FromLocal(FXFT_Get_Postscript_Name(m_Face)); - if (psName.IsEmpty()) { - psName = CFX_WideString::FromLocal("Untitled"); - } - return psName; +CFX_WideString CFX_Font::GetPsName() const { + if (m_Face == NULL) { + return CFX_WideString(); + } + CFX_WideString psName = + CFX_WideString::FromLocal(FXFT_Get_Postscript_Name(m_Face)); + if (psName.IsEmpty()) { + psName = CFX_WideString::FromLocal("Untitled"); + } + return psName; } -CFX_ByteString CFX_Font::GetFamilyName() const -{ - if (m_Face == NULL && m_pSubstFont == NULL) { - return CFX_ByteString(); - } - if (m_Face) { - return CFX_ByteString(FXFT_Get_Face_Family_Name(m_Face)); - } - return m_pSubstFont->m_Family; +CFX_ByteString CFX_Font::GetFamilyName() const { + if (m_Face == NULL && m_pSubstFont == NULL) { + return CFX_ByteString(); + } + if (m_Face) { + return CFX_ByteString(FXFT_Get_Face_Family_Name(m_Face)); + } + return m_pSubstFont->m_Family; } -CFX_ByteString CFX_Font::GetFaceName() const -{ - if (m_Face == NULL && m_pSubstFont == NULL) { - return CFX_ByteString(); - } - if (m_Face) { - CFX_ByteString facename; - CFX_ByteString style = CFX_ByteString(FXFT_Get_Face_Style_Name(m_Face)); - facename = GetFamilyName(); - if (facename.IsEmpty()) { - facename = "Untitled"; - } - if (!style.IsEmpty() && style != "Regular") { - facename += " " + style; - } - return facename; - } - return m_pSubstFont->m_Family; +CFX_ByteString CFX_Font::GetFaceName() const { + if (m_Face == NULL && m_pSubstFont == NULL) { + return CFX_ByteString(); + } + if (m_Face) { + CFX_ByteString facename; + CFX_ByteString style = CFX_ByteString(FXFT_Get_Face_Style_Name(m_Face)); + facename = GetFamilyName(); + if (facename.IsEmpty()) { + facename = "Untitled"; + } + if (!style.IsEmpty() && style != "Regular") { + facename += " " + style; + } + return facename; + } + return m_pSubstFont->m_Family; } -FX_BOOL CFX_Font::GetBBox(FX_RECT &bbox) -{ - if (m_Face == NULL) { - return FALSE; - } - int em = FXFT_Get_Face_UnitsPerEM(m_Face); - if (em == 0) { - bbox.left = FXFT_Get_Face_xMin(m_Face); - bbox.bottom = FXFT_Get_Face_yMax(m_Face); - bbox.top = FXFT_Get_Face_yMin(m_Face); - bbox.right = FXFT_Get_Face_xMax(m_Face); - } else { - bbox.left = FXFT_Get_Face_xMin(m_Face) * 1000 / em; - bbox.top = FXFT_Get_Face_yMin(m_Face) * 1000 / em; - bbox.right = FXFT_Get_Face_xMax(m_Face) * 1000 / em; - bbox.bottom = FXFT_Get_Face_yMax(m_Face) * 1000 / em; - } - return TRUE; +FX_BOOL CFX_Font::GetBBox(FX_RECT& bbox) { + if (m_Face == NULL) { + return FALSE; + } + int em = FXFT_Get_Face_UnitsPerEM(m_Face); + if (em == 0) { + bbox.left = FXFT_Get_Face_xMin(m_Face); + bbox.bottom = FXFT_Get_Face_yMax(m_Face); + bbox.top = FXFT_Get_Face_yMin(m_Face); + bbox.right = FXFT_Get_Face_xMax(m_Face); + } else { + bbox.left = FXFT_Get_Face_xMin(m_Face) * 1000 / em; + bbox.top = FXFT_Get_Face_yMin(m_Face) * 1000 / em; + bbox.right = FXFT_Get_Face_xMax(m_Face) * 1000 / em; + bbox.bottom = FXFT_Get_Face_yMax(m_Face) * 1000 / em; + } + return TRUE; } -int CFX_Font::GetHeight() -{ - if (m_Face == NULL) { - return 0; - } - int height = EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face), FXFT_Get_Face_Height(m_Face)); - return height; +int CFX_Font::GetHeight() { + if (m_Face == NULL) { + return 0; + } + int height = + EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face), FXFT_Get_Face_Height(m_Face)); + return height; } -int CFX_Font::GetMaxAdvanceWidth() -{ - if (m_Face == NULL) { - return 0; - } - int width = EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face), FXFT_Get_Face_MaxAdvanceWidth(m_Face)); - return width; +int CFX_Font::GetMaxAdvanceWidth() { + if (m_Face == NULL) { + return 0; + } + int width = EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face), + FXFT_Get_Face_MaxAdvanceWidth(m_Face)); + return width; } -int CFX_Font::GetULPos() -{ - if (m_Face == NULL) { - return 0; - } - int pos = EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face), FXFT_Get_Face_UnderLinePosition(m_Face)); - return pos; +int CFX_Font::GetULPos() { + if (m_Face == NULL) { + return 0; + } + int pos = EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face), + FXFT_Get_Face_UnderLinePosition(m_Face)); + return pos; } -int CFX_Font::GetULthickness() -{ - if (m_Face == NULL) { - return 0; - } - int thickness = EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face), FXFT_Get_Face_UnderLineThickness(m_Face)); - return thickness; +int CFX_Font::GetULthickness() { + if (m_Face == NULL) { + return 0; + } + int thickness = EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face), + FXFT_Get_Face_UnderLineThickness(m_Face)); + return thickness; } -CFX_UnicodeEncoding::CFX_UnicodeEncoding(CFX_Font* pFont) -{ - m_pFont = pFont; +CFX_UnicodeEncoding::CFX_UnicodeEncoding(CFX_Font* pFont) { + m_pFont = pFont; } -FX_DWORD CFX_UnicodeEncoding::GlyphFromCharCode(FX_DWORD charcode) -{ - FXFT_Face face = m_pFont->GetFace(); - if (!face) { - return charcode; - } - if (FXFT_Select_Charmap(face, FXFT_ENCODING_UNICODE) == 0) { - return FXFT_Get_Char_Index(face, charcode); - } - if (m_pFont->m_pSubstFont && m_pFont->m_pSubstFont->m_Charset == 2) { - FX_DWORD index = 0; - if (FXFT_Select_Charmap(face, FXFT_ENCODING_MS_SYMBOL) == 0) { - index = FXFT_Get_Char_Index(face, charcode); - } - if (!index && !FXFT_Select_Charmap(face, FXFT_ENCODING_APPLE_ROMAN)) { - return FXFT_Get_Char_Index(face, charcode); - } - } +FX_DWORD CFX_UnicodeEncoding::GlyphFromCharCode(FX_DWORD charcode) { + FXFT_Face face = m_pFont->GetFace(); + if (!face) { return charcode; -} -FX_DWORD CFX_UnicodeEncoding::GlyphFromCharCodeEx(FX_DWORD charcode, int encoding) -{ - FXFT_Face face = m_pFont->GetFace(); - if (!face) { - return charcode; - } - if (encoding == ENCODING_UNICODE) { - return GlyphFromCharCode(charcode); + } + if (FXFT_Select_Charmap(face, FXFT_ENCODING_UNICODE) == 0) { + return FXFT_Get_Char_Index(face, charcode); + } + if (m_pFont->m_pSubstFont && m_pFont->m_pSubstFont->m_Charset == 2) { + FX_DWORD index = 0; + if (FXFT_Select_Charmap(face, FXFT_ENCODING_MS_SYMBOL) == 0) { + index = FXFT_Get_Char_Index(face, charcode); } - int nmaps = FXFT_Get_Face_CharmapCount(m_pFont->m_Face); - int i = 0; - while (i < nmaps) { - int encoding = FXFT_Get_Charmap_Encoding(FXFT_Get_Face_Charmaps(face)[i++]); - if (encoding != FXFT_ENCODING_UNICODE) { - FXFT_Select_Charmap(face, encoding); - break; - } + if (!index && !FXFT_Select_Charmap(face, FXFT_ENCODING_APPLE_ROMAN)) { + return FXFT_Get_Char_Index(face, charcode); } - return FXFT_Get_Char_Index(face, charcode); + } + return charcode; +} +FX_DWORD CFX_UnicodeEncoding::GlyphFromCharCodeEx(FX_DWORD charcode, + int encoding) { + FXFT_Face face = m_pFont->GetFace(); + if (!face) { + return charcode; + } + if (encoding == ENCODING_UNICODE) { + return GlyphFromCharCode(charcode); + } + int nmaps = FXFT_Get_Face_CharmapCount(m_pFont->m_Face); + int i = 0; + while (i < nmaps) { + int encoding = FXFT_Get_Charmap_Encoding(FXFT_Get_Face_Charmaps(face)[i++]); + if (encoding != FXFT_ENCODING_UNICODE) { + FXFT_Select_Charmap(face, encoding); + break; + } + } + return FXFT_Get_Char_Index(face, charcode); } -IFX_FontEncoding* FXGE_CreateUnicodeEncoding(CFX_Font* pFont) -{ - return new CFX_UnicodeEncoding(pFont); +IFX_FontEncoding* FXGE_CreateUnicodeEncoding(CFX_Font* pFont) { + return new CFX_UnicodeEncoding(pFont); } diff --git a/core/src/fxge/ge/fx_ge_fontmap.cpp b/core/src/fxge/ge/fx_ge_fontmap.cpp index 495d95c8d7..cd2195829f 100644 --- a/core/src/fxge/ge/fx_ge_fontmap.cpp +++ b/core/src/fxge/ge/fx_ge_fontmap.cpp @@ -9,147 +9,150 @@ #include "../../../include/fxge/fx_ge.h" #include "../../../include/fxge/fx_freetype.h" #include "text_int.h" -#define GET_TT_SHORT(w) (FX_WORD)(((w)[0] << 8) | (w)[1]) -#define GET_TT_LONG(w) (FX_DWORD)(((w)[0] << 24) | ((w)[1] << 16) | ((w)[2] << 8) | (w)[3]) -CFX_SubstFont::CFX_SubstFont() -{ - m_ExtHandle = NULL; - m_Charset = 0; - m_SubstFlags = 0; - m_Weight = 0; - m_ItalicAngle = 0; - m_bSubstOfCJK = FALSE; - m_WeightCJK = 0; - m_bItlicCJK = FALSE; +#define GET_TT_SHORT(w) (FX_WORD)(((w)[0] << 8) | (w)[1]) +#define GET_TT_LONG(w) \ + (FX_DWORD)(((w)[0] << 24) | ((w)[1] << 16) | ((w)[2] << 8) | (w)[3]) +CFX_SubstFont::CFX_SubstFont() { + m_ExtHandle = NULL; + m_Charset = 0; + m_SubstFlags = 0; + m_Weight = 0; + m_ItalicAngle = 0; + m_bSubstOfCJK = FALSE; + m_WeightCJK = 0; + m_bItlicCJK = FALSE; } -CTTFontDesc::~CTTFontDesc() -{ - if (m_Type == 1) { - if (m_SingleFace.m_pFace) { - FXFT_Done_Face(m_SingleFace.m_pFace); - } - } else if (m_Type == 2) { - for (int i = 0; i < 16; i ++) - if (m_TTCFace.m_pFaces[i]) { - FXFT_Done_Face(m_TTCFace.m_pFaces[i]); - } - } - if (m_pFontData) { - FX_Free(m_pFontData); - } +CTTFontDesc::~CTTFontDesc() { + if (m_Type == 1) { + if (m_SingleFace.m_pFace) { + FXFT_Done_Face(m_SingleFace.m_pFace); + } + } else if (m_Type == 2) { + for (int i = 0; i < 16; i++) + if (m_TTCFace.m_pFaces[i]) { + FXFT_Done_Face(m_TTCFace.m_pFaces[i]); + } + } + if (m_pFontData) { + FX_Free(m_pFontData); + } } -FX_BOOL CTTFontDesc::ReleaseFace(FXFT_Face face) -{ - if (m_Type == 1) { - if (m_SingleFace.m_pFace != face) { - return FALSE; - } - } else if (m_Type == 2) { - int i; - for (i = 0; i < 16; i ++) - if (m_TTCFace.m_pFaces[i] == face) { - break; - } - if (i == 16) { - return FALSE; - } +FX_BOOL CTTFontDesc::ReleaseFace(FXFT_Face face) { + if (m_Type == 1) { + if (m_SingleFace.m_pFace != face) { + return FALSE; } - m_RefCount --; - if (m_RefCount) { - return FALSE; - } - delete this; - return TRUE; + } else if (m_Type == 2) { + int i; + for (i = 0; i < 16; i++) + if (m_TTCFace.m_pFaces[i] == face) { + break; + } + if (i == 16) { + return FALSE; + } + } + m_RefCount--; + if (m_RefCount) { + return FALSE; + } + delete this; + return TRUE; } -CFX_FontMgr::CFX_FontMgr() : m_FTLibrary(nullptr) -{ - m_pBuiltinMapper = new CFX_FontMapper(this); - FXSYS_memset(m_ExternalFonts, 0, sizeof m_ExternalFonts); +CFX_FontMgr::CFX_FontMgr() : m_FTLibrary(nullptr) { + m_pBuiltinMapper = new CFX_FontMapper(this); + FXSYS_memset(m_ExternalFonts, 0, sizeof m_ExternalFonts); } -CFX_FontMgr::~CFX_FontMgr() -{ - delete m_pBuiltinMapper; - FreeCache(); - if (m_FTLibrary) { - FXFT_Done_FreeType(m_FTLibrary); - } +CFX_FontMgr::~CFX_FontMgr() { + delete m_pBuiltinMapper; + FreeCache(); + if (m_FTLibrary) { + FXFT_Done_FreeType(m_FTLibrary); + } } -void CFX_FontMgr::InitFTLibrary() -{ - if (m_FTLibrary == NULL) { - FXFT_Init_FreeType(&m_FTLibrary); - } +void CFX_FontMgr::InitFTLibrary() { + if (m_FTLibrary == NULL) { + FXFT_Init_FreeType(&m_FTLibrary); + } } -void CFX_FontMgr::FreeCache() -{ - FX_POSITION pos = m_FaceMap.GetStartPosition(); - while(pos) { - CFX_ByteString Key; - CTTFontDesc* face; - m_FaceMap.GetNextAssoc(pos, Key, (void*&)face); - delete face; - } - m_FaceMap.RemoveAll(); +void CFX_FontMgr::FreeCache() { + FX_POSITION pos = m_FaceMap.GetStartPosition(); + while (pos) { + CFX_ByteString Key; + CTTFontDesc* face; + m_FaceMap.GetNextAssoc(pos, Key, (void*&)face); + delete face; + } + m_FaceMap.RemoveAll(); } -void CFX_FontMgr::SetSystemFontInfo(IFX_SystemFontInfo* pFontInfo) -{ - m_pBuiltinMapper->SetSystemFontInfo(pFontInfo); +void CFX_FontMgr::SetSystemFontInfo(IFX_SystemFontInfo* pFontInfo) { + m_pBuiltinMapper->SetSystemFontInfo(pFontInfo); } -FXFT_Face CFX_FontMgr::FindSubstFont(const CFX_ByteString& face_name, FX_BOOL bTrueType, - FX_DWORD flags, int weight, int italic_angle, int CharsetCP, CFX_SubstFont* pSubstFont) -{ - if (!m_FTLibrary) { - FXFT_Init_FreeType(&m_FTLibrary); - } - return m_pBuiltinMapper->FindSubstFont(face_name, bTrueType, flags, weight, italic_angle, CharsetCP, pSubstFont); +FXFT_Face CFX_FontMgr::FindSubstFont(const CFX_ByteString& face_name, + FX_BOOL bTrueType, + FX_DWORD flags, + int weight, + int italic_angle, + int CharsetCP, + CFX_SubstFont* pSubstFont) { + if (!m_FTLibrary) { + FXFT_Init_FreeType(&m_FTLibrary); + } + return m_pBuiltinMapper->FindSubstFont(face_name, bTrueType, flags, weight, + italic_angle, CharsetCP, pSubstFont); } FXFT_Face CFX_FontMgr::GetCachedFace(const CFX_ByteString& face_name, - int weight, FX_BOOL bItalic, uint8_t*& pFontData) -{ - CFX_ByteString key(face_name); - key += ','; - key += CFX_ByteString::FormatInteger(weight); - key += bItalic ? 'I' : 'N'; - CTTFontDesc* pFontDesc = NULL; - m_FaceMap.Lookup(key, (void*&)pFontDesc); - if(pFontDesc) { - pFontData = pFontDesc->m_pFontData; - pFontDesc->m_RefCount ++; - return pFontDesc->m_SingleFace.m_pFace; - } - return NULL; + int weight, + FX_BOOL bItalic, + uint8_t*& pFontData) { + CFX_ByteString key(face_name); + key += ','; + key += CFX_ByteString::FormatInteger(weight); + key += bItalic ? 'I' : 'N'; + CTTFontDesc* pFontDesc = NULL; + m_FaceMap.Lookup(key, (void*&)pFontDesc); + if (pFontDesc) { + pFontData = pFontDesc->m_pFontData; + pFontDesc->m_RefCount++; + return pFontDesc->m_SingleFace.m_pFace; + } + return NULL; } FXFT_Face CFX_FontMgr::AddCachedFace(const CFX_ByteString& face_name, - int weight, FX_BOOL bItalic, uint8_t* pData, FX_DWORD size, int face_index) -{ - CTTFontDesc* pFontDesc = new CTTFontDesc; - pFontDesc->m_Type = 1; - pFontDesc->m_SingleFace.m_pFace = NULL; - pFontDesc->m_SingleFace.m_bBold = weight; - pFontDesc->m_SingleFace.m_bItalic = bItalic; - pFontDesc->m_pFontData = pData; - pFontDesc->m_RefCount = 1; - FXFT_Library library; - if (m_FTLibrary == NULL) { - FXFT_Init_FreeType(&m_FTLibrary); - } - library = m_FTLibrary; - int ret = FXFT_New_Memory_Face(library, pData, size, face_index, &pFontDesc->m_SingleFace.m_pFace); - if (ret) { - delete pFontDesc; - return NULL; - } - ret = FXFT_Set_Pixel_Sizes(pFontDesc->m_SingleFace.m_pFace, 64, 64); - if (ret) { - delete pFontDesc; - return NULL; - } - CFX_ByteString key(face_name); - key += ','; - key += CFX_ByteString::FormatInteger(weight); - key += bItalic ? 'I' : 'N'; - m_FaceMap.SetAt(key, pFontDesc); - return pFontDesc->m_SingleFace.m_pFace; + int weight, + FX_BOOL bItalic, + uint8_t* pData, + FX_DWORD size, + int face_index) { + CTTFontDesc* pFontDesc = new CTTFontDesc; + pFontDesc->m_Type = 1; + pFontDesc->m_SingleFace.m_pFace = NULL; + pFontDesc->m_SingleFace.m_bBold = weight; + pFontDesc->m_SingleFace.m_bItalic = bItalic; + pFontDesc->m_pFontData = pData; + pFontDesc->m_RefCount = 1; + FXFT_Library library; + if (m_FTLibrary == NULL) { + FXFT_Init_FreeType(&m_FTLibrary); + } + library = m_FTLibrary; + int ret = FXFT_New_Memory_Face(library, pData, size, face_index, + &pFontDesc->m_SingleFace.m_pFace); + if (ret) { + delete pFontDesc; + return NULL; + } + ret = FXFT_Set_Pixel_Sizes(pFontDesc->m_SingleFace.m_pFace, 64, 64); + if (ret) { + delete pFontDesc; + return NULL; + } + CFX_ByteString key(face_name); + key += ','; + key += CFX_ByteString::FormatInteger(weight); + key += bItalic ? 'I' : 'N'; + m_FaceMap.SetAt(key, pFontDesc); + return pFontDesc->m_SingleFace.m_pFace; } const FX_CHAR* const g_Base14FontNames[14] = { "Courier", @@ -168,10 +171,9 @@ const FX_CHAR* const g_Base14FontNames[14] = { "ZapfDingbats", }; const struct _AltFontName { - const FX_CHAR* m_pName; - int m_Index; -} -g_AltFontNames[] = { + const FX_CHAR* m_pName; + int m_Index; +} g_AltFontNames[] = { {"Arial", 4}, {"Arial,Bold", 5}, {"Arial,BoldItalic", 6}, @@ -263,144 +265,149 @@ g_AltFontNames[] = { {"ZapfDingbats", 13}, }; extern "C" { - static int compareString(const void* key, const void* element) - { - return FXSYS_stricmp((const FX_CHAR*)key, ((_AltFontName*)element)->m_pName); - } +static int compareString(const void* key, const void* element) { + return FXSYS_stricmp((const FX_CHAR*)key, ((_AltFontName*)element)->m_pName); } -int _PDF_GetStandardFontName(CFX_ByteString& name) -{ - _AltFontName* found = (_AltFontName*)FXSYS_bsearch(name.c_str(), g_AltFontNames, - sizeof g_AltFontNames / sizeof (_AltFontName), sizeof (_AltFontName), compareString); - if (found == NULL) { - return -1; - } - name = g_Base14FontNames[found->m_Index]; - return found->m_Index; } -int GetTTCIndex(const uint8_t* pFontData, FX_DWORD ttc_size, FX_DWORD font_offset) -{ - int face_index = 0; - const uint8_t* p = pFontData + 8; - FX_DWORD nfont = GET_TT_LONG(p); - FX_DWORD index; - for (index = 0; index < nfont; index ++) { - p = pFontData + 12 + index * 4; - if (GET_TT_LONG(p) == font_offset) { - break; - } - } - if(index >= nfont) { - face_index = 0; - } else { - face_index = index; - } - return face_index; +int _PDF_GetStandardFontName(CFX_ByteString& name) { + _AltFontName* found = + (_AltFontName*)FXSYS_bsearch(name.c_str(), g_AltFontNames, + sizeof g_AltFontNames / sizeof(_AltFontName), + sizeof(_AltFontName), compareString); + if (found == NULL) { + return -1; + } + name = g_Base14FontNames[found->m_Index]; + return found->m_Index; } -FXFT_Face CFX_FontMgr::GetCachedTTCFace(int ttc_size, FX_DWORD checksum, - int font_offset, uint8_t*& pFontData) -{ - CFX_ByteString key; - key.Format("%d:%d", ttc_size, checksum); - CTTFontDesc* pFontDesc = NULL; - m_FaceMap.Lookup(key, (void*&)pFontDesc); - if (pFontDesc == NULL) { - return NULL; - } - pFontData = pFontDesc->m_pFontData; - pFontDesc->m_RefCount ++; - int face_index = GetTTCIndex(pFontDesc->m_pFontData, ttc_size, font_offset); - if (pFontDesc->m_TTCFace.m_pFaces[face_index] == NULL) { - pFontDesc->m_TTCFace.m_pFaces[face_index] = GetFixedFace(pFontDesc->m_pFontData, ttc_size, face_index); - } - return pFontDesc->m_TTCFace.m_pFaces[face_index]; +int GetTTCIndex(const uint8_t* pFontData, + FX_DWORD ttc_size, + FX_DWORD font_offset) { + int face_index = 0; + const uint8_t* p = pFontData + 8; + FX_DWORD nfont = GET_TT_LONG(p); + FX_DWORD index; + for (index = 0; index < nfont; index++) { + p = pFontData + 12 + index * 4; + if (GET_TT_LONG(p) == font_offset) { + break; + } + } + if (index >= nfont) { + face_index = 0; + } else { + face_index = index; + } + return face_index; } -FXFT_Face CFX_FontMgr::AddCachedTTCFace(int ttc_size, FX_DWORD checksum, - uint8_t* pData, FX_DWORD size, int font_offset) -{ - CFX_ByteString key; - key.Format("%d:%d", ttc_size, checksum); - CTTFontDesc* pFontDesc = new CTTFontDesc; - pFontDesc->m_Type = 2; - pFontDesc->m_pFontData = pData; - for (int i = 0; i < 16; i ++) { - pFontDesc->m_TTCFace.m_pFaces[i] = NULL; - } - pFontDesc->m_RefCount ++; - key.Format("%d:%d", ttc_size, checksum); - m_FaceMap.SetAt(key, pFontDesc); - int face_index = GetTTCIndex(pFontDesc->m_pFontData, ttc_size, font_offset); - pFontDesc->m_TTCFace.m_pFaces[face_index] = GetFixedFace(pFontDesc->m_pFontData, ttc_size, face_index); - return pFontDesc->m_TTCFace.m_pFaces[face_index]; +FXFT_Face CFX_FontMgr::GetCachedTTCFace(int ttc_size, + FX_DWORD checksum, + int font_offset, + uint8_t*& pFontData) { + CFX_ByteString key; + key.Format("%d:%d", ttc_size, checksum); + CTTFontDesc* pFontDesc = NULL; + m_FaceMap.Lookup(key, (void*&)pFontDesc); + if (pFontDesc == NULL) { + return NULL; + } + pFontData = pFontDesc->m_pFontData; + pFontDesc->m_RefCount++; + int face_index = GetTTCIndex(pFontDesc->m_pFontData, ttc_size, font_offset); + if (pFontDesc->m_TTCFace.m_pFaces[face_index] == NULL) { + pFontDesc->m_TTCFace.m_pFaces[face_index] = + GetFixedFace(pFontDesc->m_pFontData, ttc_size, face_index); + } + return pFontDesc->m_TTCFace.m_pFaces[face_index]; } -FXFT_Face CFX_FontMgr::GetFixedFace(const uint8_t* pData, FX_DWORD size, int face_index) -{ - FXFT_Library library; - if (m_FTLibrary == NULL) { - FXFT_Init_FreeType(&m_FTLibrary); - } - library = m_FTLibrary; - FXFT_Face face = NULL; - int ret = FXFT_New_Memory_Face(library, pData, size, face_index, &face); - if (ret) { - return NULL; - } - ret = FXFT_Set_Pixel_Sizes(face, 64, 64); - if (ret) { - return NULL; - } - return face; +FXFT_Face CFX_FontMgr::AddCachedTTCFace(int ttc_size, + FX_DWORD checksum, + uint8_t* pData, + FX_DWORD size, + int font_offset) { + CFX_ByteString key; + key.Format("%d:%d", ttc_size, checksum); + CTTFontDesc* pFontDesc = new CTTFontDesc; + pFontDesc->m_Type = 2; + pFontDesc->m_pFontData = pData; + for (int i = 0; i < 16; i++) { + pFontDesc->m_TTCFace.m_pFaces[i] = NULL; + } + pFontDesc->m_RefCount++; + key.Format("%d:%d", ttc_size, checksum); + m_FaceMap.SetAt(key, pFontDesc); + int face_index = GetTTCIndex(pFontDesc->m_pFontData, ttc_size, font_offset); + pFontDesc->m_TTCFace.m_pFaces[face_index] = + GetFixedFace(pFontDesc->m_pFontData, ttc_size, face_index); + return pFontDesc->m_TTCFace.m_pFaces[face_index]; } -FXFT_Face CFX_FontMgr::GetFileFace(const FX_CHAR* filename, int face_index) -{ - FXFT_Library library; - if (m_FTLibrary == NULL) { - FXFT_Init_FreeType(&m_FTLibrary); - } - library = m_FTLibrary; - FXFT_Face face = NULL; - int ret = FXFT_New_Face(library, filename, face_index, &face); - if (ret) { - return NULL; - } - ret = FXFT_Set_Pixel_Sizes(face, 64, 64); - if (ret) { - return NULL; - } - return face; +FXFT_Face CFX_FontMgr::GetFixedFace(const uint8_t* pData, + FX_DWORD size, + int face_index) { + FXFT_Library library; + if (m_FTLibrary == NULL) { + FXFT_Init_FreeType(&m_FTLibrary); + } + library = m_FTLibrary; + FXFT_Face face = NULL; + int ret = FXFT_New_Memory_Face(library, pData, size, face_index, &face); + if (ret) { + return NULL; + } + ret = FXFT_Set_Pixel_Sizes(face, 64, 64); + if (ret) { + return NULL; + } + return face; } -void CFX_FontMgr::ReleaseFace(FXFT_Face face) -{ - if (face == NULL) { - return; - } - FX_POSITION pos = m_FaceMap.GetStartPosition(); - while(pos) { - CFX_ByteString Key; - CTTFontDesc* ttface; - m_FaceMap.GetNextAssoc(pos, Key, (void*&)ttface); - if (ttface->ReleaseFace(face)) { - m_FaceMap.RemoveKey(Key); - } - } +FXFT_Face CFX_FontMgr::GetFileFace(const FX_CHAR* filename, int face_index) { + FXFT_Library library; + if (m_FTLibrary == NULL) { + FXFT_Init_FreeType(&m_FTLibrary); + } + library = m_FTLibrary; + FXFT_Face face = NULL; + int ret = FXFT_New_Face(library, filename, face_index, &face); + if (ret) { + return NULL; + } + ret = FXFT_Set_Pixel_Sizes(face, 64, 64); + if (ret) { + return NULL; + } + return face; +} +void CFX_FontMgr::ReleaseFace(FXFT_Face face) { + if (face == NULL) { + return; + } + FX_POSITION pos = m_FaceMap.GetStartPosition(); + while (pos) { + CFX_ByteString Key; + CTTFontDesc* ttface; + m_FaceMap.GetNextAssoc(pos, Key, (void*&)ttface); + if (ttface->ReleaseFace(face)) { + m_FaceMap.RemoveKey(Key); + } + } } extern "C" { - extern const unsigned char g_FoxitFixedItalicFontData [18746]; - extern const unsigned char g_FoxitFixedFontData [17597]; - extern const unsigned char g_FoxitSansItalicFontData [16339]; - extern const unsigned char g_FoxitSansFontData [15025]; - extern const unsigned char g_FoxitSerifItalicFontData [21227]; - extern const unsigned char g_FoxitSerifFontData [19469]; - extern const unsigned char g_FoxitFixedBoldItalicFontData [19151]; - extern const unsigned char g_FoxitFixedBoldFontData [18055]; - extern const unsigned char g_FoxitSansBoldItalicFontData [16418]; - extern const unsigned char g_FoxitSansBoldFontData [16344]; - extern const unsigned char g_FoxitSerifBoldItalicFontData [20733]; - extern const unsigned char g_FoxitSerifBoldFontData [19395]; - extern const unsigned char g_FoxitSymbolFontData[16729]; - extern const unsigned char g_FoxitDingbatsFontData[29513]; - extern const unsigned char g_FoxitSerifMMFontData[113417]; - extern const unsigned char g_FoxitSansMMFontData[66919]; +extern const unsigned char g_FoxitFixedItalicFontData[18746]; +extern const unsigned char g_FoxitFixedFontData[17597]; +extern const unsigned char g_FoxitSansItalicFontData[16339]; +extern const unsigned char g_FoxitSansFontData[15025]; +extern const unsigned char g_FoxitSerifItalicFontData[21227]; +extern const unsigned char g_FoxitSerifFontData[19469]; +extern const unsigned char g_FoxitFixedBoldItalicFontData[19151]; +extern const unsigned char g_FoxitFixedBoldFontData[18055]; +extern const unsigned char g_FoxitSansBoldItalicFontData[16418]; +extern const unsigned char g_FoxitSansBoldFontData[16344]; +extern const unsigned char g_FoxitSerifBoldItalicFontData[20733]; +extern const unsigned char g_FoxitSerifBoldFontData[19395]; +extern const unsigned char g_FoxitSymbolFontData[16729]; +extern const unsigned char g_FoxitDingbatsFontData[29513]; +extern const unsigned char g_FoxitSerifMMFontData[113417]; +extern const unsigned char g_FoxitSansMMFontData[66919]; }; const FoxitFonts g_FoxitFonts[14] = { {g_FoxitFixedFontData, 17597}, @@ -418,1094 +425,1089 @@ const FoxitFonts g_FoxitFonts[14] = { {g_FoxitSymbolFontData, 16729}, {g_FoxitDingbatsFontData, 29513}, }; -void _FPDFAPI_GetInternalFontData(int id, const uint8_t*& data, FX_DWORD& size) -{ - CFX_GEModule::Get()->GetFontMgr()->GetStandardFont(data, size, id); +void _FPDFAPI_GetInternalFontData(int id, + const uint8_t*& data, + FX_DWORD& size) { + CFX_GEModule::Get()->GetFontMgr()->GetStandardFont(data, size, id); } -FX_BOOL CFX_FontMgr::GetStandardFont(const uint8_t*& pFontData, FX_DWORD& size, int index) -{ - if (index > 15 || index < 0) { - return FALSE; - } - { - if (index >= 14) { - if (index == 14) { - pFontData = g_FoxitSerifMMFontData; - size = 113417; - } else { - pFontData = g_FoxitSansMMFontData; - size = 66919; - } - } else { - pFontData = g_FoxitFonts[index].m_pFontData; - size = g_FoxitFonts[index].m_dwSize; - } +FX_BOOL CFX_FontMgr::GetStandardFont(const uint8_t*& pFontData, + FX_DWORD& size, + int index) { + if (index > 15 || index < 0) { + return FALSE; + } + { + if (index >= 14) { + if (index == 14) { + pFontData = g_FoxitSerifMMFontData; + size = 113417; + } else { + pFontData = g_FoxitSansMMFontData; + size = 66919; + } + } else { + pFontData = g_FoxitFonts[index].m_pFontData; + size = g_FoxitFonts[index].m_dwSize; } - return TRUE; + } + return TRUE; } CFX_FontMapper::CFX_FontMapper(CFX_FontMgr* mgr) - : m_pFontInfo(nullptr), - m_bListLoaded(FALSE), - m_pFontEnumerator(nullptr), - m_pFontMgr(mgr) -{ - FXSYS_memset(m_FoxitFaces, 0, sizeof m_FoxitFaces); - m_MMFaces[0] = m_MMFaces[1] = NULL; + : m_pFontInfo(nullptr), + m_bListLoaded(FALSE), + m_pFontEnumerator(nullptr), + m_pFontMgr(mgr) { + FXSYS_memset(m_FoxitFaces, 0, sizeof m_FoxitFaces); + m_MMFaces[0] = m_MMFaces[1] = NULL; } -CFX_FontMapper::~CFX_FontMapper() -{ - for (int i = 0; i < 14; i ++) - if (m_FoxitFaces[i]) { - FXFT_Done_Face(m_FoxitFaces[i]); - } - if (m_MMFaces[0]) { - FXFT_Done_Face(m_MMFaces[0]); - } - if (m_MMFaces[1]) { - FXFT_Done_Face(m_MMFaces[1]); - } - if (m_pFontInfo) { - m_pFontInfo->Release(); - } +CFX_FontMapper::~CFX_FontMapper() { + for (int i = 0; i < 14; i++) + if (m_FoxitFaces[i]) { + FXFT_Done_Face(m_FoxitFaces[i]); + } + if (m_MMFaces[0]) { + FXFT_Done_Face(m_MMFaces[0]); + } + if (m_MMFaces[1]) { + FXFT_Done_Face(m_MMFaces[1]); + } + if (m_pFontInfo) { + m_pFontInfo->Release(); + } } -void CFX_FontMapper::SetSystemFontInfo(IFX_SystemFontInfo* pFontInfo) -{ - if (pFontInfo == NULL) { - return; - } - if (m_pFontInfo) { - m_pFontInfo->Release(); - } - m_pFontInfo = pFontInfo; +void CFX_FontMapper::SetSystemFontInfo(IFX_SystemFontInfo* pFontInfo) { + if (pFontInfo == NULL) { + return; + } + if (m_pFontInfo) { + m_pFontInfo->Release(); + } + m_pFontInfo = pFontInfo; } -static CFX_ByteString _TT_NormalizeName(const FX_CHAR* family) -{ - CFX_ByteString norm(family, -1); - norm.Remove(' '); - norm.Remove('-'); - norm.Remove(','); - int pos = norm.Find('+'); - if (pos > 0) { - norm = norm.Left(pos); - } - norm.MakeLower(); - return norm; +static CFX_ByteString _TT_NormalizeName(const FX_CHAR* family) { + CFX_ByteString norm(family, -1); + norm.Remove(' '); + norm.Remove('-'); + norm.Remove(','); + int pos = norm.Find('+'); + if (pos > 0) { + norm = norm.Left(pos); + } + norm.MakeLower(); + return norm; } -CFX_ByteString _FPDF_GetNameFromTT(const uint8_t* name_table, FX_DWORD name_id) -{ - const uint8_t* ptr = name_table + 2; - int name_count = GET_TT_SHORT(ptr); - int string_offset = GET_TT_SHORT(ptr + 2); - const uint8_t* string_ptr = name_table + string_offset; - ptr += 4; - for (int i = 0; i < name_count; i ++) { - if (GET_TT_SHORT(ptr + 6) == name_id && GET_TT_SHORT(ptr) == 1 && GET_TT_SHORT(ptr + 2) == 0) { - return CFX_ByteStringC(string_ptr + GET_TT_SHORT(ptr + 10), GET_TT_SHORT(ptr + 8)); - } - ptr += 12; - } - return CFX_ByteString(); +CFX_ByteString _FPDF_GetNameFromTT(const uint8_t* name_table, + FX_DWORD name_id) { + const uint8_t* ptr = name_table + 2; + int name_count = GET_TT_SHORT(ptr); + int string_offset = GET_TT_SHORT(ptr + 2); + const uint8_t* string_ptr = name_table + string_offset; + ptr += 4; + for (int i = 0; i < name_count; i++) { + if (GET_TT_SHORT(ptr + 6) == name_id && GET_TT_SHORT(ptr) == 1 && + GET_TT_SHORT(ptr + 2) == 0) { + return CFX_ByteStringC(string_ptr + GET_TT_SHORT(ptr + 10), + GET_TT_SHORT(ptr + 8)); + } + ptr += 12; + } + return CFX_ByteString(); } -static CFX_ByteString _FPDF_ReadStringFromFile(FXSYS_FILE* pFile, FX_DWORD size) -{ - CFX_ByteString buffer; - if (!FXSYS_fread(buffer.GetBuffer(size), size, 1, pFile)) { - return CFX_ByteString(); - } - buffer.ReleaseBuffer(size); - return buffer; -} -CFX_ByteString _FPDF_LoadTableFromTT(FXSYS_FILE* pFile, const uint8_t* pTables, FX_DWORD nTables, FX_DWORD tag) -{ - for (FX_DWORD i = 0; i < nTables; i ++) { - const uint8_t* p = pTables + i * 16; - if (GET_TT_LONG(p) == tag) { - FX_DWORD offset = GET_TT_LONG(p + 8); - FX_DWORD size = GET_TT_LONG(p + 12); - FXSYS_fseek(pFile, offset, FXSYS_SEEK_SET); - return _FPDF_ReadStringFromFile(pFile, size); - } - } +static CFX_ByteString _FPDF_ReadStringFromFile(FXSYS_FILE* pFile, + FX_DWORD size) { + CFX_ByteString buffer; + if (!FXSYS_fread(buffer.GetBuffer(size), size, 1, pFile)) { return CFX_ByteString(); + } + buffer.ReleaseBuffer(size); + return buffer; } -CFX_ByteString _FPDF_LoadTableFromTTStreamFile(IFX_FileStream* pFile, const uint8_t* pTables, FX_DWORD nTables, FX_DWORD tag) -{ - for (FX_DWORD i = 0; i < nTables; i ++) { - const uint8_t* p = pTables + i * 16; - if (GET_TT_LONG(p) == tag) { - FX_DWORD offset = GET_TT_LONG(p + 8); - FX_DWORD size = GET_TT_LONG(p + 12); - CFX_ByteString buffer; - if (!pFile->ReadBlock(buffer.GetBuffer(size), offset, size)) { - return CFX_ByteString(); - } - buffer.ReleaseBuffer(size); - return buffer; - } - } - return CFX_ByteString(); +CFX_ByteString _FPDF_LoadTableFromTT(FXSYS_FILE* pFile, + const uint8_t* pTables, + FX_DWORD nTables, + FX_DWORD tag) { + for (FX_DWORD i = 0; i < nTables; i++) { + const uint8_t* p = pTables + i * 16; + if (GET_TT_LONG(p) == tag) { + FX_DWORD offset = GET_TT_LONG(p + 8); + FX_DWORD size = GET_TT_LONG(p + 12); + FXSYS_fseek(pFile, offset, FXSYS_SEEK_SET); + return _FPDF_ReadStringFromFile(pFile, size); + } + } + return CFX_ByteString(); } -CFX_ByteString CFX_FontMapper::GetPSNameFromTT(void* hFont) -{ - if (m_pFontInfo == NULL) { - CFX_ByteString(); - } - CFX_ByteString result; - FX_DWORD size = m_pFontInfo->GetFontData(hFont, 0x6e616d65, NULL, 0); - if (size) { - uint8_t* buffer = FX_Alloc(uint8_t, size); - m_pFontInfo->GetFontData(hFont, 0x6e616d65, buffer, size); - result = _FPDF_GetNameFromTT(buffer, 6); - FX_Free(buffer); +CFX_ByteString _FPDF_LoadTableFromTTStreamFile(IFX_FileStream* pFile, + const uint8_t* pTables, + FX_DWORD nTables, + FX_DWORD tag) { + for (FX_DWORD i = 0; i < nTables; i++) { + const uint8_t* p = pTables + i * 16; + if (GET_TT_LONG(p) == tag) { + FX_DWORD offset = GET_TT_LONG(p + 8); + FX_DWORD size = GET_TT_LONG(p + 12); + CFX_ByteString buffer; + if (!pFile->ReadBlock(buffer.GetBuffer(size), offset, size)) { + return CFX_ByteString(); + } + buffer.ReleaseBuffer(size); + return buffer; } - return result; + } + return CFX_ByteString(); } -void CFX_FontMapper::AddInstalledFont(const CFX_ByteString& name, int charset) -{ - if (m_pFontInfo == NULL) { - return; - } - if (m_CharsetArray.Find((FX_DWORD)charset) == -1) { - m_CharsetArray.Add((FX_DWORD)charset); - m_FaceArray.Add(name); - } - if (name == m_LastFamily) { - return; - } - const uint8_t* ptr = name; - FX_BOOL bLocalized = FALSE; - for (int i = 0; i < name.GetLength(); i ++) - if (ptr[i] > 0x80) { - bLocalized = TRUE; - break; - } - if (bLocalized) { - void* hFont = m_pFontInfo->GetFont(name); - if (hFont == NULL) { - int iExact; - hFont = m_pFontInfo->MapFont(0, 0, FXFONT_DEFAULT_CHARSET, 0, name, iExact); - if (hFont == NULL) { - return; - } - } - CFX_ByteString new_name = GetPSNameFromTT(hFont); - if (!new_name.IsEmpty()) { - new_name.Insert(0, ' '); - m_InstalledTTFonts.Add(new_name); - } - m_pFontInfo->DeleteFont(hFont); - } - m_InstalledTTFonts.Add(name); - m_LastFamily = name; +CFX_ByteString CFX_FontMapper::GetPSNameFromTT(void* hFont) { + if (m_pFontInfo == NULL) { + CFX_ByteString(); + } + CFX_ByteString result; + FX_DWORD size = m_pFontInfo->GetFontData(hFont, 0x6e616d65, NULL, 0); + if (size) { + uint8_t* buffer = FX_Alloc(uint8_t, size); + m_pFontInfo->GetFontData(hFont, 0x6e616d65, buffer, size); + result = _FPDF_GetNameFromTT(buffer, 6); + FX_Free(buffer); + } + return result; } -void CFX_FontMapper::LoadInstalledFonts() -{ - if (m_pFontInfo == NULL) { - return; - } - if (m_bListLoaded) { +void CFX_FontMapper::AddInstalledFont(const CFX_ByteString& name, int charset) { + if (m_pFontInfo == NULL) { + return; + } + if (m_CharsetArray.Find((FX_DWORD)charset) == -1) { + m_CharsetArray.Add((FX_DWORD)charset); + m_FaceArray.Add(name); + } + if (name == m_LastFamily) { + return; + } + const uint8_t* ptr = name; + FX_BOOL bLocalized = FALSE; + for (int i = 0; i < name.GetLength(); i++) + if (ptr[i] > 0x80) { + bLocalized = TRUE; + break; + } + if (bLocalized) { + void* hFont = m_pFontInfo->GetFont(name); + if (hFont == NULL) { + int iExact; + hFont = + m_pFontInfo->MapFont(0, 0, FXFONT_DEFAULT_CHARSET, 0, name, iExact); + if (hFont == NULL) { return; + } } - if (m_bListLoaded) { - return; + CFX_ByteString new_name = GetPSNameFromTT(hFont); + if (!new_name.IsEmpty()) { + new_name.Insert(0, ' '); + m_InstalledTTFonts.Add(new_name); } - m_pFontInfo->EnumFontList(this); - m_bListLoaded = TRUE; + m_pFontInfo->DeleteFont(hFont); + } + m_InstalledTTFonts.Add(name); + m_LastFamily = name; } -CFX_ByteString CFX_FontMapper::MatchInstalledFonts(const CFX_ByteString& norm_name) -{ - LoadInstalledFonts(); - int i; - for (i = m_InstalledTTFonts.GetSize() - 1; i >= 0; i --) { - CFX_ByteString norm1 = _TT_NormalizeName(m_InstalledTTFonts[i]); - if (norm1 == norm_name) { - break; - } - } - if (i < 0) { - return CFX_ByteString(); - } - CFX_ByteString match = m_InstalledTTFonts[i]; - if (match[0] == ' ') { - match = m_InstalledTTFonts[i + 1]; - } - return match; +void CFX_FontMapper::LoadInstalledFonts() { + if (m_pFontInfo == NULL) { + return; + } + if (m_bListLoaded) { + return; + } + if (m_bListLoaded) { + return; + } + m_pFontInfo->EnumFontList(this); + m_bListLoaded = TRUE; +} +CFX_ByteString CFX_FontMapper::MatchInstalledFonts( + const CFX_ByteString& norm_name) { + LoadInstalledFonts(); + int i; + for (i = m_InstalledTTFonts.GetSize() - 1; i >= 0; i--) { + CFX_ByteString norm1 = _TT_NormalizeName(m_InstalledTTFonts[i]); + if (norm1 == norm_name) { + break; + } + } + if (i < 0) { + return CFX_ByteString(); + } + CFX_ByteString match = m_InstalledTTFonts[i]; + if (match[0] == ' ') { + match = m_InstalledTTFonts[i + 1]; + } + return match; } typedef struct _CHARSET_MAP_ { - uint8_t charset; - FX_WORD codepage; + uint8_t charset; + FX_WORD codepage; } CHARSET_MAP; static const CHARSET_MAP g_Codepage2CharsetTable[] = { - { 1 , 0 }, - { 2 , 42 }, - { 254, 437 }, - { 255, 850 }, - { 222, 874 }, - { 128, 932 }, - { 134, 936 }, - { 129, 949 }, - { 136, 950 }, - { 238, 1250 }, - { 204, 1251 }, - { 0, 1252 }, - { 161, 1253 }, - { 162, 1254 }, - { 177, 1255 }, - { 178, 1256 }, - { 186, 1257 }, - { 163, 1258 }, - { 130, 1361 }, - { 77, 10000 }, - { 78, 10001 }, - { 79, 10003 }, - { 80, 10008 }, - { 81, 10002 }, - { 83, 10005 }, - { 84, 10004 }, - { 85, 10006 }, - { 86, 10081 }, - { 87, 10021 }, - { 88, 10029 }, - { 89, 10007 }, + {1, 0}, {2, 42}, {254, 437}, {255, 850}, {222, 874}, + {128, 932}, {134, 936}, {129, 949}, {136, 950}, {238, 1250}, + {204, 1251}, {0, 1252}, {161, 1253}, {162, 1254}, {177, 1255}, + {178, 1256}, {186, 1257}, {163, 1258}, {130, 1361}, {77, 10000}, + {78, 10001}, {79, 10003}, {80, 10008}, {81, 10002}, {83, 10005}, + {84, 10004}, {85, 10006}, {86, 10081}, {87, 10021}, {88, 10029}, + {89, 10007}, }; -uint8_t _GetCharsetFromCodePage(FX_WORD codepage) -{ - int32_t iEnd = sizeof(g_Codepage2CharsetTable) / sizeof(CHARSET_MAP) - 1; - FXSYS_assert(iEnd >= 0); - int32_t iStart = 0, iMid; - do { - iMid = (iStart + iEnd) / 2; - const CHARSET_MAP & cp = g_Codepage2CharsetTable[iMid]; - if (codepage == cp.codepage) { - return cp.charset; - } - if (codepage < cp.codepage) { - iEnd = iMid - 1; - } else { - iStart = iMid + 1; - } - } while (iStart <= iEnd); - return 1; -} -FX_DWORD _GetCodePageRangeFromCharset(int charset) -{ - if (charset == FXFONT_EASTEUROPE_CHARSET) { - return 1 << 1; - } - if (charset == FXFONT_GREEK_CHARSET) { - return 1 << 3; - } - if (charset == FXFONT_TURKISH_CHARSET) { - return 1 << 4; - } - if (charset == FXFONT_HEBREW_CHARSET) { - return 1 << 5; - } - if (charset == FXFONT_ARABIC_CHARSET) { - return 1 << 6; - } - if (charset == FXFONT_BALTIC_CHARSET) { - return 1 << 7; - } - if (charset == FXFONT_THAI_CHARSET) { - return 1 << 16; - } - if (charset == FXFONT_SHIFTJIS_CHARSET) { - return 1 << 17; - } - if (charset == FXFONT_GB2312_CHARSET) { - return 1 << 18; - } - if (charset == FXFONT_CHINESEBIG5_CHARSET) { - return 1 << 20; - } - if (charset == FXFONT_HANGEUL_CHARSET) { - return 1 << 19; - } - if (charset == FXFONT_SYMBOL_CHARSET) { - return 1 << 31; +uint8_t _GetCharsetFromCodePage(FX_WORD codepage) { + int32_t iEnd = sizeof(g_Codepage2CharsetTable) / sizeof(CHARSET_MAP) - 1; + FXSYS_assert(iEnd >= 0); + int32_t iStart = 0, iMid; + do { + iMid = (iStart + iEnd) / 2; + const CHARSET_MAP& cp = g_Codepage2CharsetTable[iMid]; + if (codepage == cp.codepage) { + return cp.charset; + } + if (codepage < cp.codepage) { + iEnd = iMid - 1; + } else { + iStart = iMid + 1; } - return 1 << 21; + } while (iStart <= iEnd); + return 1; } -FXFT_Face CFX_FontMapper::UseInternalSubst(CFX_SubstFont* pSubstFont, int iBaseFont, int italic_angle, int weight, int picthfamily) -{ - if (iBaseFont < 12) { - if (m_FoxitFaces[iBaseFont]) { - return m_FoxitFaces[iBaseFont]; - } - const uint8_t* pFontData = NULL; - FX_DWORD size = 0; - if (m_pFontMgr->GetStandardFont(pFontData, size, iBaseFont)) { - m_FoxitFaces[iBaseFont] = m_pFontMgr->GetFixedFace(pFontData, size, 0); - return m_FoxitFaces[iBaseFont]; - } - } - pSubstFont->m_SubstFlags |= FXFONT_SUBST_MM; - pSubstFont->m_ItalicAngle = italic_angle; - if (weight) { - pSubstFont->m_Weight = weight; - } - if (picthfamily & FXFONT_FF_ROMAN) { - pSubstFont->m_Weight = pSubstFont->m_Weight * 4 / 5; - pSubstFont->m_Family = "Chrome Serif"; - if (m_MMFaces[1]) { - return m_MMFaces[1]; - } - const uint8_t* pFontData = NULL; - FX_DWORD size; - m_pFontMgr->GetStandardFont(pFontData, size, 14); - m_MMFaces[1] = m_pFontMgr->GetFixedFace(pFontData, size, 0); - return m_MMFaces[1]; - } - pSubstFont->m_Family = "Chrome Sans"; - if (m_MMFaces[0]) { - return m_MMFaces[0]; +FX_DWORD _GetCodePageRangeFromCharset(int charset) { + if (charset == FXFONT_EASTEUROPE_CHARSET) { + return 1 << 1; + } + if (charset == FXFONT_GREEK_CHARSET) { + return 1 << 3; + } + if (charset == FXFONT_TURKISH_CHARSET) { + return 1 << 4; + } + if (charset == FXFONT_HEBREW_CHARSET) { + return 1 << 5; + } + if (charset == FXFONT_ARABIC_CHARSET) { + return 1 << 6; + } + if (charset == FXFONT_BALTIC_CHARSET) { + return 1 << 7; + } + if (charset == FXFONT_THAI_CHARSET) { + return 1 << 16; + } + if (charset == FXFONT_SHIFTJIS_CHARSET) { + return 1 << 17; + } + if (charset == FXFONT_GB2312_CHARSET) { + return 1 << 18; + } + if (charset == FXFONT_CHINESEBIG5_CHARSET) { + return 1 << 20; + } + if (charset == FXFONT_HANGEUL_CHARSET) { + return 1 << 19; + } + if (charset == FXFONT_SYMBOL_CHARSET) { + return 1 << 31; + } + return 1 << 21; +} +FXFT_Face CFX_FontMapper::UseInternalSubst(CFX_SubstFont* pSubstFont, + int iBaseFont, + int italic_angle, + int weight, + int picthfamily) { + if (iBaseFont < 12) { + if (m_FoxitFaces[iBaseFont]) { + return m_FoxitFaces[iBaseFont]; } const uint8_t* pFontData = NULL; FX_DWORD size = 0; - m_pFontMgr->GetStandardFont(pFontData, size, 15); - m_MMFaces[0] = m_pFontMgr->GetFixedFace(pFontData, size, 0); + if (m_pFontMgr->GetStandardFont(pFontData, size, iBaseFont)) { + m_FoxitFaces[iBaseFont] = m_pFontMgr->GetFixedFace(pFontData, size, 0); + return m_FoxitFaces[iBaseFont]; + } + } + pSubstFont->m_SubstFlags |= FXFONT_SUBST_MM; + pSubstFont->m_ItalicAngle = italic_angle; + if (weight) { + pSubstFont->m_Weight = weight; + } + if (picthfamily & FXFONT_FF_ROMAN) { + pSubstFont->m_Weight = pSubstFont->m_Weight * 4 / 5; + pSubstFont->m_Family = "Chrome Serif"; + if (m_MMFaces[1]) { + return m_MMFaces[1]; + } + const uint8_t* pFontData = NULL; + FX_DWORD size; + m_pFontMgr->GetStandardFont(pFontData, size, 14); + m_MMFaces[1] = m_pFontMgr->GetFixedFace(pFontData, size, 0); + return m_MMFaces[1]; + } + pSubstFont->m_Family = "Chrome Sans"; + if (m_MMFaces[0]) { return m_MMFaces[0]; + } + const uint8_t* pFontData = NULL; + FX_DWORD size = 0; + m_pFontMgr->GetStandardFont(pFontData, size, 15); + m_MMFaces[0] = m_pFontMgr->GetFixedFace(pFontData, size, 0); + return m_MMFaces[0]; } const struct _AltFontFamily { - const FX_CHAR* m_pFontName; - const FX_CHAR* m_pFontFamily; -} -g_AltFontFamilies[] = { + const FX_CHAR* m_pFontName; + const FX_CHAR* m_pFontFamily; +} g_AltFontFamilies[] = { {"AGaramondPro", "Adobe Garamond Pro"}, {"BankGothicBT-Medium", "BankGothic Md BT"}, {"ForteMT", "Forte"}, }; extern "C" { - static int compareFontFamilyString(const void* key, const void* element) - { - CFX_ByteString str_key((const FX_CHAR*)key); - if (str_key.Find(((_AltFontFamily*)element)->m_pFontName) != -1) { - return 0; - } - return FXSYS_stricmp((const FX_CHAR*)key, ((_AltFontFamily*)element)->m_pFontName); - } +static int compareFontFamilyString(const void* key, const void* element) { + CFX_ByteString str_key((const FX_CHAR*)key); + if (str_key.Find(((_AltFontFamily*)element)->m_pFontName) != -1) { + return 0; + } + return FXSYS_stricmp((const FX_CHAR*)key, + ((_AltFontFamily*)element)->m_pFontName); } -#define FX_FONT_STYLE_None 0x00 -#define FX_FONT_STYLE_Bold 0x01 -#define FX_FONT_STYLE_Italic 0x02 -#define FX_FONT_STYLE_BoldBold 0x04 -static CFX_ByteString _GetFontFamily(CFX_ByteString fontName, int nStyle) -{ - if (fontName.Find("Script") >= 0) { - if ((nStyle & FX_FONT_STYLE_Bold) == FX_FONT_STYLE_Bold) { - fontName = "ScriptMTBold"; - } else if (fontName.Find("Palace") >= 0) { - fontName = "PalaceScriptMT"; - } else if (fontName.Find("French") >= 0) { - fontName = "FrenchScriptMT"; - } else if (fontName.Find("FreeStyle") >= 0) { - fontName = "FreeStyleScript"; - } - return fontName; - } - _AltFontFamily* found = (_AltFontFamily*)FXSYS_bsearch(fontName.c_str(), g_AltFontFamilies, - sizeof g_AltFontFamilies / sizeof (_AltFontFamily), sizeof (_AltFontFamily), compareFontFamilyString); - if (found == NULL) { - return fontName; - } - return found->m_pFontFamily; +} +#define FX_FONT_STYLE_None 0x00 +#define FX_FONT_STYLE_Bold 0x01 +#define FX_FONT_STYLE_Italic 0x02 +#define FX_FONT_STYLE_BoldBold 0x04 +static CFX_ByteString _GetFontFamily(CFX_ByteString fontName, int nStyle) { + if (fontName.Find("Script") >= 0) { + if ((nStyle & FX_FONT_STYLE_Bold) == FX_FONT_STYLE_Bold) { + fontName = "ScriptMTBold"; + } else if (fontName.Find("Palace") >= 0) { + fontName = "PalaceScriptMT"; + } else if (fontName.Find("French") >= 0) { + fontName = "FrenchScriptMT"; + } else if (fontName.Find("FreeStyle") >= 0) { + fontName = "FreeStyleScript"; + } + return fontName; + } + _AltFontFamily* found = (_AltFontFamily*)FXSYS_bsearch( + fontName.c_str(), g_AltFontFamilies, + sizeof g_AltFontFamilies / sizeof(_AltFontFamily), sizeof(_AltFontFamily), + compareFontFamilyString); + if (found == NULL) { + return fontName; + } + return found->m_pFontFamily; }; typedef struct _FX_FontStyle { - const FX_CHAR* style; - int32_t len; + const FX_CHAR* style; + int32_t len; } FX_FontStyle; const FX_FontStyle g_FontStyles[] = { - { "Bold", 4 }, - { "Italic", 6 }, - { "BoldItalic", 10 }, - { "Reg", 3 }, - { "Regular", 7 }, + {"Bold", 4}, {"Italic", 6}, {"BoldItalic", 10}, {"Reg", 3}, {"Regular", 7}, }; -CFX_ByteString ParseStyle(const FX_CHAR* pStyle, int iLen, int iIndex) -{ - CFX_ByteTextBuf buf; - if (!iLen || iLen <= iIndex) { - return buf.GetByteString(); - } - while (iIndex < iLen) { - if (pStyle[iIndex] == ',') { - break; - } - buf.AppendChar(pStyle[iIndex]); - ++iIndex; - } +CFX_ByteString ParseStyle(const FX_CHAR* pStyle, int iLen, int iIndex) { + CFX_ByteTextBuf buf; + if (!iLen || iLen <= iIndex) { return buf.GetByteString(); + } + while (iIndex < iLen) { + if (pStyle[iIndex] == ',') { + break; + } + buf.AppendChar(pStyle[iIndex]); + ++iIndex; + } + return buf.GetByteString(); } -int32_t GetStyleType(const CFX_ByteString &bsStyle, FX_BOOL bRevert) -{ - int32_t iLen = bsStyle.GetLength(); - if (!iLen) { - return -1; - } - int iSize = sizeof(g_FontStyles) / sizeof(FX_FontStyle); - const FX_FontStyle *pStyle = NULL; - for (int i = iSize - 1; i >= 0; --i) { - pStyle = g_FontStyles + i; - if (!pStyle || pStyle->len > iLen) { - continue; - } - if (!bRevert) { - if (bsStyle.Left(pStyle->len).Compare(pStyle->style) == 0) { - return i; - } - } else { - if (bsStyle.Right(pStyle->len).Compare(pStyle->style) == 0) { - return i; - } - } - } +int32_t GetStyleType(const CFX_ByteString& bsStyle, FX_BOOL bRevert) { + int32_t iLen = bsStyle.GetLength(); + if (!iLen) { return -1; -} -FX_BOOL CheckSupportThirdPartFont(CFX_ByteString name, int &PitchFamily) -{ - if (name == FX_BSTRC("MyriadPro")) { - PitchFamily &= ~FXFONT_FF_ROMAN; - return TRUE; + } + int iSize = sizeof(g_FontStyles) / sizeof(FX_FontStyle); + const FX_FontStyle* pStyle = NULL; + for (int i = iSize - 1; i >= 0; --i) { + pStyle = g_FontStyles + i; + if (!pStyle || pStyle->len > iLen) { + continue; + } + if (!bRevert) { + if (bsStyle.Left(pStyle->len).Compare(pStyle->style) == 0) { + return i; + } + } else { + if (bsStyle.Right(pStyle->len).Compare(pStyle->style) == 0) { + return i; + } } - return FALSE; + } + return -1; } -FXFT_Face CFX_FontMapper::FindSubstFont(const CFX_ByteString& name, FX_BOOL bTrueType, FX_DWORD flags, - int weight, int italic_angle, int WindowCP, CFX_SubstFont* pSubstFont) -{ - if (!(flags & FXFONT_USEEXTERNATTR)) { - weight = FXFONT_FW_NORMAL; - italic_angle = 0; - } - CFX_ByteString SubstName = name; - SubstName.Remove(0x20); - if (bTrueType) { - if (name[0] == '@') { - SubstName = name.Mid(1); - } - } - _PDF_GetStandardFontName(SubstName); - if (SubstName == FX_BSTRC("Symbol") && !bTrueType) { - pSubstFont->m_Family = "Chrome Symbol"; - pSubstFont->m_Charset = FXFONT_SYMBOL_CHARSET; - pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD; - if (m_FoxitFaces[12]) { - return m_FoxitFaces[12]; - } - const uint8_t* pFontData = NULL; - FX_DWORD size = 0; - m_pFontMgr->GetStandardFont(pFontData, size, 12); - m_FoxitFaces[12] = m_pFontMgr->GetFixedFace(pFontData, size, 0); - return m_FoxitFaces[12]; - } - if (SubstName == FX_BSTRC("ZapfDingbats")) { - pSubstFont->m_Family = "Chrome Dingbats"; - pSubstFont->m_Charset = FXFONT_SYMBOL_CHARSET; - pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD; - if (m_FoxitFaces[13]) { - return m_FoxitFaces[13]; - } - const uint8_t* pFontData = NULL; - FX_DWORD size = 0; - m_pFontMgr->GetStandardFont(pFontData, size, 13); - m_FoxitFaces[13] = m_pFontMgr->GetFixedFace(pFontData, size, 0); - return m_FoxitFaces[13]; +FX_BOOL CheckSupportThirdPartFont(CFX_ByteString name, int& PitchFamily) { + if (name == FX_BSTRC("MyriadPro")) { + PitchFamily &= ~FXFONT_FF_ROMAN; + return TRUE; + } + return FALSE; +} +FXFT_Face CFX_FontMapper::FindSubstFont(const CFX_ByteString& name, + FX_BOOL bTrueType, + FX_DWORD flags, + int weight, + int italic_angle, + int WindowCP, + CFX_SubstFont* pSubstFont) { + if (!(flags & FXFONT_USEEXTERNATTR)) { + weight = FXFONT_FW_NORMAL; + italic_angle = 0; + } + CFX_ByteString SubstName = name; + SubstName.Remove(0x20); + if (bTrueType) { + if (name[0] == '@') { + SubstName = name.Mid(1); + } + } + _PDF_GetStandardFontName(SubstName); + if (SubstName == FX_BSTRC("Symbol") && !bTrueType) { + pSubstFont->m_Family = "Chrome Symbol"; + pSubstFont->m_Charset = FXFONT_SYMBOL_CHARSET; + pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD; + if (m_FoxitFaces[12]) { + return m_FoxitFaces[12]; } - int iBaseFont = 0; - CFX_ByteString family, style; - FX_BOOL bHasComma = FALSE; - FX_BOOL bHasHypen = FALSE; - int find = SubstName.Find(FX_BSTRC(","), 0); - if (find >= 0) { - family = SubstName.Left(find); - _PDF_GetStandardFontName(family); - style = SubstName.Mid(find + 1); - bHasComma = TRUE; - } else { - family = SubstName; + const uint8_t* pFontData = NULL; + FX_DWORD size = 0; + m_pFontMgr->GetStandardFont(pFontData, size, 12); + m_FoxitFaces[12] = m_pFontMgr->GetFixedFace(pFontData, size, 0); + return m_FoxitFaces[12]; + } + if (SubstName == FX_BSTRC("ZapfDingbats")) { + pSubstFont->m_Family = "Chrome Dingbats"; + pSubstFont->m_Charset = FXFONT_SYMBOL_CHARSET; + pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD; + if (m_FoxitFaces[13]) { + return m_FoxitFaces[13]; } - for (; iBaseFont < 12; iBaseFont ++) - if (family == CFX_ByteStringC(g_Base14FontNames[iBaseFont])) { - break; - } - int PitchFamily = 0; - FX_BOOL bItalic = FALSE; - FX_DWORD nStyle = 0; - FX_BOOL bStyleAvail = FALSE; - if (iBaseFont < 12) { - family = g_Base14FontNames[iBaseFont]; - if ((iBaseFont % 4) == 1 || (iBaseFont % 4) == 2) { - nStyle |= FX_FONT_STYLE_Bold; - } - if ((iBaseFont % 4) / 2) { - nStyle |= FX_FONT_STYLE_Italic; - } - if (iBaseFont < 4) { - PitchFamily |= FXFONT_FF_FIXEDPITCH; - } - if (iBaseFont >= 8) { - PitchFamily |= FXFONT_FF_ROMAN; - } - } else { - if (!bHasComma) { - find = family.ReverseFind('-'); - if (find >= 0) { - style = family.Mid(find + 1); - family = family.Left(find); - bHasHypen = TRUE; - } + const uint8_t* pFontData = NULL; + FX_DWORD size = 0; + m_pFontMgr->GetStandardFont(pFontData, size, 13); + m_FoxitFaces[13] = m_pFontMgr->GetFixedFace(pFontData, size, 0); + return m_FoxitFaces[13]; + } + int iBaseFont = 0; + CFX_ByteString family, style; + FX_BOOL bHasComma = FALSE; + FX_BOOL bHasHypen = FALSE; + int find = SubstName.Find(FX_BSTRC(","), 0); + if (find >= 0) { + family = SubstName.Left(find); + _PDF_GetStandardFontName(family); + style = SubstName.Mid(find + 1); + bHasComma = TRUE; + } else { + family = SubstName; + } + for (; iBaseFont < 12; iBaseFont++) + if (family == CFX_ByteStringC(g_Base14FontNames[iBaseFont])) { + break; + } + int PitchFamily = 0; + FX_BOOL bItalic = FALSE; + FX_DWORD nStyle = 0; + FX_BOOL bStyleAvail = FALSE; + if (iBaseFont < 12) { + family = g_Base14FontNames[iBaseFont]; + if ((iBaseFont % 4) == 1 || (iBaseFont % 4) == 2) { + nStyle |= FX_FONT_STYLE_Bold; + } + if ((iBaseFont % 4) / 2) { + nStyle |= FX_FONT_STYLE_Italic; + } + if (iBaseFont < 4) { + PitchFamily |= FXFONT_FF_FIXEDPITCH; + } + if (iBaseFont >= 8) { + PitchFamily |= FXFONT_FF_ROMAN; + } + } else { + if (!bHasComma) { + find = family.ReverseFind('-'); + if (find >= 0) { + style = family.Mid(find + 1); + family = family.Left(find); + bHasHypen = TRUE; + } + } + if (!bHasHypen) { + int nLen = family.GetLength(); + int32_t nRet = GetStyleType(family, TRUE); + if (nRet > -1) { + family = family.Left(nLen - g_FontStyles[nRet].len); + if (nRet == 0) { + nStyle |= FX_FONT_STYLE_Bold; } - if (!bHasHypen) { - int nLen = family.GetLength(); - int32_t nRet = GetStyleType(family, TRUE); - if (nRet > -1) { - family = family.Left(nLen - g_FontStyles[nRet].len); - if (nRet == 0) { - nStyle |= FX_FONT_STYLE_Bold; - } - if (nRet == 1) { - nStyle |= FX_FONT_STYLE_Italic; - } - if (nRet == 2) { - nStyle |= (FX_FONT_STYLE_Bold | FX_FONT_STYLE_Italic); - } - } + if (nRet == 1) { + nStyle |= FX_FONT_STYLE_Italic; } - if (flags & FXFONT_SERIF) { - PitchFamily |= FXFONT_FF_ROMAN; + if (nRet == 2) { + nStyle |= (FX_FONT_STYLE_Bold | FX_FONT_STYLE_Italic); } - if (flags & FXFONT_SCRIPT) { - PitchFamily |= FXFONT_FF_SCRIPT; + } + } + if (flags & FXFONT_SERIF) { + PitchFamily |= FXFONT_FF_ROMAN; + } + if (flags & FXFONT_SCRIPT) { + PitchFamily |= FXFONT_FF_SCRIPT; + } + if (flags & FXFONT_FIXED_PITCH) { + PitchFamily |= FXFONT_FF_FIXEDPITCH; + } + } + if (!style.IsEmpty()) { + int nLen = style.GetLength(); + const FX_CHAR* pStyle = style; + int i = 0; + FX_BOOL bFirstItem = TRUE; + CFX_ByteString buf; + while (i < nLen) { + buf = ParseStyle(pStyle, nLen, i); + int32_t nRet = GetStyleType(buf, FALSE); + if ((i && !bStyleAvail) || (!i && nRet < 0)) { + family = SubstName; + iBaseFont = 12; + break; + } else if (nRet >= 0) { + bStyleAvail = TRUE; + } + if (nRet == 0) { + if (nStyle & FX_FONT_STYLE_Bold) { + nStyle |= FX_FONT_STYLE_BoldBold; + } else { + nStyle |= FX_FONT_STYLE_Bold; } - if (flags & FXFONT_FIXED_PITCH) { - PitchFamily |= FXFONT_FF_FIXEDPITCH; + bFirstItem = FALSE; + } + if (nRet == 1) { + if (bFirstItem) { + nStyle |= FX_FONT_STYLE_Italic; + } else { + family = SubstName; + iBaseFont = 12; } - } - if (!style.IsEmpty()) { - int nLen = style.GetLength(); - const FX_CHAR* pStyle = style; - int i = 0; - FX_BOOL bFirstItem = TRUE; - CFX_ByteString buf; - while (i < nLen) { - buf = ParseStyle(pStyle, nLen, i); - int32_t nRet = GetStyleType(buf, FALSE); - if ((i && !bStyleAvail) || (!i && nRet < 0)) { - family = SubstName; - iBaseFont = 12; - break; - } else if (nRet >= 0) { - bStyleAvail = TRUE; - } - if (nRet == 0) { - if (nStyle & FX_FONT_STYLE_Bold) { - nStyle |= FX_FONT_STYLE_BoldBold; - } else { - nStyle |= FX_FONT_STYLE_Bold; - } - bFirstItem = FALSE; - } - if (nRet == 1) { - if (bFirstItem) { - nStyle |= FX_FONT_STYLE_Italic; - } else { - family = SubstName; - iBaseFont = 12; - } - break; - } - if (nRet == 2) { - nStyle |= FX_FONT_STYLE_Italic; - if (nStyle & FX_FONT_STYLE_Bold) { - nStyle |= FX_FONT_STYLE_BoldBold; - } else { - nStyle |= FX_FONT_STYLE_Bold; - } - bFirstItem = FALSE; - } - i += buf.GetLength() + 1; + break; + } + if (nRet == 2) { + nStyle |= FX_FONT_STYLE_Italic; + if (nStyle & FX_FONT_STYLE_Bold) { + nStyle |= FX_FONT_STYLE_BoldBold; + } else { + nStyle |= FX_FONT_STYLE_Bold; } - } - weight = weight ? weight : FXFONT_FW_NORMAL; - int old_weight = weight; - if (nStyle) { - weight = nStyle & FX_FONT_STYLE_BoldBold ? 900 : (nStyle & FX_FONT_STYLE_Bold ? FXFONT_FW_BOLD : FXFONT_FW_NORMAL); - } - if (nStyle & FX_FONT_STYLE_Italic) { - bItalic = TRUE; - } - FX_BOOL bCJK = FALSE; - int iExact = 0; - int Charset = FXFONT_ANSI_CHARSET; - if (WindowCP) { - Charset = _GetCharsetFromCodePage(WindowCP); - } else if (iBaseFont == 12 && (flags & FXFONT_SYMBOLIC)) { - Charset = FXFONT_SYMBOL_CHARSET; - } - if (Charset == FXFONT_SHIFTJIS_CHARSET || Charset == FXFONT_GB2312_CHARSET || - Charset == FXFONT_HANGEUL_CHARSET || Charset == FXFONT_CHINESEBIG5_CHARSET) { - bCJK = TRUE; - } - if (m_pFontInfo == NULL) { - pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD; - return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight, PitchFamily); - } - family = _GetFontFamily(family, nStyle); - CFX_ByteString match = MatchInstalledFonts(_TT_NormalizeName(family)); - if (match.IsEmpty() && family != SubstName && (!bHasComma && (!bHasHypen || (bHasHypen && !bStyleAvail)))) { - match = MatchInstalledFonts(_TT_NormalizeName(SubstName)); - } - if (match.IsEmpty() && iBaseFont >= 12) { - if (!bCJK) { - if (!CheckSupportThirdPartFont(family, PitchFamily)) { - if (italic_angle != 0) { - bItalic = TRUE; - } else { - bItalic = FALSE; - } - weight = old_weight; - } + bFirstItem = FALSE; + } + i += buf.GetLength() + 1; + } + } + weight = weight ? weight : FXFONT_FW_NORMAL; + int old_weight = weight; + if (nStyle) { + weight = + nStyle & FX_FONT_STYLE_BoldBold + ? 900 + : (nStyle & FX_FONT_STYLE_Bold ? FXFONT_FW_BOLD : FXFONT_FW_NORMAL); + } + if (nStyle & FX_FONT_STYLE_Italic) { + bItalic = TRUE; + } + FX_BOOL bCJK = FALSE; + int iExact = 0; + int Charset = FXFONT_ANSI_CHARSET; + if (WindowCP) { + Charset = _GetCharsetFromCodePage(WindowCP); + } else if (iBaseFont == 12 && (flags & FXFONT_SYMBOLIC)) { + Charset = FXFONT_SYMBOL_CHARSET; + } + if (Charset == FXFONT_SHIFTJIS_CHARSET || Charset == FXFONT_GB2312_CHARSET || + Charset == FXFONT_HANGEUL_CHARSET || + Charset == FXFONT_CHINESEBIG5_CHARSET) { + bCJK = TRUE; + } + if (m_pFontInfo == NULL) { + pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD; + return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight, + PitchFamily); + } + family = _GetFontFamily(family, nStyle); + CFX_ByteString match = MatchInstalledFonts(_TT_NormalizeName(family)); + if (match.IsEmpty() && family != SubstName && + (!bHasComma && (!bHasHypen || (bHasHypen && !bStyleAvail)))) { + match = MatchInstalledFonts(_TT_NormalizeName(SubstName)); + } + if (match.IsEmpty() && iBaseFont >= 12) { + if (!bCJK) { + if (!CheckSupportThirdPartFont(family, PitchFamily)) { + if (italic_angle != 0) { + bItalic = TRUE; } else { - pSubstFont->m_bSubstOfCJK = TRUE; - if (nStyle) { - pSubstFont->m_WeightCJK = weight; - } else { - pSubstFont->m_WeightCJK = FXFONT_FW_NORMAL; - } - if (nStyle & FX_FONT_STYLE_Italic) { - pSubstFont->m_bItlicCJK = TRUE; - } + bItalic = FALSE; } + weight = old_weight; + } } else { - italic_angle = 0; - weight = nStyle & FX_FONT_STYLE_BoldBold ? 900 : (nStyle & FX_FONT_STYLE_Bold ? FXFONT_FW_BOLD : FXFONT_FW_NORMAL); + pSubstFont->m_bSubstOfCJK = TRUE; + if (nStyle) { + pSubstFont->m_WeightCJK = weight; + } else { + pSubstFont->m_WeightCJK = FXFONT_FW_NORMAL; + } + if (nStyle & FX_FONT_STYLE_Italic) { + pSubstFont->m_bItlicCJK = TRUE; + } + } + } else { + italic_angle = 0; + weight = + nStyle & FX_FONT_STYLE_BoldBold + ? 900 + : (nStyle & FX_FONT_STYLE_Bold ? FXFONT_FW_BOLD : FXFONT_FW_NORMAL); + } + if (!match.IsEmpty() || iBaseFont < 12) { + pSubstFont->m_SubstFlags |= FXFONT_SUBST_EXACT; + if (!match.IsEmpty()) { + family = match; } - if (!match.IsEmpty() || iBaseFont < 12) { - pSubstFont->m_SubstFlags |= FXFONT_SUBST_EXACT; - if (!match.IsEmpty()) { - family = match; - } - if (iBaseFont < 12) { - if (nStyle && !(iBaseFont % 4)) { - if ((nStyle & 0x3) == 1) { - iBaseFont += 1; - } - if ((nStyle & 0x3) == 2) { - iBaseFont += 3; - } - if ((nStyle & 0x3) == 3) { - iBaseFont += 2; - } - } - if (m_pFontMgr->m_ExternalFonts[iBaseFont].m_pFontData) { - if (m_FoxitFaces[iBaseFont]) { - return m_FoxitFaces[iBaseFont]; - } - m_FoxitFaces[iBaseFont] = m_pFontMgr->GetFixedFace(m_pFontMgr->m_ExternalFonts[iBaseFont].m_pFontData, - m_pFontMgr->m_ExternalFonts[iBaseFont].m_dwSize, 0); - if (m_FoxitFaces[iBaseFont]) { - return m_FoxitFaces[iBaseFont]; - } - } else { - family = g_Base14FontNames[iBaseFont]; - } - pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD; - } - } else { - if (flags & FXFONT_ITALIC) { - bItalic = TRUE; + if (iBaseFont < 12) { + if (nStyle && !(iBaseFont % 4)) { + if ((nStyle & 0x3) == 1) { + iBaseFont += 1; } - } - iExact = !match.IsEmpty(); - void* hFont = m_pFontInfo->MapFont(weight, bItalic, Charset, PitchFamily, family, iExact); - if (iExact) { - pSubstFont->m_SubstFlags |= FXFONT_SUBST_EXACT; - } - if (hFont == NULL) { - if (bCJK) { - if (italic_angle != 0) { - bItalic = TRUE; - } else { - bItalic = FALSE; - } - weight = old_weight; + if ((nStyle & 0x3) == 2) { + iBaseFont += 3; } - if (!match.IsEmpty()) { - hFont = m_pFontInfo->GetFont(match); - if (hFont == NULL) { - return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight, PitchFamily); - } - } else { - if (Charset == FXFONT_SYMBOL_CHARSET) { -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ || _FXM_PLATFORM_ == _FXM_PLATFORM_ANDROID_ - if (SubstName == FX_BSTRC("Symbol")) { - pSubstFont->m_Family = "Chrome Symbol"; - pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD; - pSubstFont->m_Charset = FXFONT_SYMBOL_CHARSET; - if (m_FoxitFaces[12]) { - return m_FoxitFaces[12]; - } - const uint8_t* pFontData = NULL; - FX_DWORD size = 0; - m_pFontMgr->GetStandardFont(pFontData, size, 12); - m_FoxitFaces[12] = m_pFontMgr->GetFixedFace(pFontData, size, 0); - return m_FoxitFaces[12]; - } -#endif - pSubstFont->m_SubstFlags |= FXFONT_SUBST_NONSYMBOL; - return FindSubstFont(family, bTrueType, flags & ~FXFONT_SYMBOLIC, weight, italic_angle, 0, pSubstFont); - } - if (Charset == FXFONT_ANSI_CHARSET) { - pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD; - return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight, PitchFamily); - } - int index = m_CharsetArray.Find(Charset); - if (index < 0) { - return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight, PitchFamily); - } - hFont = m_pFontInfo->GetFont(m_FaceArray[index]); + if ((nStyle & 0x3) == 3) { + iBaseFont += 2; } - } - pSubstFont->m_ExtHandle = m_pFontInfo->RetainFont(hFont); - if (hFont == NULL) { - return NULL; - } - m_pFontInfo->GetFaceName(hFont, SubstName); - if (Charset == FXFONT_DEFAULT_CHARSET) { - m_pFontInfo->GetFontCharset(hFont, Charset); - } - FX_DWORD ttc_size = m_pFontInfo->GetFontData(hFont, 0x74746366, NULL, 0); - FX_DWORD font_size = m_pFontInfo->GetFontData(hFont, 0, NULL, 0); - if(font_size == 0 && ttc_size == 0) { - m_pFontInfo->DeleteFont(hFont); - return NULL; - } - FXFT_Face face = NULL; - if (ttc_size) { - uint8_t temp[1024]; - m_pFontInfo->GetFontData(hFont, 0x74746366, temp, 1024); - FX_DWORD checksum = 0; - for (int i = 0; i < 256; i ++) { - checksum += ((FX_DWORD*)temp)[i]; + } + if (m_pFontMgr->m_ExternalFonts[iBaseFont].m_pFontData) { + if (m_FoxitFaces[iBaseFont]) { + return m_FoxitFaces[iBaseFont]; } - uint8_t* pFontData; - face = m_pFontMgr->GetCachedTTCFace(ttc_size, checksum, ttc_size - font_size, pFontData); - if (face == NULL) { - pFontData = FX_Alloc(uint8_t, ttc_size); - m_pFontInfo->GetFontData(hFont, 0x74746366, pFontData, ttc_size); - face = m_pFontMgr->AddCachedTTCFace(ttc_size, checksum, pFontData, ttc_size, - ttc_size - font_size); + m_FoxitFaces[iBaseFont] = m_pFontMgr->GetFixedFace( + m_pFontMgr->m_ExternalFonts[iBaseFont].m_pFontData, + m_pFontMgr->m_ExternalFonts[iBaseFont].m_dwSize, 0); + if (m_FoxitFaces[iBaseFont]) { + return m_FoxitFaces[iBaseFont]; } + } else { + family = g_Base14FontNames[iBaseFont]; + } + pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD; + } + } else { + if (flags & FXFONT_ITALIC) { + bItalic = TRUE; + } + } + iExact = !match.IsEmpty(); + void* hFont = m_pFontInfo->MapFont(weight, bItalic, Charset, PitchFamily, + family, iExact); + if (iExact) { + pSubstFont->m_SubstFlags |= FXFONT_SUBST_EXACT; + } + if (hFont == NULL) { + if (bCJK) { + if (italic_angle != 0) { + bItalic = TRUE; + } else { + bItalic = FALSE; + } + weight = old_weight; + } + if (!match.IsEmpty()) { + hFont = m_pFontInfo->GetFont(match); + if (hFont == NULL) { + return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight, + PitchFamily); + } } else { - uint8_t* pFontData; - face = m_pFontMgr->GetCachedFace(SubstName, weight, bItalic, pFontData); - if (face == NULL) { - pFontData = FX_Alloc(uint8_t, font_size); - m_pFontInfo->GetFontData(hFont, 0, pFontData, font_size); - face = m_pFontMgr->AddCachedFace(SubstName, weight, bItalic, pFontData, font_size, m_pFontInfo->GetFaceIndex(hFont)); + if (Charset == FXFONT_SYMBOL_CHARSET) { +#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ || \ + _FXM_PLATFORM_ == _FXM_PLATFORM_ANDROID_ + if (SubstName == FX_BSTRC("Symbol")) { + pSubstFont->m_Family = "Chrome Symbol"; + pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD; + pSubstFont->m_Charset = FXFONT_SYMBOL_CHARSET; + if (m_FoxitFaces[12]) { + return m_FoxitFaces[12]; + } + const uint8_t* pFontData = NULL; + FX_DWORD size = 0; + m_pFontMgr->GetStandardFont(pFontData, size, 12); + m_FoxitFaces[12] = m_pFontMgr->GetFixedFace(pFontData, size, 0); + return m_FoxitFaces[12]; } - } +#endif + pSubstFont->m_SubstFlags |= FXFONT_SUBST_NONSYMBOL; + return FindSubstFont(family, bTrueType, flags & ~FXFONT_SYMBOLIC, + weight, italic_angle, 0, pSubstFont); + } + if (Charset == FXFONT_ANSI_CHARSET) { + pSubstFont->m_SubstFlags |= FXFONT_SUBST_STANDARD; + return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight, + PitchFamily); + } + int index = m_CharsetArray.Find(Charset); + if (index < 0) { + return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight, + PitchFamily); + } + hFont = m_pFontInfo->GetFont(m_FaceArray[index]); + } + } + pSubstFont->m_ExtHandle = m_pFontInfo->RetainFont(hFont); + if (hFont == NULL) { + return NULL; + } + m_pFontInfo->GetFaceName(hFont, SubstName); + if (Charset == FXFONT_DEFAULT_CHARSET) { + m_pFontInfo->GetFontCharset(hFont, Charset); + } + FX_DWORD ttc_size = m_pFontInfo->GetFontData(hFont, 0x74746366, NULL, 0); + FX_DWORD font_size = m_pFontInfo->GetFontData(hFont, 0, NULL, 0); + if (font_size == 0 && ttc_size == 0) { + m_pFontInfo->DeleteFont(hFont); + return NULL; + } + FXFT_Face face = NULL; + if (ttc_size) { + uint8_t temp[1024]; + m_pFontInfo->GetFontData(hFont, 0x74746366, temp, 1024); + FX_DWORD checksum = 0; + for (int i = 0; i < 256; i++) { + checksum += ((FX_DWORD*)temp)[i]; + } + uint8_t* pFontData; + face = m_pFontMgr->GetCachedTTCFace(ttc_size, checksum, + ttc_size - font_size, pFontData); if (face == NULL) { - m_pFontInfo->DeleteFont(hFont); - return NULL; - } - pSubstFont->m_Family = SubstName; - pSubstFont->m_Charset = Charset; - FX_BOOL bNeedUpdateWeight = FALSE; - if (FXFT_Is_Face_Bold(face)) { - if (weight == FXFONT_FW_BOLD) { - bNeedUpdateWeight = FALSE; - } else { - bNeedUpdateWeight = TRUE; - } + pFontData = FX_Alloc(uint8_t, ttc_size); + m_pFontInfo->GetFontData(hFont, 0x74746366, pFontData, ttc_size); + face = m_pFontMgr->AddCachedTTCFace(ttc_size, checksum, pFontData, + ttc_size, ttc_size - font_size); + } + } else { + uint8_t* pFontData; + face = m_pFontMgr->GetCachedFace(SubstName, weight, bItalic, pFontData); + if (face == NULL) { + pFontData = FX_Alloc(uint8_t, font_size); + m_pFontInfo->GetFontData(hFont, 0, pFontData, font_size); + face = m_pFontMgr->AddCachedFace(SubstName, weight, bItalic, pFontData, + font_size, + m_pFontInfo->GetFaceIndex(hFont)); + } + } + if (face == NULL) { + m_pFontInfo->DeleteFont(hFont); + return NULL; + } + pSubstFont->m_Family = SubstName; + pSubstFont->m_Charset = Charset; + FX_BOOL bNeedUpdateWeight = FALSE; + if (FXFT_Is_Face_Bold(face)) { + if (weight == FXFONT_FW_BOLD) { + bNeedUpdateWeight = FALSE; } else { - if (weight == FXFONT_FW_NORMAL) { - bNeedUpdateWeight = FALSE; - } else { - bNeedUpdateWeight = TRUE; - } + bNeedUpdateWeight = TRUE; } - if (bNeedUpdateWeight) { - pSubstFont->m_Weight = weight; - } - if (bItalic && !FXFT_Is_Face_Italic(face)) { - if (italic_angle == 0) { - italic_angle = -12; - } else if (FXSYS_abs(italic_angle) < 5) { - italic_angle = 0; - } - pSubstFont->m_ItalicAngle = italic_angle; + } else { + if (weight == FXFONT_FW_NORMAL) { + bNeedUpdateWeight = FALSE; + } else { + bNeedUpdateWeight = TRUE; + } + } + if (bNeedUpdateWeight) { + pSubstFont->m_Weight = weight; + } + if (bItalic && !FXFT_Is_Face_Italic(face)) { + if (italic_angle == 0) { + italic_angle = -12; + } else if (FXSYS_abs(italic_angle) < 5) { + italic_angle = 0; } - m_pFontInfo->DeleteFont(hFont); - return face; + pSubstFont->m_ItalicAngle = italic_angle; + } + m_pFontInfo->DeleteFont(hFont); + return face; } extern "C" { - unsigned long _FTStreamRead(FXFT_Stream stream, unsigned long offset, - unsigned char* buffer, unsigned long count); - void _FTStreamClose(FXFT_Stream stream); +unsigned long _FTStreamRead(FXFT_Stream stream, + unsigned long offset, + unsigned char* buffer, + unsigned long count); +void _FTStreamClose(FXFT_Stream stream); }; -CFontFileFaceInfo::CFontFileFaceInfo() -{ - m_pFile = NULL; - m_Face = NULL; - m_Charsets = 0; - m_FileSize = 0; - m_FontOffset = 0; - m_Weight = 0; - m_bItalic = FALSE; - m_PitchFamily = 0; +CFontFileFaceInfo::CFontFileFaceInfo() { + m_pFile = NULL; + m_Face = NULL; + m_Charsets = 0; + m_FileSize = 0; + m_FontOffset = 0; + m_Weight = 0; + m_bItalic = FALSE; + m_PitchFamily = 0; } -CFontFileFaceInfo::~CFontFileFaceInfo() -{ - if (m_Face) { - FXFT_Done_Face(m_Face); - } - m_Face = NULL; +CFontFileFaceInfo::~CFontFileFaceInfo() { + if (m_Face) { + FXFT_Done_Face(m_Face); + } + m_Face = NULL; } -extern FX_BOOL _LoadFile(FXFT_Library library, FXFT_Face* Face, IFX_FileRead* pFile, FXFT_Stream* stream); +extern FX_BOOL _LoadFile(FXFT_Library library, + FXFT_Face* Face, + IFX_FileRead* pFile, + FXFT_Stream* stream); #if _FX_OS_ == _FX_ANDROID_ -IFX_SystemFontInfo* IFX_SystemFontInfo::CreateDefault() -{ - return NULL; +IFX_SystemFontInfo* IFX_SystemFontInfo::CreateDefault() { + return NULL; } #endif -CFX_FolderFontInfo::CFX_FolderFontInfo() -{ -} -CFX_FolderFontInfo::~CFX_FolderFontInfo() -{ - FX_POSITION pos = m_FontList.GetStartPosition(); - while (pos) { - CFX_ByteString key; - void* value; - m_FontList.GetNextAssoc(pos, key, value); - delete (CFontFaceInfo*)value; - } +CFX_FolderFontInfo::CFX_FolderFontInfo() {} +CFX_FolderFontInfo::~CFX_FolderFontInfo() { + FX_POSITION pos = m_FontList.GetStartPosition(); + while (pos) { + CFX_ByteString key; + void* value; + m_FontList.GetNextAssoc(pos, key, value); + delete (CFontFaceInfo*)value; + } } -void CFX_FolderFontInfo::AddPath(const CFX_ByteStringC& path) -{ - m_PathList.Add(path); +void CFX_FolderFontInfo::AddPath(const CFX_ByteStringC& path) { + m_PathList.Add(path); } -void CFX_FolderFontInfo::Release() -{ - delete this; +void CFX_FolderFontInfo::Release() { + delete this; } -FX_BOOL CFX_FolderFontInfo::EnumFontList(CFX_FontMapper* pMapper) -{ - m_pMapper = pMapper; - for (int i = 0; i < m_PathList.GetSize(); i ++) { - ScanPath(m_PathList[i]); - } - return TRUE; +FX_BOOL CFX_FolderFontInfo::EnumFontList(CFX_FontMapper* pMapper) { + m_pMapper = pMapper; + for (int i = 0; i < m_PathList.GetSize(); i++) { + ScanPath(m_PathList[i]); + } + return TRUE; } -void CFX_FolderFontInfo::ScanPath(CFX_ByteString& path) -{ - void* handle = FX_OpenFolder(path); - if (handle == NULL) { - return; - } - CFX_ByteString filename; - FX_BOOL bFolder; - while (FX_GetNextFile(handle, filename, bFolder)) { - if (bFolder) { - if (filename == "." || filename == "..") { - continue; - } - } else { - CFX_ByteString ext = filename.Right(4); - ext.MakeUpper(); - if (ext != ".TTF" && ext != ".OTF" && ext != ".TTC") { - continue; - } - } - CFX_ByteString fullpath = path; -#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ - fullpath += "\\"; +void CFX_FolderFontInfo::ScanPath(CFX_ByteString& path) { + void* handle = FX_OpenFolder(path); + if (handle == NULL) { + return; + } + CFX_ByteString filename; + FX_BOOL bFolder; + while (FX_GetNextFile(handle, filename, bFolder)) { + if (bFolder) { + if (filename == "." || filename == "..") { + continue; + } + } else { + CFX_ByteString ext = filename.Right(4); + ext.MakeUpper(); + if (ext != ".TTF" && ext != ".OTF" && ext != ".TTC") { + continue; + } + } + CFX_ByteString fullpath = path; +#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ + fullpath += "\\"; #else - fullpath += "/"; + fullpath += "/"; #endif - fullpath += filename; - if (bFolder) { - ScanPath(fullpath); - } else { - ScanFile(fullpath); - } - } - FX_CloseFolder(handle); -} -void CFX_FolderFontInfo::ScanFile(CFX_ByteString& path) -{ - FXSYS_FILE* pFile = FXSYS_fopen(path, "rb"); - if (pFile == NULL) { - return; - } - FXSYS_fseek(pFile, 0, FXSYS_SEEK_END); - FX_DWORD filesize = FXSYS_ftell(pFile); - uint8_t buffer[16]; - FXSYS_fseek(pFile, 0, FXSYS_SEEK_SET); - size_t readCnt = FXSYS_fread(buffer, 12, 1, pFile); - if (readCnt != 1) { - FXSYS_fclose(pFile); - return; - } - - if (GET_TT_LONG(buffer) == 0x74746366) { - FX_DWORD nFaces = GET_TT_LONG(buffer + 8); - if (nFaces > std::numeric_limits<FX_DWORD>::max() / 4) { - FXSYS_fclose(pFile); - return; - } - FX_DWORD face_bytes = nFaces * 4; - uint8_t* offsets = FX_Alloc(uint8_t, face_bytes); - readCnt = FXSYS_fread(offsets, 1, face_bytes, pFile); - if (readCnt != face_bytes) { - FX_Free(offsets); - FXSYS_fclose(pFile); - return; - } - for (FX_DWORD i = 0; i < nFaces; i ++) { - uint8_t* p = offsets + i * 4; - ReportFace(path, pFile, filesize, GET_TT_LONG(p)); - } - FX_Free(offsets); + fullpath += filename; + if (bFolder) { + ScanPath(fullpath); } else { - ReportFace(path, pFile, filesize, 0); + ScanFile(fullpath); } - FXSYS_fclose(pFile); + } + FX_CloseFolder(handle); } -void CFX_FolderFontInfo::ReportFace(CFX_ByteString& path, FXSYS_FILE* pFile, FX_DWORD filesize, FX_DWORD offset) -{ - FXSYS_fseek(pFile, offset, FXSYS_SEEK_SET); - char buffer[16]; - if (!FXSYS_fread(buffer, 12, 1, pFile)) { - return; - } - FX_DWORD nTables = GET_TT_SHORT(buffer + 4); - CFX_ByteString tables = _FPDF_ReadStringFromFile(pFile, nTables * 16); - if (tables.IsEmpty()) { - return; - } - CFX_ByteString names = _FPDF_LoadTableFromTT(pFile, tables, nTables, 0x6e616d65); - CFX_ByteString facename = _FPDF_GetNameFromTT(names, 1); - CFX_ByteString style = _FPDF_GetNameFromTT(names, 2); - if (style != "Regular") { - facename += " " + style; - } - void* p; - if (m_FontList.Lookup(facename, p)) { - return; - } - CFontFaceInfo* pInfo = new CFontFaceInfo; - pInfo->m_FilePath = path; - pInfo->m_FaceName = facename; - pInfo->m_FontTables = tables; - pInfo->m_FontOffset = offset; - pInfo->m_FileSize = filesize; - pInfo->m_Charsets = 0; - CFX_ByteString os2 = _FPDF_LoadTableFromTT(pFile, tables, nTables, 0x4f532f32); - if (os2.GetLength() >= 86) { - const uint8_t* p = (const uint8_t*)os2 + 78; - FX_DWORD codepages = GET_TT_LONG(p); - if (codepages & (1 << 17)) { - m_pMapper->AddInstalledFont(facename, FXFONT_SHIFTJIS_CHARSET); - pInfo->m_Charsets |= CHARSET_FLAG_SHIFTJIS; - } - if (codepages & (1 << 18)) { - m_pMapper->AddInstalledFont(facename, FXFONT_GB2312_CHARSET); - pInfo->m_Charsets |= CHARSET_FLAG_GB; - } - if (codepages & (1 << 20)) { - m_pMapper->AddInstalledFont(facename, FXFONT_CHINESEBIG5_CHARSET); - pInfo->m_Charsets |= CHARSET_FLAG_BIG5; - } - if ((codepages & (1 << 19)) || (codepages & (1 << 21))) { - m_pMapper->AddInstalledFont(facename, FXFONT_HANGEUL_CHARSET); - pInfo->m_Charsets |= CHARSET_FLAG_KOREAN; - } - if (codepages & (1 << 31)) { - m_pMapper->AddInstalledFont(facename, FXFONT_SYMBOL_CHARSET); - pInfo->m_Charsets |= CHARSET_FLAG_SYMBOL; - } - } - m_pMapper->AddInstalledFont(facename, FXFONT_ANSI_CHARSET); - pInfo->m_Charsets |= CHARSET_FLAG_ANSI; - pInfo->m_Styles = 0; - if (style.Find(FX_BSTRC("Bold")) > -1) { - pInfo->m_Styles |= FXFONT_BOLD; - } - if (style.Find(FX_BSTRC("Italic")) > -1 || style.Find(FX_BSTRC("Oblique")) > -1) { - pInfo->m_Styles |= FXFONT_ITALIC; - } - if (facename.Find(FX_BSTRC("Serif")) > -1) { - pInfo->m_Styles |= FXFONT_SERIF; - } - m_FontList.SetAt(facename, pInfo); -} -void* CFX_FolderFontInfo::MapFont(int weight, FX_BOOL bItalic, int charset, int pitch_family, const FX_CHAR* family, int& iExact) -{ - return NULL; +void CFX_FolderFontInfo::ScanFile(CFX_ByteString& path) { + FXSYS_FILE* pFile = FXSYS_fopen(path, "rb"); + if (pFile == NULL) { + return; + } + FXSYS_fseek(pFile, 0, FXSYS_SEEK_END); + FX_DWORD filesize = FXSYS_ftell(pFile); + uint8_t buffer[16]; + FXSYS_fseek(pFile, 0, FXSYS_SEEK_SET); + size_t readCnt = FXSYS_fread(buffer, 12, 1, pFile); + if (readCnt != 1) { + FXSYS_fclose(pFile); + return; + } + + if (GET_TT_LONG(buffer) == 0x74746366) { + FX_DWORD nFaces = GET_TT_LONG(buffer + 8); + if (nFaces > std::numeric_limits<FX_DWORD>::max() / 4) { + FXSYS_fclose(pFile); + return; + } + FX_DWORD face_bytes = nFaces * 4; + uint8_t* offsets = FX_Alloc(uint8_t, face_bytes); + readCnt = FXSYS_fread(offsets, 1, face_bytes, pFile); + if (readCnt != face_bytes) { + FX_Free(offsets); + FXSYS_fclose(pFile); + return; + } + for (FX_DWORD i = 0; i < nFaces; i++) { + uint8_t* p = offsets + i * 4; + ReportFace(path, pFile, filesize, GET_TT_LONG(p)); + } + FX_Free(offsets); + } else { + ReportFace(path, pFile, filesize, 0); + } + FXSYS_fclose(pFile); } -void* CFX_FolderFontInfo::GetFont(const FX_CHAR* face) -{ - void* p; - if (!m_FontList.Lookup(face, p)) { - return NULL; - } - return p; +void CFX_FolderFontInfo::ReportFace(CFX_ByteString& path, + FXSYS_FILE* pFile, + FX_DWORD filesize, + FX_DWORD offset) { + FXSYS_fseek(pFile, offset, FXSYS_SEEK_SET); + char buffer[16]; + if (!FXSYS_fread(buffer, 12, 1, pFile)) { + return; + } + FX_DWORD nTables = GET_TT_SHORT(buffer + 4); + CFX_ByteString tables = _FPDF_ReadStringFromFile(pFile, nTables * 16); + if (tables.IsEmpty()) { + return; + } + CFX_ByteString names = + _FPDF_LoadTableFromTT(pFile, tables, nTables, 0x6e616d65); + CFX_ByteString facename = _FPDF_GetNameFromTT(names, 1); + CFX_ByteString style = _FPDF_GetNameFromTT(names, 2); + if (style != "Regular") { + facename += " " + style; + } + void* p; + if (m_FontList.Lookup(facename, p)) { + return; + } + CFontFaceInfo* pInfo = new CFontFaceInfo; + pInfo->m_FilePath = path; + pInfo->m_FaceName = facename; + pInfo->m_FontTables = tables; + pInfo->m_FontOffset = offset; + pInfo->m_FileSize = filesize; + pInfo->m_Charsets = 0; + CFX_ByteString os2 = + _FPDF_LoadTableFromTT(pFile, tables, nTables, 0x4f532f32); + if (os2.GetLength() >= 86) { + const uint8_t* p = (const uint8_t*)os2 + 78; + FX_DWORD codepages = GET_TT_LONG(p); + if (codepages & (1 << 17)) { + m_pMapper->AddInstalledFont(facename, FXFONT_SHIFTJIS_CHARSET); + pInfo->m_Charsets |= CHARSET_FLAG_SHIFTJIS; + } + if (codepages & (1 << 18)) { + m_pMapper->AddInstalledFont(facename, FXFONT_GB2312_CHARSET); + pInfo->m_Charsets |= CHARSET_FLAG_GB; + } + if (codepages & (1 << 20)) { + m_pMapper->AddInstalledFont(facename, FXFONT_CHINESEBIG5_CHARSET); + pInfo->m_Charsets |= CHARSET_FLAG_BIG5; + } + if ((codepages & (1 << 19)) || (codepages & (1 << 21))) { + m_pMapper->AddInstalledFont(facename, FXFONT_HANGEUL_CHARSET); + pInfo->m_Charsets |= CHARSET_FLAG_KOREAN; + } + if (codepages & (1 << 31)) { + m_pMapper->AddInstalledFont(facename, FXFONT_SYMBOL_CHARSET); + pInfo->m_Charsets |= CHARSET_FLAG_SYMBOL; + } + } + m_pMapper->AddInstalledFont(facename, FXFONT_ANSI_CHARSET); + pInfo->m_Charsets |= CHARSET_FLAG_ANSI; + pInfo->m_Styles = 0; + if (style.Find(FX_BSTRC("Bold")) > -1) { + pInfo->m_Styles |= FXFONT_BOLD; + } + if (style.Find(FX_BSTRC("Italic")) > -1 || + style.Find(FX_BSTRC("Oblique")) > -1) { + pInfo->m_Styles |= FXFONT_ITALIC; + } + if (facename.Find(FX_BSTRC("Serif")) > -1) { + pInfo->m_Styles |= FXFONT_SERIF; + } + m_FontList.SetAt(facename, pInfo); } -FX_DWORD CFX_FolderFontInfo::GetFontData(void* hFont, FX_DWORD table, uint8_t* buffer, FX_DWORD size) -{ - if (hFont == NULL) { - return 0; - } - CFontFaceInfo* pFont = (CFontFaceInfo*)hFont; - FXSYS_FILE* pFile = NULL; - if (size > 0) { - pFile = FXSYS_fopen(pFont->m_FilePath, "rb"); - if (pFile == NULL) { - return 0; - } - } - FX_DWORD datasize = 0; - FX_DWORD offset; - if (table == 0) { - datasize = pFont->m_FontOffset ? 0 : pFont->m_FileSize; - offset = 0; - } else if (table == 0x74746366) { - datasize = pFont->m_FontOffset ? pFont->m_FileSize : 0; - offset = 0; - } else { - FX_DWORD nTables = pFont->m_FontTables.GetLength() / 16; - for (FX_DWORD i = 0; i < nTables; i ++) { - const uint8_t* p = (const uint8_t*)pFont->m_FontTables + i * 16; - if (GET_TT_LONG(p) == table) { - offset = GET_TT_LONG(p + 8); - datasize = GET_TT_LONG(p + 12); - } - } - } - if (datasize && size >= datasize && pFile) { - FXSYS_fseek(pFile, offset, FXSYS_SEEK_SET); - FXSYS_fread(buffer, datasize, 1, pFile); - } - if (pFile) { - FXSYS_fclose(pFile); - } - return datasize; +void* CFX_FolderFontInfo::MapFont(int weight, + FX_BOOL bItalic, + int charset, + int pitch_family, + const FX_CHAR* family, + int& iExact) { + return NULL; } -void CFX_FolderFontInfo::DeleteFont(void* hFont) -{ +void* CFX_FolderFontInfo::GetFont(const FX_CHAR* face) { + void* p; + if (!m_FontList.Lookup(face, p)) { + return NULL; + } + return p; } -FX_BOOL CFX_FolderFontInfo::GetFaceName(void* hFont, CFX_ByteString& name) -{ - if (hFont == NULL) { - return FALSE; - } - CFontFaceInfo* pFont = (CFontFaceInfo*)hFont; - name = pFont->m_FaceName; - return TRUE; +FX_DWORD CFX_FolderFontInfo::GetFontData(void* hFont, + FX_DWORD table, + uint8_t* buffer, + FX_DWORD size) { + if (hFont == NULL) { + return 0; + } + CFontFaceInfo* pFont = (CFontFaceInfo*)hFont; + FXSYS_FILE* pFile = NULL; + if (size > 0) { + pFile = FXSYS_fopen(pFont->m_FilePath, "rb"); + if (pFile == NULL) { + return 0; + } + } + FX_DWORD datasize = 0; + FX_DWORD offset; + if (table == 0) { + datasize = pFont->m_FontOffset ? 0 : pFont->m_FileSize; + offset = 0; + } else if (table == 0x74746366) { + datasize = pFont->m_FontOffset ? pFont->m_FileSize : 0; + offset = 0; + } else { + FX_DWORD nTables = pFont->m_FontTables.GetLength() / 16; + for (FX_DWORD i = 0; i < nTables; i++) { + const uint8_t* p = (const uint8_t*)pFont->m_FontTables + i * 16; + if (GET_TT_LONG(p) == table) { + offset = GET_TT_LONG(p + 8); + datasize = GET_TT_LONG(p + 12); + } + } + } + if (datasize && size >= datasize && pFile) { + FXSYS_fseek(pFile, offset, FXSYS_SEEK_SET); + FXSYS_fread(buffer, datasize, 1, pFile); + } + if (pFile) { + FXSYS_fclose(pFile); + } + return datasize; } -FX_BOOL CFX_FolderFontInfo::GetFontCharset(void* hFont, int& charset) -{ +void CFX_FolderFontInfo::DeleteFont(void* hFont) {} +FX_BOOL CFX_FolderFontInfo::GetFaceName(void* hFont, CFX_ByteString& name) { + if (hFont == NULL) { return FALSE; + } + CFontFaceInfo* pFont = (CFontFaceInfo*)hFont; + name = pFont->m_FaceName; + return TRUE; +} +FX_BOOL CFX_FolderFontInfo::GetFontCharset(void* hFont, int& charset) { + return FALSE; } diff --git a/core/src/fxge/ge/fx_ge_linux.cpp b/core/src/fxge/ge/fx_ge_linux.cpp index 861afd259c..61202597f5 100644 --- a/core/src/fxge/ge/fx_ge_linux.cpp +++ b/core/src/fxge/ge/fx_ge_linux.cpp @@ -10,10 +10,9 @@ #if _FXM_PLATFORM_ == _FXM_PLATFORM_LINUX_ static const struct { - const FX_CHAR* m_pName; - const FX_CHAR* m_pSubstName; -} -Base14Substs[] = { + const FX_CHAR* m_pName; + const FX_CHAR* m_pSubstName; +} Base14Substs[] = { {"Courier", "Courier New"}, {"Courier-Bold", "Courier New Bold"}, {"Courier-BoldOblique", "Courier New Bold Italic"}, @@ -27,205 +26,222 @@ Base14Substs[] = { {"Times-BoldItalic", "Times New Roman Bold Italic"}, {"Times-Italic", "Times New Roman Italic"}, }; -class CFX_LinuxFontInfo : public CFX_FolderFontInfo -{ -public: - void* MapFont(int weight, FX_BOOL bItalic, int charset, int pitch_family, const FX_CHAR* family, int& iExact) override; - FX_BOOL ParseFontCfg(); - void* FindFont(int weight, FX_BOOL bItalic, int charset, int pitch_family, const FX_CHAR* family, FX_BOOL bMatchName); +class CFX_LinuxFontInfo : public CFX_FolderFontInfo { + public: + void* MapFont(int weight, + FX_BOOL bItalic, + int charset, + int pitch_family, + const FX_CHAR* family, + int& iExact) override; + FX_BOOL ParseFontCfg(); + void* FindFont(int weight, + FX_BOOL bItalic, + int charset, + int pitch_family, + const FX_CHAR* family, + FX_BOOL bMatchName); }; -#define LINUX_GPNAMESIZE 6 +#define LINUX_GPNAMESIZE 6 static const struct { - const FX_CHAR* NameArr[LINUX_GPNAMESIZE]; -} -LinuxGpFontList[] = { - {{"TakaoPGothic", "VL PGothic", "IPAPGothic", "VL Gothic", "Kochi Gothic", "VL Gothic regular"}}, - {{"TakaoGothic", "VL Gothic", "IPAGothic", "Kochi Gothic", NULL, "VL Gothic regular"}}, - {{"TakaoPMincho", "IPAPMincho", "VL Gothic", "Kochi Mincho", NULL, "VL Gothic regular"}}, - {{"TakaoMincho", "IPAMincho", "VL Gothic", "Kochi Mincho", NULL, "VL Gothic regular"}}, + const FX_CHAR* NameArr[LINUX_GPNAMESIZE]; +} LinuxGpFontList[] = { + {{"TakaoPGothic", "VL PGothic", "IPAPGothic", "VL Gothic", "Kochi Gothic", + "VL Gothic regular"}}, + {{"TakaoGothic", "VL Gothic", "IPAGothic", "Kochi Gothic", NULL, + "VL Gothic regular"}}, + {{"TakaoPMincho", "IPAPMincho", "VL Gothic", "Kochi Mincho", NULL, + "VL Gothic regular"}}, + {{"TakaoMincho", "IPAMincho", "VL Gothic", "Kochi Mincho", NULL, + "VL Gothic regular"}}, }; static const FX_CHAR* const g_LinuxGbFontList[] = { - "AR PL UMing CN Light", - "WenQuanYi Micro Hei", - "AR PL UKai CN", + "AR PL UMing CN Light", "WenQuanYi Micro Hei", "AR PL UKai CN", }; static const FX_CHAR* const g_LinuxB5FontList[] = { - "AR PL UMing TW Light", - "WenQuanYi Micro Hei", - "AR PL UKai TW", + "AR PL UMing TW Light", "WenQuanYi Micro Hei", "AR PL UKai TW", }; static const FX_CHAR* const g_LinuxHGFontList[] = { "UnDotum", }; -static int32_t GetJapanesePreference(const FX_CHAR* facearr, int weight, int picth_family) -{ - CFX_ByteString face = facearr; - if (face.Find("Gothic") >= 0 || face.Find("\x83\x53\x83\x56\x83\x62\x83\x4e") >= 0) { - if (face.Find("PGothic") >= 0 || face.Find("\x82\x6f\x83\x53\x83\x56\x83\x62\x83\x4e") >= 0) { - return 0; - } - return 1; +static int32_t GetJapanesePreference(const FX_CHAR* facearr, + int weight, + int picth_family) { + CFX_ByteString face = facearr; + if (face.Find("Gothic") >= 0 || + face.Find("\x83\x53\x83\x56\x83\x62\x83\x4e") >= 0) { + if (face.Find("PGothic") >= 0 || + face.Find("\x82\x6f\x83\x53\x83\x56\x83\x62\x83\x4e") >= 0) { + return 0; } - if (face.Find("Mincho") >= 0 || face.Find("\x96\xbe\x92\xa9") >= 0) { - if (face.Find("PMincho") >= 0 || face.Find("\x82\x6f\x96\xbe\x92\xa9") >= 0) { - return 2; - } - return 3; - } - if (!(picth_family & FXFONT_FF_ROMAN) && weight > 400) { - return 0; - } - return 2; -} -void* CFX_LinuxFontInfo::MapFont(int weight, FX_BOOL bItalic, int charset, int pitch_family, const FX_CHAR* cstr_face, int& iExact) -{ - CFX_ByteString face = cstr_face; - int iBaseFont; - for (iBaseFont = 0; iBaseFont < 12; iBaseFont ++) - if (face == CFX_ByteStringC(Base14Substs[iBaseFont].m_pName)) { - face = Base14Substs[iBaseFont].m_pSubstName; - iExact = 1; - break; - } - if (iBaseFont < 12) { - return GetFont(face); - } - void* p = NULL; - FX_BOOL bCJK = TRUE; - switch (charset) { - case FXFONT_SHIFTJIS_CHARSET: { - int32_t index = GetJapanesePreference(cstr_face, weight, pitch_family); - if (index < 0) { - break; - } - for (int32_t i = 0; i < LINUX_GPNAMESIZE; i++) - if (m_FontList.Lookup(LinuxGpFontList[index].NameArr[i], p)) { - return p; - } - } - break; - case FXFONT_GB2312_CHARSET: { - static int32_t s_gbCount = sizeof(g_LinuxGbFontList) / sizeof(const FX_CHAR*); - for (int32_t i = 0; i < s_gbCount; i++) - if (m_FontList.Lookup(g_LinuxGbFontList[i], p)) { - return p; - } - } - break; - case FXFONT_CHINESEBIG5_CHARSET: { - static int32_t s_b5Count = sizeof(g_LinuxB5FontList) / sizeof(const FX_CHAR*); - for (int32_t i = 0; i < s_b5Count; i++) - if (m_FontList.Lookup(g_LinuxB5FontList[i], p)) { - return p; - } - } - break; - case FXFONT_HANGEUL_CHARSET: { - static int32_t s_hgCount = sizeof(g_LinuxHGFontList) / sizeof(const FX_CHAR*); - for (int32_t i = 0; i < s_hgCount; i++) - if (m_FontList.Lookup(g_LinuxHGFontList[i], p)) { - return p; - } - } - break; - default: - bCJK = FALSE; - break; - } - if (charset == FXFONT_ANSI_CHARSET && (pitch_family & FXFONT_FF_FIXEDPITCH)) { - return GetFont("Courier New"); - } - return FindFont(weight, bItalic, charset, pitch_family, cstr_face, !bCJK); -} -static FX_DWORD _LinuxGetCharset(int charset) -{ - switch(charset) { - case FXFONT_SHIFTJIS_CHARSET: - return CHARSET_FLAG_SHIFTJIS; - case FXFONT_GB2312_CHARSET: - return CHARSET_FLAG_GB; - case FXFONT_CHINESEBIG5_CHARSET: - return CHARSET_FLAG_BIG5; - case FXFONT_HANGEUL_CHARSET: - return CHARSET_FLAG_KOREAN; - case FXFONT_SYMBOL_CHARSET: - return CHARSET_FLAG_SYMBOL; - case FXFONT_ANSI_CHARSET: - return CHARSET_FLAG_ANSI; - default: - break; + return 1; + } + if (face.Find("Mincho") >= 0 || face.Find("\x96\xbe\x92\xa9") >= 0) { + if (face.Find("PMincho") >= 0 || + face.Find("\x82\x6f\x96\xbe\x92\xa9") >= 0) { + return 2; } + return 3; + } + if (!(picth_family & FXFONT_FF_ROMAN) && weight > 400) { return 0; + } + return 2; } -static int32_t _LinuxGetSimilarValue(int weight, FX_BOOL bItalic, int pitch_family, FX_DWORD style) -{ - int32_t iSimilarValue = 0; - if ((style & FXFONT_BOLD) == (weight > 400)) { - iSimilarValue += 16; +void* CFX_LinuxFontInfo::MapFont(int weight, + FX_BOOL bItalic, + int charset, + int pitch_family, + const FX_CHAR* cstr_face, + int& iExact) { + CFX_ByteString face = cstr_face; + int iBaseFont; + for (iBaseFont = 0; iBaseFont < 12; iBaseFont++) + if (face == CFX_ByteStringC(Base14Substs[iBaseFont].m_pName)) { + face = Base14Substs[iBaseFont].m_pSubstName; + iExact = 1; + break; } - if ((style & FXFONT_ITALIC) == bItalic) { - iSimilarValue += 16; - } - if ((style & FXFONT_SERIF) == (pitch_family & FXFONT_FF_ROMAN)) { - iSimilarValue += 16; - } - if ((style & FXFONT_SCRIPT) == (pitch_family & FXFONT_FF_SCRIPT)) { - iSimilarValue += 8; - } - if ((style & FXFONT_FIXED_PITCH) == (pitch_family & FXFONT_FF_FIXEDPITCH)) { - iSimilarValue += 8; - } - return iSimilarValue; -} -void* CFX_LinuxFontInfo::FindFont(int weight, FX_BOOL bItalic, int charset, int pitch_family, const FX_CHAR* family, FX_BOOL bMatchName) -{ - CFontFaceInfo* pFind = NULL; - FX_DWORD charset_flag = _LinuxGetCharset(charset); - int32_t iBestSimilar = 0; - FX_POSITION pos = m_FontList.GetStartPosition(); - while (pos) { - CFX_ByteString bsName; - CFontFaceInfo* pFont = NULL; - m_FontList.GetNextAssoc(pos, bsName, (void*&)pFont); - if (!(pFont->m_Charsets & charset_flag) && charset != FXFONT_DEFAULT_CHARSET) { - continue; + if (iBaseFont < 12) { + return GetFont(face); + } + void* p = NULL; + FX_BOOL bCJK = TRUE; + switch (charset) { + case FXFONT_SHIFTJIS_CHARSET: { + int32_t index = GetJapanesePreference(cstr_face, weight, pitch_family); + if (index < 0) { + break; + } + for (int32_t i = 0; i < LINUX_GPNAMESIZE; i++) + if (m_FontList.Lookup(LinuxGpFontList[index].NameArr[i], p)) { + return p; } - int32_t iSimilarValue = 0; - int32_t index = bsName.Find(family); - if (bMatchName && index < 0) { - continue; + } break; + case FXFONT_GB2312_CHARSET: { + static int32_t s_gbCount = + sizeof(g_LinuxGbFontList) / sizeof(const FX_CHAR*); + for (int32_t i = 0; i < s_gbCount; i++) + if (m_FontList.Lookup(g_LinuxGbFontList[i], p)) { + return p; } - if (!bMatchName && index > 0) { - iSimilarValue += 64; + } break; + case FXFONT_CHINESEBIG5_CHARSET: { + static int32_t s_b5Count = + sizeof(g_LinuxB5FontList) / sizeof(const FX_CHAR*); + for (int32_t i = 0; i < s_b5Count; i++) + if (m_FontList.Lookup(g_LinuxB5FontList[i], p)) { + return p; } - iSimilarValue = _LinuxGetSimilarValue(weight, bItalic, pitch_family, pFont->m_Styles); - if (iSimilarValue > iBestSimilar) { - iBestSimilar = iSimilarValue; - pFind = pFont; + } break; + case FXFONT_HANGEUL_CHARSET: { + static int32_t s_hgCount = + sizeof(g_LinuxHGFontList) / sizeof(const FX_CHAR*); + for (int32_t i = 0; i < s_hgCount; i++) + if (m_FontList.Lookup(g_LinuxHGFontList[i], p)) { + return p; } - } - return pFind; + } break; + default: + bCJK = FALSE; + break; + } + if (charset == FXFONT_ANSI_CHARSET && (pitch_family & FXFONT_FF_FIXEDPITCH)) { + return GetFont("Courier New"); + } + return FindFont(weight, bItalic, charset, pitch_family, cstr_face, !bCJK); } -IFX_SystemFontInfo* IFX_SystemFontInfo::CreateDefault() -{ - CFX_LinuxFontInfo* pInfo = new CFX_LinuxFontInfo; - if (!pInfo->ParseFontCfg()) { - pInfo->AddPath("/usr/share/fonts"); - pInfo->AddPath("/usr/share/X11/fonts/Type1"); - pInfo->AddPath("/usr/share/X11/fonts/TTF"); - pInfo->AddPath("/usr/local/share/fonts"); +static FX_DWORD _LinuxGetCharset(int charset) { + switch (charset) { + case FXFONT_SHIFTJIS_CHARSET: + return CHARSET_FLAG_SHIFTJIS; + case FXFONT_GB2312_CHARSET: + return CHARSET_FLAG_GB; + case FXFONT_CHINESEBIG5_CHARSET: + return CHARSET_FLAG_BIG5; + case FXFONT_HANGEUL_CHARSET: + return CHARSET_FLAG_KOREAN; + case FXFONT_SYMBOL_CHARSET: + return CHARSET_FLAG_SYMBOL; + case FXFONT_ANSI_CHARSET: + return CHARSET_FLAG_ANSI; + default: + break; + } + return 0; +} +static int32_t _LinuxGetSimilarValue(int weight, + FX_BOOL bItalic, + int pitch_family, + FX_DWORD style) { + int32_t iSimilarValue = 0; + if ((style & FXFONT_BOLD) == (weight > 400)) { + iSimilarValue += 16; + } + if ((style & FXFONT_ITALIC) == bItalic) { + iSimilarValue += 16; + } + if ((style & FXFONT_SERIF) == (pitch_family & FXFONT_FF_ROMAN)) { + iSimilarValue += 16; + } + if ((style & FXFONT_SCRIPT) == (pitch_family & FXFONT_FF_SCRIPT)) { + iSimilarValue += 8; + } + if ((style & FXFONT_FIXED_PITCH) == (pitch_family & FXFONT_FF_FIXEDPITCH)) { + iSimilarValue += 8; + } + return iSimilarValue; +} +void* CFX_LinuxFontInfo::FindFont(int weight, + FX_BOOL bItalic, + int charset, + int pitch_family, + const FX_CHAR* family, + FX_BOOL bMatchName) { + CFontFaceInfo* pFind = NULL; + FX_DWORD charset_flag = _LinuxGetCharset(charset); + int32_t iBestSimilar = 0; + FX_POSITION pos = m_FontList.GetStartPosition(); + while (pos) { + CFX_ByteString bsName; + CFontFaceInfo* pFont = NULL; + m_FontList.GetNextAssoc(pos, bsName, (void*&)pFont); + if (!(pFont->m_Charsets & charset_flag) && + charset != FXFONT_DEFAULT_CHARSET) { + continue; + } + int32_t iSimilarValue = 0; + int32_t index = bsName.Find(family); + if (bMatchName && index < 0) { + continue; + } + if (!bMatchName && index > 0) { + iSimilarValue += 64; + } + iSimilarValue = + _LinuxGetSimilarValue(weight, bItalic, pitch_family, pFont->m_Styles); + if (iSimilarValue > iBestSimilar) { + iBestSimilar = iSimilarValue; + pFind = pFont; } - return pInfo; + } + return pFind; } -FX_BOOL CFX_LinuxFontInfo::ParseFontCfg() -{ - return FALSE; +IFX_SystemFontInfo* IFX_SystemFontInfo::CreateDefault() { + CFX_LinuxFontInfo* pInfo = new CFX_LinuxFontInfo; + if (!pInfo->ParseFontCfg()) { + pInfo->AddPath("/usr/share/fonts"); + pInfo->AddPath("/usr/share/X11/fonts/Type1"); + pInfo->AddPath("/usr/share/X11/fonts/TTF"); + pInfo->AddPath("/usr/local/share/fonts"); + } + return pInfo; } -void CFX_GEModule::InitPlatform() -{ - m_pFontMgr->SetSystemFontInfo(IFX_SystemFontInfo::CreateDefault()); +FX_BOOL CFX_LinuxFontInfo::ParseFontCfg() { + return FALSE; } -void CFX_GEModule::DestroyPlatform() -{ +void CFX_GEModule::InitPlatform() { + m_pFontMgr->SetSystemFontInfo(IFX_SystemFontInfo::CreateDefault()); } +void CFX_GEModule::DestroyPlatform() {} #endif // _FXM_PLATFORM_ == _FXM_PLATFORM_LINUX_ diff --git a/core/src/fxge/ge/fx_ge_path.cpp b/core/src/fxge/ge/fx_ge_path.cpp index b1410b3911..b50c271c20 100644 --- a/core/src/fxge/ge/fx_ge_path.cpp +++ b/core/src/fxge/ge/fx_ge_path.cpp @@ -8,624 +8,664 @@ #include "../../../include/fxcrt/fx_system.h" #include "../../../include/fxge/fx_ge.h" -CFX_ClipRgn::CFX_ClipRgn(int width, int height) -{ +CFX_ClipRgn::CFX_ClipRgn(int width, int height) { + m_Type = RectI; + m_Box.left = m_Box.top = 0; + m_Box.right = width; + m_Box.bottom = height; +} +CFX_ClipRgn::CFX_ClipRgn(const FX_RECT& rect) { + m_Type = RectI; + m_Box = rect; +} +CFX_ClipRgn::CFX_ClipRgn(const CFX_ClipRgn& src) { + m_Type = src.m_Type; + m_Box = src.m_Box; + m_Mask = src.m_Mask; +} +CFX_ClipRgn::~CFX_ClipRgn() {} +void CFX_ClipRgn::Reset(const FX_RECT& rect) { + m_Type = RectI; + m_Box = rect; + m_Mask.SetNull(); +} +void CFX_ClipRgn::IntersectRect(const FX_RECT& rect) { + if (m_Type == RectI) { + m_Box.Intersect(rect); + return; + } + if (m_Type == MaskF) { + IntersectMaskRect(rect, m_Box, m_Mask); + return; + } +} +void CFX_ClipRgn::IntersectMaskRect(FX_RECT rect, + FX_RECT mask_rect, + CFX_DIBitmapRef Mask) { + const CFX_DIBitmap* mask_dib = Mask; + m_Type = MaskF; + m_Box = rect; + m_Box.Intersect(mask_rect); + if (m_Box.IsEmpty()) { m_Type = RectI; - m_Box.left = m_Box.top = 0; - m_Box.right = width; - m_Box.bottom = height; -} -CFX_ClipRgn::CFX_ClipRgn(const FX_RECT& rect) -{ - m_Type = RectI; - m_Box = rect; -} -CFX_ClipRgn::CFX_ClipRgn(const CFX_ClipRgn& src) -{ - m_Type = src.m_Type; - m_Box = src.m_Box; - m_Mask = src.m_Mask; -} -CFX_ClipRgn::~CFX_ClipRgn() -{ -} -void CFX_ClipRgn::Reset(const FX_RECT& rect) -{ - m_Type = RectI; - m_Box = rect; - m_Mask.SetNull(); -} -void CFX_ClipRgn::IntersectRect(const FX_RECT& rect) -{ - if (m_Type == RectI) { - m_Box.Intersect(rect); - return; - } - if (m_Type == MaskF) { - IntersectMaskRect(rect, m_Box, m_Mask); - return; - } -} -void CFX_ClipRgn::IntersectMaskRect(FX_RECT rect, FX_RECT mask_rect, CFX_DIBitmapRef Mask) -{ - const CFX_DIBitmap* mask_dib = Mask; - m_Type = MaskF; - m_Box = rect; - m_Box.Intersect(mask_rect); - if (m_Box.IsEmpty()) { - m_Type = RectI; - return; - } - if (m_Box == mask_rect) { - m_Mask = Mask; - return; - } - CFX_DIBitmap* new_dib = m_Mask.New(); + return; + } + if (m_Box == mask_rect) { + m_Mask = Mask; + return; + } + CFX_DIBitmap* new_dib = m_Mask.New(); + if (!new_dib) { + return; + } + new_dib->Create(m_Box.Width(), m_Box.Height(), FXDIB_8bppMask); + for (int row = m_Box.top; row < m_Box.bottom; row++) { + uint8_t* dest_scan = + new_dib->GetBuffer() + new_dib->GetPitch() * (row - m_Box.top); + uint8_t* src_scan = + mask_dib->GetBuffer() + mask_dib->GetPitch() * (row - mask_rect.top); + for (int col = m_Box.left; col < m_Box.right; col++) { + dest_scan[col - m_Box.left] = src_scan[col - mask_rect.left]; + } + } +} +void CFX_ClipRgn::IntersectMaskF(int left, int top, CFX_DIBitmapRef Mask) { + const CFX_DIBitmap* mask_dib = Mask; + ASSERT(mask_dib->GetFormat() == FXDIB_8bppMask); + FX_RECT mask_box(left, top, left + mask_dib->GetWidth(), + top + mask_dib->GetHeight()); + if (m_Type == RectI) { + IntersectMaskRect(m_Box, mask_box, Mask); + return; + } + if (m_Type == MaskF) { + FX_RECT new_box = m_Box; + new_box.Intersect(mask_box); + if (new_box.IsEmpty()) { + m_Type = RectI; + m_Mask.SetNull(); + m_Box = new_box; + return; + } + CFX_DIBitmapRef new_mask; + CFX_DIBitmap* new_dib = new_mask.New(); if (!new_dib) { - return; - } - new_dib->Create(m_Box.Width(), m_Box.Height(), FXDIB_8bppMask); - for (int row = m_Box.top; row < m_Box.bottom; row ++) { - uint8_t* dest_scan = new_dib->GetBuffer() + new_dib->GetPitch() * (row - m_Box.top); - uint8_t* src_scan = mask_dib->GetBuffer() + mask_dib->GetPitch() * (row - mask_rect.top); - for (int col = m_Box.left; col < m_Box.right; col ++) { - dest_scan[col - m_Box.left] = src_scan[col - mask_rect.left]; - } - } -} -void CFX_ClipRgn::IntersectMaskF(int left, int top, CFX_DIBitmapRef Mask) -{ - const CFX_DIBitmap* mask_dib = Mask; - ASSERT(mask_dib->GetFormat() == FXDIB_8bppMask); - FX_RECT mask_box(left, top, left + mask_dib->GetWidth(), top + mask_dib->GetHeight()); - if (m_Type == RectI) { - IntersectMaskRect(m_Box, mask_box, Mask); - return; - } - if (m_Type == MaskF) { - FX_RECT new_box = m_Box; - new_box.Intersect(mask_box); - if (new_box.IsEmpty()) { - m_Type = RectI; - m_Mask.SetNull(); - m_Box = new_box; - return; - } - CFX_DIBitmapRef new_mask; - CFX_DIBitmap* new_dib = new_mask.New(); - if (!new_dib) { - return; - } - new_dib->Create(new_box.Width(), new_box.Height(), FXDIB_8bppMask); - const CFX_DIBitmap* old_dib = m_Mask; - for (int row = new_box.top; row < new_box.bottom; row ++) { - uint8_t* old_scan = old_dib->GetBuffer() + (row - m_Box.top) * old_dib->GetPitch(); - uint8_t* mask_scan = mask_dib->GetBuffer() + (row - top) * mask_dib->GetPitch(); - uint8_t* new_scan = new_dib->GetBuffer() + (row - new_box.top) * new_dib->GetPitch(); - for (int col = new_box.left; col < new_box.right; col ++) { - new_scan[col - new_box.left] = old_scan[col - m_Box.left] * mask_scan[col - left] / 255; - } - } - m_Box = new_box; - m_Mask = new_mask; - return; - } - ASSERT(FALSE); -} -CFX_PathData::CFX_PathData() -{ - m_PointCount = m_AllocCount = 0; - m_pPoints = NULL; -} -CFX_PathData::~CFX_PathData() -{ + return; + } + new_dib->Create(new_box.Width(), new_box.Height(), FXDIB_8bppMask); + const CFX_DIBitmap* old_dib = m_Mask; + for (int row = new_box.top; row < new_box.bottom; row++) { + uint8_t* old_scan = + old_dib->GetBuffer() + (row - m_Box.top) * old_dib->GetPitch(); + uint8_t* mask_scan = + mask_dib->GetBuffer() + (row - top) * mask_dib->GetPitch(); + uint8_t* new_scan = + new_dib->GetBuffer() + (row - new_box.top) * new_dib->GetPitch(); + for (int col = new_box.left; col < new_box.right; col++) { + new_scan[col - new_box.left] = + old_scan[col - m_Box.left] * mask_scan[col - left] / 255; + } + } + m_Box = new_box; + m_Mask = new_mask; + return; + } + ASSERT(FALSE); +} +CFX_PathData::CFX_PathData() { + m_PointCount = m_AllocCount = 0; + m_pPoints = NULL; +} +CFX_PathData::~CFX_PathData() { + if (m_pPoints) { + FX_Free(m_pPoints); + } +} +void CFX_PathData::SetPointCount(int nPoints) { + m_PointCount = nPoints; + if (m_AllocCount < nPoints) { if (m_pPoints) { - FX_Free(m_pPoints); - } -} -void CFX_PathData::SetPointCount(int nPoints) -{ - m_PointCount = nPoints; - if (m_AllocCount < nPoints) { - if (m_pPoints) { - FX_Free(m_pPoints); - m_pPoints = NULL; - } - m_pPoints = FX_Alloc(FX_PATHPOINT, nPoints); - m_AllocCount = nPoints; - } -} -void CFX_PathData::AllocPointCount(int nPoints) -{ - if (m_AllocCount < nPoints) { - FX_PATHPOINT* pNewBuf = FX_Alloc(FX_PATHPOINT, nPoints); - if (m_PointCount) { - FXSYS_memcpy(pNewBuf, m_pPoints, m_PointCount * sizeof(FX_PATHPOINT)); - } - if (m_pPoints) { - FX_Free(m_pPoints); - } - m_pPoints = pNewBuf; - m_AllocCount = nPoints; + FX_Free(m_pPoints); + m_pPoints = NULL; } + m_pPoints = FX_Alloc(FX_PATHPOINT, nPoints); + m_AllocCount = nPoints; + } } -CFX_PathData::CFX_PathData(const CFX_PathData& src) -{ - m_PointCount = m_AllocCount = src.m_PointCount; - m_pPoints = FX_Alloc(FX_PATHPOINT, src.m_PointCount); - FXSYS_memcpy(m_pPoints, src.m_pPoints, sizeof(FX_PATHPOINT) * m_PointCount); -} -void CFX_PathData::TrimPoints(int nPoints) -{ - if (m_PointCount <= nPoints) { - return; - } - SetPointCount(nPoints); -} -void CFX_PathData::AddPointCount(int addPoints) -{ - pdfium::base::CheckedNumeric<int> safe_new_count = m_PointCount; - safe_new_count += addPoints; - int new_count = safe_new_count.ValueOrDie(); - AllocPointCount(new_count); - m_PointCount = new_count; -} -void CFX_PathData::Append(const CFX_PathData* pSrc, const CFX_AffineMatrix* pMatrix) -{ - int old_count = m_PointCount; - AddPointCount(pSrc->m_PointCount); - FXSYS_memcpy(m_pPoints + old_count, pSrc->m_pPoints, pSrc->m_PointCount * sizeof(FX_PATHPOINT)); - if (pMatrix) { - for (int i = 0; i < pSrc->m_PointCount; i ++) { - pMatrix->Transform(m_pPoints[old_count + i].m_PointX, m_pPoints[old_count + i].m_PointY); - } - } -} -void CFX_PathData::SetPoint(int index, FX_FLOAT x, FX_FLOAT y, int flag) -{ - ASSERT(index < m_PointCount); - m_pPoints[index].m_PointX = x; - m_pPoints[index].m_PointY = y; - m_pPoints[index].m_Flag = flag; -} -void CFX_PathData::AppendRect(FX_FLOAT left, FX_FLOAT bottom, FX_FLOAT right, FX_FLOAT top) -{ - int old_count = m_PointCount; - AddPointCount(5); - FX_PATHPOINT* pPoints = m_pPoints + old_count; - pPoints[0].m_PointX = pPoints[1].m_PointX = pPoints[4].m_PointX = left; - pPoints[2].m_PointX = pPoints[3].m_PointX = right; - pPoints[0].m_PointY = pPoints[3].m_PointY = pPoints[4].m_PointY = bottom; - pPoints[1].m_PointY = pPoints[2].m_PointY = top; - pPoints[0].m_Flag = FXPT_MOVETO; - pPoints[1].m_Flag = pPoints[2].m_Flag = pPoints[3].m_Flag = FXPT_LINETO; - pPoints[4].m_Flag = FXPT_LINETO | FXPT_CLOSEFIGURE; -} -CFX_FloatRect CFX_PathData::GetBoundingBox() const -{ - CFX_FloatRect rect; +void CFX_PathData::AllocPointCount(int nPoints) { + if (m_AllocCount < nPoints) { + FX_PATHPOINT* pNewBuf = FX_Alloc(FX_PATHPOINT, nPoints); if (m_PointCount) { - rect.InitRect(m_pPoints[0].m_PointX, m_pPoints[0].m_PointY); - for (int i = 1; i < m_PointCount; i ++) { - rect.UpdateRect(m_pPoints[i].m_PointX, m_pPoints[i].m_PointY); - } - } - return rect; -} -static void _UpdateLineEndPoints(CFX_FloatRect& rect, FX_FLOAT start_x, FX_FLOAT start_y, FX_FLOAT end_x, FX_FLOAT end_y, - FX_FLOAT hw) -{ - if (start_x == end_x) { - if (start_y == end_y) { - rect.UpdateRect(end_x + hw, end_y + hw); - rect.UpdateRect(end_x - hw, end_y - hw); - return; - } - FX_FLOAT point_y; - if (end_y < start_y) { - point_y = end_y - hw; - } else { - point_y = end_y + hw; - } - rect.UpdateRect(end_x + hw, point_y); - rect.UpdateRect(end_x - hw, point_y); - return; + FXSYS_memcpy(pNewBuf, m_pPoints, m_PointCount * sizeof(FX_PATHPOINT)); } + if (m_pPoints) { + FX_Free(m_pPoints); + } + m_pPoints = pNewBuf; + m_AllocCount = nPoints; + } +} +CFX_PathData::CFX_PathData(const CFX_PathData& src) { + m_PointCount = m_AllocCount = src.m_PointCount; + m_pPoints = FX_Alloc(FX_PATHPOINT, src.m_PointCount); + FXSYS_memcpy(m_pPoints, src.m_pPoints, sizeof(FX_PATHPOINT) * m_PointCount); +} +void CFX_PathData::TrimPoints(int nPoints) { + if (m_PointCount <= nPoints) { + return; + } + SetPointCount(nPoints); +} +void CFX_PathData::AddPointCount(int addPoints) { + pdfium::base::CheckedNumeric<int> safe_new_count = m_PointCount; + safe_new_count += addPoints; + int new_count = safe_new_count.ValueOrDie(); + AllocPointCount(new_count); + m_PointCount = new_count; +} +void CFX_PathData::Append(const CFX_PathData* pSrc, + const CFX_AffineMatrix* pMatrix) { + int old_count = m_PointCount; + AddPointCount(pSrc->m_PointCount); + FXSYS_memcpy(m_pPoints + old_count, pSrc->m_pPoints, + pSrc->m_PointCount * sizeof(FX_PATHPOINT)); + if (pMatrix) { + for (int i = 0; i < pSrc->m_PointCount; i++) { + pMatrix->Transform(m_pPoints[old_count + i].m_PointX, + m_pPoints[old_count + i].m_PointY); + } + } +} +void CFX_PathData::SetPoint(int index, FX_FLOAT x, FX_FLOAT y, int flag) { + ASSERT(index < m_PointCount); + m_pPoints[index].m_PointX = x; + m_pPoints[index].m_PointY = y; + m_pPoints[index].m_Flag = flag; +} +void CFX_PathData::AppendRect(FX_FLOAT left, + FX_FLOAT bottom, + FX_FLOAT right, + FX_FLOAT top) { + int old_count = m_PointCount; + AddPointCount(5); + FX_PATHPOINT* pPoints = m_pPoints + old_count; + pPoints[0].m_PointX = pPoints[1].m_PointX = pPoints[4].m_PointX = left; + pPoints[2].m_PointX = pPoints[3].m_PointX = right; + pPoints[0].m_PointY = pPoints[3].m_PointY = pPoints[4].m_PointY = bottom; + pPoints[1].m_PointY = pPoints[2].m_PointY = top; + pPoints[0].m_Flag = FXPT_MOVETO; + pPoints[1].m_Flag = pPoints[2].m_Flag = pPoints[3].m_Flag = FXPT_LINETO; + pPoints[4].m_Flag = FXPT_LINETO | FXPT_CLOSEFIGURE; +} +CFX_FloatRect CFX_PathData::GetBoundingBox() const { + CFX_FloatRect rect; + if (m_PointCount) { + rect.InitRect(m_pPoints[0].m_PointX, m_pPoints[0].m_PointY); + for (int i = 1; i < m_PointCount; i++) { + rect.UpdateRect(m_pPoints[i].m_PointX, m_pPoints[i].m_PointY); + } + } + return rect; +} +static void _UpdateLineEndPoints(CFX_FloatRect& rect, + FX_FLOAT start_x, + FX_FLOAT start_y, + FX_FLOAT end_x, + FX_FLOAT end_y, + FX_FLOAT hw) { + if (start_x == end_x) { if (start_y == end_y) { - FX_FLOAT point_x; - if (end_x < start_x) { - point_x = end_x - hw; - } else { - point_x = end_x + hw; - } - rect.UpdateRect(point_x, end_y + hw); - rect.UpdateRect(point_x, end_y - hw); - return; - } - FX_FLOAT dx = end_x - start_x; - FX_FLOAT dy = end_y - start_y; - FX_FLOAT ll = FXSYS_sqrt2(dx, dy); - FX_FLOAT mx = end_x + hw * dx / ll; - FX_FLOAT my = end_y + hw * dy / ll; - FX_FLOAT dx1 = hw * dy / ll; - FX_FLOAT dy1 = hw * dx / ll; - rect.UpdateRect(mx - dx1, my + dy1); - rect.UpdateRect(mx + dx1, my - dy1); -} -static void _UpdateLineJoinPoints(CFX_FloatRect& rect, FX_FLOAT start_x, FX_FLOAT start_y, - FX_FLOAT middle_x, FX_FLOAT middle_y, FX_FLOAT end_x, FX_FLOAT end_y, - FX_FLOAT half_width, FX_FLOAT miter_limit) -{ - FX_FLOAT start_k = 0, start_c = 0, end_k = 0, end_c = 0, start_len = 0, start_dc = 0, end_len = 0, end_dc = 0; - FX_BOOL bStartVert = FXSYS_fabs(start_x - middle_x) < 1.0f / 20; - FX_BOOL bEndVert = FXSYS_fabs(middle_x - end_x) < 1.0f / 20; - if (bStartVert && bEndVert) { - int start_dir = middle_y > start_y ? 1 : -1; - FX_FLOAT point_y = middle_y + half_width * start_dir; - rect.UpdateRect(middle_x + half_width, point_y); - rect.UpdateRect(middle_x - half_width, point_y); - return; - } - if (!bStartVert) { - start_k = FXSYS_Div(middle_y - start_y, middle_x - start_x); - start_c = middle_y - FXSYS_Mul(start_k, middle_x); - start_len = FXSYS_sqrt2(start_x - middle_x, start_y - middle_y); - start_dc = (FX_FLOAT)FXSYS_fabs(FXSYS_MulDiv(half_width, start_len, start_x - middle_x)); - } - if (!bEndVert) { - end_k = FXSYS_Div(end_y - middle_y, end_x - middle_x); - end_c = middle_y - FXSYS_Mul(end_k, middle_x); - end_len = FXSYS_sqrt2(end_x - middle_x, end_y - middle_y); - end_dc = (FX_FLOAT)FXSYS_fabs(FXSYS_MulDiv(half_width, end_len, end_x - middle_x)); - } - if (bStartVert) { - FX_FLOAT outside_x = start_x; - if (end_x < start_x) { - outside_x += half_width; - } else { - outside_x -= half_width; - } - FX_FLOAT outside_y; - if (start_y < FXSYS_Mul(end_k, start_x) + end_c) { - outside_y = FXSYS_Mul(end_k, outside_x) + end_c + end_dc; - } else { - outside_y = FXSYS_Mul(end_k, outside_x) + end_c - end_dc; - } - rect.UpdateRect(outside_x, outside_y); - return; + rect.UpdateRect(end_x + hw, end_y + hw); + rect.UpdateRect(end_x - hw, end_y - hw); + return; } - if (bEndVert) { - FX_FLOAT outside_x = end_x; - if (start_x < end_x) { - outside_x += half_width; - } else { - outside_x -= half_width; - } - FX_FLOAT outside_y; - if (end_y < FXSYS_Mul(start_k, end_x) + start_c) { - outside_y = FXSYS_Mul(start_k, outside_x) + start_c + start_dc; - } else { - outside_y = FXSYS_Mul(start_k, outside_x) + start_c - start_dc; - } - rect.UpdateRect(outside_x, outside_y); - return; - } - if (FXSYS_fabs(start_k - end_k) < 1.0f / 20) { - int start_dir = middle_x > start_x ? 1 : -1; - int end_dir = end_x > middle_x ? 1 : -1; - if (start_dir == end_dir) { - _UpdateLineEndPoints(rect, middle_x, middle_y, end_x, end_y, half_width); - } else { - _UpdateLineEndPoints(rect, start_x, start_y, middle_x, middle_y, half_width); - } - return; - } - FX_FLOAT start_outside_c = start_c; - if (end_y < FXSYS_Mul(start_k, end_x) + start_c) { - start_outside_c += start_dc; + FX_FLOAT point_y; + if (end_y < start_y) { + point_y = end_y - hw; + } else { + point_y = end_y + hw; + } + rect.UpdateRect(end_x + hw, point_y); + rect.UpdateRect(end_x - hw, point_y); + return; + } + if (start_y == end_y) { + FX_FLOAT point_x; + if (end_x < start_x) { + point_x = end_x - hw; } else { - start_outside_c -= start_dc; + point_x = end_x + hw; + } + rect.UpdateRect(point_x, end_y + hw); + rect.UpdateRect(point_x, end_y - hw); + return; + } + FX_FLOAT dx = end_x - start_x; + FX_FLOAT dy = end_y - start_y; + FX_FLOAT ll = FXSYS_sqrt2(dx, dy); + FX_FLOAT mx = end_x + hw * dx / ll; + FX_FLOAT my = end_y + hw * dy / ll; + FX_FLOAT dx1 = hw * dy / ll; + FX_FLOAT dy1 = hw * dx / ll; + rect.UpdateRect(mx - dx1, my + dy1); + rect.UpdateRect(mx + dx1, my - dy1); +} +static void _UpdateLineJoinPoints(CFX_FloatRect& rect, + FX_FLOAT start_x, + FX_FLOAT start_y, + FX_FLOAT middle_x, + FX_FLOAT middle_y, + FX_FLOAT end_x, + FX_FLOAT end_y, + FX_FLOAT half_width, + FX_FLOAT miter_limit) { + FX_FLOAT start_k = 0, start_c = 0, end_k = 0, end_c = 0, start_len = 0, + start_dc = 0, end_len = 0, end_dc = 0; + FX_BOOL bStartVert = FXSYS_fabs(start_x - middle_x) < 1.0f / 20; + FX_BOOL bEndVert = FXSYS_fabs(middle_x - end_x) < 1.0f / 20; + if (bStartVert && bEndVert) { + int start_dir = middle_y > start_y ? 1 : -1; + FX_FLOAT point_y = middle_y + half_width * start_dir; + rect.UpdateRect(middle_x + half_width, point_y); + rect.UpdateRect(middle_x - half_width, point_y); + return; + } + if (!bStartVert) { + start_k = FXSYS_Div(middle_y - start_y, middle_x - start_x); + start_c = middle_y - FXSYS_Mul(start_k, middle_x); + start_len = FXSYS_sqrt2(start_x - middle_x, start_y - middle_y); + start_dc = (FX_FLOAT)FXSYS_fabs( + FXSYS_MulDiv(half_width, start_len, start_x - middle_x)); + } + if (!bEndVert) { + end_k = FXSYS_Div(end_y - middle_y, end_x - middle_x); + end_c = middle_y - FXSYS_Mul(end_k, middle_x); + end_len = FXSYS_sqrt2(end_x - middle_x, end_y - middle_y); + end_dc = (FX_FLOAT)FXSYS_fabs( + FXSYS_MulDiv(half_width, end_len, end_x - middle_x)); + } + if (bStartVert) { + FX_FLOAT outside_x = start_x; + if (end_x < start_x) { + outside_x += half_width; + } else { + outside_x -= half_width; } - FX_FLOAT end_outside_c = end_c; + FX_FLOAT outside_y; if (start_y < FXSYS_Mul(end_k, start_x) + end_c) { - end_outside_c += end_dc; + outside_y = FXSYS_Mul(end_k, outside_x) + end_c + end_dc; } else { - end_outside_c -= end_dc; - } - FX_FLOAT join_x = FXSYS_Div(end_outside_c - start_outside_c, start_k - end_k); - FX_FLOAT join_y = FXSYS_Mul(start_k, join_x) + start_outside_c; - rect.UpdateRect(join_x, join_y); -} -CFX_FloatRect CFX_PathData::GetBoundingBox(FX_FLOAT line_width, FX_FLOAT miter_limit) const -{ - CFX_FloatRect rect(100000 * 1.0f, 100000 * 1.0f, -100000 * 1.0f, -100000 * 1.0f); - int iPoint = 0; - FX_FLOAT half_width = line_width; - int iStartPoint, iEndPoint, iMiddlePoint; - FX_BOOL bJoin; - while (iPoint < m_PointCount) { - if (m_pPoints[iPoint].m_Flag == FXPT_MOVETO) { - iStartPoint = iPoint + 1; - iEndPoint = iPoint; - bJoin = FALSE; - } else { - if (m_pPoints[iPoint].m_Flag == FXPT_BEZIERTO) { - rect.UpdateRect(m_pPoints[iPoint].m_PointX, m_pPoints[iPoint].m_PointY); - rect.UpdateRect(m_pPoints[iPoint + 1].m_PointX, m_pPoints[iPoint + 1].m_PointY); - iPoint += 2; - } - if (iPoint == m_PointCount - 1 || m_pPoints[iPoint + 1].m_Flag == FXPT_MOVETO) { - iStartPoint = iPoint - 1; - iEndPoint = iPoint; - bJoin = FALSE; - } else { - iStartPoint = iPoint - 1; - iMiddlePoint = iPoint; - iEndPoint = iPoint + 1; - bJoin = TRUE; - } - } - FX_FLOAT start_x = m_pPoints[iStartPoint].m_PointX; - FX_FLOAT start_y = m_pPoints[iStartPoint].m_PointY; - FX_FLOAT end_x = m_pPoints[iEndPoint].m_PointX; - FX_FLOAT end_y = m_pPoints[iEndPoint].m_PointY; - if (bJoin) { - FX_FLOAT middle_x = m_pPoints[iMiddlePoint].m_PointX; - FX_FLOAT middle_y = m_pPoints[iMiddlePoint].m_PointY; - _UpdateLineJoinPoints(rect, start_x, start_y, middle_x, middle_y, end_x, end_y, half_width, miter_limit); - } else { - _UpdateLineEndPoints(rect, start_x, start_y, end_x, end_y, half_width); - } - iPoint ++; - } - return rect; -} -void CFX_PathData::Transform(const CFX_AffineMatrix* pMatrix) -{ - if (pMatrix == NULL) { - return; - } - for (int i = 0; i < m_PointCount; i ++) { - pMatrix->Transform(m_pPoints[i].m_PointX, m_pPoints[i].m_PointY); - } -} -FX_BOOL CFX_PathData::GetZeroAreaPath(CFX_PathData& NewPath, CFX_AffineMatrix* pMatrix, FX_BOOL&bThin, FX_BOOL bAdjust) const -{ - if (m_PointCount < 3) { - return FALSE; - } - if (m_PointCount == 3 && (m_pPoints[0].m_Flag & FXPT_TYPE) == FXPT_MOVETO && - (m_pPoints[1].m_Flag & FXPT_TYPE) == FXPT_LINETO && (m_pPoints[2].m_Flag & FXPT_TYPE) == FXPT_LINETO - && m_pPoints[0].m_PointX == m_pPoints[2].m_PointX && m_pPoints[0].m_PointY == m_pPoints[2].m_PointY) { - NewPath.AddPointCount(2); - if (bAdjust) { - if (pMatrix) { - FX_FLOAT x = m_pPoints[0].m_PointX, y = m_pPoints[0].m_PointY; - pMatrix->TransformPoint(x, y); - x = (int)x + 0.5f; - y = (int)y + 0.5f; - NewPath.SetPoint(0, x, y, FXPT_MOVETO); - x = m_pPoints[1].m_PointX, y = m_pPoints[1].m_PointY; - pMatrix->TransformPoint(x, y); - x = (int)x + 0.5f; - y = (int)y + 0.5f; - NewPath.SetPoint(1, x, y, FXPT_LINETO); - pMatrix->SetIdentity(); - } else { - FX_FLOAT x = (int)m_pPoints[0].m_PointX + 0.5f, y = (int)m_pPoints[0].m_PointY + 0.5f; - NewPath.SetPoint(0, x, y, FXPT_MOVETO); - x = (int)m_pPoints[1].m_PointX + 0.5f, y = (int)m_pPoints[1].m_PointY + 0.5f; - NewPath.SetPoint(1, x, y, FXPT_LINETO); - } - } else { - NewPath.SetPoint(0, m_pPoints[0].m_PointX, m_pPoints[0].m_PointY, FXPT_MOVETO); - NewPath.SetPoint(1, m_pPoints[1].m_PointX, m_pPoints[1].m_PointY, FXPT_LINETO); - } - if (m_pPoints[0].m_PointX != m_pPoints[1].m_PointX && m_pPoints[0].m_PointY != m_pPoints[1].m_PointY) { - bThin = TRUE; - } - return TRUE; - } - if (((m_PointCount > 3) && (m_PointCount % 2))) { - int mid = m_PointCount / 2; - FX_BOOL bZeroArea = FALSE; - CFX_PathData t_path; - for (int i = 0; i < mid; i++) { - if (!(m_pPoints[mid - i - 1].m_PointX == m_pPoints[mid + i + 1].m_PointX - && m_pPoints[mid - i - 1].m_PointY == m_pPoints[mid + i + 1].m_PointY && - ((m_pPoints[mid - i - 1].m_Flag & FXPT_TYPE) != FXPT_BEZIERTO && (m_pPoints[mid + i + 1].m_Flag & FXPT_TYPE) != FXPT_BEZIERTO))) { - bZeroArea = TRUE; - break; - } - int new_count = t_path.GetPointCount(); - t_path.AddPointCount(2); - t_path.SetPoint(new_count, m_pPoints[mid - i].m_PointX, m_pPoints[mid - i].m_PointY, FXPT_MOVETO); - t_path.SetPoint(new_count + 1, m_pPoints[mid - i - 1].m_PointX, m_pPoints[mid - i - 1].m_PointY, FXPT_LINETO); - } - if (!bZeroArea) { - NewPath.Append(&t_path, NULL); - bThin = TRUE; - return TRUE; - } - } - int stratPoint = 0; - int next = 0, i; - for (i = 0; i < m_PointCount; i++) { - int point_type = m_pPoints[i].m_Flag & FXPT_TYPE; - if (point_type == FXPT_MOVETO) { - stratPoint = i; - } else if (point_type == FXPT_LINETO) { - next = (i + 1 - stratPoint) % (m_PointCount - stratPoint) + stratPoint; - if ((m_pPoints[next].m_Flag & FXPT_TYPE) != FXPT_BEZIERTO && (m_pPoints[next].m_Flag & FXPT_TYPE) != FXPT_MOVETO) { - if((m_pPoints[i - 1].m_PointX == m_pPoints[i].m_PointX && m_pPoints[i].m_PointX == m_pPoints[next].m_PointX) - && ((m_pPoints[i].m_PointY - m_pPoints[i - 1].m_PointY) * (m_pPoints[i].m_PointY - m_pPoints[next].m_PointY) > 0)) { - int pre = i; - if (FXSYS_fabs(m_pPoints[i].m_PointY - m_pPoints[i - 1].m_PointY) - < FXSYS_fabs(m_pPoints[i].m_PointY - m_pPoints[next].m_PointY)) { - pre --; - next--; - } - int new_count = NewPath.GetPointCount(); - NewPath.AddPointCount(2); - NewPath.SetPoint(new_count, m_pPoints[pre].m_PointX, m_pPoints[pre].m_PointY, FXPT_MOVETO); - NewPath.SetPoint(new_count + 1, m_pPoints[next].m_PointX, m_pPoints[next].m_PointY, FXPT_LINETO); - } else if((m_pPoints[i - 1].m_PointY == m_pPoints[i].m_PointY && m_pPoints[i].m_PointY == m_pPoints[next].m_PointY) - && ((m_pPoints[i].m_PointX - m_pPoints[i - 1].m_PointX) * (m_pPoints[i].m_PointX - m_pPoints[next].m_PointX) > 0)) { - int pre = i; - if (FXSYS_fabs(m_pPoints[i].m_PointX - m_pPoints[i - 1].m_PointX) - < FXSYS_fabs(m_pPoints[i].m_PointX - m_pPoints[next].m_PointX)) { - pre --; - next--; - } - int new_count = NewPath.GetPointCount(); - NewPath.AddPointCount(2); - NewPath.SetPoint(new_count, m_pPoints[pre].m_PointX, m_pPoints[pre].m_PointY, FXPT_MOVETO); - NewPath.SetPoint(new_count + 1, m_pPoints[next].m_PointX, m_pPoints[next].m_PointY, FXPT_LINETO); - } else if ((m_pPoints[i - 1].m_Flag & FXPT_TYPE) == FXPT_MOVETO && (m_pPoints[next].m_Flag & FXPT_TYPE) == FXPT_LINETO && - m_pPoints[i - 1].m_PointX == m_pPoints[next].m_PointX && m_pPoints[i - 1].m_PointY == m_pPoints[next].m_PointY - && m_pPoints[next].m_Flag & FXPT_CLOSEFIGURE) { - int new_count = NewPath.GetPointCount(); - NewPath.AddPointCount(2); - NewPath.SetPoint(new_count, m_pPoints[i - 1].m_PointX, m_pPoints[i - 1].m_PointY, FXPT_MOVETO); - NewPath.SetPoint(new_count + 1, m_pPoints[i].m_PointX, m_pPoints[i].m_PointY, FXPT_LINETO); - bThin = TRUE; - } - } - } else if (point_type == FXPT_BEZIERTO) { - i += 2; - continue; - } + outside_y = FXSYS_Mul(end_k, outside_x) + end_c - end_dc; + } + rect.UpdateRect(outside_x, outside_y); + return; + } + if (bEndVert) { + FX_FLOAT outside_x = end_x; + if (start_x < end_x) { + outside_x += half_width; + } else { + outside_x -= half_width; } - if (m_PointCount > 3 && NewPath.GetPointCount()) { - bThin = TRUE; + FX_FLOAT outside_y; + if (end_y < FXSYS_Mul(start_k, end_x) + start_c) { + outside_y = FXSYS_Mul(start_k, outside_x) + start_c + start_dc; + } else { + outside_y = FXSYS_Mul(start_k, outside_x) + start_c - start_dc; + } + rect.UpdateRect(outside_x, outside_y); + return; + } + if (FXSYS_fabs(start_k - end_k) < 1.0f / 20) { + int start_dir = middle_x > start_x ? 1 : -1; + int end_dir = end_x > middle_x ? 1 : -1; + if (start_dir == end_dir) { + _UpdateLineEndPoints(rect, middle_x, middle_y, end_x, end_y, half_width); + } else { + _UpdateLineEndPoints(rect, start_x, start_y, middle_x, middle_y, + half_width); + } + return; + } + FX_FLOAT start_outside_c = start_c; + if (end_y < FXSYS_Mul(start_k, end_x) + start_c) { + start_outside_c += start_dc; + } else { + start_outside_c -= start_dc; + } + FX_FLOAT end_outside_c = end_c; + if (start_y < FXSYS_Mul(end_k, start_x) + end_c) { + end_outside_c += end_dc; + } else { + end_outside_c -= end_dc; + } + FX_FLOAT join_x = FXSYS_Div(end_outside_c - start_outside_c, start_k - end_k); + FX_FLOAT join_y = FXSYS_Mul(start_k, join_x) + start_outside_c; + rect.UpdateRect(join_x, join_y); +} +CFX_FloatRect CFX_PathData::GetBoundingBox(FX_FLOAT line_width, + FX_FLOAT miter_limit) const { + CFX_FloatRect rect(100000 * 1.0f, 100000 * 1.0f, -100000 * 1.0f, + -100000 * 1.0f); + int iPoint = 0; + FX_FLOAT half_width = line_width; + int iStartPoint, iEndPoint, iMiddlePoint; + FX_BOOL bJoin; + while (iPoint < m_PointCount) { + if (m_pPoints[iPoint].m_Flag == FXPT_MOVETO) { + iStartPoint = iPoint + 1; + iEndPoint = iPoint; + bJoin = FALSE; + } else { + if (m_pPoints[iPoint].m_Flag == FXPT_BEZIERTO) { + rect.UpdateRect(m_pPoints[iPoint].m_PointX, m_pPoints[iPoint].m_PointY); + rect.UpdateRect(m_pPoints[iPoint + 1].m_PointX, + m_pPoints[iPoint + 1].m_PointY); + iPoint += 2; + } + if (iPoint == m_PointCount - 1 || + m_pPoints[iPoint + 1].m_Flag == FXPT_MOVETO) { + iStartPoint = iPoint - 1; + iEndPoint = iPoint; + bJoin = FALSE; + } else { + iStartPoint = iPoint - 1; + iMiddlePoint = iPoint; + iEndPoint = iPoint + 1; + bJoin = TRUE; + } + } + FX_FLOAT start_x = m_pPoints[iStartPoint].m_PointX; + FX_FLOAT start_y = m_pPoints[iStartPoint].m_PointY; + FX_FLOAT end_x = m_pPoints[iEndPoint].m_PointX; + FX_FLOAT end_y = m_pPoints[iEndPoint].m_PointY; + if (bJoin) { + FX_FLOAT middle_x = m_pPoints[iMiddlePoint].m_PointX; + FX_FLOAT middle_y = m_pPoints[iMiddlePoint].m_PointY; + _UpdateLineJoinPoints(rect, start_x, start_y, middle_x, middle_y, end_x, + end_y, half_width, miter_limit); + } else { + _UpdateLineEndPoints(rect, start_x, start_y, end_x, end_y, half_width); + } + iPoint++; + } + return rect; +} +void CFX_PathData::Transform(const CFX_AffineMatrix* pMatrix) { + if (pMatrix == NULL) { + return; + } + for (int i = 0; i < m_PointCount; i++) { + pMatrix->Transform(m_pPoints[i].m_PointX, m_pPoints[i].m_PointY); + } +} +FX_BOOL CFX_PathData::GetZeroAreaPath(CFX_PathData& NewPath, + CFX_AffineMatrix* pMatrix, + FX_BOOL& bThin, + FX_BOOL bAdjust) const { + if (m_PointCount < 3) { + return FALSE; + } + if (m_PointCount == 3 && (m_pPoints[0].m_Flag & FXPT_TYPE) == FXPT_MOVETO && + (m_pPoints[1].m_Flag & FXPT_TYPE) == FXPT_LINETO && + (m_pPoints[2].m_Flag & FXPT_TYPE) == FXPT_LINETO && + m_pPoints[0].m_PointX == m_pPoints[2].m_PointX && + m_pPoints[0].m_PointY == m_pPoints[2].m_PointY) { + NewPath.AddPointCount(2); + if (bAdjust) { + if (pMatrix) { + FX_FLOAT x = m_pPoints[0].m_PointX, y = m_pPoints[0].m_PointY; + pMatrix->TransformPoint(x, y); + x = (int)x + 0.5f; + y = (int)y + 0.5f; + NewPath.SetPoint(0, x, y, FXPT_MOVETO); + x = m_pPoints[1].m_PointX, y = m_pPoints[1].m_PointY; + pMatrix->TransformPoint(x, y); + x = (int)x + 0.5f; + y = (int)y + 0.5f; + NewPath.SetPoint(1, x, y, FXPT_LINETO); + pMatrix->SetIdentity(); + } else { + FX_FLOAT x = (int)m_pPoints[0].m_PointX + 0.5f, + y = (int)m_pPoints[0].m_PointY + 0.5f; + NewPath.SetPoint(0, x, y, FXPT_MOVETO); + x = (int)m_pPoints[1].m_PointX + 0.5f, + y = (int)m_pPoints[1].m_PointY + 0.5f; + NewPath.SetPoint(1, x, y, FXPT_LINETO); + } + } else { + NewPath.SetPoint(0, m_pPoints[0].m_PointX, m_pPoints[0].m_PointY, + FXPT_MOVETO); + NewPath.SetPoint(1, m_pPoints[1].m_PointX, m_pPoints[1].m_PointY, + FXPT_LINETO); } - if (NewPath.GetPointCount() == 0) { - return FALSE; + if (m_pPoints[0].m_PointX != m_pPoints[1].m_PointX && + m_pPoints[0].m_PointY != m_pPoints[1].m_PointY) { + bThin = TRUE; } return TRUE; -} -FX_BOOL CFX_PathData::IsRect() const -{ - if (m_PointCount != 5 && m_PointCount != 4) { - return FALSE; - } - if ((m_PointCount == 5 && (m_pPoints[0].m_PointX != m_pPoints[4].m_PointX || - m_pPoints[0].m_PointY != m_pPoints[4].m_PointY)) || - (m_pPoints[0].m_PointX == m_pPoints[2].m_PointX && m_pPoints[0].m_PointY == m_pPoints[2].m_PointY) || - (m_pPoints[1].m_PointX == m_pPoints[3].m_PointX && m_pPoints[1].m_PointY == m_pPoints[3].m_PointY)) { - return FALSE; - } - if (m_pPoints[0].m_PointX != m_pPoints[3].m_PointX && m_pPoints[0].m_PointY != m_pPoints[3].m_PointY) { - return FALSE; - } - for (int i = 1; i < 4; i ++) { - if ((m_pPoints[i].m_Flag & FXPT_TYPE) != FXPT_LINETO) { - return FALSE; - } - if (m_pPoints[i].m_PointX != m_pPoints[i - 1].m_PointX && m_pPoints[i].m_PointY != m_pPoints[i - 1].m_PointY) { - return FALSE; - } - } - return m_PointCount == 5 || (m_pPoints[3].m_Flag & FXPT_CLOSEFIGURE); -} -FX_BOOL CFX_PathData::IsRect(const CFX_AffineMatrix* pMatrix, CFX_FloatRect* pRect) const -{ - if (pMatrix == NULL) { - if (!IsRect()) { - return FALSE; - } - if (pRect) { - pRect->left = m_pPoints[0].m_PointX; - pRect->right = m_pPoints[2].m_PointX; - pRect->bottom = m_pPoints[0].m_PointY; - pRect->top = m_pPoints[2].m_PointY; - pRect->Normalize(); - } - return TRUE; - } - if (m_PointCount != 5 && m_PointCount != 4) { - return FALSE; - } - if ((m_PointCount == 5 && (m_pPoints[0].m_PointX != m_pPoints[4].m_PointX || m_pPoints[0].m_PointY != m_pPoints[4].m_PointY)) || - (m_pPoints[1].m_PointX == m_pPoints[3].m_PointX && m_pPoints[1].m_PointY == m_pPoints[3].m_PointY)) { - return FALSE; - } - if (m_PointCount == 4 && m_pPoints[0].m_PointX != m_pPoints[3].m_PointX && m_pPoints[0].m_PointY != m_pPoints[3].m_PointY) { - return FALSE; - } - FX_FLOAT x[5], y[5]; - for (int i = 0; i < m_PointCount; i ++) { - pMatrix->Transform(m_pPoints[i].m_PointX, m_pPoints[i].m_PointY, x[i], y[i]); - if (i) { - if ((m_pPoints[i].m_Flag & FXPT_TYPE) != FXPT_LINETO) { - return FALSE; - } - if (x[i] != x[i - 1] && y[i] != y[i - 1]) { - return FALSE; - } + } + if (((m_PointCount > 3) && (m_PointCount % 2))) { + int mid = m_PointCount / 2; + FX_BOOL bZeroArea = FALSE; + CFX_PathData t_path; + for (int i = 0; i < mid; i++) { + if (!(m_pPoints[mid - i - 1].m_PointX == + m_pPoints[mid + i + 1].m_PointX && + m_pPoints[mid - i - 1].m_PointY == + m_pPoints[mid + i + 1].m_PointY && + ((m_pPoints[mid - i - 1].m_Flag & FXPT_TYPE) != FXPT_BEZIERTO && + (m_pPoints[mid + i + 1].m_Flag & FXPT_TYPE) != FXPT_BEZIERTO))) { + bZeroArea = TRUE; + break; + } + int new_count = t_path.GetPointCount(); + t_path.AddPointCount(2); + t_path.SetPoint(new_count, m_pPoints[mid - i].m_PointX, + m_pPoints[mid - i].m_PointY, FXPT_MOVETO); + t_path.SetPoint(new_count + 1, m_pPoints[mid - i - 1].m_PointX, + m_pPoints[mid - i - 1].m_PointY, FXPT_LINETO); + } + if (!bZeroArea) { + NewPath.Append(&t_path, NULL); + bThin = TRUE; + return TRUE; + } + } + int stratPoint = 0; + int next = 0, i; + for (i = 0; i < m_PointCount; i++) { + int point_type = m_pPoints[i].m_Flag & FXPT_TYPE; + if (point_type == FXPT_MOVETO) { + stratPoint = i; + } else if (point_type == FXPT_LINETO) { + next = (i + 1 - stratPoint) % (m_PointCount - stratPoint) + stratPoint; + if ((m_pPoints[next].m_Flag & FXPT_TYPE) != FXPT_BEZIERTO && + (m_pPoints[next].m_Flag & FXPT_TYPE) != FXPT_MOVETO) { + if ((m_pPoints[i - 1].m_PointX == m_pPoints[i].m_PointX && + m_pPoints[i].m_PointX == m_pPoints[next].m_PointX) && + ((m_pPoints[i].m_PointY - m_pPoints[i - 1].m_PointY) * + (m_pPoints[i].m_PointY - m_pPoints[next].m_PointY) > + 0)) { + int pre = i; + if (FXSYS_fabs(m_pPoints[i].m_PointY - m_pPoints[i - 1].m_PointY) < + FXSYS_fabs(m_pPoints[i].m_PointY - m_pPoints[next].m_PointY)) { + pre--; + next--; + } + int new_count = NewPath.GetPointCount(); + NewPath.AddPointCount(2); + NewPath.SetPoint(new_count, m_pPoints[pre].m_PointX, + m_pPoints[pre].m_PointY, FXPT_MOVETO); + NewPath.SetPoint(new_count + 1, m_pPoints[next].m_PointX, + m_pPoints[next].m_PointY, FXPT_LINETO); + } else if ((m_pPoints[i - 1].m_PointY == m_pPoints[i].m_PointY && + m_pPoints[i].m_PointY == m_pPoints[next].m_PointY) && + ((m_pPoints[i].m_PointX - m_pPoints[i - 1].m_PointX) * + (m_pPoints[i].m_PointX - m_pPoints[next].m_PointX) > + 0)) { + int pre = i; + if (FXSYS_fabs(m_pPoints[i].m_PointX - m_pPoints[i - 1].m_PointX) < + FXSYS_fabs(m_pPoints[i].m_PointX - m_pPoints[next].m_PointX)) { + pre--; + next--; + } + int new_count = NewPath.GetPointCount(); + NewPath.AddPointCount(2); + NewPath.SetPoint(new_count, m_pPoints[pre].m_PointX, + m_pPoints[pre].m_PointY, FXPT_MOVETO); + NewPath.SetPoint(new_count + 1, m_pPoints[next].m_PointX, + m_pPoints[next].m_PointY, FXPT_LINETO); + } else if ((m_pPoints[i - 1].m_Flag & FXPT_TYPE) == FXPT_MOVETO && + (m_pPoints[next].m_Flag & FXPT_TYPE) == FXPT_LINETO && + m_pPoints[i - 1].m_PointX == m_pPoints[next].m_PointX && + m_pPoints[i - 1].m_PointY == m_pPoints[next].m_PointY && + m_pPoints[next].m_Flag & FXPT_CLOSEFIGURE) { + int new_count = NewPath.GetPointCount(); + NewPath.AddPointCount(2); + NewPath.SetPoint(new_count, m_pPoints[i - 1].m_PointX, + m_pPoints[i - 1].m_PointY, FXPT_MOVETO); + NewPath.SetPoint(new_count + 1, m_pPoints[i].m_PointX, + m_pPoints[i].m_PointY, FXPT_LINETO); + bThin = TRUE; } + } + } else if (point_type == FXPT_BEZIERTO) { + i += 2; + continue; + } + } + if (m_PointCount > 3 && NewPath.GetPointCount()) { + bThin = TRUE; + } + if (NewPath.GetPointCount() == 0) { + return FALSE; + } + return TRUE; +} +FX_BOOL CFX_PathData::IsRect() const { + if (m_PointCount != 5 && m_PointCount != 4) { + return FALSE; + } + if ((m_PointCount == 5 && (m_pPoints[0].m_PointX != m_pPoints[4].m_PointX || + m_pPoints[0].m_PointY != m_pPoints[4].m_PointY)) || + (m_pPoints[0].m_PointX == m_pPoints[2].m_PointX && + m_pPoints[0].m_PointY == m_pPoints[2].m_PointY) || + (m_pPoints[1].m_PointX == m_pPoints[3].m_PointX && + m_pPoints[1].m_PointY == m_pPoints[3].m_PointY)) { + return FALSE; + } + if (m_pPoints[0].m_PointX != m_pPoints[3].m_PointX && + m_pPoints[0].m_PointY != m_pPoints[3].m_PointY) { + return FALSE; + } + for (int i = 1; i < 4; i++) { + if ((m_pPoints[i].m_Flag & FXPT_TYPE) != FXPT_LINETO) { + return FALSE; + } + if (m_pPoints[i].m_PointX != m_pPoints[i - 1].m_PointX && + m_pPoints[i].m_PointY != m_pPoints[i - 1].m_PointY) { + return FALSE; + } + } + return m_PointCount == 5 || (m_pPoints[3].m_Flag & FXPT_CLOSEFIGURE); +} +FX_BOOL CFX_PathData::IsRect(const CFX_AffineMatrix* pMatrix, + CFX_FloatRect* pRect) const { + if (pMatrix == NULL) { + if (!IsRect()) { + return FALSE; } if (pRect) { - pRect->left = x[0]; - pRect->right = x[2]; - pRect->bottom = y[0]; - pRect->top = y[2]; - pRect->Normalize(); + pRect->left = m_pPoints[0].m_PointX; + pRect->right = m_pPoints[2].m_PointX; + pRect->bottom = m_pPoints[0].m_PointY; + pRect->top = m_pPoints[2].m_PointY; + pRect->Normalize(); } return TRUE; -} -void CFX_PathData::Copy(const CFX_PathData &src) -{ - SetPointCount(src.m_PointCount); - FXSYS_memcpy(m_pPoints, src.m_pPoints, sizeof(FX_PATHPOINT) * m_PointCount); -} -CFX_GraphStateData::CFX_GraphStateData() -{ - m_LineCap = LineCapButt; - m_DashCount = 0; - m_DashArray = NULL; - m_DashPhase = 0; - m_LineJoin = LineJoinMiter; - m_MiterLimit = 10 * 1.0f; - m_LineWidth = 1.0f; -} -CFX_GraphStateData::CFX_GraphStateData(const CFX_GraphStateData& src) -{ - m_DashArray = NULL; - Copy(src); -} -void CFX_GraphStateData::Copy(const CFX_GraphStateData& src) -{ - m_LineCap = src.m_LineCap; - m_DashCount = src.m_DashCount; - if (m_DashArray) { - FX_Free(m_DashArray); - } - m_DashArray = NULL; - m_DashPhase = src.m_DashPhase; - m_LineJoin = src.m_LineJoin; - m_MiterLimit = src.m_MiterLimit; - m_LineWidth = src.m_LineWidth; - if (m_DashCount) { - m_DashArray = FX_Alloc(FX_FLOAT, m_DashCount); - FXSYS_memcpy(m_DashArray, src.m_DashArray, m_DashCount * sizeof(FX_FLOAT)); - } -} -CFX_GraphStateData::~CFX_GraphStateData() -{ - if (m_DashArray) { - FX_Free(m_DashArray); - } -} -void CFX_GraphStateData::SetDashCount(int count) -{ - if (m_DashArray) { - FX_Free(m_DashArray); - } - m_DashArray = NULL; - m_DashCount = count; - if (count == 0) { - return; - } - m_DashArray = FX_Alloc(FX_FLOAT, count); + } + if (m_PointCount != 5 && m_PointCount != 4) { + return FALSE; + } + if ((m_PointCount == 5 && (m_pPoints[0].m_PointX != m_pPoints[4].m_PointX || + m_pPoints[0].m_PointY != m_pPoints[4].m_PointY)) || + (m_pPoints[1].m_PointX == m_pPoints[3].m_PointX && + m_pPoints[1].m_PointY == m_pPoints[3].m_PointY)) { + return FALSE; + } + if (m_PointCount == 4 && m_pPoints[0].m_PointX != m_pPoints[3].m_PointX && + m_pPoints[0].m_PointY != m_pPoints[3].m_PointY) { + return FALSE; + } + FX_FLOAT x[5], y[5]; + for (int i = 0; i < m_PointCount; i++) { + pMatrix->Transform(m_pPoints[i].m_PointX, m_pPoints[i].m_PointY, x[i], + y[i]); + if (i) { + if ((m_pPoints[i].m_Flag & FXPT_TYPE) != FXPT_LINETO) { + return FALSE; + } + if (x[i] != x[i - 1] && y[i] != y[i - 1]) { + return FALSE; + } + } + } + if (pRect) { + pRect->left = x[0]; + pRect->right = x[2]; + pRect->bottom = y[0]; + pRect->top = y[2]; + pRect->Normalize(); + } + return TRUE; +} +void CFX_PathData::Copy(const CFX_PathData& src) { + SetPointCount(src.m_PointCount); + FXSYS_memcpy(m_pPoints, src.m_pPoints, sizeof(FX_PATHPOINT) * m_PointCount); +} +CFX_GraphStateData::CFX_GraphStateData() { + m_LineCap = LineCapButt; + m_DashCount = 0; + m_DashArray = NULL; + m_DashPhase = 0; + m_LineJoin = LineJoinMiter; + m_MiterLimit = 10 * 1.0f; + m_LineWidth = 1.0f; +} +CFX_GraphStateData::CFX_GraphStateData(const CFX_GraphStateData& src) { + m_DashArray = NULL; + Copy(src); +} +void CFX_GraphStateData::Copy(const CFX_GraphStateData& src) { + m_LineCap = src.m_LineCap; + m_DashCount = src.m_DashCount; + if (m_DashArray) { + FX_Free(m_DashArray); + } + m_DashArray = NULL; + m_DashPhase = src.m_DashPhase; + m_LineJoin = src.m_LineJoin; + m_MiterLimit = src.m_MiterLimit; + m_LineWidth = src.m_LineWidth; + if (m_DashCount) { + m_DashArray = FX_Alloc(FX_FLOAT, m_DashCount); + FXSYS_memcpy(m_DashArray, src.m_DashArray, m_DashCount * sizeof(FX_FLOAT)); + } +} +CFX_GraphStateData::~CFX_GraphStateData() { + if (m_DashArray) { + FX_Free(m_DashArray); + } +} +void CFX_GraphStateData::SetDashCount(int count) { + if (m_DashArray) { + FX_Free(m_DashArray); + } + m_DashArray = NULL; + m_DashCount = count; + if (count == 0) { + return; + } + m_DashArray = FX_Alloc(FX_FLOAT, count); } diff --git a/core/src/fxge/ge/fx_ge_ps.cpp b/core/src/fxge/ge/fx_ge_ps.cpp index ba5c5fbabb..d20825d458 100644 --- a/core/src/fxge/ge/fx_ge_ps.cpp +++ b/core/src/fxge/ge/fx_ge_ps.cpp @@ -8,172 +8,173 @@ #include "../../../include/fxcodec/fx_codec.h" #include "text_int.h" struct PSGlyph { - CFX_Font* m_pFont; - FX_DWORD m_GlyphIndex; - FX_BOOL m_bGlyphAdjust; - FX_FLOAT m_AdjustMatrix[4]; + CFX_Font* m_pFont; + FX_DWORD m_GlyphIndex; + FX_BOOL m_bGlyphAdjust; + FX_FLOAT m_AdjustMatrix[4]; }; -class CPSFont -{ -public: - PSGlyph m_Glyphs[256]; - int m_nGlyphs; +class CPSFont { + public: + PSGlyph m_Glyphs[256]; + int m_nGlyphs; }; -CFX_PSRenderer::CFX_PSRenderer() -{ - m_pOutput = NULL; - m_bColorSet = m_bGraphStateSet = FALSE; - m_bInited = FALSE; +CFX_PSRenderer::CFX_PSRenderer() { + m_pOutput = NULL; + m_bColorSet = m_bGraphStateSet = FALSE; + m_bInited = FALSE; } -CFX_PSRenderer::~CFX_PSRenderer() -{ - for (int i = 0; i < (int)m_PSFontList.GetSize(); i ++) { - CPSFont* pFont = m_PSFontList[i]; - delete pFont; - } +CFX_PSRenderer::~CFX_PSRenderer() { + for (int i = 0; i < (int)m_PSFontList.GetSize(); i++) { + CPSFont* pFont = m_PSFontList[i]; + delete pFont; + } } -#define OUTPUT_PS(str) m_pOutput->OutputPS(str, sizeof str-1) -void CFX_PSRenderer::Init(IFX_PSOutput* pOutput, int pslevel, int width, int height, FX_BOOL bCmykOutput) -{ - m_PSLevel = pslevel; - m_pOutput = pOutput; - m_ClipBox.left = m_ClipBox.top = 0; - m_ClipBox.right = width; - m_ClipBox.bottom = height; - m_bCmykOutput = bCmykOutput; +#define OUTPUT_PS(str) m_pOutput->OutputPS(str, sizeof str - 1) +void CFX_PSRenderer::Init(IFX_PSOutput* pOutput, + int pslevel, + int width, + int height, + FX_BOOL bCmykOutput) { + m_PSLevel = pslevel; + m_pOutput = pOutput; + m_ClipBox.left = m_ClipBox.top = 0; + m_ClipBox.right = width; + m_ClipBox.bottom = height; + m_bCmykOutput = bCmykOutput; } -FX_BOOL CFX_PSRenderer::StartRendering() -{ - if (m_bInited) { - return TRUE; - } - static const char init_str[] = "\nsave\n/im/initmatrix load def\n" - "/n/newpath load def/m/moveto load def/l/lineto load def/c/curveto load def/h/closepath load def\n" - "/f/fill load def/F/eofill load def/s/stroke load def/W/clip load def/W*/eoclip load def\n" - "/rg/setrgbcolor load def/k/setcmykcolor load def\n" - "/J/setlinecap load def/j/setlinejoin load def/w/setlinewidth load def/M/setmiterlimit load def/d/setdash load def\n" - "/q/gsave load def/Q/grestore load def/iM/imagemask load def\n" - "/Tj/show load def/Ff/findfont load def/Fs/scalefont load def/Sf/setfont load def\n" - "/cm/concat load def/Cm/currentmatrix load def/mx/matrix load def/sm/setmatrix load def\n" - ; - OUTPUT_PS(init_str); - m_bInited = TRUE; +FX_BOOL CFX_PSRenderer::StartRendering() { + if (m_bInited) { return TRUE; + } + static const char init_str[] = + "\nsave\n/im/initmatrix load def\n" + "/n/newpath load def/m/moveto load def/l/lineto load def/c/curveto load " + "def/h/closepath load def\n" + "/f/fill load def/F/eofill load def/s/stroke load def/W/clip load " + "def/W*/eoclip load def\n" + "/rg/setrgbcolor load def/k/setcmykcolor load def\n" + "/J/setlinecap load def/j/setlinejoin load def/w/setlinewidth load " + "def/M/setmiterlimit load def/d/setdash load def\n" + "/q/gsave load def/Q/grestore load def/iM/imagemask load def\n" + "/Tj/show load def/Ff/findfont load def/Fs/scalefont load def/Sf/setfont " + "load def\n" + "/cm/concat load def/Cm/currentmatrix load def/mx/matrix load " + "def/sm/setmatrix load def\n"; + OUTPUT_PS(init_str); + m_bInited = TRUE; + return TRUE; } -void CFX_PSRenderer::EndRendering() -{ - if (m_bInited) { - OUTPUT_PS("\nrestore\n"); - } - m_bInited = FALSE; +void CFX_PSRenderer::EndRendering() { + if (m_bInited) { + OUTPUT_PS("\nrestore\n"); + } + m_bInited = FALSE; } -void CFX_PSRenderer::SaveState() -{ - StartRendering(); - OUTPUT_PS("q\n"); - m_ClipBoxStack.Add(m_ClipBox); +void CFX_PSRenderer::SaveState() { + StartRendering(); + OUTPUT_PS("q\n"); + m_ClipBoxStack.Add(m_ClipBox); } -void CFX_PSRenderer::RestoreState(FX_BOOL bKeepSaved) -{ - StartRendering(); - if (bKeepSaved) { - OUTPUT_PS("Q\nq\n"); - } else { - OUTPUT_PS("Q\n"); - } - m_bColorSet = m_bGraphStateSet = FALSE; - m_ClipBox = m_ClipBoxStack.GetAt(m_ClipBoxStack.GetSize() - 1); - if (!bKeepSaved) { - m_ClipBoxStack.RemoveAt(m_ClipBoxStack.GetSize() - 1); - } +void CFX_PSRenderer::RestoreState(FX_BOOL bKeepSaved) { + StartRendering(); + if (bKeepSaved) { + OUTPUT_PS("Q\nq\n"); + } else { + OUTPUT_PS("Q\n"); + } + m_bColorSet = m_bGraphStateSet = FALSE; + m_ClipBox = m_ClipBoxStack.GetAt(m_ClipBoxStack.GetSize() - 1); + if (!bKeepSaved) { + m_ClipBoxStack.RemoveAt(m_ClipBoxStack.GetSize() - 1); + } } -void CFX_PSRenderer::OutputPath(const CFX_PathData* pPathData, const CFX_AffineMatrix* pObject2Device) -{ - int nPoints = pPathData->GetPointCount(); - CFX_ByteTextBuf buf; - buf.EstimateSize(nPoints * 10); - for (int i = 0; i < nPoints; i ++) { - uint8_t flag = pPathData->GetFlag(i); - FX_FLOAT x = pPathData->GetPointX(i); - FX_FLOAT y = pPathData->GetPointY(i); +void CFX_PSRenderer::OutputPath(const CFX_PathData* pPathData, + const CFX_AffineMatrix* pObject2Device) { + int nPoints = pPathData->GetPointCount(); + CFX_ByteTextBuf buf; + buf.EstimateSize(nPoints * 10); + for (int i = 0; i < nPoints; i++) { + uint8_t flag = pPathData->GetFlag(i); + FX_FLOAT x = pPathData->GetPointX(i); + FX_FLOAT y = pPathData->GetPointY(i); + if (pObject2Device) { + pObject2Device->Transform(x, y); + } + buf << x << FX_BSTRC(" ") << y; + switch (flag & FXPT_TYPE) { + case FXPT_MOVETO: + buf << FX_BSTRC(" m "); + break; + case FXPT_LINETO: + if (flag & FXPT_CLOSEFIGURE) { + buf << FX_BSTRC(" l h "); + } else { + buf << FX_BSTRC(" l "); + } + break; + case FXPT_BEZIERTO: { + FX_FLOAT x1 = pPathData->GetPointX(i + 1); + FX_FLOAT x2 = pPathData->GetPointX(i + 2); + FX_FLOAT y1 = pPathData->GetPointY(i + 1); + FX_FLOAT y2 = pPathData->GetPointY(i + 2); if (pObject2Device) { - pObject2Device->Transform(x, y); + pObject2Device->Transform(x1, y1); + pObject2Device->Transform(x2, y2); } - buf << x << FX_BSTRC(" ") << y; - switch (flag & FXPT_TYPE) { - case FXPT_MOVETO: - buf << FX_BSTRC(" m "); - break; - case FXPT_LINETO: - if (flag & FXPT_CLOSEFIGURE) { - buf << FX_BSTRC(" l h "); - } else { - buf << FX_BSTRC(" l "); - } - break; - case FXPT_BEZIERTO: { - FX_FLOAT x1 = pPathData->GetPointX(i + 1); - FX_FLOAT x2 = pPathData->GetPointX(i + 2); - FX_FLOAT y1 = pPathData->GetPointY(i + 1); - FX_FLOAT y2 = pPathData->GetPointY(i + 2); - if (pObject2Device) { - pObject2Device->Transform(x1, y1); - pObject2Device->Transform(x2, y2); - } - buf << FX_BSTRC(" ") << x1 << FX_BSTRC(" ") << y1 << FX_BSTRC(" ") << x2 << FX_BSTRC(" ") << y2; - if (flag & FXPT_CLOSEFIGURE) { - buf << FX_BSTRC(" c h\n"); - } else { - buf << FX_BSTRC(" c\n"); - } - i += 2; - break; - } + buf << FX_BSTRC(" ") << x1 << FX_BSTRC(" ") << y1 << FX_BSTRC(" ") << x2 + << FX_BSTRC(" ") << y2; + if (flag & FXPT_CLOSEFIGURE) { + buf << FX_BSTRC(" c h\n"); + } else { + buf << FX_BSTRC(" c\n"); } + i += 2; + break; + } } - m_pOutput->OutputPS((const FX_CHAR*)buf.GetBuffer(), buf.GetSize()); + } + m_pOutput->OutputPS((const FX_CHAR*)buf.GetBuffer(), buf.GetSize()); } void CFX_PSRenderer::SetClip_PathFill(const CFX_PathData* pPathData, const CFX_AffineMatrix* pObject2Device, - int fill_mode - ) -{ - StartRendering(); - OutputPath(pPathData, pObject2Device); - CFX_FloatRect rect = pPathData->GetBoundingBox(); - if (pObject2Device) { - rect.Transform(pObject2Device); - } - m_ClipBox.Intersect(rect.GetOutterRect()); - if ((fill_mode & 3) == FXFILL_WINDING) { - OUTPUT_PS("W n\n"); - } else { - OUTPUT_PS("W* n\n"); - } + int fill_mode) { + StartRendering(); + OutputPath(pPathData, pObject2Device); + CFX_FloatRect rect = pPathData->GetBoundingBox(); + if (pObject2Device) { + rect.Transform(pObject2Device); + } + m_ClipBox.Intersect(rect.GetOutterRect()); + if ((fill_mode & 3) == FXFILL_WINDING) { + OUTPUT_PS("W n\n"); + } else { + OUTPUT_PS("W* n\n"); + } } void CFX_PSRenderer::SetClip_PathStroke(const CFX_PathData* pPathData, const CFX_AffineMatrix* pObject2Device, - const CFX_GraphStateData* pGraphState - ) -{ - StartRendering(); - SetGraphState(pGraphState); - if (pObject2Device) { - CFX_ByteTextBuf buf; - buf << FX_BSTRC("mx Cm [") << pObject2Device->a << FX_BSTRC(" ") << pObject2Device->b << FX_BSTRC(" ") << - pObject2Device->c << FX_BSTRC(" ") << pObject2Device->d << FX_BSTRC(" ") << pObject2Device->e << - FX_BSTRC(" ") << pObject2Device->f << FX_BSTRC("]cm "); - m_pOutput->OutputPS((const FX_CHAR*)buf.GetBuffer(), buf.GetSize()); - } - OutputPath(pPathData, NULL); - CFX_FloatRect rect = pPathData->GetBoundingBox(pGraphState->m_LineWidth, pGraphState->m_MiterLimit); - rect.Transform(pObject2Device); - m_ClipBox.Intersect(rect.GetOutterRect()); - if (pObject2Device) { - OUTPUT_PS("strokepath W n sm\n"); - } else { - OUTPUT_PS("strokepath W n\n"); - } + const CFX_GraphStateData* pGraphState) { + StartRendering(); + SetGraphState(pGraphState); + if (pObject2Device) { + CFX_ByteTextBuf buf; + buf << FX_BSTRC("mx Cm [") << pObject2Device->a << FX_BSTRC(" ") + << pObject2Device->b << FX_BSTRC(" ") << pObject2Device->c + << FX_BSTRC(" ") << pObject2Device->d << FX_BSTRC(" ") + << pObject2Device->e << FX_BSTRC(" ") << pObject2Device->f + << FX_BSTRC("]cm "); + m_pOutput->OutputPS((const FX_CHAR*)buf.GetBuffer(), buf.GetSize()); + } + OutputPath(pPathData, NULL); + CFX_FloatRect rect = pPathData->GetBoundingBox(pGraphState->m_LineWidth, + pGraphState->m_MiterLimit); + rect.Transform(pObject2Device); + m_ClipBox.Intersect(rect.GetOutterRect()); + if (pObject2Device) { + OUTPUT_PS("strokepath W n sm\n"); + } else { + OUTPUT_PS("strokepath W n\n"); + } } FX_BOOL CFX_PSRenderer::DrawPath(const CFX_PathData* pPathData, const CFX_AffineMatrix* pObject2Device, @@ -182,463 +183,536 @@ FX_BOOL CFX_PSRenderer::DrawPath(const CFX_PathData* pPathData, FX_DWORD stroke_color, int fill_mode, int alpha_flag, - void* pIccTransform - ) -{ - StartRendering(); - int fill_alpha = FXGETFLAG_COLORTYPE(alpha_flag) ? FXGETFLAG_ALPHA_FILL(alpha_flag) : FXARGB_A(fill_color); - int stroke_alpha = FXGETFLAG_COLORTYPE(alpha_flag) ? FXGETFLAG_ALPHA_STROKE(alpha_flag) : FXARGB_A(stroke_color); - if (fill_alpha && fill_alpha < 255) { - return FALSE; - } - if (stroke_alpha && stroke_alpha < 255) { - return FALSE; - } - if (fill_alpha == 0 && stroke_alpha == 0) { - return FALSE; - } - if (stroke_alpha) { - SetGraphState(pGraphState); - if (pObject2Device) { - CFX_ByteTextBuf buf; - buf << FX_BSTRC("mx Cm [") << pObject2Device->a << FX_BSTRC(" ") << pObject2Device->b << FX_BSTRC(" ") << - pObject2Device->c << FX_BSTRC(" ") << pObject2Device->d << FX_BSTRC(" ") << pObject2Device->e << - FX_BSTRC(" ") << pObject2Device->f << FX_BSTRC("]cm "); - m_pOutput->OutputPS((const FX_CHAR*)buf.GetBuffer(), buf.GetSize()); - } - } - OutputPath(pPathData, stroke_alpha ? NULL : pObject2Device); - if (fill_mode && fill_alpha) { - SetColor(fill_color, alpha_flag, pIccTransform); - if ((fill_mode & 3) == FXFILL_WINDING) { - if (stroke_alpha) { - OUTPUT_PS("q f Q "); - } else { - OUTPUT_PS("f"); - } - } else if ((fill_mode & 3) == FXFILL_ALTERNATE) { - if (stroke_alpha) { - OUTPUT_PS("q F Q "); - } else { - OUTPUT_PS("F"); - } - } - } - if (stroke_alpha) { - SetColor(stroke_color, alpha_flag, pIccTransform); - if (pObject2Device) { - OUTPUT_PS("s sm"); - } else { - OUTPUT_PS("s"); - } + void* pIccTransform) { + StartRendering(); + int fill_alpha = FXGETFLAG_COLORTYPE(alpha_flag) + ? FXGETFLAG_ALPHA_FILL(alpha_flag) + : FXARGB_A(fill_color); + int stroke_alpha = FXGETFLAG_COLORTYPE(alpha_flag) + ? FXGETFLAG_ALPHA_STROKE(alpha_flag) + : FXARGB_A(stroke_color); + if (fill_alpha && fill_alpha < 255) { + return FALSE; + } + if (stroke_alpha && stroke_alpha < 255) { + return FALSE; + } + if (fill_alpha == 0 && stroke_alpha == 0) { + return FALSE; + } + if (stroke_alpha) { + SetGraphState(pGraphState); + if (pObject2Device) { + CFX_ByteTextBuf buf; + buf << FX_BSTRC("mx Cm [") << pObject2Device->a << FX_BSTRC(" ") + << pObject2Device->b << FX_BSTRC(" ") << pObject2Device->c + << FX_BSTRC(" ") << pObject2Device->d << FX_BSTRC(" ") + << pObject2Device->e << FX_BSTRC(" ") << pObject2Device->f + << FX_BSTRC("]cm "); + m_pOutput->OutputPS((const FX_CHAR*)buf.GetBuffer(), buf.GetSize()); + } + } + OutputPath(pPathData, stroke_alpha ? NULL : pObject2Device); + if (fill_mode && fill_alpha) { + SetColor(fill_color, alpha_flag, pIccTransform); + if ((fill_mode & 3) == FXFILL_WINDING) { + if (stroke_alpha) { + OUTPUT_PS("q f Q "); + } else { + OUTPUT_PS("f"); + } + } else if ((fill_mode & 3) == FXFILL_ALTERNATE) { + if (stroke_alpha) { + OUTPUT_PS("q F Q "); + } else { + OUTPUT_PS("F"); + } + } + } + if (stroke_alpha) { + SetColor(stroke_color, alpha_flag, pIccTransform); + if (pObject2Device) { + OUTPUT_PS("s sm"); + } else { + OUTPUT_PS("s"); } - OUTPUT_PS("\n"); - return TRUE; + } + OUTPUT_PS("\n"); + return TRUE; } -void CFX_PSRenderer::SetGraphState(const CFX_GraphStateData* pGraphState) -{ - CFX_ByteTextBuf buf; - if (!m_bGraphStateSet || m_CurGraphState.m_LineCap != pGraphState->m_LineCap) { - buf << pGraphState->m_LineCap << FX_BSTRC(" J\n"); - } - if (!m_bGraphStateSet || m_CurGraphState.m_DashCount != pGraphState->m_DashCount || - FXSYS_memcmp(m_CurGraphState.m_DashArray, pGraphState->m_DashArray, sizeof(FX_FLOAT)*m_CurGraphState.m_DashCount)) { - buf << FX_BSTRC("["); - for (int i = 0; i < pGraphState->m_DashCount; i ++) { - buf << pGraphState->m_DashArray[i] << FX_BSTRC(" "); - } - buf << FX_BSTRC("]") << pGraphState->m_DashPhase << FX_BSTRC(" d\n"); - } - if (!m_bGraphStateSet || m_CurGraphState.m_LineJoin != pGraphState->m_LineJoin) { - buf << pGraphState->m_LineJoin << FX_BSTRC(" j\n"); - } - if (!m_bGraphStateSet || m_CurGraphState.m_LineWidth != pGraphState->m_LineWidth) { - buf << pGraphState->m_LineWidth << FX_BSTRC(" w\n"); - } - if (!m_bGraphStateSet || m_CurGraphState.m_MiterLimit != pGraphState->m_MiterLimit) { - buf << pGraphState->m_MiterLimit << FX_BSTRC(" M\n"); - } - m_CurGraphState.Copy(*pGraphState); - m_bGraphStateSet = TRUE; - if (buf.GetSize()) { - m_pOutput->OutputPS((const FX_CHAR*)buf.GetBuffer(), buf.GetSize()); - } +void CFX_PSRenderer::SetGraphState(const CFX_GraphStateData* pGraphState) { + CFX_ByteTextBuf buf; + if (!m_bGraphStateSet || + m_CurGraphState.m_LineCap != pGraphState->m_LineCap) { + buf << pGraphState->m_LineCap << FX_BSTRC(" J\n"); + } + if (!m_bGraphStateSet || + m_CurGraphState.m_DashCount != pGraphState->m_DashCount || + FXSYS_memcmp(m_CurGraphState.m_DashArray, pGraphState->m_DashArray, + sizeof(FX_FLOAT) * m_CurGraphState.m_DashCount)) { + buf << FX_BSTRC("["); + for (int i = 0; i < pGraphState->m_DashCount; i++) { + buf << pGraphState->m_DashArray[i] << FX_BSTRC(" "); + } + buf << FX_BSTRC("]") << pGraphState->m_DashPhase << FX_BSTRC(" d\n"); + } + if (!m_bGraphStateSet || + m_CurGraphState.m_LineJoin != pGraphState->m_LineJoin) { + buf << pGraphState->m_LineJoin << FX_BSTRC(" j\n"); + } + if (!m_bGraphStateSet || + m_CurGraphState.m_LineWidth != pGraphState->m_LineWidth) { + buf << pGraphState->m_LineWidth << FX_BSTRC(" w\n"); + } + if (!m_bGraphStateSet || + m_CurGraphState.m_MiterLimit != pGraphState->m_MiterLimit) { + buf << pGraphState->m_MiterLimit << FX_BSTRC(" M\n"); + } + m_CurGraphState.Copy(*pGraphState); + m_bGraphStateSet = TRUE; + if (buf.GetSize()) { + m_pOutput->OutputPS((const FX_CHAR*)buf.GetBuffer(), buf.GetSize()); + } } -static void FaxCompressData(uint8_t* src_buf, int width, int height, uint8_t*& dest_buf, FX_DWORD& dest_size) -{ - CCodec_ModuleMgr* pEncoders = CFX_GEModule::Get()->GetCodecModule(); - if (width * height > 128 && pEncoders && pEncoders->GetFaxModule()->Encode(src_buf, width, height, (width + 7) / 8, dest_buf, dest_size)) { - FX_Free(src_buf); - } else { - dest_buf = src_buf; - dest_size = (width + 7) / 8 * height; - } +static void FaxCompressData(uint8_t* src_buf, + int width, + int height, + uint8_t*& dest_buf, + FX_DWORD& dest_size) { + CCodec_ModuleMgr* pEncoders = CFX_GEModule::Get()->GetCodecModule(); + if (width * height > 128 && pEncoders && + pEncoders->GetFaxModule()->Encode(src_buf, width, height, (width + 7) / 8, + dest_buf, dest_size)) { + FX_Free(src_buf); + } else { + dest_buf = src_buf; + dest_size = (width + 7) / 8 * height; + } } -static void PSCompressData(int PSLevel, uint8_t* src_buf, FX_DWORD src_size, - uint8_t*& output_buf, FX_DWORD& output_size, const FX_CHAR*& filter) -{ - output_buf = src_buf; - output_size = src_size; - filter = ""; - if (src_size < 1024) { - return; - } - CCodec_ModuleMgr* pEncoders = CFX_GEModule::Get()->GetCodecModule(); - uint8_t* dest_buf = NULL; - FX_DWORD dest_size = src_size; - if (PSLevel >= 3) { - if (pEncoders && pEncoders->GetFlateModule()->Encode(src_buf, src_size, dest_buf, dest_size)) { - filter = "/FlateDecode filter "; - } - } else { - if (pEncoders && pEncoders->GetBasicModule()->RunLengthEncode(src_buf, src_size, dest_buf, dest_size)) { - filter = "/RunLengthDecode filter "; - } - } - if (dest_size < src_size) { - output_buf = dest_buf; - output_size = dest_size; - } else { - filter = NULL; - if (dest_buf) { - FX_Free(dest_buf); - } - } +static void PSCompressData(int PSLevel, + uint8_t* src_buf, + FX_DWORD src_size, + uint8_t*& output_buf, + FX_DWORD& output_size, + const FX_CHAR*& filter) { + output_buf = src_buf; + output_size = src_size; + filter = ""; + if (src_size < 1024) { + return; + } + CCodec_ModuleMgr* pEncoders = CFX_GEModule::Get()->GetCodecModule(); + uint8_t* dest_buf = NULL; + FX_DWORD dest_size = src_size; + if (PSLevel >= 3) { + if (pEncoders && + pEncoders->GetFlateModule()->Encode(src_buf, src_size, dest_buf, + dest_size)) { + filter = "/FlateDecode filter "; + } + } else { + if (pEncoders && + pEncoders->GetBasicModule()->RunLengthEncode(src_buf, src_size, + dest_buf, dest_size)) { + filter = "/RunLengthDecode filter "; + } + } + if (dest_size < src_size) { + output_buf = dest_buf; + output_size = dest_size; + } else { + filter = NULL; + if (dest_buf) { + FX_Free(dest_buf); + } + } } -FX_BOOL CFX_PSRenderer::SetDIBits(const CFX_DIBSource* pSource, FX_DWORD color, int left, int top, - int alpha_flag, void* pIccTransform) -{ - StartRendering(); - CFX_AffineMatrix matrix((FX_FLOAT)(pSource->GetWidth()), 0.0f, 0.0f, -(FX_FLOAT)(pSource->GetHeight()), - (FX_FLOAT)(left), (FX_FLOAT)(top + pSource->GetHeight())); - return DrawDIBits(pSource, color, &matrix, 0, alpha_flag, pIccTransform); +FX_BOOL CFX_PSRenderer::SetDIBits(const CFX_DIBSource* pSource, + FX_DWORD color, + int left, + int top, + int alpha_flag, + void* pIccTransform) { + StartRendering(); + CFX_AffineMatrix matrix((FX_FLOAT)(pSource->GetWidth()), 0.0f, 0.0f, + -(FX_FLOAT)(pSource->GetHeight()), (FX_FLOAT)(left), + (FX_FLOAT)(top + pSource->GetHeight())); + return DrawDIBits(pSource, color, &matrix, 0, alpha_flag, pIccTransform); } -FX_BOOL CFX_PSRenderer::StretchDIBits(const CFX_DIBSource* pSource, FX_DWORD color, int dest_left, int dest_top, - int dest_width, int dest_height, FX_DWORD flags, - int alpha_flag, void* pIccTransform) -{ - StartRendering(); - CFX_AffineMatrix matrix((FX_FLOAT)(dest_width), 0.0f, 0.0f, (FX_FLOAT)(-dest_height), - (FX_FLOAT)(dest_left), (FX_FLOAT)(dest_top + dest_height)); - return DrawDIBits(pSource, color, &matrix, flags, alpha_flag, pIccTransform); +FX_BOOL CFX_PSRenderer::StretchDIBits(const CFX_DIBSource* pSource, + FX_DWORD color, + int dest_left, + int dest_top, + int dest_width, + int dest_height, + FX_DWORD flags, + int alpha_flag, + void* pIccTransform) { + StartRendering(); + CFX_AffineMatrix matrix((FX_FLOAT)(dest_width), 0.0f, 0.0f, + (FX_FLOAT)(-dest_height), (FX_FLOAT)(dest_left), + (FX_FLOAT)(dest_top + dest_height)); + return DrawDIBits(pSource, color, &matrix, flags, alpha_flag, pIccTransform); } -FX_BOOL CFX_PSRenderer::DrawDIBits(const CFX_DIBSource* pSource, FX_DWORD color, - const CFX_AffineMatrix* pMatrix, FX_DWORD flags, - int alpha_flag, void* pIccTransform) -{ - StartRendering(); - if ((pMatrix->a == 0 && pMatrix->b == 0) || (pMatrix->c == 0 && pMatrix->d == 0)) { - return TRUE; - } - if (pSource->HasAlpha()) { - return FALSE; - } - int alpha = FXGETFLAG_COLORTYPE(alpha_flag) ? FXGETFLAG_ALPHA_FILL(color) : FXARGB_A(color); - if (pSource->IsAlphaMask() && (alpha < 255 || pSource->GetBPP() != 1)) { - return FALSE; - } - OUTPUT_PS("q\n"); - CFX_ByteTextBuf buf; - buf << FX_BSTRC("[") << pMatrix->a << FX_BSTRC(" ") << pMatrix->b << FX_BSTRC(" ") << - pMatrix->c << FX_BSTRC(" ") << pMatrix->d << FX_BSTRC(" ") << pMatrix->e << - FX_BSTRC(" ") << pMatrix->f << FX_BSTRC("]cm "); - int width = pSource->GetWidth(); - int height = pSource->GetHeight(); - buf << width << FX_BSTRC(" ") << height; - if (pSource->GetBPP() == 1 && pSource->GetPalette() == NULL) { - int pitch = (width + 7) / 8; - FX_DWORD src_size = height * pitch; - uint8_t* src_buf = FX_Alloc(uint8_t, src_size); - for (int row = 0; row < height; row ++) { - const uint8_t* src_scan = pSource->GetScanline(row); - FXSYS_memcpy(src_buf + row * pitch, src_scan, pitch); - } - uint8_t* output_buf; - FX_DWORD output_size; - FaxCompressData(src_buf, width, height, output_buf, output_size); - if (pSource->IsAlphaMask()) { - SetColor(color, alpha_flag, pIccTransform); - m_bColorSet = FALSE; - buf << FX_BSTRC(" true["); - } else { - buf << FX_BSTRC(" 1["); - } - buf << width << FX_BSTRC(" 0 0 -") << height << FX_BSTRC(" 0 ") << height << - FX_BSTRC("]currentfile/ASCII85Decode filter "); - if (output_buf != src_buf) - buf << FX_BSTRC("<</K -1/EndOfBlock false/Columns ") << width << FX_BSTRC("/Rows ") << height << - FX_BSTRC(">>/CCITTFaxDecode filter "); - if (pSource->IsAlphaMask()) { - buf << FX_BSTRC("iM\n"); - } else { - buf << FX_BSTRC("false 1 colorimage\n"); - } - m_pOutput->OutputPS((const FX_CHAR*)buf.GetBuffer(), buf.GetSize()); - WritePSBinary(output_buf, output_size); - FX_Free(output_buf); - } else { - CFX_DIBSource* pConverted = (CFX_DIBSource*)pSource; - if (pIccTransform) { - FXDIB_Format format = m_bCmykOutput ? FXDIB_Cmyk : FXDIB_Rgb; - pConverted = pSource->CloneConvert(format, NULL, pIccTransform); - } else { - switch (pSource->GetFormat()) { - case FXDIB_1bppRgb: - case FXDIB_Rgb32: - pConverted = pSource->CloneConvert(FXDIB_Rgb); - break; - case FXDIB_8bppRgb: - if (pSource->GetPalette() != NULL) { - pConverted = pSource->CloneConvert(FXDIB_Rgb); - } - break; - case FXDIB_1bppCmyk: - pConverted = pSource->CloneConvert(FXDIB_Cmyk); - break; - case FXDIB_8bppCmyk: - if (pSource->GetPalette() != NULL) { - pConverted = pSource->CloneConvert(FXDIB_Cmyk); - } - break; - default: - break; - } - } - if (pConverted == NULL) { - OUTPUT_PS("\nQ\n"); - return FALSE; - } - int Bpp = pConverted->GetBPP() / 8; - uint8_t* output_buf = NULL; - FX_STRSIZE output_size = 0; - const FX_CHAR* filter = NULL; - if (flags & FXRENDER_IMAGE_LOSSY) { - CCodec_ModuleMgr* pEncoders = CFX_GEModule::Get()->GetCodecModule(); - if (pEncoders && pEncoders->GetJpegModule()->Encode(pConverted, output_buf, output_size)) { - filter = "/DCTDecode filter "; - } - } - if (filter == NULL) { - int src_pitch = width * Bpp; - output_size = height * src_pitch; - output_buf = FX_Alloc(uint8_t, output_size); - for (int row = 0; row < height; row ++) { - const uint8_t* src_scan = pConverted->GetScanline(row); - uint8_t* dest_scan = output_buf + row * src_pitch; - if (Bpp == 3) { - for (int col = 0; col < width; col ++) { - *dest_scan++ = src_scan[2]; - *dest_scan++ = src_scan[1]; - *dest_scan++ = *src_scan; - src_scan += 3; - } - } else { - FXSYS_memcpy(dest_scan, src_scan, src_pitch); - } - } - uint8_t* compressed_buf; - FX_DWORD compressed_size; - PSCompressData(m_PSLevel, output_buf, output_size, compressed_buf, compressed_size, filter); - if (output_buf != compressed_buf) { - FX_Free(output_buf); - } - output_buf = compressed_buf; - output_size = compressed_size; - } - if (pConverted != pSource) { - delete pConverted; - pConverted = NULL; - } - buf << FX_BSTRC(" 8["); - buf << width << FX_BSTRC(" 0 0 -") << height << FX_BSTRC(" 0 ") << height << FX_BSTRC("]"); - buf << FX_BSTRC("currentfile/ASCII85Decode filter "); - if (filter) { - buf << filter; - } - buf << FX_BSTRC("false ") << Bpp; - buf << FX_BSTRC(" colorimage\n"); - m_pOutput->OutputPS((const FX_CHAR*)buf.GetBuffer(), buf.GetSize()); - WritePSBinary(output_buf, output_size); - FX_Free(output_buf); - } - OUTPUT_PS("\nQ\n"); +FX_BOOL CFX_PSRenderer::DrawDIBits(const CFX_DIBSource* pSource, + FX_DWORD color, + const CFX_AffineMatrix* pMatrix, + FX_DWORD flags, + int alpha_flag, + void* pIccTransform) { + StartRendering(); + if ((pMatrix->a == 0 && pMatrix->b == 0) || + (pMatrix->c == 0 && pMatrix->d == 0)) { return TRUE; -} -void CFX_PSRenderer::SetColor(FX_DWORD color, int alpha_flag, void* pIccTransform) -{ - if (!CFX_GEModule::Get()->GetCodecModule() || !CFX_GEModule::Get()->GetCodecModule()->GetIccModule()) { - pIccTransform = NULL; + } + if (pSource->HasAlpha()) { + return FALSE; + } + int alpha = FXGETFLAG_COLORTYPE(alpha_flag) ? FXGETFLAG_ALPHA_FILL(color) + : FXARGB_A(color); + if (pSource->IsAlphaMask() && (alpha < 255 || pSource->GetBPP() != 1)) { + return FALSE; + } + OUTPUT_PS("q\n"); + CFX_ByteTextBuf buf; + buf << FX_BSTRC("[") << pMatrix->a << FX_BSTRC(" ") << pMatrix->b + << FX_BSTRC(" ") << pMatrix->c << FX_BSTRC(" ") << pMatrix->d + << FX_BSTRC(" ") << pMatrix->e << FX_BSTRC(" ") << pMatrix->f + << FX_BSTRC("]cm "); + int width = pSource->GetWidth(); + int height = pSource->GetHeight(); + buf << width << FX_BSTRC(" ") << height; + if (pSource->GetBPP() == 1 && pSource->GetPalette() == NULL) { + int pitch = (width + 7) / 8; + FX_DWORD src_size = height * pitch; + uint8_t* src_buf = FX_Alloc(uint8_t, src_size); + for (int row = 0; row < height; row++) { + const uint8_t* src_scan = pSource->GetScanline(row); + FXSYS_memcpy(src_buf + row * pitch, src_scan, pitch); + } + uint8_t* output_buf; + FX_DWORD output_size; + FaxCompressData(src_buf, width, height, output_buf, output_size); + if (pSource->IsAlphaMask()) { + SetColor(color, alpha_flag, pIccTransform); + m_bColorSet = FALSE; + buf << FX_BSTRC(" true["); + } else { + buf << FX_BSTRC(" 1["); + } + buf << width << FX_BSTRC(" 0 0 -") << height << FX_BSTRC(" 0 ") << height + << FX_BSTRC("]currentfile/ASCII85Decode filter "); + if (output_buf != src_buf) + buf << FX_BSTRC("<</K -1/EndOfBlock false/Columns ") << width + << FX_BSTRC("/Rows ") << height + << FX_BSTRC(">>/CCITTFaxDecode filter "); + if (pSource->IsAlphaMask()) { + buf << FX_BSTRC("iM\n"); + } else { + buf << FX_BSTRC("false 1 colorimage\n"); } - FX_BOOL bCMYK = FALSE; + m_pOutput->OutputPS((const FX_CHAR*)buf.GetBuffer(), buf.GetSize()); + WritePSBinary(output_buf, output_size); + FX_Free(output_buf); + } else { + CFX_DIBSource* pConverted = (CFX_DIBSource*)pSource; if (pIccTransform) { - ICodec_IccModule* pIccModule = CFX_GEModule::Get()->GetCodecModule()->GetIccModule(); - color = FXGETFLAG_COLORTYPE(alpha_flag) ? FXCMYK_TODIB(color) : FXARGB_TODIB(color); - uint8_t* pColor = (uint8_t*)&color; - pIccModule->TranslateScanline(pIccTransform, pColor, pColor, 1); - color = m_bCmykOutput ? FXCMYK_TODIB(color) : FXARGB_TODIB(color); - bCMYK = m_bCmykOutput; + FXDIB_Format format = m_bCmykOutput ? FXDIB_Cmyk : FXDIB_Rgb; + pConverted = pSource->CloneConvert(format, NULL, pIccTransform); } else { - bCMYK = FXGETFLAG_COLORTYPE(alpha_flag); - } - if (bCMYK != m_bCmykOutput || !m_bColorSet || m_LastColor != color) { - CFX_ByteTextBuf buf; - if (bCMYK) { - buf << FXSYS_GetCValue(color) / 255.0 << FX_BSTRC(" ") << FXSYS_GetMValue(color) / 255.0 << FX_BSTRC(" ") - << FXSYS_GetYValue(color) / 255.0 << FX_BSTRC(" ") << FXSYS_GetKValue(color) / 255.0 << FX_BSTRC(" k\n"); + switch (pSource->GetFormat()) { + case FXDIB_1bppRgb: + case FXDIB_Rgb32: + pConverted = pSource->CloneConvert(FXDIB_Rgb); + break; + case FXDIB_8bppRgb: + if (pSource->GetPalette() != NULL) { + pConverted = pSource->CloneConvert(FXDIB_Rgb); + } + break; + case FXDIB_1bppCmyk: + pConverted = pSource->CloneConvert(FXDIB_Cmyk); + break; + case FXDIB_8bppCmyk: + if (pSource->GetPalette() != NULL) { + pConverted = pSource->CloneConvert(FXDIB_Cmyk); + } + break; + default: + break; + } + } + if (pConverted == NULL) { + OUTPUT_PS("\nQ\n"); + return FALSE; + } + int Bpp = pConverted->GetBPP() / 8; + uint8_t* output_buf = NULL; + FX_STRSIZE output_size = 0; + const FX_CHAR* filter = NULL; + if (flags & FXRENDER_IMAGE_LOSSY) { + CCodec_ModuleMgr* pEncoders = CFX_GEModule::Get()->GetCodecModule(); + if (pEncoders && + pEncoders->GetJpegModule()->Encode(pConverted, output_buf, + output_size)) { + filter = "/DCTDecode filter "; + } + } + if (filter == NULL) { + int src_pitch = width * Bpp; + output_size = height * src_pitch; + output_buf = FX_Alloc(uint8_t, output_size); + for (int row = 0; row < height; row++) { + const uint8_t* src_scan = pConverted->GetScanline(row); + uint8_t* dest_scan = output_buf + row * src_pitch; + if (Bpp == 3) { + for (int col = 0; col < width; col++) { + *dest_scan++ = src_scan[2]; + *dest_scan++ = src_scan[1]; + *dest_scan++ = *src_scan; + src_scan += 3; + } } else { - buf << FXARGB_R(color) / 255.0 << FX_BSTRC(" ") << FXARGB_G(color) / 255.0 << FX_BSTRC(" ") - << FXARGB_B(color) / 255.0 << FX_BSTRC(" rg\n"); + FXSYS_memcpy(dest_scan, src_scan, src_pitch); } - if (bCMYK == m_bCmykOutput) { - m_bColorSet = TRUE; - m_LastColor = color; - } - m_pOutput->OutputPS((const FX_CHAR*)buf.GetBuffer(), buf.GetSize()); - } + } + uint8_t* compressed_buf; + FX_DWORD compressed_size; + PSCompressData(m_PSLevel, output_buf, output_size, compressed_buf, + compressed_size, filter); + if (output_buf != compressed_buf) { + FX_Free(output_buf); + } + output_buf = compressed_buf; + output_size = compressed_size; + } + if (pConverted != pSource) { + delete pConverted; + pConverted = NULL; + } + buf << FX_BSTRC(" 8["); + buf << width << FX_BSTRC(" 0 0 -") << height << FX_BSTRC(" 0 ") << height + << FX_BSTRC("]"); + buf << FX_BSTRC("currentfile/ASCII85Decode filter "); + if (filter) { + buf << filter; + } + buf << FX_BSTRC("false ") << Bpp; + buf << FX_BSTRC(" colorimage\n"); + m_pOutput->OutputPS((const FX_CHAR*)buf.GetBuffer(), buf.GetSize()); + WritePSBinary(output_buf, output_size); + FX_Free(output_buf); + } + OUTPUT_PS("\nQ\n"); + return TRUE; } -void CFX_PSRenderer::FindPSFontGlyph(CFX_FaceCache* pFaceCache, CFX_Font* pFont, const FXTEXT_CHARPOS& charpos, - int& ps_fontnum, int &ps_glyphindex) -{ - for (int i = 0; i < (int)m_PSFontList.GetSize(); i ++) { - CPSFont* pPSFont = m_PSFontList[i]; - for (int j = 0; j < pPSFont->m_nGlyphs; j ++) - if (pPSFont->m_Glyphs[j].m_pFont == pFont && pPSFont->m_Glyphs[j].m_GlyphIndex == charpos.m_GlyphIndex) { - if ((!pPSFont->m_Glyphs[j].m_bGlyphAdjust && !charpos.m_bGlyphAdjust) || - (pPSFont->m_Glyphs[j].m_bGlyphAdjust && charpos.m_bGlyphAdjust && - (FXSYS_fabs(pPSFont->m_Glyphs[j].m_AdjustMatrix[0] - charpos.m_AdjustMatrix[0]) < 0.01 && - FXSYS_fabs(pPSFont->m_Glyphs[j].m_AdjustMatrix[1] - charpos.m_AdjustMatrix[1]) < 0.01 && - FXSYS_fabs(pPSFont->m_Glyphs[j].m_AdjustMatrix[2] - charpos.m_AdjustMatrix[2]) < 0.01 && - FXSYS_fabs(pPSFont->m_Glyphs[j].m_AdjustMatrix[3] - charpos.m_AdjustMatrix[3]) < 0.01))) { - ps_fontnum = i; - ps_glyphindex = j; - return; - } - } - } - if (m_PSFontList.GetSize() == 0 || m_PSFontList[m_PSFontList.GetSize() - 1]->m_nGlyphs == 256) { - CPSFont* pPSFont = new CPSFont; - pPSFont->m_nGlyphs = 0; - m_PSFontList.Add(pPSFont); - CFX_ByteTextBuf buf; - buf << FX_BSTRC("8 dict begin/FontType 3 def/FontMatrix[1 0 0 1 0 0]def\n" - "/FontBBox[0 0 0 0]def/Encoding 256 array def 0 1 255{Encoding exch/.notdef put}for\n" - "/CharProcs 1 dict def CharProcs begin/.notdef {} def end\n" - "/BuildGlyph{1 0 -10 -10 10 10 setcachedevice exch/CharProcs get exch 2 copy known not{pop/.notdef}if get exec}bind def\n" - "/BuildChar{1 index/Encoding get exch get 1 index/BuildGlyph get exec}bind def\n" - "currentdict end\n"); - buf << FX_BSTRC("/X") << m_PSFontList.GetSize() - 1 << FX_BSTRC(" exch definefont pop\n"); - m_pOutput->OutputPS((const FX_CHAR*)buf.GetBuffer(), buf.GetSize()); - buf.Clear(); - } - ps_fontnum = m_PSFontList.GetSize() - 1; - CPSFont* pPSFont = m_PSFontList[ps_fontnum]; - ps_glyphindex = pPSFont->m_nGlyphs; - pPSFont->m_Glyphs[ps_glyphindex].m_GlyphIndex = charpos.m_GlyphIndex; - pPSFont->m_Glyphs[ps_glyphindex].m_pFont = pFont; - pPSFont->m_Glyphs[ps_glyphindex].m_bGlyphAdjust = charpos.m_bGlyphAdjust; - if (charpos.m_bGlyphAdjust) { - pPSFont->m_Glyphs[ps_glyphindex].m_AdjustMatrix[0] = charpos.m_AdjustMatrix[0]; - pPSFont->m_Glyphs[ps_glyphindex].m_AdjustMatrix[1] = charpos.m_AdjustMatrix[1]; - pPSFont->m_Glyphs[ps_glyphindex].m_AdjustMatrix[2] = charpos.m_AdjustMatrix[2]; - pPSFont->m_Glyphs[ps_glyphindex].m_AdjustMatrix[3] = charpos.m_AdjustMatrix[3]; - } - pPSFont->m_nGlyphs ++; - CFX_AffineMatrix matrix; - if (charpos.m_bGlyphAdjust) - matrix.Set(charpos.m_AdjustMatrix[0], charpos.m_AdjustMatrix[1], - charpos.m_AdjustMatrix[2], charpos.m_AdjustMatrix[3], 0, 0); - matrix.Concat(1.0f, 0, 0, 1.0f, 0, 0); - const CFX_PathData* pPathData = pFaceCache->LoadGlyphPath(pFont, charpos.m_GlyphIndex, charpos.m_FontCharWidth); - if (pPathData == NULL) { - return; - } - CFX_PathData TransformedPath(*pPathData); - if (charpos.m_bGlyphAdjust) { - TransformedPath.Transform(&matrix); - } +void CFX_PSRenderer::SetColor(FX_DWORD color, + int alpha_flag, + void* pIccTransform) { + if (!CFX_GEModule::Get()->GetCodecModule() || + !CFX_GEModule::Get()->GetCodecModule()->GetIccModule()) { + pIccTransform = NULL; + } + FX_BOOL bCMYK = FALSE; + if (pIccTransform) { + ICodec_IccModule* pIccModule = + CFX_GEModule::Get()->GetCodecModule()->GetIccModule(); + color = FXGETFLAG_COLORTYPE(alpha_flag) ? FXCMYK_TODIB(color) + : FXARGB_TODIB(color); + uint8_t* pColor = (uint8_t*)&color; + pIccModule->TranslateScanline(pIccTransform, pColor, pColor, 1); + color = m_bCmykOutput ? FXCMYK_TODIB(color) : FXARGB_TODIB(color); + bCMYK = m_bCmykOutput; + } else { + bCMYK = FXGETFLAG_COLORTYPE(alpha_flag); + } + if (bCMYK != m_bCmykOutput || !m_bColorSet || m_LastColor != color) { CFX_ByteTextBuf buf; - buf << FX_BSTRC("/X") << ps_fontnum << FX_BSTRC(" Ff/CharProcs get begin/") - << ps_glyphindex << FX_BSTRC("{"); - buf << FX_BSTRC("n "); - for (int p = 0; p < TransformedPath.GetPointCount(); p ++) { - FX_FLOAT x = TransformedPath.GetPointX(p), y = TransformedPath.GetPointY(p); - switch (TransformedPath.GetFlag(p) & FXPT_TYPE) { - case FXPT_MOVETO: { - buf << x << FX_BSTRC(" ") << y << FX_BSTRC(" m\n"); - break; - } - case FXPT_LINETO: { - buf << x << FX_BSTRC(" ") << y << FX_BSTRC(" l\n"); - break; - } - case FXPT_BEZIERTO: { - buf << x << FX_BSTRC(" ") << y << FX_BSTRC(" ") - << TransformedPath.GetPointX(p + 1) << FX_BSTRC(" ") - << TransformedPath.GetPointY(p + 1) << FX_BSTRC(" ") - << TransformedPath.GetPointX(p + 2) << FX_BSTRC(" ") - << TransformedPath.GetPointY(p + 2) << FX_BSTRC(" c\n"); - p += 2; - break; - } - } + if (bCMYK) { + buf << FXSYS_GetCValue(color) / 255.0 << FX_BSTRC(" ") + << FXSYS_GetMValue(color) / 255.0 << FX_BSTRC(" ") + << FXSYS_GetYValue(color) / 255.0 << FX_BSTRC(" ") + << FXSYS_GetKValue(color) / 255.0 << FX_BSTRC(" k\n"); + } else { + buf << FXARGB_R(color) / 255.0 << FX_BSTRC(" ") << FXARGB_G(color) / 255.0 + << FX_BSTRC(" ") << FXARGB_B(color) / 255.0 << FX_BSTRC(" rg\n"); + } + if (bCMYK == m_bCmykOutput) { + m_bColorSet = TRUE; + m_LastColor = color; } - buf << FX_BSTRC("f"); - buf << FX_BSTRC("}bind def end\n"); - buf << FX_BSTRC("/X") << ps_fontnum << FX_BSTRC(" Ff/Encoding get ") << ps_glyphindex - << FX_BSTRC("/") << ps_glyphindex << FX_BSTRC(" put\n"); m_pOutput->OutputPS((const FX_CHAR*)buf.GetBuffer(), buf.GetSize()); + } } -FX_BOOL CFX_PSRenderer::DrawText(int nChars, const FXTEXT_CHARPOS* pCharPos, CFX_Font* pFont, - CFX_FontCache* pCache, const CFX_AffineMatrix* pObject2Device, - FX_FLOAT font_size, FX_DWORD color, - int alpha_flag, void* pIccTransform) -{ - StartRendering(); - int alpha = FXGETFLAG_COLORTYPE(alpha_flag) ? FXGETFLAG_ALPHA_FILL(alpha_flag) : FXARGB_A(color); - if (alpha < 255) { - return FALSE; - } - if ((pObject2Device->a == 0 && pObject2Device->b == 0) || (pObject2Device->c == 0 && pObject2Device->d == 0)) { - return TRUE; - } - SetColor(color, alpha_flag, pIccTransform); - CFX_ByteTextBuf buf; - buf << FX_BSTRC("q[") << pObject2Device->a << FX_BSTRC(" ") << pObject2Device->b << FX_BSTRC(" ") - << pObject2Device->c << FX_BSTRC(" ") << pObject2Device->d; - buf << FX_BSTRC(" ") << pObject2Device->e << FX_BSTRC(" ") << pObject2Device->f << "]cm\n"; - if (pCache == NULL) { - pCache = CFX_GEModule::Get()->GetFontCache(); - } - CFX_FaceCache* pFaceCache = pCache->GetCachedFace(pFont); - FX_FONTCACHE_DEFINE(pCache, pFont); - int last_fontnum = -1; - for (int i = 0; i < nChars; i ++) { - int ps_fontnum, ps_glyphindex; - FindPSFontGlyph(pFaceCache, pFont, pCharPos[i], ps_fontnum, ps_glyphindex); - if (last_fontnum != ps_fontnum) { - buf << FX_BSTRC("/X") << ps_fontnum << FX_BSTRC(" Ff ") << font_size - << FX_BSTRC(" Fs Sf "); - last_fontnum = ps_fontnum; +void CFX_PSRenderer::FindPSFontGlyph(CFX_FaceCache* pFaceCache, + CFX_Font* pFont, + const FXTEXT_CHARPOS& charpos, + int& ps_fontnum, + int& ps_glyphindex) { + for (int i = 0; i < (int)m_PSFontList.GetSize(); i++) { + CPSFont* pPSFont = m_PSFontList[i]; + for (int j = 0; j < pPSFont->m_nGlyphs; j++) + if (pPSFont->m_Glyphs[j].m_pFont == pFont && + pPSFont->m_Glyphs[j].m_GlyphIndex == charpos.m_GlyphIndex) { + if ((!pPSFont->m_Glyphs[j].m_bGlyphAdjust && !charpos.m_bGlyphAdjust) || + (pPSFont->m_Glyphs[j].m_bGlyphAdjust && charpos.m_bGlyphAdjust && + (FXSYS_fabs(pPSFont->m_Glyphs[j].m_AdjustMatrix[0] - + charpos.m_AdjustMatrix[0]) < 0.01 && + FXSYS_fabs(pPSFont->m_Glyphs[j].m_AdjustMatrix[1] - + charpos.m_AdjustMatrix[1]) < 0.01 && + FXSYS_fabs(pPSFont->m_Glyphs[j].m_AdjustMatrix[2] - + charpos.m_AdjustMatrix[2]) < 0.01 && + FXSYS_fabs(pPSFont->m_Glyphs[j].m_AdjustMatrix[3] - + charpos.m_AdjustMatrix[3]) < 0.01))) { + ps_fontnum = i; + ps_glyphindex = j; + return; } - buf << pCharPos[i].m_OriginX << FX_BSTRC(" ") - << pCharPos[i].m_OriginY << FX_BSTRC(" m"); - CFX_ByteString hex; - hex.Format("<%02X>", ps_glyphindex); - buf << hex << FX_BSTRC("Tj\n"); - } - buf << FX_BSTRC("Q\n"); + } + } + if (m_PSFontList.GetSize() == 0 || + m_PSFontList[m_PSFontList.GetSize() - 1]->m_nGlyphs == 256) { + CPSFont* pPSFont = new CPSFont; + pPSFont->m_nGlyphs = 0; + m_PSFontList.Add(pPSFont); + CFX_ByteTextBuf buf; + buf << FX_BSTRC( + "8 dict begin/FontType 3 def/FontMatrix[1 0 0 1 0 0]def\n" + "/FontBBox[0 0 0 0]def/Encoding 256 array def 0 1 255{Encoding " + "exch/.notdef put}for\n" + "/CharProcs 1 dict def CharProcs begin/.notdef {} def end\n" + "/BuildGlyph{1 0 -10 -10 10 10 setcachedevice exch/CharProcs get exch " + "2 copy known not{pop/.notdef}if get exec}bind def\n" + "/BuildChar{1 index/Encoding get exch get 1 index/BuildGlyph get " + "exec}bind def\n" + "currentdict end\n"); + buf << FX_BSTRC("/X") << m_PSFontList.GetSize() - 1 + << FX_BSTRC(" exch definefont pop\n"); m_pOutput->OutputPS((const FX_CHAR*)buf.GetBuffer(), buf.GetSize()); + buf.Clear(); + } + ps_fontnum = m_PSFontList.GetSize() - 1; + CPSFont* pPSFont = m_PSFontList[ps_fontnum]; + ps_glyphindex = pPSFont->m_nGlyphs; + pPSFont->m_Glyphs[ps_glyphindex].m_GlyphIndex = charpos.m_GlyphIndex; + pPSFont->m_Glyphs[ps_glyphindex].m_pFont = pFont; + pPSFont->m_Glyphs[ps_glyphindex].m_bGlyphAdjust = charpos.m_bGlyphAdjust; + if (charpos.m_bGlyphAdjust) { + pPSFont->m_Glyphs[ps_glyphindex].m_AdjustMatrix[0] = + charpos.m_AdjustMatrix[0]; + pPSFont->m_Glyphs[ps_glyphindex].m_AdjustMatrix[1] = + charpos.m_AdjustMatrix[1]; + pPSFont->m_Glyphs[ps_glyphindex].m_AdjustMatrix[2] = + charpos.m_AdjustMatrix[2]; + pPSFont->m_Glyphs[ps_glyphindex].m_AdjustMatrix[3] = + charpos.m_AdjustMatrix[3]; + } + pPSFont->m_nGlyphs++; + CFX_AffineMatrix matrix; + if (charpos.m_bGlyphAdjust) + matrix.Set(charpos.m_AdjustMatrix[0], charpos.m_AdjustMatrix[1], + charpos.m_AdjustMatrix[2], charpos.m_AdjustMatrix[3], 0, 0); + matrix.Concat(1.0f, 0, 0, 1.0f, 0, 0); + const CFX_PathData* pPathData = pFaceCache->LoadGlyphPath( + pFont, charpos.m_GlyphIndex, charpos.m_FontCharWidth); + if (pPathData == NULL) { + return; + } + CFX_PathData TransformedPath(*pPathData); + if (charpos.m_bGlyphAdjust) { + TransformedPath.Transform(&matrix); + } + CFX_ByteTextBuf buf; + buf << FX_BSTRC("/X") << ps_fontnum << FX_BSTRC(" Ff/CharProcs get begin/") + << ps_glyphindex << FX_BSTRC("{"); + buf << FX_BSTRC("n "); + for (int p = 0; p < TransformedPath.GetPointCount(); p++) { + FX_FLOAT x = TransformedPath.GetPointX(p), y = TransformedPath.GetPointY(p); + switch (TransformedPath.GetFlag(p) & FXPT_TYPE) { + case FXPT_MOVETO: { + buf << x << FX_BSTRC(" ") << y << FX_BSTRC(" m\n"); + break; + } + case FXPT_LINETO: { + buf << x << FX_BSTRC(" ") << y << FX_BSTRC(" l\n"); + break; + } + case FXPT_BEZIERTO: { + buf << x << FX_BSTRC(" ") << y << FX_BSTRC(" ") + << TransformedPath.GetPointX(p + 1) << FX_BSTRC(" ") + << TransformedPath.GetPointY(p + 1) << FX_BSTRC(" ") + << TransformedPath.GetPointX(p + 2) << FX_BSTRC(" ") + << TransformedPath.GetPointY(p + 2) << FX_BSTRC(" c\n"); + p += 2; + break; + } + } + } + buf << FX_BSTRC("f"); + buf << FX_BSTRC("}bind def end\n"); + buf << FX_BSTRC("/X") << ps_fontnum << FX_BSTRC(" Ff/Encoding get ") + << ps_glyphindex << FX_BSTRC("/") << ps_glyphindex << FX_BSTRC(" put\n"); + m_pOutput->OutputPS((const FX_CHAR*)buf.GetBuffer(), buf.GetSize()); +} +FX_BOOL CFX_PSRenderer::DrawText(int nChars, + const FXTEXT_CHARPOS* pCharPos, + CFX_Font* pFont, + CFX_FontCache* pCache, + const CFX_AffineMatrix* pObject2Device, + FX_FLOAT font_size, + FX_DWORD color, + int alpha_flag, + void* pIccTransform) { + StartRendering(); + int alpha = FXGETFLAG_COLORTYPE(alpha_flag) ? FXGETFLAG_ALPHA_FILL(alpha_flag) + : FXARGB_A(color); + if (alpha < 255) { + return FALSE; + } + if ((pObject2Device->a == 0 && pObject2Device->b == 0) || + (pObject2Device->c == 0 && pObject2Device->d == 0)) { return TRUE; + } + SetColor(color, alpha_flag, pIccTransform); + CFX_ByteTextBuf buf; + buf << FX_BSTRC("q[") << pObject2Device->a << FX_BSTRC(" ") + << pObject2Device->b << FX_BSTRC(" ") << pObject2Device->c + << FX_BSTRC(" ") << pObject2Device->d; + buf << FX_BSTRC(" ") << pObject2Device->e << FX_BSTRC(" ") + << pObject2Device->f << "]cm\n"; + if (pCache == NULL) { + pCache = CFX_GEModule::Get()->GetFontCache(); + } + CFX_FaceCache* pFaceCache = pCache->GetCachedFace(pFont); + FX_FONTCACHE_DEFINE(pCache, pFont); + int last_fontnum = -1; + for (int i = 0; i < nChars; i++) { + int ps_fontnum, ps_glyphindex; + FindPSFontGlyph(pFaceCache, pFont, pCharPos[i], ps_fontnum, ps_glyphindex); + if (last_fontnum != ps_fontnum) { + buf << FX_BSTRC("/X") << ps_fontnum << FX_BSTRC(" Ff ") << font_size + << FX_BSTRC(" Fs Sf "); + last_fontnum = ps_fontnum; + } + buf << pCharPos[i].m_OriginX << FX_BSTRC(" ") << pCharPos[i].m_OriginY + << FX_BSTRC(" m"); + CFX_ByteString hex; + hex.Format("<%02X>", ps_glyphindex); + buf << hex << FX_BSTRC("Tj\n"); + } + buf << FX_BSTRC("Q\n"); + m_pOutput->OutputPS((const FX_CHAR*)buf.GetBuffer(), buf.GetSize()); + return TRUE; } -void CFX_PSRenderer::WritePSBinary(const uint8_t* data, int len) -{ - uint8_t* dest_buf; - FX_DWORD dest_size; - CCodec_ModuleMgr* pEncoders = CFX_GEModule::Get()->GetCodecModule(); - if (pEncoders && pEncoders->GetBasicModule()->A85Encode(data, len, dest_buf, dest_size)) { - m_pOutput->OutputPS((const FX_CHAR*)dest_buf, dest_size); - FX_Free(dest_buf); - } else { - m_pOutput->OutputPS((const FX_CHAR*)data, len); - } +void CFX_PSRenderer::WritePSBinary(const uint8_t* data, int len) { + uint8_t* dest_buf; + FX_DWORD dest_size; + CCodec_ModuleMgr* pEncoders = CFX_GEModule::Get()->GetCodecModule(); + if (pEncoders && + pEncoders->GetBasicModule()->A85Encode(data, len, dest_buf, dest_size)) { + m_pOutput->OutputPS((const FX_CHAR*)dest_buf, dest_size); + FX_Free(dest_buf); + } else { + m_pOutput->OutputPS((const FX_CHAR*)data, len); + } } diff --git a/core/src/fxge/ge/fx_ge_text.cpp b/core/src/fxge/ge/fx_ge_text.cpp index 59a4cfb37d..7a84330ac0 100644 --- a/core/src/fxge/ge/fx_ge_text.cpp +++ b/core/src/fxge/ge/fx_ge_text.cpp @@ -10,1709 +10,1969 @@ #include "text_int.h" #undef FX_GAMMA #undef FX_GAMMA_INVERSE -#define FX_GAMMA(value) (value) -#define FX_GAMMA_INVERSE(value) (value) +#define FX_GAMMA(value) (value) +#define FX_GAMMA_INVERSE(value) (value) namespace { void ResetTransform(FT_Face face) { - FXFT_Matrix matrix; - matrix.xx = 0x10000L; - matrix.xy = 0; - matrix.yx = 0; - matrix.yy = 0x10000L; - FXFT_Set_Transform(face, &matrix, 0); + FXFT_Matrix matrix; + matrix.xx = 0x10000L; + matrix.xy = 0; + matrix.yx = 0; + matrix.yy = 0x10000L; + FXFT_Set_Transform(face, &matrix, 0); } // Sets the given transform on the font, and resets it to the identity when it // goes out of scope. -class ScopedFontTransform -{ -public: - ScopedFontTransform(FT_Face face, FXFT_Matrix* matrix) : m_Face(face) { - FXFT_Set_Transform(m_Face, matrix, 0); - } +class ScopedFontTransform { + public: + ScopedFontTransform(FT_Face face, FXFT_Matrix* matrix) : m_Face(face) { + FXFT_Set_Transform(m_Face, matrix, 0); + } - ~ScopedFontTransform() { - ResetTransform(m_Face); - } + ~ScopedFontTransform() { ResetTransform(m_Face); } -private: - FT_Face m_Face; + private: + FT_Face m_Face; }; - } -FX_RECT FXGE_GetGlyphsBBox(FXTEXT_GLYPHPOS* pGlyphAndPos, int nChars, int anti_alias, FX_FLOAT retinaScaleX, FX_FLOAT retinaScaleY) -{ - FX_RECT rect(0, 0, 0, 0); - FX_BOOL bStarted = FALSE; - for (int iChar = 0; iChar < nChars; iChar ++) { - FXTEXT_GLYPHPOS& glyph = pGlyphAndPos[iChar]; - const CFX_GlyphBitmap* pGlyph = glyph.m_pGlyph; - if (pGlyph == NULL) { - continue; - } - int char_left = glyph.m_OriginX + pGlyph->m_Left; - int char_width = (int)(pGlyph->m_Bitmap.GetWidth() / retinaScaleX); - if (anti_alias == FXFT_RENDER_MODE_LCD) { - char_width /= 3; - } - int char_right = char_left + char_width; - int char_top = glyph.m_OriginY - pGlyph->m_Top; - int char_bottom = char_top + (int)(pGlyph->m_Bitmap.GetHeight() / retinaScaleY); - if (!bStarted) { - rect.left = char_left; - rect.right = char_right; - rect.top = char_top; - rect.bottom = char_bottom; - bStarted = TRUE; - } else { - if (rect.left > char_left) { - rect.left = char_left; - } - if (rect.right < char_right) { - rect.right = char_right; - } - if (rect.top > char_top) { - rect.top = char_top; - } - if (rect.bottom < char_bottom) { - rect.bottom = char_bottom; - } - } - } - return rect; +FX_RECT FXGE_GetGlyphsBBox(FXTEXT_GLYPHPOS* pGlyphAndPos, + int nChars, + int anti_alias, + FX_FLOAT retinaScaleX, + FX_FLOAT retinaScaleY) { + FX_RECT rect(0, 0, 0, 0); + FX_BOOL bStarted = FALSE; + for (int iChar = 0; iChar < nChars; iChar++) { + FXTEXT_GLYPHPOS& glyph = pGlyphAndPos[iChar]; + const CFX_GlyphBitmap* pGlyph = glyph.m_pGlyph; + if (pGlyph == NULL) { + continue; + } + int char_left = glyph.m_OriginX + pGlyph->m_Left; + int char_width = (int)(pGlyph->m_Bitmap.GetWidth() / retinaScaleX); + if (anti_alias == FXFT_RENDER_MODE_LCD) { + char_width /= 3; + } + int char_right = char_left + char_width; + int char_top = glyph.m_OriginY - pGlyph->m_Top; + int char_bottom = + char_top + (int)(pGlyph->m_Bitmap.GetHeight() / retinaScaleY); + if (!bStarted) { + rect.left = char_left; + rect.right = char_right; + rect.top = char_top; + rect.bottom = char_bottom; + bStarted = TRUE; + } else { + if (rect.left > char_left) { + rect.left = char_left; + } + if (rect.right < char_right) { + rect.right = char_right; + } + if (rect.top > char_top) { + rect.top = char_top; + } + if (rect.bottom < char_bottom) { + rect.bottom = char_bottom; + } + } + } + return rect; } -static void _AdjustGlyphSpace(FXTEXT_GLYPHPOS* pGlyphAndPos, int nChars) -{ - ASSERT(nChars > 1); - FX_BOOL bVertical = FALSE; - if (pGlyphAndPos[nChars - 1].m_OriginX == pGlyphAndPos[0].m_OriginX) { - bVertical = TRUE; - } else if (pGlyphAndPos[nChars - 1].m_OriginY != pGlyphAndPos[0].m_OriginY) { - return; - } - int i = nChars - 1; - int* next_origin = bVertical ? &pGlyphAndPos[i].m_OriginY : &pGlyphAndPos[i].m_OriginX; - FX_FLOAT next_origin_f = bVertical ? pGlyphAndPos[i].m_fOriginY : pGlyphAndPos[i].m_fOriginX; - for (i --; i > 0; i --) { - int* this_origin = bVertical ? &pGlyphAndPos[i].m_OriginY : &pGlyphAndPos[i].m_OriginX; - FX_FLOAT this_origin_f = bVertical ? pGlyphAndPos[i].m_fOriginY : pGlyphAndPos[i].m_fOriginX; - int space = (*next_origin) - (*this_origin); - FX_FLOAT space_f = next_origin_f - this_origin_f; - FX_FLOAT error = (FX_FLOAT)(FXSYS_fabs(space_f) - FXSYS_fabs((FX_FLOAT)(space))); - if (error > 0.5f) { - *this_origin += space > 0 ? -1 : 1; - } - next_origin = this_origin; - next_origin_f = this_origin_f; - } +static void _AdjustGlyphSpace(FXTEXT_GLYPHPOS* pGlyphAndPos, int nChars) { + ASSERT(nChars > 1); + FX_BOOL bVertical = FALSE; + if (pGlyphAndPos[nChars - 1].m_OriginX == pGlyphAndPos[0].m_OriginX) { + bVertical = TRUE; + } else if (pGlyphAndPos[nChars - 1].m_OriginY != pGlyphAndPos[0].m_OriginY) { + return; + } + int i = nChars - 1; + int* next_origin = + bVertical ? &pGlyphAndPos[i].m_OriginY : &pGlyphAndPos[i].m_OriginX; + FX_FLOAT next_origin_f = + bVertical ? pGlyphAndPos[i].m_fOriginY : pGlyphAndPos[i].m_fOriginX; + for (i--; i > 0; i--) { + int* this_origin = + bVertical ? &pGlyphAndPos[i].m_OriginY : &pGlyphAndPos[i].m_OriginX; + FX_FLOAT this_origin_f = + bVertical ? pGlyphAndPos[i].m_fOriginY : pGlyphAndPos[i].m_fOriginX; + int space = (*next_origin) - (*this_origin); + FX_FLOAT space_f = next_origin_f - this_origin_f; + FX_FLOAT error = + (FX_FLOAT)(FXSYS_fabs(space_f) - FXSYS_fabs((FX_FLOAT)(space))); + if (error > 0.5f) { + *this_origin += space > 0 ? -1 : 1; + } + next_origin = this_origin; + next_origin_f = this_origin_f; + } } static const uint8_t g_TextGammaAdjust[256] = { - 0, 2, 3, 4, 6, 7, 8, 10, 11, 12, 13, 15, 16, 17, 18, 19, - 21, 22, 23, 24, 25, 26, 27, 29, 30, 31, 32, 33, 34, 35, 36, 38, - 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 71, 72, - 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, - 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, - 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, - 121, 122, 123, 124, 125, 126, 127, 128, 129, 129, 130, 131, 132, 133, 134, 135, - 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, - 152, 153, 154, 155, 156, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, - 167, 168, 169, 170, 171, 172, 173, 174, 174, 175, 176, 177, 178, 179, 180, 181, - 182, 183, 184, 185, 186, 187, 188, 189, 190, 190, 191, 192, 193, 194, 195, 196, - 197, 198, 199, 200, 201, 202, 203, 204, 204, 205, 206, 207, 208, 209, 210, 211, - 212, 213, 214, 215, 216, 217, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, - 227, 228, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 239, 240, - 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 250, 251, 252, 253, 254, 255, + 0, 2, 3, 4, 6, 7, 8, 10, 11, 12, 13, 15, 16, 17, 18, + 19, 21, 22, 23, 24, 25, 26, 27, 29, 30, 31, 32, 33, 34, 35, + 36, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 51, 52, + 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, + 68, 69, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, + 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, + 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, + 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, + 129, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, + 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 156, + 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, + 172, 173, 174, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, + 186, 187, 188, 189, 190, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, + 200, 201, 202, 203, 204, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, + 214, 215, 216, 217, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, + 228, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 239, 240, + 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 250, 251, 252, 253, 254, + 255, }; #define ADJUST_ALPHA(background, foreground, src_alpha, text_flags, a) \ - src_alpha = g_TextGammaAdjust[(uint8_t)src_alpha]; -void _Color2Argb(FX_ARGB& argb, FX_DWORD color, int alpha_flag, void* pIccTransform) -{ - if (pIccTransform == NULL && !FXGETFLAG_COLORTYPE(alpha_flag)) { - argb = color; - return; - } - if (!CFX_GEModule::Get()->GetCodecModule() || !CFX_GEModule::Get()->GetCodecModule()->GetIccModule()) { - pIccTransform = NULL; - } - uint8_t bgra[4]; - if (pIccTransform) { - ICodec_IccModule* pIccModule = CFX_GEModule::Get()->GetCodecModule()->GetIccModule(); - color = FXGETFLAG_COLORTYPE(alpha_flag) ? FXCMYK_TODIB(color) : FXARGB_TODIB(color); - pIccModule->TranslateScanline(pIccTransform, bgra, (const uint8_t*)&color, 1); - bgra[3] = FXGETFLAG_COLORTYPE(alpha_flag) ? - (alpha_flag >> 24) ? FXGETFLAG_ALPHA_FILL(alpha_flag) : FXGETFLAG_ALPHA_STROKE(alpha_flag) : - FXARGB_A(color); - argb = FXARGB_MAKE(bgra[3], bgra[2], bgra[1], bgra[0]); - return; - } - AdobeCMYK_to_sRGB1(FXSYS_GetCValue(color), FXSYS_GetMValue(color), - FXSYS_GetYValue(color), FXSYS_GetKValue(color), - bgra[2], bgra[1], bgra[0]); - bgra[3] = (alpha_flag >> 24) ? FXGETFLAG_ALPHA_FILL(alpha_flag) : FXGETFLAG_ALPHA_STROKE(alpha_flag); + src_alpha = g_TextGammaAdjust[(uint8_t)src_alpha]; +void _Color2Argb(FX_ARGB& argb, + FX_DWORD color, + int alpha_flag, + void* pIccTransform) { + if (pIccTransform == NULL && !FXGETFLAG_COLORTYPE(alpha_flag)) { + argb = color; + return; + } + if (!CFX_GEModule::Get()->GetCodecModule() || + !CFX_GEModule::Get()->GetCodecModule()->GetIccModule()) { + pIccTransform = NULL; + } + uint8_t bgra[4]; + if (pIccTransform) { + ICodec_IccModule* pIccModule = + CFX_GEModule::Get()->GetCodecModule()->GetIccModule(); + color = FXGETFLAG_COLORTYPE(alpha_flag) ? FXCMYK_TODIB(color) + : FXARGB_TODIB(color); + pIccModule->TranslateScanline(pIccTransform, bgra, (const uint8_t*)&color, + 1); + bgra[3] = FXGETFLAG_COLORTYPE(alpha_flag) + ? (alpha_flag >> 24) ? FXGETFLAG_ALPHA_FILL(alpha_flag) + : FXGETFLAG_ALPHA_STROKE(alpha_flag) + : FXARGB_A(color); argb = FXARGB_MAKE(bgra[3], bgra[2], bgra[1], bgra[0]); + return; + } + AdobeCMYK_to_sRGB1(FXSYS_GetCValue(color), FXSYS_GetMValue(color), + FXSYS_GetYValue(color), FXSYS_GetKValue(color), bgra[2], + bgra[1], bgra[0]); + bgra[3] = (alpha_flag >> 24) ? FXGETFLAG_ALPHA_FILL(alpha_flag) + : FXGETFLAG_ALPHA_STROKE(alpha_flag); + argb = FXARGB_MAKE(bgra[3], bgra[2], bgra[1], bgra[0]); } -FX_BOOL CFX_RenderDevice::DrawNormalText(int nChars, const FXTEXT_CHARPOS* pCharPos, - CFX_Font* pFont, CFX_FontCache* pCache, - FX_FLOAT font_size, const CFX_AffineMatrix* pText2Device, - FX_DWORD fill_color, FX_DWORD text_flags, - int alpha_flag, void* pIccTransform) -{ - int nativetext_flags = text_flags; - if (m_DeviceClass != FXDC_DISPLAY) { - if (!(text_flags & FXTEXT_PRINTGRAPHICTEXT)) { -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ - if (!(text_flags & FXFONT_CIDFONT) && pFont->GetPsName().Find(CFX_WideString::FromLocal("+ZJHL")) == -1) +FX_BOOL CFX_RenderDevice::DrawNormalText(int nChars, + const FXTEXT_CHARPOS* pCharPos, + CFX_Font* pFont, + CFX_FontCache* pCache, + FX_FLOAT font_size, + const CFX_AffineMatrix* pText2Device, + FX_DWORD fill_color, + FX_DWORD text_flags, + int alpha_flag, + void* pIccTransform) { + int nativetext_flags = text_flags; + if (m_DeviceClass != FXDC_DISPLAY) { + if (!(text_flags & FXTEXT_PRINTGRAPHICTEXT)) { +#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ + if (!(text_flags & FXFONT_CIDFONT) && + pFont->GetPsName().Find(CFX_WideString::FromLocal("+ZJHL")) == -1) #ifdef FOXIT_CHROME_BUILD - if (pFont->GetPsName() != CFX_WideString::FromLocal("CNAAJI+cmex10")) + if (pFont->GetPsName() != CFX_WideString::FromLocal("CNAAJI+cmex10")) #endif #endif - if (m_pDeviceDriver->DrawDeviceText(nChars, pCharPos, pFont, pCache, pText2Device, font_size, fill_color, alpha_flag, pIccTransform)) { - return TRUE; - } - } - int alpha = FXGETFLAG_COLORTYPE(alpha_flag) ? FXGETFLAG_ALPHA_FILL(alpha_flag) : FXARGB_A(fill_color); - if (alpha < 255) { - return FALSE; - } - } else if (!(text_flags & FXTEXT_NO_NATIVETEXT)) { -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ - if (!(text_flags & FXFONT_CIDFONT)) + if (m_pDeviceDriver->DrawDeviceText( + nChars, pCharPos, pFont, pCache, pText2Device, font_size, + fill_color, alpha_flag, pIccTransform)) { + return TRUE; + } + } + int alpha = FXGETFLAG_COLORTYPE(alpha_flag) + ? FXGETFLAG_ALPHA_FILL(alpha_flag) + : FXARGB_A(fill_color); + if (alpha < 255) { + return FALSE; + } + } else if (!(text_flags & FXTEXT_NO_NATIVETEXT)) { +#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ + if (!(text_flags & FXFONT_CIDFONT)) #ifdef FOXIT_CHROME_BUILD - if (pFont->GetPsName() != CFX_WideString::FromLocal("CNAAJI+cmex10")) + if (pFont->GetPsName() != CFX_WideString::FromLocal("CNAAJI+cmex10")) #endif #endif - if (m_pDeviceDriver->DrawDeviceText(nChars, pCharPos, pFont, pCache, pText2Device, font_size, fill_color, alpha_flag, pIccTransform)) { - return TRUE; - } - } - CFX_AffineMatrix char2device, deviceCtm, text2Device; - if (pText2Device) { - char2device = *pText2Device; - text2Device = *pText2Device; - } - char2device.Scale(font_size, -font_size); - if (FXSYS_fabs(char2device.a) + FXSYS_fabs(char2device.b) > 50 * 1.0f || - ((m_DeviceClass == FXDC_PRINTER && !m_pDeviceDriver->IsPSPrintDriver()) - && !(text_flags & FXTEXT_PRINTIMAGETEXT))) { - if (pFont->GetFace() != NULL || (pFont->GetSubstFont()->m_SubstFlags & FXFONT_SUBST_GLYPHPATH)) { - int nPathFlags = (text_flags & FXTEXT_NOSMOOTH) == 0 ? 0 : FXFILL_NOPATHSMOOTH; - return DrawTextPath(nChars, pCharPos, pFont, pCache, font_size, pText2Device, NULL, NULL, fill_color, 0, NULL, nPathFlags, alpha_flag, pIccTransform); - } - } - int anti_alias = FXFT_RENDER_MODE_MONO; - FX_BOOL bNormal = FALSE; - if ((text_flags & FXTEXT_NOSMOOTH) == 0) { - if (m_DeviceClass == FXDC_DISPLAY && m_bpp > 1) { - FX_BOOL bClearType; - if (pFont->GetFace() == NULL && !(pFont->GetSubstFont()->m_SubstFlags & FXFONT_SUBST_CLEARTYPE)) { - bClearType = FALSE; - } else { - bClearType = text_flags & FXTEXT_CLEARTYPE; - } - if ((m_RenderCaps & (FXRC_ALPHA_OUTPUT | FXRC_CMYK_OUTPUT))) { - anti_alias = FXFT_RENDER_MODE_LCD; - bNormal = TRUE; - } else if (m_bpp < 16) { - anti_alias = FXFT_RENDER_MODE_NORMAL; - } else { - if (bClearType == FALSE) { - anti_alias = FXFT_RENDER_MODE_LCD; - bNormal = TRUE; - } else { - anti_alias = FXFT_RENDER_MODE_LCD; - } - } + if (m_pDeviceDriver->DrawDeviceText(nChars, pCharPos, pFont, pCache, + pText2Device, font_size, fill_color, + alpha_flag, pIccTransform)) { + return TRUE; } - } - if (pCache == NULL) { - pCache = CFX_GEModule::Get()->GetFontCache(); - } - CFX_FaceCache* pFaceCache = pCache->GetCachedFace(pFont); - FX_FONTCACHE_DEFINE(pCache, pFont); - FXTEXT_GLYPHPOS* pGlyphAndPos = FX_Alloc(FXTEXT_GLYPHPOS, nChars); - int iChar; - deviceCtm = char2device; - CFX_AffineMatrix matrixCTM = GetCTM(); - FX_FLOAT scale_x = FXSYS_fabs(matrixCTM.a); - FX_FLOAT scale_y = FXSYS_fabs(matrixCTM.d); - deviceCtm.Concat(scale_x, 0, 0, scale_y, 0, 0); - text2Device.Concat(scale_x, 0, 0, scale_y, 0, 0); - for (iChar = 0; iChar < nChars; iChar ++) { - FXTEXT_GLYPHPOS& glyph = pGlyphAndPos[iChar]; - const FXTEXT_CHARPOS& charpos = pCharPos[iChar]; - glyph.m_fOriginX = charpos.m_OriginX; - glyph.m_fOriginY = charpos.m_OriginY; - text2Device.Transform(glyph.m_fOriginX, glyph.m_fOriginY); - if (anti_alias < FXFT_RENDER_MODE_LCD) { - glyph.m_OriginX = FXSYS_round(glyph.m_fOriginX); + } + CFX_AffineMatrix char2device, deviceCtm, text2Device; + if (pText2Device) { + char2device = *pText2Device; + text2Device = *pText2Device; + } + char2device.Scale(font_size, -font_size); + if (FXSYS_fabs(char2device.a) + FXSYS_fabs(char2device.b) > 50 * 1.0f || + ((m_DeviceClass == FXDC_PRINTER && !m_pDeviceDriver->IsPSPrintDriver()) && + !(text_flags & FXTEXT_PRINTIMAGETEXT))) { + if (pFont->GetFace() != NULL || + (pFont->GetSubstFont()->m_SubstFlags & FXFONT_SUBST_GLYPHPATH)) { + int nPathFlags = + (text_flags & FXTEXT_NOSMOOTH) == 0 ? 0 : FXFILL_NOPATHSMOOTH; + return DrawTextPath(nChars, pCharPos, pFont, pCache, font_size, + pText2Device, NULL, NULL, fill_color, 0, NULL, + nPathFlags, alpha_flag, pIccTransform); + } + } + int anti_alias = FXFT_RENDER_MODE_MONO; + FX_BOOL bNormal = FALSE; + if ((text_flags & FXTEXT_NOSMOOTH) == 0) { + if (m_DeviceClass == FXDC_DISPLAY && m_bpp > 1) { + FX_BOOL bClearType; + if (pFont->GetFace() == NULL && + !(pFont->GetSubstFont()->m_SubstFlags & FXFONT_SUBST_CLEARTYPE)) { + bClearType = FALSE; + } else { + bClearType = text_flags & FXTEXT_CLEARTYPE; + } + if ((m_RenderCaps & (FXRC_ALPHA_OUTPUT | FXRC_CMYK_OUTPUT))) { + anti_alias = FXFT_RENDER_MODE_LCD; + bNormal = TRUE; + } else if (m_bpp < 16) { + anti_alias = FXFT_RENDER_MODE_NORMAL; + } else { + if (bClearType == FALSE) { + anti_alias = FXFT_RENDER_MODE_LCD; + bNormal = TRUE; } else { - glyph.m_OriginX = (int)FXSYS_floor(glyph.m_fOriginX); + anti_alias = FXFT_RENDER_MODE_LCD; } - glyph.m_OriginY = FXSYS_round(glyph.m_fOriginY); - if (charpos.m_bGlyphAdjust) { - CFX_AffineMatrix new_matrix(charpos.m_AdjustMatrix[0], charpos.m_AdjustMatrix[1], - charpos.m_AdjustMatrix[2], charpos.m_AdjustMatrix[3], 0, 0); - new_matrix.Concat(deviceCtm); - glyph.m_pGlyph = pFaceCache->LoadGlyphBitmap(pFont, charpos.m_GlyphIndex, charpos.m_bFontStyle, &new_matrix, - charpos.m_FontCharWidth, anti_alias, nativetext_flags); - } else - glyph.m_pGlyph = pFaceCache->LoadGlyphBitmap(pFont, charpos.m_GlyphIndex, charpos.m_bFontStyle, &deviceCtm, - charpos.m_FontCharWidth, anti_alias, nativetext_flags); - } - if (anti_alias < FXFT_RENDER_MODE_LCD && nChars > 1) { - _AdjustGlyphSpace(pGlyphAndPos, nChars); - } - FX_RECT bmp_rect1 = FXGE_GetGlyphsBBox(pGlyphAndPos, nChars, anti_alias); - if (scale_x > 1 && scale_y > 1) { - bmp_rect1.left--; - bmp_rect1.top --; - bmp_rect1.right ++; - bmp_rect1.bottom ++; + } + } + } + if (pCache == NULL) { + pCache = CFX_GEModule::Get()->GetFontCache(); + } + CFX_FaceCache* pFaceCache = pCache->GetCachedFace(pFont); + FX_FONTCACHE_DEFINE(pCache, pFont); + FXTEXT_GLYPHPOS* pGlyphAndPos = FX_Alloc(FXTEXT_GLYPHPOS, nChars); + int iChar; + deviceCtm = char2device; + CFX_AffineMatrix matrixCTM = GetCTM(); + FX_FLOAT scale_x = FXSYS_fabs(matrixCTM.a); + FX_FLOAT scale_y = FXSYS_fabs(matrixCTM.d); + deviceCtm.Concat(scale_x, 0, 0, scale_y, 0, 0); + text2Device.Concat(scale_x, 0, 0, scale_y, 0, 0); + for (iChar = 0; iChar < nChars; iChar++) { + FXTEXT_GLYPHPOS& glyph = pGlyphAndPos[iChar]; + const FXTEXT_CHARPOS& charpos = pCharPos[iChar]; + glyph.m_fOriginX = charpos.m_OriginX; + glyph.m_fOriginY = charpos.m_OriginY; + text2Device.Transform(glyph.m_fOriginX, glyph.m_fOriginY); + if (anti_alias < FXFT_RENDER_MODE_LCD) { + glyph.m_OriginX = FXSYS_round(glyph.m_fOriginX); + } else { + glyph.m_OriginX = (int)FXSYS_floor(glyph.m_fOriginX); + } + glyph.m_OriginY = FXSYS_round(glyph.m_fOriginY); + if (charpos.m_bGlyphAdjust) { + CFX_AffineMatrix new_matrix( + charpos.m_AdjustMatrix[0], charpos.m_AdjustMatrix[1], + charpos.m_AdjustMatrix[2], charpos.m_AdjustMatrix[3], 0, 0); + new_matrix.Concat(deviceCtm); + glyph.m_pGlyph = pFaceCache->LoadGlyphBitmap( + pFont, charpos.m_GlyphIndex, charpos.m_bFontStyle, &new_matrix, + charpos.m_FontCharWidth, anti_alias, nativetext_flags); + } else + glyph.m_pGlyph = pFaceCache->LoadGlyphBitmap( + pFont, charpos.m_GlyphIndex, charpos.m_bFontStyle, &deviceCtm, + charpos.m_FontCharWidth, anti_alias, nativetext_flags); + } + if (anti_alias < FXFT_RENDER_MODE_LCD && nChars > 1) { + _AdjustGlyphSpace(pGlyphAndPos, nChars); + } + FX_RECT bmp_rect1 = FXGE_GetGlyphsBBox(pGlyphAndPos, nChars, anti_alias); + if (scale_x > 1 && scale_y > 1) { + bmp_rect1.left--; + bmp_rect1.top--; + bmp_rect1.right++; + bmp_rect1.bottom++; + } + FX_RECT bmp_rect(FXSYS_round((FX_FLOAT)(bmp_rect1.left) / scale_x), + FXSYS_round((FX_FLOAT)(bmp_rect1.top) / scale_y), + FXSYS_round((FX_FLOAT)bmp_rect1.right / scale_x), + FXSYS_round((FX_FLOAT)bmp_rect1.bottom / scale_y)); + bmp_rect.Intersect(m_ClipBox); + if (bmp_rect.IsEmpty()) { + FX_Free(pGlyphAndPos); + return TRUE; + } + int pixel_width = FXSYS_round(bmp_rect.Width() * scale_x); + int pixel_height = FXSYS_round(bmp_rect.Height() * scale_y); + int pixel_left = FXSYS_round(bmp_rect.left * scale_x); + int pixel_top = FXSYS_round(bmp_rect.top * scale_y); + if (anti_alias == FXFT_RENDER_MODE_MONO) { + CFX_DIBitmap bitmap; + if (!bitmap.Create(pixel_width, pixel_height, FXDIB_1bppMask)) { + FX_Free(pGlyphAndPos); + return FALSE; + } + bitmap.Clear(0); + for (iChar = 0; iChar < nChars; iChar++) { + FXTEXT_GLYPHPOS& glyph = pGlyphAndPos[iChar]; + if (glyph.m_pGlyph == NULL) { + continue; + } + const CFX_DIBitmap* pGlyph = &glyph.m_pGlyph->m_Bitmap; + bitmap.TransferBitmap( + glyph.m_OriginX + glyph.m_pGlyph->m_Left - pixel_left, + glyph.m_OriginY - glyph.m_pGlyph->m_Top - pixel_top, + pGlyph->GetWidth(), pGlyph->GetHeight(), pGlyph, 0, 0); } - FX_RECT bmp_rect(FXSYS_round((FX_FLOAT)(bmp_rect1.left) / scale_x), FXSYS_round((FX_FLOAT)(bmp_rect1.top) / scale_y), - FXSYS_round((FX_FLOAT)bmp_rect1.right / scale_x), FXSYS_round((FX_FLOAT)bmp_rect1.bottom / scale_y)); - bmp_rect.Intersect(m_ClipBox); - if (bmp_rect.IsEmpty()) { + FX_Free(pGlyphAndPos); + return SetBitMask(&bitmap, bmp_rect.left, bmp_rect.top, fill_color); + } + CFX_DIBitmap bitmap; + if (m_bpp == 8) { + if (!bitmap.Create(pixel_width, pixel_height, FXDIB_8bppMask)) { + FX_Free(pGlyphAndPos); + return FALSE; + } + } else { + if (!CreateCompatibleBitmap(&bitmap, pixel_width, pixel_height)) { + FX_Free(pGlyphAndPos); + return FALSE; + } + } + if (!bitmap.HasAlpha() && !bitmap.IsAlphaMask()) { + bitmap.Clear(0xFFFFFFFF); + if (!GetDIBits(&bitmap, bmp_rect.left, bmp_rect.top)) { + FX_Free(pGlyphAndPos); + return FALSE; + } + } else { + bitmap.Clear(0); + if (bitmap.m_pAlphaMask) { + bitmap.m_pAlphaMask->Clear(0); + } + } + int dest_width = pixel_width; + uint8_t* dest_buf = bitmap.GetBuffer(); + int dest_pitch = bitmap.GetPitch(); + int Bpp = bitmap.GetBPP() / 8; + int a, r, g, b; + if (anti_alias == FXFT_RENDER_MODE_LCD) { + _Color2Argb(fill_color, fill_color, alpha_flag | (1 << 24), pIccTransform); + ArgbDecode(fill_color, a, r, g, b); + r = FX_GAMMA(r); + g = FX_GAMMA(g); + b = FX_GAMMA(b); + } + for (iChar = 0; iChar < nChars; iChar++) { + FXTEXT_GLYPHPOS& glyph = pGlyphAndPos[iChar]; + if (glyph.m_pGlyph == NULL) { + continue; + } + const CFX_DIBitmap* pGlyph = &glyph.m_pGlyph->m_Bitmap; + int left = glyph.m_OriginX + glyph.m_pGlyph->m_Left - pixel_left; + int top = glyph.m_OriginY - glyph.m_pGlyph->m_Top - pixel_top; + int ncols = pGlyph->GetWidth(); + int nrows = pGlyph->GetHeight(); + if (anti_alias == FXFT_RENDER_MODE_NORMAL) { + if (!bitmap.CompositeMask(left, top, ncols, nrows, pGlyph, fill_color, 0, + 0, FXDIB_BLEND_NORMAL, NULL, FALSE, alpha_flag, + pIccTransform)) { FX_Free(pGlyphAndPos); - return TRUE; - } - int pixel_width = FXSYS_round(bmp_rect.Width() * scale_x); - int pixel_height = FXSYS_round(bmp_rect.Height() * scale_y); - int pixel_left = FXSYS_round(bmp_rect.left * scale_x); - int pixel_top = FXSYS_round(bmp_rect.top * scale_y); - if (anti_alias == FXFT_RENDER_MODE_MONO) { - CFX_DIBitmap bitmap; - if (!bitmap.Create(pixel_width, pixel_height, FXDIB_1bppMask)) { - FX_Free(pGlyphAndPos); - return FALSE; + return FALSE; + } + continue; + } + FX_BOOL bBGRStripe = text_flags & FXTEXT_BGR_STRIPE; + ncols /= 3; + int x_subpixel = (int)(glyph.m_fOriginX * 3) % 3; + uint8_t* src_buf = pGlyph->GetBuffer(); + int src_pitch = pGlyph->GetPitch(); + int start_col = left; + if (start_col < 0) { + start_col = 0; + } + int end_col = left + ncols; + if (end_col > dest_width) { + end_col = dest_width; + } + if (start_col >= end_col) { + continue; + } + if (bitmap.GetFormat() == FXDIB_Argb) { + for (int row = 0; row < nrows; row++) { + int dest_row = row + top; + if (dest_row < 0 || dest_row >= bitmap.GetHeight()) { + continue; } - bitmap.Clear(0); - for (iChar = 0; iChar < nChars; iChar ++) { - FXTEXT_GLYPHPOS& glyph = pGlyphAndPos[iChar]; - if (glyph.m_pGlyph == NULL) { - continue; + uint8_t* src_scan = src_buf + row * src_pitch + (start_col - left) * 3; + uint8_t* dest_scan = + dest_buf + dest_row * dest_pitch + (start_col << 2); + if (bBGRStripe) { + if (x_subpixel == 0) { + for (int col = start_col; col < end_col; col++) { + int src_alpha = src_scan[2]; + src_alpha = src_alpha * a / 255; + dest_scan[2] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); + src_alpha = src_scan[1]; + src_alpha = src_alpha * a / 255; + dest_scan[1] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); + src_alpha = src_scan[0]; + src_alpha = src_alpha * a / 255; + dest_scan[0] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); + dest_scan[3] = 255; + dest_scan += 4; + src_scan += 3; } - const CFX_DIBitmap* pGlyph = &glyph.m_pGlyph->m_Bitmap; - bitmap.TransferBitmap(glyph.m_OriginX + glyph.m_pGlyph->m_Left - pixel_left, - glyph.m_OriginY - glyph.m_pGlyph->m_Top - pixel_top, - pGlyph->GetWidth(), pGlyph->GetHeight(), pGlyph, 0, 0); - } - FX_Free(pGlyphAndPos); - return SetBitMask(&bitmap, bmp_rect.left, bmp_rect.top, fill_color); - } - CFX_DIBitmap bitmap; - if (m_bpp == 8) { - if (!bitmap.Create(pixel_width, pixel_height, FXDIB_8bppMask)) { - FX_Free(pGlyphAndPos); - return FALSE; - } - } else { - if (!CreateCompatibleBitmap(&bitmap, pixel_width, pixel_height)) { - FX_Free(pGlyphAndPos); - return FALSE; - } - } - if (!bitmap.HasAlpha() && !bitmap.IsAlphaMask()) { - bitmap.Clear(0xFFFFFFFF); - if (!GetDIBits(&bitmap, bmp_rect.left, bmp_rect.top)) { - FX_Free(pGlyphAndPos); - return FALSE; - } - } else { - bitmap.Clear(0); - if (bitmap.m_pAlphaMask) { - bitmap.m_pAlphaMask->Clear(0); - } - } - int dest_width = pixel_width; - uint8_t* dest_buf = bitmap.GetBuffer(); - int dest_pitch = bitmap.GetPitch(); - int Bpp = bitmap.GetBPP() / 8; - int a, r, g, b; - if (anti_alias == FXFT_RENDER_MODE_LCD) { - _Color2Argb(fill_color, fill_color, alpha_flag | (1 << 24), pIccTransform); - ArgbDecode(fill_color, a, r, g, b); - r = FX_GAMMA(r); - g = FX_GAMMA(g); - b = FX_GAMMA(b); - } - for (iChar = 0; iChar < nChars; iChar ++) { - FXTEXT_GLYPHPOS& glyph = pGlyphAndPos[iChar]; - if (glyph.m_pGlyph == NULL) { - continue; - } - const CFX_DIBitmap* pGlyph = &glyph.m_pGlyph->m_Bitmap; - int left = glyph.m_OriginX + glyph.m_pGlyph->m_Left - pixel_left; - int top = glyph.m_OriginY - glyph.m_pGlyph->m_Top - pixel_top; - int ncols = pGlyph->GetWidth(); - int nrows = pGlyph->GetHeight(); - if (anti_alias == FXFT_RENDER_MODE_NORMAL) { - if (!bitmap.CompositeMask(left, top, ncols, nrows, pGlyph, fill_color, - 0, 0, FXDIB_BLEND_NORMAL, NULL, FALSE, alpha_flag, pIccTransform)) { - FX_Free(pGlyphAndPos); - return FALSE; + } else if (x_subpixel == 1) { + int src_alpha = src_scan[1]; + ADJUST_ALPHA(dest_scan[2], r, src_alpha, nativetext_flags, a); + src_alpha = src_alpha * a / 255; + dest_scan[2] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); + src_alpha = src_scan[0]; + ADJUST_ALPHA(dest_scan[1], g, src_alpha, nativetext_flags, a); + src_alpha = src_alpha * a / 255; + dest_scan[1] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); + if (start_col > left) { + src_alpha = src_scan[-1]; + ADJUST_ALPHA(dest_scan[0], b, src_alpha, nativetext_flags, a); + src_alpha = src_alpha * a / 255; + dest_scan[0] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); } - continue; - } - FX_BOOL bBGRStripe = text_flags & FXTEXT_BGR_STRIPE; - ncols /= 3; - int x_subpixel = (int)(glyph.m_fOriginX * 3) % 3; - uint8_t* src_buf = pGlyph->GetBuffer(); - int src_pitch = pGlyph->GetPitch(); - int start_col = left; - if (start_col < 0) { - start_col = 0; - } - int end_col = left + ncols; - if (end_col > dest_width) { - end_col = dest_width; - } - if (start_col >= end_col) { - continue; - } - if (bitmap.GetFormat() == FXDIB_Argb) { - for (int row = 0; row < nrows; row ++) { - int dest_row = row + top; - if (dest_row < 0 || dest_row >= bitmap.GetHeight()) { - continue; + dest_scan[3] = 255; + dest_scan += 4; + src_scan += 3; + for (int col = start_col + 1; col < end_col - 1; col++) { + int src_alpha = src_scan[1]; + ADJUST_ALPHA(dest_scan[2], r, src_alpha, nativetext_flags, a); + src_alpha = src_alpha * a / 255; + dest_scan[2] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); + src_alpha = src_scan[0]; + ADJUST_ALPHA(dest_scan[1], g, src_alpha, nativetext_flags, a); + src_alpha = src_alpha * a / 255; + dest_scan[1] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); + src_alpha = src_scan[-1]; + ADJUST_ALPHA(dest_scan[0], b, src_alpha, nativetext_flags, a); + src_alpha = src_alpha * a / 255; + dest_scan[0] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); + dest_scan[3] = 255; + dest_scan += 4; + src_scan += 3; + } + } else { + int src_alpha = src_scan[0]; + ADJUST_ALPHA(dest_scan[2], r, src_alpha, nativetext_flags, a); + src_alpha = src_alpha * a / 255; + dest_scan[2] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); + if (start_col > left) { + src_alpha = src_scan[-1]; + ADJUST_ALPHA(dest_scan[1], g, src_alpha, nativetext_flags, a); + src_alpha = src_alpha * a / 255; + dest_scan[1] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); + src_alpha = src_scan[-2]; + ADJUST_ALPHA(dest_scan[0], b, src_alpha, nativetext_flags, a); + src_alpha = src_alpha * a / 255; + dest_scan[0] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); + } + dest_scan[3] = 255; + dest_scan += 4; + src_scan += 3; + for (int col = start_col + 1; col < end_col - 1; col++) { + int src_alpha = src_scan[0]; + ADJUST_ALPHA(dest_scan[2], r, src_alpha, nativetext_flags, a); + src_alpha = src_alpha * a / 255; + dest_scan[2] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); + src_alpha = src_scan[-1]; + ADJUST_ALPHA(dest_scan[1], g, src_alpha, nativetext_flags, a); + src_alpha = src_alpha * a / 255; + dest_scan[1] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); + src_alpha = src_scan[-2]; + ADJUST_ALPHA(dest_scan[0], b, src_alpha, nativetext_flags, a); + src_alpha = src_alpha * a / 255; + dest_scan[0] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); + dest_scan[3] = 255; + dest_scan += 4; + src_scan += 3; + } + } + } else { + if (x_subpixel == 0) { + for (int col = start_col; col < end_col; col++) { + if (bNormal) { + int src_alpha1 = (src_scan[0] + src_scan[1] + src_scan[2]) / 3; + ADJUST_ALPHA(dest_scan[2], r, src_alpha1, nativetext_flags, a); + src_alpha1 = src_alpha1 * a / 255; + uint8_t back_alpha = dest_scan[3]; + if (back_alpha == 0) { + FXARGB_SETDIB(dest_scan, FXARGB_MAKE(src_alpha1, r, g, b)); + dest_scan += 4; + src_scan += 3; + continue; } - uint8_t* src_scan = src_buf + row * src_pitch + (start_col - left) * 3; - uint8_t* dest_scan = dest_buf + dest_row * dest_pitch + (start_col << 2); - if (bBGRStripe) { - if (x_subpixel == 0) { - for (int col = start_col; col < end_col; col ++) { - int src_alpha = src_scan[2]; - src_alpha = src_alpha * a / 255; - dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); - src_alpha = src_scan[1]; - src_alpha = src_alpha * a / 255; - dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); - src_alpha = src_scan[0]; - src_alpha = src_alpha * a / 255; - dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); - dest_scan[3] = 255; - dest_scan += 4; - src_scan += 3; - } - } else if (x_subpixel == 1) { - int src_alpha = src_scan[1]; - ADJUST_ALPHA(dest_scan[2], r, src_alpha, nativetext_flags, a); - src_alpha = src_alpha * a / 255; - dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); - src_alpha = src_scan[0]; - ADJUST_ALPHA(dest_scan[1], g, src_alpha, nativetext_flags, a); - src_alpha = src_alpha * a / 255; - dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); - if (start_col > left) { - src_alpha = src_scan[-1]; - ADJUST_ALPHA(dest_scan[0], b, src_alpha, nativetext_flags, a); - src_alpha = src_alpha * a / 255; - dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); - } - dest_scan[3] = 255; - dest_scan += 4; - src_scan += 3; - for (int col = start_col + 1; col < end_col - 1; col ++) { - int src_alpha = src_scan[1]; - ADJUST_ALPHA(dest_scan[2], r, src_alpha, nativetext_flags, a); - src_alpha = src_alpha * a / 255; - dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); - src_alpha = src_scan[0]; - ADJUST_ALPHA(dest_scan[1], g, src_alpha, nativetext_flags, a); - src_alpha = src_alpha * a / 255; - dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); - src_alpha = src_scan[-1]; - ADJUST_ALPHA(dest_scan[0], b, src_alpha, nativetext_flags, a); - src_alpha = src_alpha * a / 255; - dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); - dest_scan[3] = 255; - dest_scan += 4; - src_scan += 3; - } - } else { - int src_alpha = src_scan[0]; - ADJUST_ALPHA(dest_scan[2], r, src_alpha, nativetext_flags, a); - src_alpha = src_alpha * a / 255; - dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); - if (start_col > left) { - src_alpha = src_scan[-1]; - ADJUST_ALPHA(dest_scan[1], g, src_alpha, nativetext_flags, a); - src_alpha = src_alpha * a / 255; - dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); - src_alpha = src_scan[-2]; - ADJUST_ALPHA(dest_scan[0], b, src_alpha, nativetext_flags, a); - src_alpha = src_alpha * a / 255; - dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); - } - dest_scan[3] = 255; - dest_scan += 4; - src_scan += 3; - for (int col = start_col + 1; col < end_col - 1; col ++) { - int src_alpha = src_scan[0]; - ADJUST_ALPHA(dest_scan[2], r, src_alpha, nativetext_flags, a); - src_alpha = src_alpha * a / 255; - dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); - src_alpha = src_scan[-1]; - ADJUST_ALPHA(dest_scan[1], g, src_alpha, nativetext_flags, a); - src_alpha = src_alpha * a / 255; - dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); - src_alpha = src_scan[-2]; - ADJUST_ALPHA(dest_scan[0], b, src_alpha, nativetext_flags, a); - src_alpha = src_alpha * a / 255; - dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); - dest_scan[3] = 255; - dest_scan += 4; - src_scan += 3; - } - } + if (src_alpha1 == 0) { + dest_scan += 4; + src_scan += 3; + continue; + } + uint8_t dest_alpha = + back_alpha + src_alpha1 - back_alpha * src_alpha1 / 255; + dest_scan[3] = dest_alpha; + int alpha_ratio = src_alpha1 * 255 / dest_alpha; + dest_scan[2] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, alpha_ratio)); + dest_scan[1] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, alpha_ratio)); + dest_scan[0] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, alpha_ratio)); + dest_scan += 4; + src_scan += 3; + continue; + } + int src_alpha = src_scan[0]; + ADJUST_ALPHA(dest_scan[2], r, src_alpha, nativetext_flags, a); + src_alpha = src_alpha * a / 255; + dest_scan[2] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); + src_alpha = src_scan[1]; + ADJUST_ALPHA(dest_scan[1], g, src_alpha, nativetext_flags, a); + src_alpha = src_alpha * a / 255; + dest_scan[1] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); + src_alpha = src_scan[2]; + ADJUST_ALPHA(dest_scan[0], b, src_alpha, nativetext_flags, a); + src_alpha = src_alpha * a / 255; + dest_scan[0] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); + dest_scan[3] = 255; + dest_scan += 4; + src_scan += 3; + } + } else if (x_subpixel == 1) { + if (bNormal) { + int src_alpha1 = + start_col > left + ? ((src_scan[-1] + src_scan[0] + src_scan[1]) / 3) + : ((src_scan[0] + src_scan[1]) / 3); + ADJUST_ALPHA(dest_scan[2], r, src_alpha1, nativetext_flags, a); + src_alpha1 = src_alpha1 * a / 255; + if (src_alpha1 == 0) { + dest_scan += 4; + src_scan += 3; + } else { + uint8_t back_alpha = dest_scan[3]; + if (back_alpha == 0) { + FXARGB_SETDIB(dest_scan, FXARGB_MAKE(src_alpha1, r, g, b)); } else { - if (x_subpixel == 0) { - for (int col = start_col; col < end_col; col ++) { - if (bNormal) { - int src_alpha1 = (src_scan[0] + src_scan[1] + src_scan[2]) / 3; - ADJUST_ALPHA(dest_scan[2], r, src_alpha1, nativetext_flags, a); - src_alpha1 = src_alpha1 * a / 255; - uint8_t back_alpha = dest_scan[3]; - if (back_alpha == 0) { - FXARGB_SETDIB(dest_scan, FXARGB_MAKE(src_alpha1, r, g, b)); - dest_scan += 4; - src_scan += 3; - continue; - } - if (src_alpha1 == 0) { - dest_scan += 4; - src_scan += 3; - continue; - } - uint8_t dest_alpha = back_alpha + src_alpha1 - back_alpha * src_alpha1 / 255; - dest_scan[3] = dest_alpha; - int alpha_ratio = src_alpha1 * 255 / dest_alpha; - dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, alpha_ratio)); - dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, alpha_ratio)); - dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, alpha_ratio)); - dest_scan += 4; - src_scan += 3; - continue; - } - int src_alpha = src_scan[0]; - ADJUST_ALPHA(dest_scan[2], r, src_alpha, nativetext_flags, a); - src_alpha = src_alpha * a / 255; - dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); - src_alpha = src_scan[1]; - ADJUST_ALPHA(dest_scan[1], g, src_alpha, nativetext_flags, a); - src_alpha = src_alpha * a / 255; - dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); - src_alpha = src_scan[2]; - ADJUST_ALPHA(dest_scan[0], b, src_alpha, nativetext_flags, a); - src_alpha = src_alpha * a / 255; - dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); - dest_scan[3] = 255; - dest_scan += 4; - src_scan += 3; - } - } else if (x_subpixel == 1) { - if (bNormal) { - int src_alpha1 = start_col > left ? ((src_scan[-1] + src_scan[0] + src_scan[1]) / 3) : ((src_scan[0] + src_scan[1]) / 3); - ADJUST_ALPHA(dest_scan[2], r, src_alpha1, nativetext_flags, a); - src_alpha1 = src_alpha1 * a / 255; - if (src_alpha1 == 0) { - dest_scan += 4; - src_scan += 3; - } else { - uint8_t back_alpha = dest_scan[3]; - if (back_alpha == 0) { - FXARGB_SETDIB(dest_scan, FXARGB_MAKE(src_alpha1, r, g, b)); - } else { - uint8_t dest_alpha = back_alpha + src_alpha1 - back_alpha * src_alpha1 / 255; - dest_scan[3] = dest_alpha; - int alpha_ratio = src_alpha1 * 255 / dest_alpha; - dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, alpha_ratio)); - dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, alpha_ratio)); - dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, alpha_ratio)); - } - dest_scan += 4; - src_scan += 3; - } - } else { - if (start_col > left) { - int src_alpha = src_scan[-1]; - ADJUST_ALPHA(dest_scan[2], r, src_alpha, nativetext_flags, a); - src_alpha = src_alpha * a / 255; - dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); - } - int src_alpha = src_scan[0]; - ADJUST_ALPHA(dest_scan[1], g, src_alpha, nativetext_flags, a); - src_alpha = src_alpha * a / 255; - dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); - src_alpha = src_scan[1]; - ADJUST_ALPHA(dest_scan[0], b, src_alpha, nativetext_flags, a); - src_alpha = src_alpha * a / 255; - dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); - dest_scan[3] = 255; - dest_scan += 4; - src_scan += 3; - } - for (int col = start_col + 1; col < end_col; col ++) { - if (bNormal) { - int src_alpha1 = (src_scan[-1] + src_scan[0] + src_scan[1]) / 3; - ADJUST_ALPHA(dest_scan[2], r, src_alpha1, nativetext_flags, a); - src_alpha1 = src_alpha1 * a / 255; - uint8_t back_alpha = dest_scan[3]; - if (back_alpha == 0) { - FXARGB_SETDIB(dest_scan, FXARGB_MAKE(src_alpha1, r, g, b)); - dest_scan += 4; - src_scan += 3; - continue; - } - if (src_alpha1 == 0) { - dest_scan += 4; - src_scan += 3; - continue; - } - uint8_t dest_alpha = back_alpha + src_alpha1 - back_alpha * src_alpha1 / 255; - dest_scan[3] = dest_alpha; - int alpha_ratio = src_alpha1 * 255 / dest_alpha; - dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, alpha_ratio)); - dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, alpha_ratio)); - dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, alpha_ratio)); - dest_scan += 4; - src_scan += 3; - continue; - } - int src_alpha = src_scan[-1]; - ADJUST_ALPHA(dest_scan[2], r, src_alpha, nativetext_flags, a); - src_alpha = src_alpha * a / 255; - dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); - src_alpha = src_scan[0]; - ADJUST_ALPHA(dest_scan[1], g, src_alpha, nativetext_flags, a); - src_alpha = src_alpha * a / 255; - dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); - src_alpha = src_scan[1]; - ADJUST_ALPHA(dest_scan[0], b, src_alpha, nativetext_flags, a); - src_alpha = src_alpha * a / 255; - dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); - dest_scan[3] = 255; - dest_scan += 4; - src_scan += 3; - } - } else { - if (bNormal) { - int src_alpha1 = start_col > left ? ((src_scan[-2] + src_scan[-1] + src_scan[0]) / 3) : ((src_scan[0]) / 3); - ADJUST_ALPHA(dest_scan[2], r, src_alpha1, nativetext_flags, a); - src_alpha1 = src_alpha1 * a / 255; - if (src_alpha1 == 0) { - dest_scan += 4; - src_scan += 3; - } else { - uint8_t back_alpha = dest_scan[3]; - if (back_alpha == 0) { - FXARGB_SETDIB(dest_scan, FXARGB_MAKE(src_alpha1, r, g, b)); - } else { - uint8_t dest_alpha = back_alpha + src_alpha1 - back_alpha * src_alpha1 / 255; - dest_scan[3] = dest_alpha; - int alpha_ratio = src_alpha1 * 255 / dest_alpha; - dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, alpha_ratio)); - dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, alpha_ratio)); - dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, alpha_ratio)); - } - dest_scan += 4; - src_scan += 3; - } - } else { - if (start_col > left) { - int src_alpha = src_scan[-2]; - ADJUST_ALPHA(dest_scan[2], r, src_alpha, nativetext_flags, a); - src_alpha = src_alpha * a / 255; - dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); - src_alpha = src_scan[-1]; - ADJUST_ALPHA(dest_scan[1], g, src_alpha, nativetext_flags, a); - src_alpha = src_alpha * a / 255; - dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); - } - int src_alpha = src_scan[0]; - ADJUST_ALPHA(dest_scan[0], b, src_alpha, nativetext_flags, a); - src_alpha = src_alpha * a / 255; - dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); - dest_scan[3] = 255; - dest_scan += 4; - src_scan += 3; - } - for (int col = start_col + 1; col < end_col; col ++) { - if (bNormal) { - int src_alpha1 = (src_scan[-2] + src_scan[-1] + src_scan[0]) / 3; - ADJUST_ALPHA(dest_scan[2], r, src_alpha1, nativetext_flags, a); - src_alpha1 = src_alpha1 * a / 255; - uint8_t back_alpha = dest_scan[3]; - if (back_alpha == 0) { - FXARGB_SETDIB(dest_scan, FXARGB_MAKE(src_alpha1, r, g, b)); - dest_scan += 4; - src_scan += 3; - continue; - } - if (src_alpha1 == 0) { - dest_scan += 4; - src_scan += 3; - continue; - } - uint8_t dest_alpha = back_alpha + src_alpha1 - back_alpha * src_alpha1 / 255; - dest_scan[3] = dest_alpha; - int alpha_ratio = src_alpha1 * 255 / dest_alpha; - dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, alpha_ratio)); - dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, alpha_ratio)); - dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, alpha_ratio)); - dest_scan += 4; - src_scan += 3; - continue; - } - int src_alpha = src_scan[-2]; - ADJUST_ALPHA(dest_scan[2], r, src_alpha, nativetext_flags, a); - src_alpha = src_alpha * a / 255; - dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); - src_alpha = src_scan[-1]; - ADJUST_ALPHA(dest_scan[1], g, src_alpha, nativetext_flags, a); - src_alpha = src_alpha * a / 255; - dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); - src_alpha = src_scan[0]; - ADJUST_ALPHA(dest_scan[0], b, src_alpha, nativetext_flags, a); - src_alpha = src_alpha * a / 255; - dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); - dest_scan[3] = 255; - dest_scan += 4; - src_scan += 3; - } - } + uint8_t dest_alpha = + back_alpha + src_alpha1 - back_alpha * src_alpha1 / 255; + dest_scan[3] = dest_alpha; + int alpha_ratio = src_alpha1 * 255 / dest_alpha; + dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE( + FX_GAMMA(dest_scan[2]), r, alpha_ratio)); + dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE( + FX_GAMMA(dest_scan[1]), g, alpha_ratio)); + dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE( + FX_GAMMA(dest_scan[0]), b, alpha_ratio)); } + dest_scan += 4; + src_scan += 3; + } + } else { + if (start_col > left) { + int src_alpha = src_scan[-1]; + ADJUST_ALPHA(dest_scan[2], r, src_alpha, nativetext_flags, a); + src_alpha = src_alpha * a / 255; + dest_scan[2] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); + } + int src_alpha = src_scan[0]; + ADJUST_ALPHA(dest_scan[1], g, src_alpha, nativetext_flags, a); + src_alpha = src_alpha * a / 255; + dest_scan[1] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); + src_alpha = src_scan[1]; + ADJUST_ALPHA(dest_scan[0], b, src_alpha, nativetext_flags, a); + src_alpha = src_alpha * a / 255; + dest_scan[0] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); + dest_scan[3] = 255; + dest_scan += 4; + src_scan += 3; } - } else { - for (int row = 0; row < nrows; row ++) { - int dest_row = row + top; - if (dest_row < 0 || dest_row >= bitmap.GetHeight()) { - continue; + for (int col = start_col + 1; col < end_col; col++) { + if (bNormal) { + int src_alpha1 = (src_scan[-1] + src_scan[0] + src_scan[1]) / 3; + ADJUST_ALPHA(dest_scan[2], r, src_alpha1, nativetext_flags, a); + src_alpha1 = src_alpha1 * a / 255; + uint8_t back_alpha = dest_scan[3]; + if (back_alpha == 0) { + FXARGB_SETDIB(dest_scan, FXARGB_MAKE(src_alpha1, r, g, b)); + dest_scan += 4; + src_scan += 3; + continue; } - uint8_t* src_scan = src_buf + row * src_pitch + (start_col - left) * 3; - uint8_t* dest_scan = dest_buf + dest_row * dest_pitch + start_col * Bpp; - if (bBGRStripe) { - if (x_subpixel == 0) { - for (int col = start_col; col < end_col; col ++) { - int src_alpha = src_scan[2]; - ADJUST_ALPHA(dest_scan[2], r, src_alpha, nativetext_flags, a); - src_alpha = src_alpha * a / 255; - dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); - src_alpha = src_scan[1]; - ADJUST_ALPHA(dest_scan[1], g, src_alpha, nativetext_flags, a); - src_alpha = src_alpha * a / 255; - dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); - src_alpha = src_scan[0]; - ADJUST_ALPHA(dest_scan[0], b, src_alpha, nativetext_flags, a); - src_alpha = src_alpha * a / 255; - dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); - dest_scan += Bpp; - src_scan += 3; - } - } else if (x_subpixel == 1) { - int src_alpha = src_scan[1]; - ADJUST_ALPHA(dest_scan[2], r, src_alpha, nativetext_flags, a); - src_alpha = src_alpha * a / 255; - dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); - src_alpha = src_scan[0]; - ADJUST_ALPHA(dest_scan[1], g, src_alpha, nativetext_flags, a); - src_alpha = src_alpha * a / 255; - dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); - if (start_col > left) { - src_alpha = src_scan[-1]; - ADJUST_ALPHA(dest_scan[0], b, src_alpha, nativetext_flags, a); - src_alpha = src_alpha * a / 255; - dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); - } - dest_scan += Bpp; - src_scan += 3; - for (int col = start_col + 1; col < end_col - 1; col ++) { - int src_alpha = src_scan[1]; - ADJUST_ALPHA(dest_scan[2], r, src_alpha, nativetext_flags, a); - src_alpha = src_alpha * a / 255; - dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); - src_alpha = src_scan[0]; - ADJUST_ALPHA(dest_scan[1], g, src_alpha, nativetext_flags, a); - src_alpha = src_alpha * a / 255; - dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); - src_alpha = src_scan[-1]; - ADJUST_ALPHA(dest_scan[0], b, src_alpha, nativetext_flags, a); - src_alpha = src_alpha * a / 255; - dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); - dest_scan += Bpp; - src_scan += 3; - } - } else { - int src_alpha = src_scan[0]; - ADJUST_ALPHA(dest_scan[2], r, src_alpha, nativetext_flags, a); - src_alpha = src_alpha * a / 255; - dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); - if (start_col > left) { - src_alpha = src_scan[-1]; - ADJUST_ALPHA(dest_scan[1], g, src_alpha, nativetext_flags, a); - src_alpha = src_alpha * a / 255; - dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); - src_alpha = src_scan[-2]; - ADJUST_ALPHA(dest_scan[0], b, src_alpha, nativetext_flags, a); - src_alpha = src_alpha * a / 255; - dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); - } - dest_scan += Bpp; - src_scan += 3; - for (int col = start_col + 1; col < end_col - 1; col ++) { - int src_alpha = src_scan[0]; - ADJUST_ALPHA(dest_scan[2], r, src_alpha, nativetext_flags, a); - src_alpha = src_alpha * a / 255; - dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); - src_alpha = src_scan[-1]; - ADJUST_ALPHA(dest_scan[1], g, src_alpha, nativetext_flags, a); - src_alpha = src_alpha * a / 255; - dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); - src_alpha = src_scan[-2]; - ADJUST_ALPHA(dest_scan[0], b, src_alpha, nativetext_flags, a); - src_alpha = src_alpha * a / 255; - dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); - dest_scan += Bpp; - src_scan += 3; - } - } + if (src_alpha1 == 0) { + dest_scan += 4; + src_scan += 3; + continue; + } + uint8_t dest_alpha = + back_alpha + src_alpha1 - back_alpha * src_alpha1 / 255; + dest_scan[3] = dest_alpha; + int alpha_ratio = src_alpha1 * 255 / dest_alpha; + dest_scan[2] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, alpha_ratio)); + dest_scan[1] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, alpha_ratio)); + dest_scan[0] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, alpha_ratio)); + dest_scan += 4; + src_scan += 3; + continue; + } + int src_alpha = src_scan[-1]; + ADJUST_ALPHA(dest_scan[2], r, src_alpha, nativetext_flags, a); + src_alpha = src_alpha * a / 255; + dest_scan[2] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); + src_alpha = src_scan[0]; + ADJUST_ALPHA(dest_scan[1], g, src_alpha, nativetext_flags, a); + src_alpha = src_alpha * a / 255; + dest_scan[1] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); + src_alpha = src_scan[1]; + ADJUST_ALPHA(dest_scan[0], b, src_alpha, nativetext_flags, a); + src_alpha = src_alpha * a / 255; + dest_scan[0] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); + dest_scan[3] = 255; + dest_scan += 4; + src_scan += 3; + } + } else { + if (bNormal) { + int src_alpha1 = + start_col > left + ? ((src_scan[-2] + src_scan[-1] + src_scan[0]) / 3) + : ((src_scan[0]) / 3); + ADJUST_ALPHA(dest_scan[2], r, src_alpha1, nativetext_flags, a); + src_alpha1 = src_alpha1 * a / 255; + if (src_alpha1 == 0) { + dest_scan += 4; + src_scan += 3; + } else { + uint8_t back_alpha = dest_scan[3]; + if (back_alpha == 0) { + FXARGB_SETDIB(dest_scan, FXARGB_MAKE(src_alpha1, r, g, b)); } else { - if (x_subpixel == 0) { - for (int col = start_col; col < end_col; col ++) { - if (bNormal) { - int src_alpha1 = (src_scan[0] + src_scan[1] + src_scan[2]) / 3; - ADJUST_ALPHA(dest_scan[2], r, src_alpha1, nativetext_flags, a); - src_alpha1 = src_alpha1 * a / 255; - if (src_alpha1 == 0) { - dest_scan += Bpp; - src_scan += 3; - continue; - } - dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha1)); - dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha1)); - dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha1)); - dest_scan += Bpp; - src_scan += 3; - continue; - } - int src_alpha = src_scan[0]; - ADJUST_ALPHA(dest_scan[2], r, src_alpha, nativetext_flags, a); - src_alpha = src_alpha * a / 255; - dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); - src_alpha = src_scan[1]; - ADJUST_ALPHA(dest_scan[1], g, src_alpha, nativetext_flags, a); - src_alpha = src_alpha * a / 255; - dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); - src_alpha = src_scan[2]; - ADJUST_ALPHA(dest_scan[0], b, src_alpha, nativetext_flags, a); - src_alpha = src_alpha * a / 255; - dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); - dest_scan += Bpp; - src_scan += 3; - } - } else if (x_subpixel == 1) { - if (bNormal) { - int src_alpha1 = start_col > left ? (src_scan[0] + src_scan[1] + src_scan[-1]) / 3 : (src_scan[0] + src_scan[1]) / 3; - ADJUST_ALPHA(dest_scan[2], r, src_alpha1, nativetext_flags, a); - src_alpha1 = src_alpha1 * a / 255; - dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha1)); - dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha1)); - dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha1)); - dest_scan += Bpp; - src_scan += 3; - } else { - if (start_col > left) { - int src_alpha = src_scan[-1]; - ADJUST_ALPHA(dest_scan[2], r, src_alpha, nativetext_flags, a); - src_alpha = src_alpha * a / 255; - dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); - } - int src_alpha = src_scan[0]; - ADJUST_ALPHA(dest_scan[1], g, src_alpha, nativetext_flags, a); - src_alpha = src_alpha * a / 255; - dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); - src_alpha = src_scan[1]; - ADJUST_ALPHA(dest_scan[0], b, src_alpha, nativetext_flags, a); - src_alpha = src_alpha * a / 255; - dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); - dest_scan += Bpp; - src_scan += 3; - } - for (int col = start_col + 1; col < end_col; col ++) { - if (bNormal) { - int src_alpha1 = (src_scan[0] + src_scan[1] + src_scan[-1]) / 3; - ADJUST_ALPHA(dest_scan[2], r, src_alpha1, nativetext_flags, a); - src_alpha1 = src_alpha1 * a / 255; - if (src_alpha1 == 0) { - dest_scan += Bpp; - src_scan += 3; - continue; - } - dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha1)); - dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha1)); - dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha1)); - dest_scan += Bpp; - src_scan += 3; - continue; - } - int src_alpha = src_scan[-1]; - ADJUST_ALPHA(dest_scan[2], r, src_alpha, nativetext_flags, a); - src_alpha = src_alpha * a / 255; - dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); - src_alpha = src_scan[0]; - ADJUST_ALPHA(dest_scan[1], g, src_alpha, nativetext_flags, a); - src_alpha = src_alpha * a / 255; - dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); - src_alpha = src_scan[1]; - ADJUST_ALPHA(dest_scan[0], b, src_alpha, nativetext_flags, a); - src_alpha = src_alpha * a / 255; - dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); - dest_scan += Bpp; - src_scan += 3; - } - } else { - if (bNormal) { - int src_alpha1 = start_col > left ? (src_scan[0] + src_scan[-2] + src_scan[-1]) / 3 : src_scan[0] / 3; - ADJUST_ALPHA(dest_scan[2], r, src_alpha1, nativetext_flags, a); - src_alpha1 = src_alpha1 * a / 255; - dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha1)); - dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha1)); - dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha1)); - dest_scan += Bpp; - src_scan += 3; - } else { - if (start_col > left) { - int src_alpha = src_scan[-2]; - ADJUST_ALPHA(dest_scan[2], r, src_alpha, nativetext_flags, a); - src_alpha = src_alpha * a / 255; - dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); - src_alpha = src_scan[-1]; - ADJUST_ALPHA(dest_scan[1], g, src_alpha, nativetext_flags, a); - src_alpha = src_alpha * a / 255; - dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); - } - int src_alpha = src_scan[0]; - ADJUST_ALPHA(dest_scan[0], b, src_alpha, nativetext_flags, a); - src_alpha = src_alpha * a / 255; - dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); - dest_scan += Bpp; - src_scan += 3; - } - for (int col = start_col + 1; col < end_col; col ++) { - if (bNormal) { - int src_alpha1 = ((int)(src_scan[0]) + (int)(src_scan[-2]) + (int)(src_scan[-1])) / 3; - ADJUST_ALPHA(dest_scan[2], r, src_alpha1, nativetext_flags, a); - src_alpha1 = src_alpha1 * a / 255; - if (src_alpha1 == 0) { - dest_scan += Bpp; - src_scan += 3; - continue; - } - dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha1)); - dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha1)); - dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha1)); - dest_scan += Bpp; - src_scan += 3; - continue; - } - int src_alpha = src_scan[-2]; - ADJUST_ALPHA(dest_scan[2], r, src_alpha, nativetext_flags, a); - src_alpha = src_alpha * a / 255; - dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); - src_alpha = src_scan[-1]; - ADJUST_ALPHA(dest_scan[1], g, src_alpha, nativetext_flags, a); - src_alpha = src_alpha * a / 255; - dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); - src_alpha = src_scan[0]; - ADJUST_ALPHA(dest_scan[0], b, src_alpha, nativetext_flags, a); - src_alpha = src_alpha * a / 255; - dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); - dest_scan += Bpp; - src_scan += 3; - } - } + uint8_t dest_alpha = + back_alpha + src_alpha1 - back_alpha * src_alpha1 / 255; + dest_scan[3] = dest_alpha; + int alpha_ratio = src_alpha1 * 255 / dest_alpha; + dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE( + FX_GAMMA(dest_scan[2]), r, alpha_ratio)); + dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE( + FX_GAMMA(dest_scan[1]), g, alpha_ratio)); + dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE( + FX_GAMMA(dest_scan[0]), b, alpha_ratio)); + } + dest_scan += 4; + src_scan += 3; + } + } else { + if (start_col > left) { + int src_alpha = src_scan[-2]; + ADJUST_ALPHA(dest_scan[2], r, src_alpha, nativetext_flags, a); + src_alpha = src_alpha * a / 255; + dest_scan[2] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); + src_alpha = src_scan[-1]; + ADJUST_ALPHA(dest_scan[1], g, src_alpha, nativetext_flags, a); + src_alpha = src_alpha * a / 255; + dest_scan[1] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); + } + int src_alpha = src_scan[0]; + ADJUST_ALPHA(dest_scan[0], b, src_alpha, nativetext_flags, a); + src_alpha = src_alpha * a / 255; + dest_scan[0] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); + dest_scan[3] = 255; + dest_scan += 4; + src_scan += 3; + } + for (int col = start_col + 1; col < end_col; col++) { + if (bNormal) { + int src_alpha1 = + (src_scan[-2] + src_scan[-1] + src_scan[0]) / 3; + ADJUST_ALPHA(dest_scan[2], r, src_alpha1, nativetext_flags, a); + src_alpha1 = src_alpha1 * a / 255; + uint8_t back_alpha = dest_scan[3]; + if (back_alpha == 0) { + FXARGB_SETDIB(dest_scan, FXARGB_MAKE(src_alpha1, r, g, b)); + dest_scan += 4; + src_scan += 3; + continue; + } + if (src_alpha1 == 0) { + dest_scan += 4; + src_scan += 3; + continue; } + uint8_t dest_alpha = + back_alpha + src_alpha1 - back_alpha * src_alpha1 / 255; + dest_scan[3] = dest_alpha; + int alpha_ratio = src_alpha1 * 255 / dest_alpha; + dest_scan[2] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, alpha_ratio)); + dest_scan[1] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, alpha_ratio)); + dest_scan[0] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, alpha_ratio)); + dest_scan += 4; + src_scan += 3; + continue; + } + int src_alpha = src_scan[-2]; + ADJUST_ALPHA(dest_scan[2], r, src_alpha, nativetext_flags, a); + src_alpha = src_alpha * a / 255; + dest_scan[2] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); + src_alpha = src_scan[-1]; + ADJUST_ALPHA(dest_scan[1], g, src_alpha, nativetext_flags, a); + src_alpha = src_alpha * a / 255; + dest_scan[1] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); + src_alpha = src_scan[0]; + ADJUST_ALPHA(dest_scan[0], b, src_alpha, nativetext_flags, a); + src_alpha = src_alpha * a / 255; + dest_scan[0] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); + dest_scan[3] = 255; + dest_scan += 4; + src_scan += 3; } + } } - } - if (bitmap.IsAlphaMask()) { - SetBitMask(&bitmap, bmp_rect.left, bmp_rect.top, fill_color, alpha_flag, pIccTransform); + } } else { - SetDIBits(&bitmap, bmp_rect.left, bmp_rect.top); - } - FX_Free(pGlyphAndPos); - return TRUE; -} -FX_BOOL CFX_RenderDevice::DrawTextPath(int nChars, const FXTEXT_CHARPOS* pCharPos, - CFX_Font* pFont, CFX_FontCache* pCache, - FX_FLOAT font_size, const CFX_AffineMatrix* pText2User, - const CFX_AffineMatrix* pUser2Device, const CFX_GraphStateData* pGraphState, - FX_DWORD fill_color, FX_ARGB stroke_color, CFX_PathData* pClippingPath, int nFlag, - int alpha_flag, void* pIccTransform, int blend_type) -{ - if (pCache == NULL) { - pCache = CFX_GEModule::Get()->GetFontCache(); - } - CFX_FaceCache* pFaceCache = pCache->GetCachedFace(pFont); - FX_FONTCACHE_DEFINE(pCache, pFont); - for (int iChar = 0; iChar < nChars; iChar ++) { - const FXTEXT_CHARPOS& charpos = pCharPos[iChar]; - CFX_AffineMatrix matrix; - if (charpos.m_bGlyphAdjust) - matrix.Set(charpos.m_AdjustMatrix[0], charpos.m_AdjustMatrix[1], - charpos.m_AdjustMatrix[2], charpos.m_AdjustMatrix[3], 0, 0); - matrix.Concat(font_size, 0, 0, font_size, charpos.m_OriginX, charpos.m_OriginY); - const CFX_PathData* pPath = pFaceCache->LoadGlyphPath(pFont, charpos.m_GlyphIndex, charpos.m_FontCharWidth); - if (pPath == NULL) { - continue; + for (int row = 0; row < nrows; row++) { + int dest_row = row + top; + if (dest_row < 0 || dest_row >= bitmap.GetHeight()) { + continue; } - matrix.Concat(*pText2User); - CFX_PathData TransformedPath(*pPath); - TransformedPath.Transform(&matrix); - FX_BOOL bHasAlpha = FXGETFLAG_COLORTYPE(alpha_flag) ? - (FXGETFLAG_ALPHA_FILL(alpha_flag) || FXGETFLAG_ALPHA_STROKE(alpha_flag)) : - (fill_color || stroke_color); - if (bHasAlpha) { - int fill_mode = nFlag; - if (FXGETFLAG_COLORTYPE(alpha_flag)) { - if (FXGETFLAG_ALPHA_FILL(alpha_flag)) { - fill_mode |= FXFILL_WINDING; + uint8_t* src_scan = src_buf + row * src_pitch + (start_col - left) * 3; + uint8_t* dest_scan = dest_buf + dest_row * dest_pitch + start_col * Bpp; + if (bBGRStripe) { + if (x_subpixel == 0) { + for (int col = start_col; col < end_col; col++) { + int src_alpha = src_scan[2]; + ADJUST_ALPHA(dest_scan[2], r, src_alpha, nativetext_flags, a); + src_alpha = src_alpha * a / 255; + dest_scan[2] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); + src_alpha = src_scan[1]; + ADJUST_ALPHA(dest_scan[1], g, src_alpha, nativetext_flags, a); + src_alpha = src_alpha * a / 255; + dest_scan[1] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); + src_alpha = src_scan[0]; + ADJUST_ALPHA(dest_scan[0], b, src_alpha, nativetext_flags, a); + src_alpha = src_alpha * a / 255; + dest_scan[0] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); + dest_scan += Bpp; + src_scan += 3; + } + } else if (x_subpixel == 1) { + int src_alpha = src_scan[1]; + ADJUST_ALPHA(dest_scan[2], r, src_alpha, nativetext_flags, a); + src_alpha = src_alpha * a / 255; + dest_scan[2] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); + src_alpha = src_scan[0]; + ADJUST_ALPHA(dest_scan[1], g, src_alpha, nativetext_flags, a); + src_alpha = src_alpha * a / 255; + dest_scan[1] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); + if (start_col > left) { + src_alpha = src_scan[-1]; + ADJUST_ALPHA(dest_scan[0], b, src_alpha, nativetext_flags, a); + src_alpha = src_alpha * a / 255; + dest_scan[0] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); + } + dest_scan += Bpp; + src_scan += 3; + for (int col = start_col + 1; col < end_col - 1; col++) { + int src_alpha = src_scan[1]; + ADJUST_ALPHA(dest_scan[2], r, src_alpha, nativetext_flags, a); + src_alpha = src_alpha * a / 255; + dest_scan[2] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); + src_alpha = src_scan[0]; + ADJUST_ALPHA(dest_scan[1], g, src_alpha, nativetext_flags, a); + src_alpha = src_alpha * a / 255; + dest_scan[1] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); + src_alpha = src_scan[-1]; + ADJUST_ALPHA(dest_scan[0], b, src_alpha, nativetext_flags, a); + src_alpha = src_alpha * a / 255; + dest_scan[0] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); + dest_scan += Bpp; + src_scan += 3; + } + } else { + int src_alpha = src_scan[0]; + ADJUST_ALPHA(dest_scan[2], r, src_alpha, nativetext_flags, a); + src_alpha = src_alpha * a / 255; + dest_scan[2] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); + if (start_col > left) { + src_alpha = src_scan[-1]; + ADJUST_ALPHA(dest_scan[1], g, src_alpha, nativetext_flags, a); + src_alpha = src_alpha * a / 255; + dest_scan[1] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); + src_alpha = src_scan[-2]; + ADJUST_ALPHA(dest_scan[0], b, src_alpha, nativetext_flags, a); + src_alpha = src_alpha * a / 255; + dest_scan[0] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); + } + dest_scan += Bpp; + src_scan += 3; + for (int col = start_col + 1; col < end_col - 1; col++) { + int src_alpha = src_scan[0]; + ADJUST_ALPHA(dest_scan[2], r, src_alpha, nativetext_flags, a); + src_alpha = src_alpha * a / 255; + dest_scan[2] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); + src_alpha = src_scan[-1]; + ADJUST_ALPHA(dest_scan[1], g, src_alpha, nativetext_flags, a); + src_alpha = src_alpha * a / 255; + dest_scan[1] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); + src_alpha = src_scan[-2]; + ADJUST_ALPHA(dest_scan[0], b, src_alpha, nativetext_flags, a); + src_alpha = src_alpha * a / 255; + dest_scan[0] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); + dest_scan += Bpp; + src_scan += 3; + } + } + } else { + if (x_subpixel == 0) { + for (int col = start_col; col < end_col; col++) { + if (bNormal) { + int src_alpha1 = (src_scan[0] + src_scan[1] + src_scan[2]) / 3; + ADJUST_ALPHA(dest_scan[2], r, src_alpha1, nativetext_flags, a); + src_alpha1 = src_alpha1 * a / 255; + if (src_alpha1 == 0) { + dest_scan += Bpp; + src_scan += 3; + continue; } + dest_scan[2] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha1)); + dest_scan[1] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha1)); + dest_scan[0] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha1)); + dest_scan += Bpp; + src_scan += 3; + continue; + } + int src_alpha = src_scan[0]; + ADJUST_ALPHA(dest_scan[2], r, src_alpha, nativetext_flags, a); + src_alpha = src_alpha * a / 255; + dest_scan[2] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); + src_alpha = src_scan[1]; + ADJUST_ALPHA(dest_scan[1], g, src_alpha, nativetext_flags, a); + src_alpha = src_alpha * a / 255; + dest_scan[1] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); + src_alpha = src_scan[2]; + ADJUST_ALPHA(dest_scan[0], b, src_alpha, nativetext_flags, a); + src_alpha = src_alpha * a / 255; + dest_scan[0] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); + dest_scan += Bpp; + src_scan += 3; + } + } else if (x_subpixel == 1) { + if (bNormal) { + int src_alpha1 = + start_col > left + ? (src_scan[0] + src_scan[1] + src_scan[-1]) / 3 + : (src_scan[0] + src_scan[1]) / 3; + ADJUST_ALPHA(dest_scan[2], r, src_alpha1, nativetext_flags, a); + src_alpha1 = src_alpha1 * a / 255; + dest_scan[2] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha1)); + dest_scan[1] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha1)); + dest_scan[0] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha1)); + dest_scan += Bpp; + src_scan += 3; } else { - if (fill_color) { - fill_mode |= FXFILL_WINDING; + if (start_col > left) { + int src_alpha = src_scan[-1]; + ADJUST_ALPHA(dest_scan[2], r, src_alpha, nativetext_flags, a); + src_alpha = src_alpha * a / 255; + dest_scan[2] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); + } + int src_alpha = src_scan[0]; + ADJUST_ALPHA(dest_scan[1], g, src_alpha, nativetext_flags, a); + src_alpha = src_alpha * a / 255; + dest_scan[1] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); + src_alpha = src_scan[1]; + ADJUST_ALPHA(dest_scan[0], b, src_alpha, nativetext_flags, a); + src_alpha = src_alpha * a / 255; + dest_scan[0] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); + dest_scan += Bpp; + src_scan += 3; + } + for (int col = start_col + 1; col < end_col; col++) { + if (bNormal) { + int src_alpha1 = (src_scan[0] + src_scan[1] + src_scan[-1]) / 3; + ADJUST_ALPHA(dest_scan[2], r, src_alpha1, nativetext_flags, a); + src_alpha1 = src_alpha1 * a / 255; + if (src_alpha1 == 0) { + dest_scan += Bpp; + src_scan += 3; + continue; } + dest_scan[2] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha1)); + dest_scan[1] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha1)); + dest_scan[0] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha1)); + dest_scan += Bpp; + src_scan += 3; + continue; + } + int src_alpha = src_scan[-1]; + ADJUST_ALPHA(dest_scan[2], r, src_alpha, nativetext_flags, a); + src_alpha = src_alpha * a / 255; + dest_scan[2] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); + src_alpha = src_scan[0]; + ADJUST_ALPHA(dest_scan[1], g, src_alpha, nativetext_flags, a); + src_alpha = src_alpha * a / 255; + dest_scan[1] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); + src_alpha = src_scan[1]; + ADJUST_ALPHA(dest_scan[0], b, src_alpha, nativetext_flags, a); + src_alpha = src_alpha * a / 255; + dest_scan[0] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); + dest_scan += Bpp; + src_scan += 3; } - fill_mode |= FX_FILL_TEXT_MODE; - if (!DrawPath(&TransformedPath, pUser2Device, pGraphState, fill_color, stroke_color, fill_mode, alpha_flag, pIccTransform, blend_type)) { - return FALSE; + } else { + if (bNormal) { + int src_alpha1 = + start_col > left + ? (src_scan[0] + src_scan[-2] + src_scan[-1]) / 3 + : src_scan[0] / 3; + ADJUST_ALPHA(dest_scan[2], r, src_alpha1, nativetext_flags, a); + src_alpha1 = src_alpha1 * a / 255; + dest_scan[2] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha1)); + dest_scan[1] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha1)); + dest_scan[0] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha1)); + dest_scan += Bpp; + src_scan += 3; + } else { + if (start_col > left) { + int src_alpha = src_scan[-2]; + ADJUST_ALPHA(dest_scan[2], r, src_alpha, nativetext_flags, a); + src_alpha = src_alpha * a / 255; + dest_scan[2] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); + src_alpha = src_scan[-1]; + ADJUST_ALPHA(dest_scan[1], g, src_alpha, nativetext_flags, a); + src_alpha = src_alpha * a / 255; + dest_scan[1] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); + } + int src_alpha = src_scan[0]; + ADJUST_ALPHA(dest_scan[0], b, src_alpha, nativetext_flags, a); + src_alpha = src_alpha * a / 255; + dest_scan[0] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); + dest_scan += Bpp; + src_scan += 3; } + for (int col = start_col + 1; col < end_col; col++) { + if (bNormal) { + int src_alpha1 = ((int)(src_scan[0]) + (int)(src_scan[-2]) + + (int)(src_scan[-1])) / + 3; + ADJUST_ALPHA(dest_scan[2], r, src_alpha1, nativetext_flags, a); + src_alpha1 = src_alpha1 * a / 255; + if (src_alpha1 == 0) { + dest_scan += Bpp; + src_scan += 3; + continue; + } + dest_scan[2] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha1)); + dest_scan[1] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha1)); + dest_scan[0] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha1)); + dest_scan += Bpp; + src_scan += 3; + continue; + } + int src_alpha = src_scan[-2]; + ADJUST_ALPHA(dest_scan[2], r, src_alpha, nativetext_flags, a); + src_alpha = src_alpha * a / 255; + dest_scan[2] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); + src_alpha = src_scan[-1]; + ADJUST_ALPHA(dest_scan[1], g, src_alpha, nativetext_flags, a); + src_alpha = src_alpha * a / 255; + dest_scan[1] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); + src_alpha = src_scan[0]; + ADJUST_ALPHA(dest_scan[0], b, src_alpha, nativetext_flags, a); + src_alpha = src_alpha * a / 255; + dest_scan[0] = FX_GAMMA_INVERSE( + FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); + dest_scan += Bpp; + src_scan += 3; + } + } } - if (pClippingPath) { - pClippingPath->Append(&TransformedPath, pUser2Device); + } + } + } + if (bitmap.IsAlphaMask()) { + SetBitMask(&bitmap, bmp_rect.left, bmp_rect.top, fill_color, alpha_flag, + pIccTransform); + } else { + SetDIBits(&bitmap, bmp_rect.left, bmp_rect.top); + } + FX_Free(pGlyphAndPos); + return TRUE; +} +FX_BOOL CFX_RenderDevice::DrawTextPath(int nChars, + const FXTEXT_CHARPOS* pCharPos, + CFX_Font* pFont, + CFX_FontCache* pCache, + FX_FLOAT font_size, + const CFX_AffineMatrix* pText2User, + const CFX_AffineMatrix* pUser2Device, + const CFX_GraphStateData* pGraphState, + FX_DWORD fill_color, + FX_ARGB stroke_color, + CFX_PathData* pClippingPath, + int nFlag, + int alpha_flag, + void* pIccTransform, + int blend_type) { + if (pCache == NULL) { + pCache = CFX_GEModule::Get()->GetFontCache(); + } + CFX_FaceCache* pFaceCache = pCache->GetCachedFace(pFont); + FX_FONTCACHE_DEFINE(pCache, pFont); + for (int iChar = 0; iChar < nChars; iChar++) { + const FXTEXT_CHARPOS& charpos = pCharPos[iChar]; + CFX_AffineMatrix matrix; + if (charpos.m_bGlyphAdjust) + matrix.Set(charpos.m_AdjustMatrix[0], charpos.m_AdjustMatrix[1], + charpos.m_AdjustMatrix[2], charpos.m_AdjustMatrix[3], 0, 0); + matrix.Concat(font_size, 0, 0, font_size, charpos.m_OriginX, + charpos.m_OriginY); + const CFX_PathData* pPath = pFaceCache->LoadGlyphPath( + pFont, charpos.m_GlyphIndex, charpos.m_FontCharWidth); + if (pPath == NULL) { + continue; + } + matrix.Concat(*pText2User); + CFX_PathData TransformedPath(*pPath); + TransformedPath.Transform(&matrix); + FX_BOOL bHasAlpha = FXGETFLAG_COLORTYPE(alpha_flag) + ? (FXGETFLAG_ALPHA_FILL(alpha_flag) || + FXGETFLAG_ALPHA_STROKE(alpha_flag)) + : (fill_color || stroke_color); + if (bHasAlpha) { + int fill_mode = nFlag; + if (FXGETFLAG_COLORTYPE(alpha_flag)) { + if (FXGETFLAG_ALPHA_FILL(alpha_flag)) { + fill_mode |= FXFILL_WINDING; } + } else { + if (fill_color) { + fill_mode |= FXFILL_WINDING; + } + } + fill_mode |= FX_FILL_TEXT_MODE; + if (!DrawPath(&TransformedPath, pUser2Device, pGraphState, fill_color, + stroke_color, fill_mode, alpha_flag, pIccTransform, + blend_type)) { + return FALSE; + } } - return TRUE; + if (pClippingPath) { + pClippingPath->Append(&TransformedPath, pUser2Device); + } + } + return TRUE; } -CFX_FontCache::~CFX_FontCache() -{ - FreeCache(TRUE); +CFX_FontCache::~CFX_FontCache() { + FreeCache(TRUE); } -CFX_FaceCache* CFX_FontCache::GetCachedFace(CFX_Font* pFont) -{ - FXFT_Face internal_face = pFont->GetFace(); - const FX_BOOL bExternal = internal_face == nullptr; - FXFT_Face face = bExternal ? - (FXFT_Face)pFont->GetSubstFont()->m_ExtHandle : internal_face; - CFX_FTCacheMap& map = bExternal ? m_ExtFaceMap : m_FTFaceMap; - auto it = map.find(face); - if (it != map.end()) { - CFX_CountedFaceCache* counted_face_cache = it->second; - counted_face_cache->m_nCount++; - return counted_face_cache->m_Obj; - } +CFX_FaceCache* CFX_FontCache::GetCachedFace(CFX_Font* pFont) { + FXFT_Face internal_face = pFont->GetFace(); + const FX_BOOL bExternal = internal_face == nullptr; + FXFT_Face face = + bExternal ? (FXFT_Face)pFont->GetSubstFont()->m_ExtHandle : internal_face; + CFX_FTCacheMap& map = bExternal ? m_ExtFaceMap : m_FTFaceMap; + auto it = map.find(face); + if (it != map.end()) { + CFX_CountedFaceCache* counted_face_cache = it->second; + counted_face_cache->m_nCount++; + return counted_face_cache->m_Obj; + } - CFX_FaceCache* face_cache = new CFX_FaceCache(bExternal ? nullptr : face); - CFX_CountedFaceCache* counted_face_cache = new CFX_CountedFaceCache; - counted_face_cache->m_nCount = 2; - counted_face_cache->m_Obj = face_cache; - map[face] = counted_face_cache; - return face_cache; + CFX_FaceCache* face_cache = new CFX_FaceCache(bExternal ? nullptr : face); + CFX_CountedFaceCache* counted_face_cache = new CFX_CountedFaceCache; + counted_face_cache->m_nCount = 2; + counted_face_cache->m_Obj = face_cache; + map[face] = counted_face_cache; + return face_cache; } -void CFX_FontCache::ReleaseCachedFace(CFX_Font* pFont) -{ - FXFT_Face internal_face = pFont->GetFace(); - const FX_BOOL bExternal = internal_face == nullptr; - FXFT_Face face = bExternal ? - (FXFT_Face)pFont->GetSubstFont()->m_ExtHandle : internal_face; - CFX_FTCacheMap& map = bExternal ? m_ExtFaceMap : m_FTFaceMap; +void CFX_FontCache::ReleaseCachedFace(CFX_Font* pFont) { + FXFT_Face internal_face = pFont->GetFace(); + const FX_BOOL bExternal = internal_face == nullptr; + FXFT_Face face = + bExternal ? (FXFT_Face)pFont->GetSubstFont()->m_ExtHandle : internal_face; + CFX_FTCacheMap& map = bExternal ? m_ExtFaceMap : m_FTFaceMap; - auto it = map.find(face); - if (it == map.end()) - return; + auto it = map.find(face); + if (it == map.end()) + return; - CFX_CountedFaceCache* counted_face_cache = it->second; - if (counted_face_cache->m_nCount > 1) { - counted_face_cache->m_nCount--; - } + CFX_CountedFaceCache* counted_face_cache = it->second; + if (counted_face_cache->m_nCount > 1) { + counted_face_cache->m_nCount--; + } } -void CFX_FontCache::FreeCache(FX_BOOL bRelease) -{ - for (auto it = m_FTFaceMap.begin(); it != m_FTFaceMap.end();) { - auto curr_it = it++; - CFX_CountedFaceCache* cache = curr_it->second; - if (bRelease || cache->m_nCount < 2) { - delete cache->m_Obj; - delete cache; - m_FTFaceMap.erase(curr_it); - } - } +void CFX_FontCache::FreeCache(FX_BOOL bRelease) { + for (auto it = m_FTFaceMap.begin(); it != m_FTFaceMap.end();) { + auto curr_it = it++; + CFX_CountedFaceCache* cache = curr_it->second; + if (bRelease || cache->m_nCount < 2) { + delete cache->m_Obj; + delete cache; + m_FTFaceMap.erase(curr_it); + } + } - for (auto it = m_ExtFaceMap.begin(); it != m_ExtFaceMap.end();) { - auto curr_it = it++; - CFX_CountedFaceCache* cache = curr_it->second; - if (bRelease || cache->m_nCount < 2) { - delete cache->m_Obj; - delete cache; - m_ExtFaceMap.erase(curr_it); - } - } + for (auto it = m_ExtFaceMap.begin(); it != m_ExtFaceMap.end();) { + auto curr_it = it++; + CFX_CountedFaceCache* cache = curr_it->second; + if (bRelease || cache->m_nCount < 2) { + delete cache->m_Obj; + delete cache; + m_ExtFaceMap.erase(curr_it); + } + } } -CFX_FaceCache::CFX_FaceCache(FXFT_Face face) -{ - m_Face = face; -} -CFX_FaceCache::~CFX_FaceCache() -{ - FX_POSITION pos = m_SizeMap.GetStartPosition(); - CFX_ByteString Key; - CFX_SizeGlyphCache* pSizeCache = NULL; - while(pos) { - m_SizeMap.GetNextAssoc( pos, Key, (void*&)pSizeCache); - delete pSizeCache; - } - m_SizeMap.RemoveAll(); - pos = m_PathMap.GetStartPosition(); - void* key1; - CFX_PathData* pPath; - while (pos) { - m_PathMap.GetNextAssoc(pos, key1, (void*&)pPath); - delete pPath; - } - m_PathMap.RemoveAll(); +CFX_FaceCache::CFX_FaceCache(FXFT_Face face) { + m_Face = face; } -#if _FXM_PLATFORM_ != _FXM_PLATFORM_APPLE_ -void CFX_FaceCache::InitPlatform() -{ +CFX_FaceCache::~CFX_FaceCache() { + FX_POSITION pos = m_SizeMap.GetStartPosition(); + CFX_ByteString Key; + CFX_SizeGlyphCache* pSizeCache = NULL; + while (pos) { + m_SizeMap.GetNextAssoc(pos, Key, (void*&)pSizeCache); + delete pSizeCache; + } + m_SizeMap.RemoveAll(); + pos = m_PathMap.GetStartPosition(); + void* key1; + CFX_PathData* pPath; + while (pos) { + m_PathMap.GetNextAssoc(pos, key1, (void*&)pPath); + delete pPath; + } + m_PathMap.RemoveAll(); } +#if _FXM_PLATFORM_ != _FXM_PLATFORM_APPLE_ +void CFX_FaceCache::InitPlatform() {} #endif -CFX_GlyphBitmap* CFX_FaceCache::LookUpGlyphBitmap(CFX_Font* pFont, const CFX_AffineMatrix* pMatrix, - CFX_ByteStringC& FaceGlyphsKey, FX_DWORD glyph_index, FX_BOOL bFontStyle, - int dest_width, int anti_alias) -{ - CFX_SizeGlyphCache* pSizeCache = NULL; - if (!m_SizeMap.Lookup(FaceGlyphsKey, (void*&)pSizeCache)) { - pSizeCache = new CFX_SizeGlyphCache; - m_SizeMap.SetAt(FaceGlyphsKey, pSizeCache); - } - CFX_GlyphBitmap* pGlyphBitmap = NULL; - if (pSizeCache->m_GlyphMap.Lookup((void*)(uintptr_t)glyph_index, (void*&)pGlyphBitmap)) { - return pGlyphBitmap; - } - pGlyphBitmap = RenderGlyph(pFont, glyph_index, bFontStyle, pMatrix, dest_width, anti_alias); - if (pGlyphBitmap == NULL) { - return NULL; - } - pSizeCache->m_GlyphMap.SetAt((void*)(uintptr_t)glyph_index, pGlyphBitmap); +CFX_GlyphBitmap* CFX_FaceCache::LookUpGlyphBitmap( + CFX_Font* pFont, + const CFX_AffineMatrix* pMatrix, + CFX_ByteStringC& FaceGlyphsKey, + FX_DWORD glyph_index, + FX_BOOL bFontStyle, + int dest_width, + int anti_alias) { + CFX_SizeGlyphCache* pSizeCache = NULL; + if (!m_SizeMap.Lookup(FaceGlyphsKey, (void*&)pSizeCache)) { + pSizeCache = new CFX_SizeGlyphCache; + m_SizeMap.SetAt(FaceGlyphsKey, pSizeCache); + } + CFX_GlyphBitmap* pGlyphBitmap = NULL; + if (pSizeCache->m_GlyphMap.Lookup((void*)(uintptr_t)glyph_index, + (void*&)pGlyphBitmap)) { return pGlyphBitmap; + } + pGlyphBitmap = RenderGlyph(pFont, glyph_index, bFontStyle, pMatrix, + dest_width, anti_alias); + if (pGlyphBitmap == NULL) { + return NULL; + } + pSizeCache->m_GlyphMap.SetAt((void*)(uintptr_t)glyph_index, pGlyphBitmap); + return pGlyphBitmap; } -const CFX_GlyphBitmap* CFX_FaceCache::LoadGlyphBitmap(CFX_Font* pFont, FX_DWORD glyph_index, FX_BOOL bFontStyle, const CFX_AffineMatrix* pMatrix, - int dest_width, int anti_alias, int& text_flags) -{ - if (glyph_index == (FX_DWORD) - 1) { - return NULL; - } - _CFX_UniqueKeyGen keygen; -#if _FXM_PLATFORM_ != _FXM_PLATFORM_APPLE_ +const CFX_GlyphBitmap* CFX_FaceCache::LoadGlyphBitmap( + CFX_Font* pFont, + FX_DWORD glyph_index, + FX_BOOL bFontStyle, + const CFX_AffineMatrix* pMatrix, + int dest_width, + int anti_alias, + int& text_flags) { + if (glyph_index == (FX_DWORD)-1) { + return NULL; + } + _CFX_UniqueKeyGen keygen; +#if _FXM_PLATFORM_ != _FXM_PLATFORM_APPLE_ + if (pFont->GetSubstFont()) + keygen.Generate(9, (int)(pMatrix->a * 10000), (int)(pMatrix->b * 10000), + (int)(pMatrix->c * 10000), (int)(pMatrix->d * 10000), + dest_width, anti_alias, pFont->GetSubstFont()->m_Weight, + pFont->GetSubstFont()->m_ItalicAngle, pFont->IsVertical()); + else + keygen.Generate(6, (int)(pMatrix->a * 10000), (int)(pMatrix->b * 10000), + (int)(pMatrix->c * 10000), (int)(pMatrix->d * 10000), + dest_width, anti_alias); +#else + if (text_flags & FXTEXT_NO_NATIVETEXT) { if (pFont->GetSubstFont()) - keygen.Generate(9, (int)(pMatrix->a * 10000), (int)(pMatrix->b * 10000), - (int)(pMatrix->c * 10000), (int)(pMatrix->d * 10000), dest_width, anti_alias, - pFont->GetSubstFont()->m_Weight, pFont->GetSubstFont()->m_ItalicAngle, pFont->IsVertical()); + keygen.Generate(9, (int)(pMatrix->a * 10000), (int)(pMatrix->b * 10000), + (int)(pMatrix->c * 10000), (int)(pMatrix->d * 10000), + dest_width, anti_alias, pFont->GetSubstFont()->m_Weight, + pFont->GetSubstFont()->m_ItalicAngle, + pFont->IsVertical()); else - keygen.Generate(6, (int)(pMatrix->a * 10000), (int)(pMatrix->b * 10000), - (int)(pMatrix->c * 10000), (int)(pMatrix->d * 10000), dest_width, anti_alias); -#else - if (text_flags & FXTEXT_NO_NATIVETEXT) { - if (pFont->GetSubstFont()) - keygen.Generate(9, (int)(pMatrix->a * 10000), (int)(pMatrix->b * 10000), - (int)(pMatrix->c * 10000), (int)(pMatrix->d * 10000), dest_width, anti_alias, - pFont->GetSubstFont()->m_Weight, pFont->GetSubstFont()->m_ItalicAngle, pFont->IsVertical()); - else - keygen.Generate(6, (int)(pMatrix->a * 10000), (int)(pMatrix->b * 10000), - (int)(pMatrix->c * 10000), (int)(pMatrix->d * 10000), dest_width, anti_alias); - } else { - if (pFont->GetSubstFont()) - keygen.Generate(10, (int)(pMatrix->a * 10000), (int)(pMatrix->b * 10000), - (int)(pMatrix->c * 10000), (int)(pMatrix->d * 10000), dest_width, anti_alias, - pFont->GetSubstFont()->m_Weight, pFont->GetSubstFont()->m_ItalicAngle, pFont->IsVertical(), 3); - else - keygen.Generate(7, (int)(pMatrix->a * 10000), (int)(pMatrix->b * 10000), - (int)(pMatrix->c * 10000), (int)(pMatrix->d * 10000), dest_width, anti_alias, 3); - } -#endif - CFX_ByteStringC FaceGlyphsKey(keygen.m_Key, keygen.m_KeyLen); -#if _FXM_PLATFORM_ != _FXM_PLATFORM_APPLE_ - return LookUpGlyphBitmap(pFont, pMatrix, FaceGlyphsKey, glyph_index, bFontStyle, dest_width, anti_alias); -#else - if (text_flags & FXTEXT_NO_NATIVETEXT) { - return LookUpGlyphBitmap(pFont, pMatrix, FaceGlyphsKey, glyph_index, bFontStyle, dest_width, anti_alias); - } - CFX_GlyphBitmap* pGlyphBitmap; - CFX_SizeGlyphCache* pSizeCache = NULL; - if (m_SizeMap.Lookup(FaceGlyphsKey, (void*&)pSizeCache)) { - if (pSizeCache->m_GlyphMap.Lookup((void*)(uintptr_t)glyph_index, (void*&)pGlyphBitmap)) { - return pGlyphBitmap; - } - pGlyphBitmap = RenderGlyph_Nativetext(pFont, glyph_index, pMatrix, dest_width, anti_alias); - if (pGlyphBitmap) { - pSizeCache->m_GlyphMap.SetAt((void*)(uintptr_t)glyph_index, pGlyphBitmap); - return pGlyphBitmap; - } - } else { - pGlyphBitmap = RenderGlyph_Nativetext(pFont, glyph_index, pMatrix, dest_width, anti_alias); - if (pGlyphBitmap) { - pSizeCache = new CFX_SizeGlyphCache; - m_SizeMap.SetAt(FaceGlyphsKey, pSizeCache); - pSizeCache->m_GlyphMap.SetAt((void*)(uintptr_t)glyph_index, pGlyphBitmap); - return pGlyphBitmap; - } - } + keygen.Generate(6, (int)(pMatrix->a * 10000), (int)(pMatrix->b * 10000), + (int)(pMatrix->c * 10000), (int)(pMatrix->d * 10000), + dest_width, anti_alias); + } else { if (pFont->GetSubstFont()) - keygen.Generate(9, (int)(pMatrix->a * 10000), (int)(pMatrix->b * 10000), - (int)(pMatrix->c * 10000), (int)(pMatrix->d * 10000), dest_width, anti_alias, - pFont->GetSubstFont()->m_Weight, pFont->GetSubstFont()->m_ItalicAngle, pFont->IsVertical()); + keygen.Generate(10, (int)(pMatrix->a * 10000), (int)(pMatrix->b * 10000), + (int)(pMatrix->c * 10000), (int)(pMatrix->d * 10000), + dest_width, anti_alias, pFont->GetSubstFont()->m_Weight, + pFont->GetSubstFont()->m_ItalicAngle, pFont->IsVertical(), + 3); else - keygen.Generate(6, (int)(pMatrix->a * 10000), (int)(pMatrix->b * 10000), - (int)(pMatrix->c * 10000), (int)(pMatrix->d * 10000), dest_width, anti_alias); - CFX_ByteStringC FaceGlyphsKey2(keygen.m_Key, keygen.m_KeyLen); - text_flags |= FXTEXT_NO_NATIVETEXT; - return LookUpGlyphBitmap(pFont, pMatrix, FaceGlyphsKey2, glyph_index, bFontStyle, dest_width, anti_alias); + keygen.Generate(7, (int)(pMatrix->a * 10000), (int)(pMatrix->b * 10000), + (int)(pMatrix->c * 10000), (int)(pMatrix->d * 10000), + dest_width, anti_alias, 3); + } +#endif + CFX_ByteStringC FaceGlyphsKey(keygen.m_Key, keygen.m_KeyLen); +#if _FXM_PLATFORM_ != _FXM_PLATFORM_APPLE_ + return LookUpGlyphBitmap(pFont, pMatrix, FaceGlyphsKey, glyph_index, + bFontStyle, dest_width, anti_alias); +#else + if (text_flags & FXTEXT_NO_NATIVETEXT) { + return LookUpGlyphBitmap(pFont, pMatrix, FaceGlyphsKey, glyph_index, + bFontStyle, dest_width, anti_alias); + } + CFX_GlyphBitmap* pGlyphBitmap; + CFX_SizeGlyphCache* pSizeCache = NULL; + if (m_SizeMap.Lookup(FaceGlyphsKey, (void*&)pSizeCache)) { + if (pSizeCache->m_GlyphMap.Lookup((void*)(uintptr_t)glyph_index, + (void*&)pGlyphBitmap)) { + return pGlyphBitmap; + } + pGlyphBitmap = RenderGlyph_Nativetext(pFont, glyph_index, pMatrix, + dest_width, anti_alias); + if (pGlyphBitmap) { + pSizeCache->m_GlyphMap.SetAt((void*)(uintptr_t)glyph_index, pGlyphBitmap); + return pGlyphBitmap; + } + } else { + pGlyphBitmap = RenderGlyph_Nativetext(pFont, glyph_index, pMatrix, + dest_width, anti_alias); + if (pGlyphBitmap) { + pSizeCache = new CFX_SizeGlyphCache; + m_SizeMap.SetAt(FaceGlyphsKey, pSizeCache); + pSizeCache->m_GlyphMap.SetAt((void*)(uintptr_t)glyph_index, pGlyphBitmap); + return pGlyphBitmap; + } + } + if (pFont->GetSubstFont()) + keygen.Generate(9, (int)(pMatrix->a * 10000), (int)(pMatrix->b * 10000), + (int)(pMatrix->c * 10000), (int)(pMatrix->d * 10000), + dest_width, anti_alias, pFont->GetSubstFont()->m_Weight, + pFont->GetSubstFont()->m_ItalicAngle, pFont->IsVertical()); + else + keygen.Generate(6, (int)(pMatrix->a * 10000), (int)(pMatrix->b * 10000), + (int)(pMatrix->c * 10000), (int)(pMatrix->d * 10000), + dest_width, anti_alias); + CFX_ByteStringC FaceGlyphsKey2(keygen.m_Key, keygen.m_KeyLen); + text_flags |= FXTEXT_NO_NATIVETEXT; + return LookUpGlyphBitmap(pFont, pMatrix, FaceGlyphsKey2, glyph_index, + bFontStyle, dest_width, anti_alias); #endif } -CFX_SizeGlyphCache::~CFX_SizeGlyphCache() -{ - FX_POSITION pos = m_GlyphMap.GetStartPosition(); - void* Key; - CFX_GlyphBitmap* pGlyphBitmap = NULL; - while(pos) { - m_GlyphMap.GetNextAssoc(pos, Key, (void*&)pGlyphBitmap); - delete pGlyphBitmap; - } - m_GlyphMap.RemoveAll(); +CFX_SizeGlyphCache::~CFX_SizeGlyphCache() { + FX_POSITION pos = m_GlyphMap.GetStartPosition(); + void* Key; + CFX_GlyphBitmap* pGlyphBitmap = NULL; + while (pos) { + m_GlyphMap.GetNextAssoc(pos, Key, (void*&)pGlyphBitmap); + delete pGlyphBitmap; + } + m_GlyphMap.RemoveAll(); } -#define CONTRAST_RAMP_STEP 1 -void CFX_Font::AdjustMMParams(int glyph_index, int dest_width, int weight) -{ - FXFT_MM_Var pMasters = NULL; - FXFT_Get_MM_Var(m_Face, &pMasters); - if (pMasters == NULL) { - return; - } - long coords[2]; - if (weight == 0) { - coords[0] = FXFT_Get_MM_Axis_Def(FXFT_Get_MM_Axis(pMasters, 0)) / 65536; - } else { - coords[0] = weight; - } - if (dest_width == 0) { - coords[1] = FXFT_Get_MM_Axis_Def(FXFT_Get_MM_Axis(pMasters, 1)) / 65536; - } else { - int min_param = FXFT_Get_MM_Axis_Min(FXFT_Get_MM_Axis(pMasters, 1)) / 65536; - int max_param = FXFT_Get_MM_Axis_Max(FXFT_Get_MM_Axis(pMasters, 1)) / 65536; - coords[1] = min_param; - int error = FXFT_Set_MM_Design_Coordinates(m_Face, 2, coords); - error = FXFT_Load_Glyph(m_Face, glyph_index, FXFT_LOAD_NO_SCALE | FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH); - int min_width = FXFT_Get_Glyph_HoriAdvance(m_Face) * 1000 / FXFT_Get_Face_UnitsPerEM(m_Face); - coords[1] = max_param; - error = FXFT_Set_MM_Design_Coordinates(m_Face, 2, coords); - error = FXFT_Load_Glyph(m_Face, glyph_index, FXFT_LOAD_NO_SCALE | FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH); - int max_width = FXFT_Get_Glyph_HoriAdvance(m_Face) * 1000 / FXFT_Get_Face_UnitsPerEM(m_Face); - if (max_width == min_width) { - return; - } - int param = min_param + (max_param - min_param) * (dest_width - min_width) / (max_width - min_width); - coords[1] = param; - } - FXFT_Free(m_Face, pMasters); - FXFT_Set_MM_Design_Coordinates(m_Face, 2, coords); +#define CONTRAST_RAMP_STEP 1 +void CFX_Font::AdjustMMParams(int glyph_index, int dest_width, int weight) { + FXFT_MM_Var pMasters = NULL; + FXFT_Get_MM_Var(m_Face, &pMasters); + if (pMasters == NULL) { + return; + } + long coords[2]; + if (weight == 0) { + coords[0] = FXFT_Get_MM_Axis_Def(FXFT_Get_MM_Axis(pMasters, 0)) / 65536; + } else { + coords[0] = weight; + } + if (dest_width == 0) { + coords[1] = FXFT_Get_MM_Axis_Def(FXFT_Get_MM_Axis(pMasters, 1)) / 65536; + } else { + int min_param = FXFT_Get_MM_Axis_Min(FXFT_Get_MM_Axis(pMasters, 1)) / 65536; + int max_param = FXFT_Get_MM_Axis_Max(FXFT_Get_MM_Axis(pMasters, 1)) / 65536; + coords[1] = min_param; + int error = FXFT_Set_MM_Design_Coordinates(m_Face, 2, coords); + error = FXFT_Load_Glyph( + m_Face, glyph_index, + FXFT_LOAD_NO_SCALE | FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH); + int min_width = FXFT_Get_Glyph_HoriAdvance(m_Face) * 1000 / + FXFT_Get_Face_UnitsPerEM(m_Face); + coords[1] = max_param; + error = FXFT_Set_MM_Design_Coordinates(m_Face, 2, coords); + error = FXFT_Load_Glyph( + m_Face, glyph_index, + FXFT_LOAD_NO_SCALE | FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH); + int max_width = FXFT_Get_Glyph_HoriAdvance(m_Face) * 1000 / + FXFT_Get_Face_UnitsPerEM(m_Face); + if (max_width == min_width) { + return; + } + int param = min_param + + (max_param - min_param) * (dest_width - min_width) / + (max_width - min_width); + coords[1] = param; + } + FXFT_Free(m_Face, pMasters); + FXFT_Set_MM_Design_Coordinates(m_Face, 2, coords); } static const size_t ANGLESKEW_ARRAY_SIZE = 30; static const char g_AngleSkew[ANGLESKEW_ARRAY_SIZE] = { - 0, 2, 3, 5, 7, 9, 11, 12, 14, 16, - 18, 19, 21, 23, 25, 27, 29, 31, 32, 34, - 36, 38, 40, 42, 45, 47, 49, 51, 53, 55, + 0, 2, 3, 5, 7, 9, 11, 12, 14, 16, 18, 19, 21, 23, 25, + 27, 29, 31, 32, 34, 36, 38, 40, 42, 45, 47, 49, 51, 53, 55, }; static const size_t WEIGHTPOW_ARRAY_SIZE = 100; static const uint8_t g_WeightPow[WEIGHTPOW_ARRAY_SIZE] = { - 0, 3, 6, 7, 8, 9, 11, 12, 14, 15, 16, 17, 18, 19, 20, - 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 35, 36, 36, - 37, 37, 37, 38, 38, 38, 39, 39, 39, 40, 40, 40, 41, 41, 41, 42, 42, 42, - 42, 43, 43, 43, 44, 44, 44, 44, 45, 45, 45, 45, 46, 46, 46, 46, 47, 47, - 47, 47, 48, 48, 48, 48, 48, 49, 49, 49, 49, 50, 50, 50, 50, 50, 51, 51, - 51, 51, 51, 52, 52, 52, 52, 52, 53, 53, 53, 53, 53, + 0, 3, 6, 7, 8, 9, 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, + 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 35, 36, 36, 37, + 37, 37, 38, 38, 38, 39, 39, 39, 40, 40, 40, 41, 41, 41, 42, 42, 42, + 42, 43, 43, 43, 44, 44, 44, 44, 45, 45, 45, 45, 46, 46, 46, 46, 47, + 47, 47, 47, 48, 48, 48, 48, 48, 49, 49, 49, 49, 50, 50, 50, 50, 50, + 51, 51, 51, 51, 51, 52, 52, 52, 52, 52, 53, 53, 53, 53, 53, }; static const uint8_t g_WeightPow_11[WEIGHTPOW_ARRAY_SIZE] = { - 0, 4, 7, 8, 9, 10, 12, 13, 15, 17, 18, 19, 20, 21, 22, - 23, 24, 25, 26, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 39, 39, 40, 40, - 41, 41, 41, 42, 42, 42, 43, 43, 43, 44, 44, 44, 45, 45, 45, 46, 46, 46, - 46, 43, 47, 47, 48, 48, 48, 48, 45, 50, 50, 50, 46, 51, 51, 51, 52, 52, - 52, 52, 53, 53, 53, 53, 53, 54, 54, 54, 54, 55, 55, 55, 55, 55, 56, 56, - 56, 56, 56, 57, 57, 57, 57, 57, 58, 58, 58, 58, 58, + 0, 4, 7, 8, 9, 10, 12, 13, 15, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 39, 39, 40, 40, 41, + 41, 41, 42, 42, 42, 43, 43, 43, 44, 44, 44, 45, 45, 45, 46, 46, 46, + 46, 43, 47, 47, 48, 48, 48, 48, 45, 50, 50, 50, 46, 51, 51, 51, 52, + 52, 52, 52, 53, 53, 53, 53, 53, 54, 54, 54, 54, 55, 55, 55, 55, 55, + 56, 56, 56, 56, 56, 57, 57, 57, 57, 57, 58, 58, 58, 58, 58, }; static const uint8_t g_WeightPow_SHIFTJIS[WEIGHTPOW_ARRAY_SIZE] = { - 0, 0, 1, 2, 3, 4, 5, 7, 8, 10, 11, 13, 14, 16, 17, 19, 21, 22, 24, 26, 28, - 30, 32, 33, 35, 37, 39, 41, 43, 45, 48, 48, 48, 48, 49, 49, 49, 50, 50, 50, 50, - 51, 51, 51, 51, 52, 52, 52, 52, 52, 53, 53, 53, 53, 53, 54, 54, 54, 54, 54, 55, 55, - 55, 55, 55, 56, 56, 56, 56, 56 , 56, 57, 57, 57 , 57 , 57, 57, 57, 58, 58, 58, 58, 58, - 58, 58, 59, 59, 59, 59, 59, 59, 59, 60, 60, 60, 60, 60, 60, 60, 60, + 0, 0, 1, 2, 3, 4, 5, 7, 8, 10, 11, 13, 14, 16, 17, 19, 21, + 22, 24, 26, 28, 30, 32, 33, 35, 37, 39, 41, 43, 45, 48, 48, 48, 48, + 49, 49, 49, 50, 50, 50, 50, 51, 51, 51, 51, 52, 52, 52, 52, 52, 53, + 53, 53, 53, 53, 54, 54, 54, 54, 54, 55, 55, 55, 55, 55, 56, 56, 56, + 56, 56, 56, 57, 57, 57, 57, 57, 57, 57, 58, 58, 58, 58, 58, 58, 58, + 59, 59, 59, 59, 59, 59, 59, 60, 60, 60, 60, 60, 60, 60, 60, }; -static void _GammaAdjust(uint8_t* pData, int nWid, int nHei, int src_pitch, const uint8_t* gammaTable) -{ - int count = nHei * src_pitch; - for(int i = 0; i < count; i++) { - pData[i] = gammaTable[pData[i]]; - } +static void _GammaAdjust(uint8_t* pData, + int nWid, + int nHei, + int src_pitch, + const uint8_t* gammaTable) { + int count = nHei * src_pitch; + for (int i = 0; i < count; i++) { + pData[i] = gammaTable[pData[i]]; + } } -static void _ContrastAdjust(uint8_t* pDataIn, uint8_t* pDataOut, int nWid, int nHei, int nSrcRowBytes, int nDstRowBytes) -{ - int col, row, temp; - int max = 0, min = 255; - FX_FLOAT rate; - for (row = 0; row < nHei; row ++) { - uint8_t* pRow = pDataIn + row * nSrcRowBytes; - for (col = 0; col < nWid; col++) { - temp = *pRow ++; - if (temp > max) { - max = temp; - } - if (temp < min) { - min = temp; - } - } - } - temp = max - min; - if (0 == temp || 255 == temp) { - int rowbytes = FXSYS_abs(nSrcRowBytes) > nDstRowBytes ? nDstRowBytes : FXSYS_abs(nSrcRowBytes); - for (row = 0; row < nHei; row ++) { - FXSYS_memcpy(pDataOut + row * nDstRowBytes, pDataIn + row * nSrcRowBytes, rowbytes); - } - return; - } - rate = 255.f / temp; - for (row = 0; row < nHei; row ++) { - uint8_t* pSrcRow = pDataIn + row * nSrcRowBytes; - uint8_t* pDstRow = pDataOut + row * nDstRowBytes; - for (col = 0; col < nWid; col ++) { - temp = (int)((*(pSrcRow++) - min) * rate + 0.5); - if (temp > 255) { - temp = 255; - } else if (temp < 0) { - temp = 0; - } - *pDstRow ++ = (uint8_t)temp; - } - } +static void _ContrastAdjust(uint8_t* pDataIn, + uint8_t* pDataOut, + int nWid, + int nHei, + int nSrcRowBytes, + int nDstRowBytes) { + int col, row, temp; + int max = 0, min = 255; + FX_FLOAT rate; + for (row = 0; row < nHei; row++) { + uint8_t* pRow = pDataIn + row * nSrcRowBytes; + for (col = 0; col < nWid; col++) { + temp = *pRow++; + if (temp > max) { + max = temp; + } + if (temp < min) { + min = temp; + } + } + } + temp = max - min; + if (0 == temp || 255 == temp) { + int rowbytes = FXSYS_abs(nSrcRowBytes) > nDstRowBytes + ? nDstRowBytes + : FXSYS_abs(nSrcRowBytes); + for (row = 0; row < nHei; row++) { + FXSYS_memcpy(pDataOut + row * nDstRowBytes, pDataIn + row * nSrcRowBytes, + rowbytes); + } + return; + } + rate = 255.f / temp; + for (row = 0; row < nHei; row++) { + uint8_t* pSrcRow = pDataIn + row * nSrcRowBytes; + uint8_t* pDstRow = pDataOut + row * nDstRowBytes; + for (col = 0; col < nWid; col++) { + temp = (int)((*(pSrcRow++) - min) * rate + 0.5); + if (temp > 255) { + temp = 255; + } else if (temp < 0) { + temp = 0; + } + *pDstRow++ = (uint8_t)temp; + } + } } -CFX_GlyphBitmap* CFX_FaceCache::RenderGlyph(CFX_Font* pFont, FX_DWORD glyph_index, FX_BOOL bFontStyle, - const CFX_AffineMatrix* pMatrix, int dest_width, int anti_alias) -{ - if (m_Face == NULL) { - return NULL; - } - FXFT_Matrix ft_matrix; - ft_matrix.xx = (signed long)(pMatrix->GetA() / 64 * 65536); - ft_matrix.xy = (signed long)(pMatrix->GetC() / 64 * 65536); - ft_matrix.yx = (signed long)(pMatrix->GetB() / 64 * 65536); - ft_matrix.yy = (signed long)(pMatrix->GetD() / 64 * 65536); - FX_BOOL bUseCJKSubFont = FALSE; - const CFX_SubstFont* pSubstFont = pFont->GetSubstFont(); - if (pSubstFont) { - bUseCJKSubFont = pSubstFont->m_bSubstOfCJK && bFontStyle; - int skew = 0; - if (bUseCJKSubFont) { - skew = pSubstFont->m_bItlicCJK ? -15 : 0; - } else { - skew = pSubstFont->m_ItalicAngle; - } - if (skew) { - skew = skew <= -ANGLESKEW_ARRAY_SIZE ? -58 : -g_AngleSkew[-skew]; - if (pFont->IsVertical()) { - ft_matrix.yx += ft_matrix.yy * skew / 100; - } else { - ft_matrix.xy += -ft_matrix.xx * skew / 100; - } - } - if (pSubstFont->m_SubstFlags & FXFONT_SUBST_MM) { - pFont->AdjustMMParams(glyph_index, dest_width, pFont->GetSubstFont()->m_Weight); - } - } - ScopedFontTransform scoped_transform(m_Face, &ft_matrix); - int load_flags = (m_Face->face_flags & FT_FACE_FLAG_SFNT) ? FXFT_LOAD_NO_BITMAP : (FXFT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING); - int error = FXFT_Load_Glyph(m_Face, glyph_index, load_flags); - if (error) { - //if an error is returned, try to reload glyphs without hinting. - if (load_flags & FT_LOAD_NO_HINTING || load_flags & FT_LOAD_NO_SCALE) { - return NULL; - } - - load_flags |= FT_LOAD_NO_HINTING; - error = FXFT_Load_Glyph(m_Face, glyph_index, load_flags); - - if (error) { - return NULL; - } - } - int weight = 0; +CFX_GlyphBitmap* CFX_FaceCache::RenderGlyph(CFX_Font* pFont, + FX_DWORD glyph_index, + FX_BOOL bFontStyle, + const CFX_AffineMatrix* pMatrix, + int dest_width, + int anti_alias) { + if (m_Face == NULL) { + return NULL; + } + FXFT_Matrix ft_matrix; + ft_matrix.xx = (signed long)(pMatrix->GetA() / 64 * 65536); + ft_matrix.xy = (signed long)(pMatrix->GetC() / 64 * 65536); + ft_matrix.yx = (signed long)(pMatrix->GetB() / 64 * 65536); + ft_matrix.yy = (signed long)(pMatrix->GetD() / 64 * 65536); + FX_BOOL bUseCJKSubFont = FALSE; + const CFX_SubstFont* pSubstFont = pFont->GetSubstFont(); + if (pSubstFont) { + bUseCJKSubFont = pSubstFont->m_bSubstOfCJK && bFontStyle; + int skew = 0; if (bUseCJKSubFont) { - weight = pSubstFont->m_WeightCJK; + skew = pSubstFont->m_bItlicCJK ? -15 : 0; } else { - weight = pSubstFont ? pSubstFont->m_Weight : 0; - } - if (pSubstFont && !(pSubstFont->m_SubstFlags & FXFONT_SUBST_MM) && weight > 400) { - int index = (weight - 400) / 10; - if (index >= WEIGHTPOW_ARRAY_SIZE) { - return NULL; - } - int level = 0; - if (pSubstFont->m_Charset == FXFONT_SHIFTJIS_CHARSET) { - level = g_WeightPow_SHIFTJIS[index] * 2 * (FXSYS_abs((int)(ft_matrix.xx)) + FXSYS_abs((int)(ft_matrix.xy))) / 36655; - } else { - level = g_WeightPow_11[index] * (FXSYS_abs((int)(ft_matrix.xx)) + FXSYS_abs((int)(ft_matrix.xy))) / 36655; - } - FXFT_Outline_Embolden(FXFT_Get_Glyph_Outline(m_Face), level); + skew = pSubstFont->m_ItalicAngle; + } + if (skew) { + skew = skew <= -ANGLESKEW_ARRAY_SIZE ? -58 : -g_AngleSkew[-skew]; + if (pFont->IsVertical()) { + ft_matrix.yx += ft_matrix.yy * skew / 100; + } else { + ft_matrix.xy += -ft_matrix.xx * skew / 100; + } + } + if (pSubstFont->m_SubstFlags & FXFONT_SUBST_MM) { + pFont->AdjustMMParams(glyph_index, dest_width, + pFont->GetSubstFont()->m_Weight); + } + } + ScopedFontTransform scoped_transform(m_Face, &ft_matrix); + int load_flags = (m_Face->face_flags & FT_FACE_FLAG_SFNT) + ? FXFT_LOAD_NO_BITMAP + : (FXFT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING); + int error = FXFT_Load_Glyph(m_Face, glyph_index, load_flags); + if (error) { + // if an error is returned, try to reload glyphs without hinting. + if (load_flags & FT_LOAD_NO_HINTING || load_flags & FT_LOAD_NO_SCALE) { + return NULL; } - FXFT_Library_SetLcdFilter(CFX_GEModule::Get()->GetFontMgr()->m_FTLibrary, FT_LCD_FILTER_DEFAULT); - error = FXFT_Render_Glyph(m_Face, anti_alias); + + load_flags |= FT_LOAD_NO_HINTING; + error = FXFT_Load_Glyph(m_Face, glyph_index, load_flags); + if (error) { - return NULL; - } - int bmwidth = FXFT_Get_Bitmap_Width(FXFT_Get_Glyph_Bitmap(m_Face)); - int bmheight = FXFT_Get_Bitmap_Rows(FXFT_Get_Glyph_Bitmap(m_Face)); - if (bmwidth > 2048 || bmheight > 2048) { - return NULL; - } - int dib_width = bmwidth; - CFX_GlyphBitmap* pGlyphBitmap = new CFX_GlyphBitmap; - pGlyphBitmap->m_Bitmap.Create(dib_width, bmheight, - anti_alias == FXFT_RENDER_MODE_MONO ? FXDIB_1bppMask : FXDIB_8bppMask); - pGlyphBitmap->m_Left = FXFT_Get_Glyph_BitmapLeft(m_Face); - pGlyphBitmap->m_Top = FXFT_Get_Glyph_BitmapTop(m_Face); - int dest_pitch = pGlyphBitmap->m_Bitmap.GetPitch(); - int src_pitch = FXFT_Get_Bitmap_Pitch(FXFT_Get_Glyph_Bitmap(m_Face)); - uint8_t* pDestBuf = pGlyphBitmap->m_Bitmap.GetBuffer(); - uint8_t* pSrcBuf = (uint8_t*)FXFT_Get_Bitmap_Buffer(FXFT_Get_Glyph_Bitmap(m_Face)); - if (anti_alias != FXFT_RENDER_MODE_MONO && FXFT_Get_Bitmap_PixelMode(FXFT_Get_Glyph_Bitmap(m_Face)) == FXFT_PIXEL_MODE_MONO) { - int bytes = anti_alias == FXFT_RENDER_MODE_LCD ? 3 : 1; - for(int i = 0; i < bmheight; i++) - for(int n = 0; n < bmwidth; n++) { - uint8_t data = (pSrcBuf[i * src_pitch + n / 8] & (0x80 >> (n % 8))) ? 255 : 0; - for (int b = 0; b < bytes; b ++) { - pDestBuf[i * dest_pitch + n * bytes + b] = data; - } - } + return NULL; + } + } + int weight = 0; + if (bUseCJKSubFont) { + weight = pSubstFont->m_WeightCJK; + } else { + weight = pSubstFont ? pSubstFont->m_Weight : 0; + } + if (pSubstFont && !(pSubstFont->m_SubstFlags & FXFONT_SUBST_MM) && + weight > 400) { + int index = (weight - 400) / 10; + if (index >= WEIGHTPOW_ARRAY_SIZE) { + return NULL; + } + int level = 0; + if (pSubstFont->m_Charset == FXFONT_SHIFTJIS_CHARSET) { + level = + g_WeightPow_SHIFTJIS[index] * 2 * + (FXSYS_abs((int)(ft_matrix.xx)) + FXSYS_abs((int)(ft_matrix.xy))) / + 36655; } else { - FXSYS_memset(pDestBuf, 0, dest_pitch * bmheight); - if (anti_alias == FXFT_RENDER_MODE_MONO && FXFT_Get_Bitmap_PixelMode(FXFT_Get_Glyph_Bitmap(m_Face)) == FXFT_PIXEL_MODE_MONO) { - int rowbytes = FXSYS_abs(src_pitch) > dest_pitch ? dest_pitch : FXSYS_abs(src_pitch); - for (int row = 0; row < bmheight; row ++) { - FXSYS_memcpy(pDestBuf + row * dest_pitch, pSrcBuf + row * src_pitch, rowbytes); - } - } else { - _ContrastAdjust(pSrcBuf, pDestBuf, bmwidth, bmheight, src_pitch, dest_pitch); - _GammaAdjust(pDestBuf, bmwidth, bmheight, dest_pitch, CFX_GEModule::Get()->GetTextGammaTable()); + level = g_WeightPow_11[index] * (FXSYS_abs((int)(ft_matrix.xx)) + + FXSYS_abs((int)(ft_matrix.xy))) / + 36655; + } + FXFT_Outline_Embolden(FXFT_Get_Glyph_Outline(m_Face), level); + } + FXFT_Library_SetLcdFilter(CFX_GEModule::Get()->GetFontMgr()->m_FTLibrary, + FT_LCD_FILTER_DEFAULT); + error = FXFT_Render_Glyph(m_Face, anti_alias); + if (error) { + return NULL; + } + int bmwidth = FXFT_Get_Bitmap_Width(FXFT_Get_Glyph_Bitmap(m_Face)); + int bmheight = FXFT_Get_Bitmap_Rows(FXFT_Get_Glyph_Bitmap(m_Face)); + if (bmwidth > 2048 || bmheight > 2048) { + return NULL; + } + int dib_width = bmwidth; + CFX_GlyphBitmap* pGlyphBitmap = new CFX_GlyphBitmap; + pGlyphBitmap->m_Bitmap.Create( + dib_width, bmheight, + anti_alias == FXFT_RENDER_MODE_MONO ? FXDIB_1bppMask : FXDIB_8bppMask); + pGlyphBitmap->m_Left = FXFT_Get_Glyph_BitmapLeft(m_Face); + pGlyphBitmap->m_Top = FXFT_Get_Glyph_BitmapTop(m_Face); + int dest_pitch = pGlyphBitmap->m_Bitmap.GetPitch(); + int src_pitch = FXFT_Get_Bitmap_Pitch(FXFT_Get_Glyph_Bitmap(m_Face)); + uint8_t* pDestBuf = pGlyphBitmap->m_Bitmap.GetBuffer(); + uint8_t* pSrcBuf = + (uint8_t*)FXFT_Get_Bitmap_Buffer(FXFT_Get_Glyph_Bitmap(m_Face)); + if (anti_alias != FXFT_RENDER_MODE_MONO && + FXFT_Get_Bitmap_PixelMode(FXFT_Get_Glyph_Bitmap(m_Face)) == + FXFT_PIXEL_MODE_MONO) { + int bytes = anti_alias == FXFT_RENDER_MODE_LCD ? 3 : 1; + for (int i = 0; i < bmheight; i++) + for (int n = 0; n < bmwidth; n++) { + uint8_t data = + (pSrcBuf[i * src_pitch + n / 8] & (0x80 >> (n % 8))) ? 255 : 0; + for (int b = 0; b < bytes; b++) { + pDestBuf[i * dest_pitch + n * bytes + b] = data; } + } + } else { + FXSYS_memset(pDestBuf, 0, dest_pitch * bmheight); + if (anti_alias == FXFT_RENDER_MODE_MONO && + FXFT_Get_Bitmap_PixelMode(FXFT_Get_Glyph_Bitmap(m_Face)) == + FXFT_PIXEL_MODE_MONO) { + int rowbytes = + FXSYS_abs(src_pitch) > dest_pitch ? dest_pitch : FXSYS_abs(src_pitch); + for (int row = 0; row < bmheight; row++) { + FXSYS_memcpy(pDestBuf + row * dest_pitch, pSrcBuf + row * src_pitch, + rowbytes); + } + } else { + _ContrastAdjust(pSrcBuf, pDestBuf, bmwidth, bmheight, src_pitch, + dest_pitch); + _GammaAdjust(pDestBuf, bmwidth, bmheight, dest_pitch, + CFX_GEModule::Get()->GetTextGammaTable()); } - return pGlyphBitmap; + } + return pGlyphBitmap; } -FX_BOOL _OutputGlyph(void* dib, int x, int y, CFX_Font* pFont, - int glyph_index, FX_ARGB argb) -{ - CFX_DIBitmap* pDib = (CFX_DIBitmap*)dib; - FXFT_Face face = pFont->GetFace(); - int error = FXFT_Load_Glyph(face, glyph_index, FXFT_LOAD_NO_BITMAP); - if (error) { - return FALSE; - } - error = FXFT_Render_Glyph(face, FXFT_RENDER_MODE_NORMAL); - if (error) { - return FALSE; - } - int bmwidth = FXFT_Get_Bitmap_Width(FXFT_Get_Glyph_Bitmap(face)); - int bmheight = FXFT_Get_Bitmap_Rows(FXFT_Get_Glyph_Bitmap(face)); - int left = FXFT_Get_Glyph_BitmapLeft(face); - int top = FXFT_Get_Glyph_BitmapTop(face); - const uint8_t* src_buf = (const uint8_t*)FXFT_Get_Bitmap_Buffer(FXFT_Get_Glyph_Bitmap(face)); - int src_pitch = FXFT_Get_Bitmap_Pitch(FXFT_Get_Glyph_Bitmap(face)); - CFX_DIBitmap mask; - mask.Create(bmwidth, bmheight, FXDIB_8bppMask); - uint8_t* dest_buf = mask.GetBuffer(); - int dest_pitch = mask.GetPitch(); - for (int row = 0; row < bmheight; row ++) { - const uint8_t* src_scan = src_buf + row * src_pitch; - uint8_t* dest_scan = dest_buf + row * dest_pitch; - FXSYS_memcpy(dest_scan, src_scan, dest_pitch); - } - pDib->CompositeMask(x + left, y - top, bmwidth, bmheight, &mask, argb, 0, 0); - return TRUE; +FX_BOOL _OutputGlyph(void* dib, + int x, + int y, + CFX_Font* pFont, + int glyph_index, + FX_ARGB argb) { + CFX_DIBitmap* pDib = (CFX_DIBitmap*)dib; + FXFT_Face face = pFont->GetFace(); + int error = FXFT_Load_Glyph(face, glyph_index, FXFT_LOAD_NO_BITMAP); + if (error) { + return FALSE; + } + error = FXFT_Render_Glyph(face, FXFT_RENDER_MODE_NORMAL); + if (error) { + return FALSE; + } + int bmwidth = FXFT_Get_Bitmap_Width(FXFT_Get_Glyph_Bitmap(face)); + int bmheight = FXFT_Get_Bitmap_Rows(FXFT_Get_Glyph_Bitmap(face)); + int left = FXFT_Get_Glyph_BitmapLeft(face); + int top = FXFT_Get_Glyph_BitmapTop(face); + const uint8_t* src_buf = + (const uint8_t*)FXFT_Get_Bitmap_Buffer(FXFT_Get_Glyph_Bitmap(face)); + int src_pitch = FXFT_Get_Bitmap_Pitch(FXFT_Get_Glyph_Bitmap(face)); + CFX_DIBitmap mask; + mask.Create(bmwidth, bmheight, FXDIB_8bppMask); + uint8_t* dest_buf = mask.GetBuffer(); + int dest_pitch = mask.GetPitch(); + for (int row = 0; row < bmheight; row++) { + const uint8_t* src_scan = src_buf + row * src_pitch; + uint8_t* dest_scan = dest_buf + row * dest_pitch; + FXSYS_memcpy(dest_scan, src_scan, dest_pitch); + } + pDib->CompositeMask(x + left, y - top, bmwidth, bmheight, &mask, argb, 0, 0); + return TRUE; } -FX_BOOL OutputText(void* dib, int x, int y, CFX_Font* pFont, double font_size, - CFX_AffineMatrix* pText_matrix, unsigned short const* text, unsigned long argb) -{ - if (!pFont) { - return FALSE; - } - FXFT_Face face = pFont->GetFace(); - FXFT_Select_Charmap(pFont->m_Face, FXFT_ENCODING_UNICODE); - if (pText_matrix) { - FXFT_Matrix ft_matrix; - ft_matrix.xx = (signed long)(pText_matrix->a / 64 * 65536); - ft_matrix.xy = (signed long)(pText_matrix->c / 64 * 65536); - ft_matrix.yx = (signed long)(pText_matrix->b / 64 * 65536); - ft_matrix.yy = (signed long)(pText_matrix->d / 64 * 65536); - FXFT_Set_Transform(face, &ft_matrix, 0); - } - FX_FLOAT x_pos = 0; - for (; *text != 0; text ++) { - FX_WCHAR unicode = *text; - int glyph_index = FXFT_Get_Char_Index(pFont->m_Face, unicode); - if (glyph_index <= 0) { - continue; - } - int err = FXFT_Load_Glyph(pFont->m_Face, glyph_index, FXFT_LOAD_NO_SCALE | FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH); - if (err) { - continue; - } - int w = FXFT_Get_Glyph_HoriAdvance(pFont->m_Face); - int em = FXFT_Get_Face_UnitsPerEM(pFont->m_Face); - FX_FLOAT x1, y1; - pText_matrix->Transform(x_pos, 0, x1, y1); - _OutputGlyph(dib, (int)x1 + x, (int) - y1 + y, pFont, - glyph_index, argb); - x_pos += (FX_FLOAT)w / em; - } - if (pText_matrix) - ResetTransform(face); - return TRUE; +FX_BOOL OutputText(void* dib, + int x, + int y, + CFX_Font* pFont, + double font_size, + CFX_AffineMatrix* pText_matrix, + unsigned short const* text, + unsigned long argb) { + if (!pFont) { + return FALSE; + } + FXFT_Face face = pFont->GetFace(); + FXFT_Select_Charmap(pFont->m_Face, FXFT_ENCODING_UNICODE); + if (pText_matrix) { + FXFT_Matrix ft_matrix; + ft_matrix.xx = (signed long)(pText_matrix->a / 64 * 65536); + ft_matrix.xy = (signed long)(pText_matrix->c / 64 * 65536); + ft_matrix.yx = (signed long)(pText_matrix->b / 64 * 65536); + ft_matrix.yy = (signed long)(pText_matrix->d / 64 * 65536); + FXFT_Set_Transform(face, &ft_matrix, 0); + } + FX_FLOAT x_pos = 0; + for (; *text != 0; text++) { + FX_WCHAR unicode = *text; + int glyph_index = FXFT_Get_Char_Index(pFont->m_Face, unicode); + if (glyph_index <= 0) { + continue; + } + int err = FXFT_Load_Glyph( + pFont->m_Face, glyph_index, + FXFT_LOAD_NO_SCALE | FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH); + if (err) { + continue; + } + int w = FXFT_Get_Glyph_HoriAdvance(pFont->m_Face); + int em = FXFT_Get_Face_UnitsPerEM(pFont->m_Face); + FX_FLOAT x1, y1; + pText_matrix->Transform(x_pos, 0, x1, y1); + _OutputGlyph(dib, (int)x1 + x, (int)-y1 + y, pFont, glyph_index, argb); + x_pos += (FX_FLOAT)w / em; + } + if (pText_matrix) + ResetTransform(face); + return TRUE; } -FX_BOOL OutputGlyph(void* dib, int x, int y, CFX_Font* pFont, double font_size, - CFX_AffineMatrix* pMatrix, unsigned long glyph_index, unsigned long argb) -{ - FXFT_Matrix ft_matrix; - if (pMatrix) { - ft_matrix.xx = (signed long)(pMatrix->a * font_size / 64 * 65536); - ft_matrix.xy = (signed long)(pMatrix->c * font_size / 64 * 65536); - ft_matrix.yx = (signed long)(pMatrix->b * font_size / 64 * 65536); - ft_matrix.yy = (signed long)(pMatrix->d * font_size / 64 * 65536); - } else { - ft_matrix.xx = (signed long)(font_size / 64 * 65536); - ft_matrix.xy = ft_matrix.yx = 0; - ft_matrix.yy = (signed long)(font_size / 64 * 65536); - } - ScopedFontTransform scoped_transform(pFont->m_Face, &ft_matrix); - FX_BOOL ret = _OutputGlyph(dib, x, y, pFont, - glyph_index, argb); - return ret; +FX_BOOL OutputGlyph(void* dib, + int x, + int y, + CFX_Font* pFont, + double font_size, + CFX_AffineMatrix* pMatrix, + unsigned long glyph_index, + unsigned long argb) { + FXFT_Matrix ft_matrix; + if (pMatrix) { + ft_matrix.xx = (signed long)(pMatrix->a * font_size / 64 * 65536); + ft_matrix.xy = (signed long)(pMatrix->c * font_size / 64 * 65536); + ft_matrix.yx = (signed long)(pMatrix->b * font_size / 64 * 65536); + ft_matrix.yy = (signed long)(pMatrix->d * font_size / 64 * 65536); + } else { + ft_matrix.xx = (signed long)(font_size / 64 * 65536); + ft_matrix.xy = ft_matrix.yx = 0; + ft_matrix.yy = (signed long)(font_size / 64 * 65536); + } + ScopedFontTransform scoped_transform(pFont->m_Face, &ft_matrix); + FX_BOOL ret = _OutputGlyph(dib, x, y, pFont, glyph_index, argb); + return ret; } -const CFX_PathData* CFX_FaceCache::LoadGlyphPath(CFX_Font* pFont, FX_DWORD glyph_index, int dest_width) -{ - if (m_Face == NULL || glyph_index == (FX_DWORD) - 1) { - return NULL; - } - CFX_PathData* pGlyphPath = NULL; - void* key; - if (pFont->GetSubstFont()) - key = (void*)(uintptr_t)(glyph_index + ((pFont->GetSubstFont()->m_Weight / 16) << 15) + - ((pFont->GetSubstFont()->m_ItalicAngle / 2) << 21) + ((dest_width / 16) << 25) + - (pFont->IsVertical() << 31)); - else { - key = (void*)(uintptr_t)glyph_index; - } - if (m_PathMap.Lookup(key, (void*&)pGlyphPath)) { - return pGlyphPath; - } - pGlyphPath = pFont->LoadGlyphPath(glyph_index, dest_width); - m_PathMap.SetAt(key, pGlyphPath); +const CFX_PathData* CFX_FaceCache::LoadGlyphPath(CFX_Font* pFont, + FX_DWORD glyph_index, + int dest_width) { + if (m_Face == NULL || glyph_index == (FX_DWORD)-1) { + return NULL; + } + CFX_PathData* pGlyphPath = NULL; + void* key; + if (pFont->GetSubstFont()) + key = (void*)(uintptr_t)( + glyph_index + ((pFont->GetSubstFont()->m_Weight / 16) << 15) + + ((pFont->GetSubstFont()->m_ItalicAngle / 2) << 21) + + ((dest_width / 16) << 25) + (pFont->IsVertical() << 31)); + else { + key = (void*)(uintptr_t)glyph_index; + } + if (m_PathMap.Lookup(key, (void*&)pGlyphPath)) { return pGlyphPath; + } + pGlyphPath = pFont->LoadGlyphPath(glyph_index, dest_width); + m_PathMap.SetAt(key, pGlyphPath); + return pGlyphPath; } typedef struct { - FX_BOOL m_bCount; - int m_PointCount; - FX_PATHPOINT* m_pPoints; - int m_CurX; - int m_CurY; - FX_FLOAT m_CoordUnit; + FX_BOOL m_bCount; + int m_PointCount; + FX_PATHPOINT* m_pPoints; + int m_CurX; + int m_CurY; + FX_FLOAT m_CoordUnit; } OUTLINE_PARAMS; -void _Outline_CheckEmptyContour(OUTLINE_PARAMS* param) -{ - if (param->m_PointCount >= 2 && param->m_pPoints[param->m_PointCount - 2].m_Flag == FXPT_MOVETO && - param->m_pPoints[param->m_PointCount - 2].m_PointX == param->m_pPoints[param->m_PointCount - 1].m_PointX && - param->m_pPoints[param->m_PointCount - 2].m_PointY == param->m_pPoints[param->m_PointCount - 1].m_PointY) { - param->m_PointCount -= 2; - } - if (param->m_PointCount >= 4 && param->m_pPoints[param->m_PointCount - 4].m_Flag == FXPT_MOVETO && - param->m_pPoints[param->m_PointCount - 3].m_Flag == FXPT_BEZIERTO && - param->m_pPoints[param->m_PointCount - 3].m_PointX == param->m_pPoints[param->m_PointCount - 4].m_PointX && - param->m_pPoints[param->m_PointCount - 3].m_PointY == param->m_pPoints[param->m_PointCount - 4].m_PointY && - param->m_pPoints[param->m_PointCount - 2].m_PointX == param->m_pPoints[param->m_PointCount - 4].m_PointX && - param->m_pPoints[param->m_PointCount - 2].m_PointY == param->m_pPoints[param->m_PointCount - 4].m_PointY && - param->m_pPoints[param->m_PointCount - 1].m_PointX == param->m_pPoints[param->m_PointCount - 4].m_PointX && - param->m_pPoints[param->m_PointCount - 1].m_PointY == param->m_pPoints[param->m_PointCount - 4].m_PointY) { - param->m_PointCount -= 4; - } +void _Outline_CheckEmptyContour(OUTLINE_PARAMS* param) { + if (param->m_PointCount >= 2 && + param->m_pPoints[param->m_PointCount - 2].m_Flag == FXPT_MOVETO && + param->m_pPoints[param->m_PointCount - 2].m_PointX == + param->m_pPoints[param->m_PointCount - 1].m_PointX && + param->m_pPoints[param->m_PointCount - 2].m_PointY == + param->m_pPoints[param->m_PointCount - 1].m_PointY) { + param->m_PointCount -= 2; + } + if (param->m_PointCount >= 4 && + param->m_pPoints[param->m_PointCount - 4].m_Flag == FXPT_MOVETO && + param->m_pPoints[param->m_PointCount - 3].m_Flag == FXPT_BEZIERTO && + param->m_pPoints[param->m_PointCount - 3].m_PointX == + param->m_pPoints[param->m_PointCount - 4].m_PointX && + param->m_pPoints[param->m_PointCount - 3].m_PointY == + param->m_pPoints[param->m_PointCount - 4].m_PointY && + param->m_pPoints[param->m_PointCount - 2].m_PointX == + param->m_pPoints[param->m_PointCount - 4].m_PointX && + param->m_pPoints[param->m_PointCount - 2].m_PointY == + param->m_pPoints[param->m_PointCount - 4].m_PointY && + param->m_pPoints[param->m_PointCount - 1].m_PointX == + param->m_pPoints[param->m_PointCount - 4].m_PointX && + param->m_pPoints[param->m_PointCount - 1].m_PointY == + param->m_pPoints[param->m_PointCount - 4].m_PointY) { + param->m_PointCount -= 4; + } } extern "C" { - static int _Outline_MoveTo(const FXFT_Vector* to, void* user) - { - OUTLINE_PARAMS* param = (OUTLINE_PARAMS*)user; - if (!param->m_bCount) { - _Outline_CheckEmptyContour(param); - param->m_pPoints[param->m_PointCount].m_PointX = to->x / param->m_CoordUnit; - param->m_pPoints[param->m_PointCount].m_PointY = to->y / param->m_CoordUnit; - param->m_pPoints[param->m_PointCount].m_Flag = FXPT_MOVETO; - param->m_CurX = to->x; - param->m_CurY = to->y; - if (param->m_PointCount) { - param->m_pPoints[param->m_PointCount - 1].m_Flag |= FXPT_CLOSEFIGURE; - } - } - param->m_PointCount ++; - return 0; - } +static int _Outline_MoveTo(const FXFT_Vector* to, void* user) { + OUTLINE_PARAMS* param = (OUTLINE_PARAMS*)user; + if (!param->m_bCount) { + _Outline_CheckEmptyContour(param); + param->m_pPoints[param->m_PointCount].m_PointX = to->x / param->m_CoordUnit; + param->m_pPoints[param->m_PointCount].m_PointY = to->y / param->m_CoordUnit; + param->m_pPoints[param->m_PointCount].m_Flag = FXPT_MOVETO; + param->m_CurX = to->x; + param->m_CurY = to->y; + if (param->m_PointCount) { + param->m_pPoints[param->m_PointCount - 1].m_Flag |= FXPT_CLOSEFIGURE; + } + } + param->m_PointCount++; + return 0; +} }; extern "C" { - static int _Outline_LineTo(const FXFT_Vector* to, void* user) - { - OUTLINE_PARAMS* param = (OUTLINE_PARAMS*)user; - if (!param->m_bCount) { - param->m_pPoints[param->m_PointCount].m_PointX = to->x / param->m_CoordUnit; - param->m_pPoints[param->m_PointCount].m_PointY = to->y / param->m_CoordUnit; - param->m_pPoints[param->m_PointCount].m_Flag = FXPT_LINETO; - param->m_CurX = to->x; - param->m_CurY = to->y; - } - param->m_PointCount ++; - return 0; - } +static int _Outline_LineTo(const FXFT_Vector* to, void* user) { + OUTLINE_PARAMS* param = (OUTLINE_PARAMS*)user; + if (!param->m_bCount) { + param->m_pPoints[param->m_PointCount].m_PointX = to->x / param->m_CoordUnit; + param->m_pPoints[param->m_PointCount].m_PointY = to->y / param->m_CoordUnit; + param->m_pPoints[param->m_PointCount].m_Flag = FXPT_LINETO; + param->m_CurX = to->x; + param->m_CurY = to->y; + } + param->m_PointCount++; + return 0; +} }; extern "C" { - static int _Outline_ConicTo(const FXFT_Vector* control, const FXFT_Vector* to, void* user) - { - OUTLINE_PARAMS* param = (OUTLINE_PARAMS*)user; - if (!param->m_bCount) { - param->m_pPoints[param->m_PointCount].m_PointX = (param->m_CurX + (control->x - param->m_CurX) * 2 / 3) / param->m_CoordUnit; - param->m_pPoints[param->m_PointCount].m_PointY = (param->m_CurY + (control->y - param->m_CurY) * 2 / 3) / param->m_CoordUnit; - param->m_pPoints[param->m_PointCount].m_Flag = FXPT_BEZIERTO; - param->m_pPoints[param->m_PointCount + 1].m_PointX = (control->x + (to->x - control->x) / 3) / param->m_CoordUnit; - param->m_pPoints[param->m_PointCount + 1].m_PointY = (control->y + (to->y - control->y) / 3) / param->m_CoordUnit; - param->m_pPoints[param->m_PointCount + 1].m_Flag = FXPT_BEZIERTO; - param->m_pPoints[param->m_PointCount + 2].m_PointX = to->x / param->m_CoordUnit; - param->m_pPoints[param->m_PointCount + 2].m_PointY = to->y / param->m_CoordUnit; - param->m_pPoints[param->m_PointCount + 2].m_Flag = FXPT_BEZIERTO; - param->m_CurX = to->x; - param->m_CurY = to->y; - } - param->m_PointCount += 3; - return 0; - } +static int _Outline_ConicTo(const FXFT_Vector* control, + const FXFT_Vector* to, + void* user) { + OUTLINE_PARAMS* param = (OUTLINE_PARAMS*)user; + if (!param->m_bCount) { + param->m_pPoints[param->m_PointCount].m_PointX = + (param->m_CurX + (control->x - param->m_CurX) * 2 / 3) / + param->m_CoordUnit; + param->m_pPoints[param->m_PointCount].m_PointY = + (param->m_CurY + (control->y - param->m_CurY) * 2 / 3) / + param->m_CoordUnit; + param->m_pPoints[param->m_PointCount].m_Flag = FXPT_BEZIERTO; + param->m_pPoints[param->m_PointCount + 1].m_PointX = + (control->x + (to->x - control->x) / 3) / param->m_CoordUnit; + param->m_pPoints[param->m_PointCount + 1].m_PointY = + (control->y + (to->y - control->y) / 3) / param->m_CoordUnit; + param->m_pPoints[param->m_PointCount + 1].m_Flag = FXPT_BEZIERTO; + param->m_pPoints[param->m_PointCount + 2].m_PointX = + to->x / param->m_CoordUnit; + param->m_pPoints[param->m_PointCount + 2].m_PointY = + to->y / param->m_CoordUnit; + param->m_pPoints[param->m_PointCount + 2].m_Flag = FXPT_BEZIERTO; + param->m_CurX = to->x; + param->m_CurY = to->y; + } + param->m_PointCount += 3; + return 0; +} }; extern "C" { - static int _Outline_CubicTo(const FXFT_Vector* control1, const FXFT_Vector* control2, const FXFT_Vector* to, void* user) - { - OUTLINE_PARAMS* param = (OUTLINE_PARAMS*)user; - if (!param->m_bCount) { - param->m_pPoints[param->m_PointCount].m_PointX = control1->x / param->m_CoordUnit; - param->m_pPoints[param->m_PointCount].m_PointY = control1->y / param->m_CoordUnit; - param->m_pPoints[param->m_PointCount].m_Flag = FXPT_BEZIERTO; - param->m_pPoints[param->m_PointCount + 1].m_PointX = control2->x / param->m_CoordUnit; - param->m_pPoints[param->m_PointCount + 1].m_PointY = control2->y / param->m_CoordUnit; - param->m_pPoints[param->m_PointCount + 1].m_Flag = FXPT_BEZIERTO; - param->m_pPoints[param->m_PointCount + 2].m_PointX = to->x / param->m_CoordUnit; - param->m_pPoints[param->m_PointCount + 2].m_PointY = to->y / param->m_CoordUnit; - param->m_pPoints[param->m_PointCount + 2].m_Flag = FXPT_BEZIERTO; - param->m_CurX = to->x; - param->m_CurY = to->y; - } - param->m_PointCount += 3; - return 0; - } +static int _Outline_CubicTo(const FXFT_Vector* control1, + const FXFT_Vector* control2, + const FXFT_Vector* to, + void* user) { + OUTLINE_PARAMS* param = (OUTLINE_PARAMS*)user; + if (!param->m_bCount) { + param->m_pPoints[param->m_PointCount].m_PointX = + control1->x / param->m_CoordUnit; + param->m_pPoints[param->m_PointCount].m_PointY = + control1->y / param->m_CoordUnit; + param->m_pPoints[param->m_PointCount].m_Flag = FXPT_BEZIERTO; + param->m_pPoints[param->m_PointCount + 1].m_PointX = + control2->x / param->m_CoordUnit; + param->m_pPoints[param->m_PointCount + 1].m_PointY = + control2->y / param->m_CoordUnit; + param->m_pPoints[param->m_PointCount + 1].m_Flag = FXPT_BEZIERTO; + param->m_pPoints[param->m_PointCount + 2].m_PointX = + to->x / param->m_CoordUnit; + param->m_pPoints[param->m_PointCount + 2].m_PointY = + to->y / param->m_CoordUnit; + param->m_pPoints[param->m_PointCount + 2].m_Flag = FXPT_BEZIERTO; + param->m_CurX = to->x; + param->m_CurY = to->y; + } + param->m_PointCount += 3; + return 0; +} }; -CFX_PathData* CFX_Font::LoadGlyphPath(FX_DWORD glyph_index, int dest_width) -{ - if (m_Face == NULL) { - return NULL; - } - FXFT_Set_Pixel_Sizes(m_Face, 0, 64); - FXFT_Matrix ft_matrix = {65536, 0, 0, 65536}; - if (m_pSubstFont) { - if (m_pSubstFont->m_ItalicAngle) { - int skew = m_pSubstFont->m_ItalicAngle; - skew = skew <= -ANGLESKEW_ARRAY_SIZE ? -58 : -g_AngleSkew[-skew]; - if (m_bVertical) { - ft_matrix.yx += ft_matrix.yy * skew / 100; - } else { - ft_matrix.xy += -ft_matrix.xx * skew / 100; - } - } - if (m_pSubstFont->m_SubstFlags & FXFONT_SUBST_MM) { - AdjustMMParams(glyph_index, dest_width, m_pSubstFont->m_Weight); - } - } - ScopedFontTransform scoped_transform(m_Face, &ft_matrix); - int load_flags = FXFT_LOAD_NO_BITMAP; - if (!(m_Face->face_flags & FT_FACE_FLAG_SFNT) || !FT_IS_TRICKY(m_Face)) { - load_flags |= FT_LOAD_NO_HINTING; - } - int error = FXFT_Load_Glyph(m_Face, glyph_index, load_flags); - if (error) { - return NULL; - } - if (m_pSubstFont && !(m_pSubstFont->m_SubstFlags & FXFONT_SUBST_MM) && m_pSubstFont->m_Weight > 400) { - int index = (m_pSubstFont->m_Weight - 400) / 10; - if (index >= WEIGHTPOW_ARRAY_SIZE) - index = WEIGHTPOW_ARRAY_SIZE - 1; - int level = 0; - if (m_pSubstFont->m_Charset == FXFONT_SHIFTJIS_CHARSET) { - level = g_WeightPow_SHIFTJIS[index] * 2 * 65536 / 36655; - } else { - level = g_WeightPow[index] * 2; - } - FXFT_Outline_Embolden(FXFT_Get_Glyph_Outline(m_Face), level); - } - FXFT_Outline_Funcs funcs; - funcs.move_to = _Outline_MoveTo; - funcs.line_to = _Outline_LineTo; - funcs.conic_to = _Outline_ConicTo; - funcs.cubic_to = _Outline_CubicTo; - funcs.shift = 0; - funcs.delta = 0; - OUTLINE_PARAMS params; - params.m_bCount = TRUE; - params.m_PointCount = 0; - FXFT_Outline_Decompose(FXFT_Get_Glyph_Outline(m_Face), &funcs, ¶ms); - if (params.m_PointCount == 0) { - return NULL; - } - CFX_PathData* pPath = new CFX_PathData; - pPath->SetPointCount(params.m_PointCount); - params.m_bCount = FALSE; - params.m_PointCount = 0; - params.m_pPoints = pPath->GetPoints(); - params.m_CurX = params.m_CurY = 0; - params.m_CoordUnit = 64 * 64.0; - FXFT_Outline_Decompose(FXFT_Get_Glyph_Outline(m_Face), &funcs, ¶ms); - _Outline_CheckEmptyContour(¶ms); - pPath->TrimPoints(params.m_PointCount); - if (params.m_PointCount) { - pPath->GetPoints()[params.m_PointCount - 1].m_Flag |= FXPT_CLOSEFIGURE; - } - return pPath; +CFX_PathData* CFX_Font::LoadGlyphPath(FX_DWORD glyph_index, int dest_width) { + if (m_Face == NULL) { + return NULL; + } + FXFT_Set_Pixel_Sizes(m_Face, 0, 64); + FXFT_Matrix ft_matrix = {65536, 0, 0, 65536}; + if (m_pSubstFont) { + if (m_pSubstFont->m_ItalicAngle) { + int skew = m_pSubstFont->m_ItalicAngle; + skew = skew <= -ANGLESKEW_ARRAY_SIZE ? -58 : -g_AngleSkew[-skew]; + if (m_bVertical) { + ft_matrix.yx += ft_matrix.yy * skew / 100; + } else { + ft_matrix.xy += -ft_matrix.xx * skew / 100; + } + } + if (m_pSubstFont->m_SubstFlags & FXFONT_SUBST_MM) { + AdjustMMParams(glyph_index, dest_width, m_pSubstFont->m_Weight); + } + } + ScopedFontTransform scoped_transform(m_Face, &ft_matrix); + int load_flags = FXFT_LOAD_NO_BITMAP; + if (!(m_Face->face_flags & FT_FACE_FLAG_SFNT) || !FT_IS_TRICKY(m_Face)) { + load_flags |= FT_LOAD_NO_HINTING; + } + int error = FXFT_Load_Glyph(m_Face, glyph_index, load_flags); + if (error) { + return NULL; + } + if (m_pSubstFont && !(m_pSubstFont->m_SubstFlags & FXFONT_SUBST_MM) && + m_pSubstFont->m_Weight > 400) { + int index = (m_pSubstFont->m_Weight - 400) / 10; + if (index >= WEIGHTPOW_ARRAY_SIZE) + index = WEIGHTPOW_ARRAY_SIZE - 1; + int level = 0; + if (m_pSubstFont->m_Charset == FXFONT_SHIFTJIS_CHARSET) { + level = g_WeightPow_SHIFTJIS[index] * 2 * 65536 / 36655; + } else { + level = g_WeightPow[index] * 2; + } + FXFT_Outline_Embolden(FXFT_Get_Glyph_Outline(m_Face), level); + } + FXFT_Outline_Funcs funcs; + funcs.move_to = _Outline_MoveTo; + funcs.line_to = _Outline_LineTo; + funcs.conic_to = _Outline_ConicTo; + funcs.cubic_to = _Outline_CubicTo; + funcs.shift = 0; + funcs.delta = 0; + OUTLINE_PARAMS params; + params.m_bCount = TRUE; + params.m_PointCount = 0; + FXFT_Outline_Decompose(FXFT_Get_Glyph_Outline(m_Face), &funcs, ¶ms); + if (params.m_PointCount == 0) { + return NULL; + } + CFX_PathData* pPath = new CFX_PathData; + pPath->SetPointCount(params.m_PointCount); + params.m_bCount = FALSE; + params.m_PointCount = 0; + params.m_pPoints = pPath->GetPoints(); + params.m_CurX = params.m_CurY = 0; + params.m_CoordUnit = 64 * 64.0; + FXFT_Outline_Decompose(FXFT_Get_Glyph_Outline(m_Face), &funcs, ¶ms); + _Outline_CheckEmptyContour(¶ms); + pPath->TrimPoints(params.m_PointCount); + if (params.m_PointCount) { + pPath->GetPoints()[params.m_PointCount - 1].m_Flag |= FXPT_CLOSEFIGURE; + } + return pPath; } -void _CFX_UniqueKeyGen::Generate(int count, ...) -{ - va_list argList; - va_start(argList, count); - for (int i = 0; i < count; i ++) { - int p = va_arg(argList, int); - ((FX_DWORD*)m_Key)[i] = p; - } - va_end(argList); - m_KeyLen = count * sizeof(FX_DWORD); +void _CFX_UniqueKeyGen::Generate(int count, ...) { + va_list argList; + va_start(argList, count); + for (int i = 0; i < count; i++) { + int p = va_arg(argList, int); + ((FX_DWORD*)m_Key)[i] = p; + } + va_end(argList); + m_KeyLen = count * sizeof(FX_DWORD); } diff --git a/core/src/fxge/ge/text_int.h b/core/src/fxge/ge/text_int.h index 12fac6a60a..a05907162c 100644 --- a/core/src/fxge/ge/text_int.h +++ b/core/src/fxge/ge/text_int.h @@ -8,98 +8,86 @@ #define CORE_SRC_FXGE_GE_TEXT_INT_H_ struct _CFX_UniqueKeyGen { - void Generate(int count, ...); - FX_CHAR m_Key[128]; - int m_KeyLen; + void Generate(int count, ...); + FX_CHAR m_Key[128]; + int m_KeyLen; }; -class CFX_SizeGlyphCache -{ -public: - CFX_SizeGlyphCache() - { - m_GlyphMap.InitHashTable(253); - } - ~CFX_SizeGlyphCache(); - CFX_MapPtrToPtr m_GlyphMap; +class CFX_SizeGlyphCache { + public: + CFX_SizeGlyphCache() { m_GlyphMap.InitHashTable(253); } + ~CFX_SizeGlyphCache(); + CFX_MapPtrToPtr m_GlyphMap; }; -class CTTFontDesc -{ -public: - CTTFontDesc() - { - m_Type = 0; - m_pFontData = NULL; - m_RefCount = 0; - } - ~CTTFontDesc(); - FX_BOOL ReleaseFace(FXFT_Face face); - int m_Type; - union { - struct { - FX_BOOL m_bItalic; - FX_BOOL m_bBold; - FXFT_Face m_pFace; - } m_SingleFace; - struct { - FXFT_Face m_pFaces[16]; - } m_TTCFace; - }; - uint8_t* m_pFontData; - int m_RefCount; +class CTTFontDesc { + public: + CTTFontDesc() { + m_Type = 0; + m_pFontData = NULL; + m_RefCount = 0; + } + ~CTTFontDesc(); + FX_BOOL ReleaseFace(FXFT_Face face); + int m_Type; + union { + struct { + FX_BOOL m_bItalic; + FX_BOOL m_bBold; + FXFT_Face m_pFace; + } m_SingleFace; + struct { + FXFT_Face m_pFaces[16]; + } m_TTCFace; + }; + uint8_t* m_pFontData; + int m_RefCount; }; -class CFX_UnicodeEncoding : public IFX_FontEncoding -{ -public: - CFX_UnicodeEncoding(CFX_Font* pFont); - virtual FX_DWORD GlyphFromCharCodeEx(FX_DWORD charcode, int encoding = ENCODING_UNICODE); -private: - CFX_Font* m_pFont; - virtual FX_DWORD GlyphFromCharCode(FX_DWORD charcode); - virtual CFX_WideString UnicodeFromCharCode(FX_DWORD charcode) const - { - return CFX_WideString((FX_WCHAR)charcode); - } - virtual FX_DWORD CharCodeFromUnicode(FX_WCHAR Unicode) const - { - return Unicode; - } - virtual FX_BOOL IsUnicodeCompatible() const - { - return TRUE; - } +class CFX_UnicodeEncoding : public IFX_FontEncoding { + public: + CFX_UnicodeEncoding(CFX_Font* pFont); + virtual FX_DWORD GlyphFromCharCodeEx(FX_DWORD charcode, + int encoding = ENCODING_UNICODE); + + private: + CFX_Font* m_pFont; + virtual FX_DWORD GlyphFromCharCode(FX_DWORD charcode); + virtual CFX_WideString UnicodeFromCharCode(FX_DWORD charcode) const { + return CFX_WideString((FX_WCHAR)charcode); + } + virtual FX_DWORD CharCodeFromUnicode(FX_WCHAR Unicode) const { + return Unicode; + } + virtual FX_BOOL IsUnicodeCompatible() const { return TRUE; } }; -#define CHARSET_FLAG_ANSI 1 -#define CHARSET_FLAG_SYMBOL 2 -#define CHARSET_FLAG_SHIFTJIS 4 -#define CHARSET_FLAG_BIG5 8 -#define CHARSET_FLAG_GB 16 -#define CHARSET_FLAG_KOREAN 32 -class CFontFaceInfo -{ -public: - CFX_ByteString m_FilePath; - CFX_ByteString m_FaceName; - FX_DWORD m_Styles; - FX_DWORD m_Charsets; - FX_DWORD m_FontOffset; - FX_DWORD m_FileSize; - CFX_ByteString m_FontTables; +#define CHARSET_FLAG_ANSI 1 +#define CHARSET_FLAG_SYMBOL 2 +#define CHARSET_FLAG_SHIFTJIS 4 +#define CHARSET_FLAG_BIG5 8 +#define CHARSET_FLAG_GB 16 +#define CHARSET_FLAG_KOREAN 32 +class CFontFaceInfo { + public: + CFX_ByteString m_FilePath; + CFX_ByteString m_FaceName; + FX_DWORD m_Styles; + FX_DWORD m_Charsets; + FX_DWORD m_FontOffset; + FX_DWORD m_FileSize; + CFX_ByteString m_FontTables; }; -class CFontFileFaceInfo -{ -public: - CFontFileFaceInfo(); - ~CFontFileFaceInfo(); - IFX_FileStream* m_pFile; - FXFT_Face m_Face; - CFX_ByteString m_FaceName; - FX_DWORD m_Charsets; - FX_DWORD m_FileSize; - FX_DWORD m_FontOffset; - int m_Weight; - FX_BOOL m_bItalic; - int m_PitchFamily; - CFX_ByteString m_FontTables; +class CFontFileFaceInfo { + public: + CFontFileFaceInfo(); + ~CFontFileFaceInfo(); + IFX_FileStream* m_pFile; + FXFT_Face m_Face; + CFX_ByteString m_FaceName; + FX_DWORD m_Charsets; + FX_DWORD m_FileSize; + FX_DWORD m_FontOffset; + int m_Weight; + FX_BOOL m_bItalic; + int m_PitchFamily; + CFX_ByteString m_FontTables; }; #endif // CORE_SRC_FXGE_GE_TEXT_INT_H_ |