From 3f3b45cc74b0499912409f766a595945dbbfc4c5 Mon Sep 17 00:00:00 2001 From: John Abd-El-Malek Date: Fri, 23 May 2014 17:28:10 -0700 Subject: Convert all line endings to LF. --- core/src/fxge/ge/fx_ge.cpp | 158 +- core/src/fxge/ge/fx_ge_device.cpp | 810 ++++---- core/src/fxge/ge/fx_ge_font.cpp | 916 +++++----- core/src/fxge/ge/fx_ge_fontmap.cpp | 3116 +++++++++++++++---------------- core/src/fxge/ge/fx_ge_linux.cpp | 518 +++--- core/src/fxge/ge/fx_ge_path.cpp | 1308 ++++++------- core/src/fxge/ge/fx_ge_ps.cpp | 1314 ++++++------- core/src/fxge/ge/fx_ge_text.cpp | 3548 ++++++++++++++++++------------------ core/src/fxge/ge/text_int.h | 200 +- 9 files changed, 5944 insertions(+), 5944 deletions(-) (limited to 'core/src/fxge/ge') diff --git a/core/src/fxge/ge/fx_ge.cpp b/core/src/fxge/ge/fx_ge.cpp index df200d5b48..d044d721e6 100644 --- a/core/src/fxge/ge/fx_ge.cpp +++ b/core/src/fxge/ge/fx_ge.cpp @@ -1,79 +1,79 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#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() -{ - if (m_pFontCache) { - delete m_pFontCache; - } - m_pFontCache = NULL; - if (m_pFontMgr) { - delete m_pFontMgr; - } - m_pFontMgr = NULL; - DestroyPlatform(); -} -CFX_GEModule* CFX_GEModule::Get() -{ - return g_pGEModule; -} -void CFX_GEModule::Create() -{ - g_pGEModule = FX_NEW CFX_GEModule; - if (!g_pGEModule) { - return; - } - g_pGEModule->m_pFontMgr = FX_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() -{ - if (g_pGEModule) { - delete g_pGEModule; - } - g_pGEModule = NULL; -} -CFX_FontCache* CFX_GEModule::GetFontCache() -{ - if (m_pFontCache == NULL) { - m_pFontCache = FX_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] = (FX_BYTE)(FXSYS_pow((FX_FLOAT)i / 255, gammaValue) * 255.0f + 0.5f); - i++; - } -} -FX_LPCBYTE CFX_GEModule::GetTextGammaTable() -{ - return m_GammaValue; -} -void CFX_GEModule::SetExtFontMapper(IFX_FontMapper* pFontMapper) -{ - GetFontMgr()->m_pExtMapper = pFontMapper; - pFontMapper->m_pFontMgr = m_pFontMgr; -} +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#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() +{ + if (m_pFontCache) { + delete m_pFontCache; + } + m_pFontCache = NULL; + if (m_pFontMgr) { + delete m_pFontMgr; + } + m_pFontMgr = NULL; + DestroyPlatform(); +} +CFX_GEModule* CFX_GEModule::Get() +{ + return g_pGEModule; +} +void CFX_GEModule::Create() +{ + g_pGEModule = FX_NEW CFX_GEModule; + if (!g_pGEModule) { + return; + } + g_pGEModule->m_pFontMgr = FX_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() +{ + if (g_pGEModule) { + delete g_pGEModule; + } + g_pGEModule = NULL; +} +CFX_FontCache* CFX_GEModule::GetFontCache() +{ + if (m_pFontCache == NULL) { + m_pFontCache = FX_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] = (FX_BYTE)(FXSYS_pow((FX_FLOAT)i / 255, gammaValue) * 255.0f + 0.5f); + i++; + } +} +FX_LPCBYTE CFX_GEModule::GetTextGammaTable() +{ + return m_GammaValue; +} +void CFX_GEModule::SetExtFontMapper(IFX_FontMapper* pFontMapper) +{ + GetFontMgr()->m_pExtMapper = pFontMapper; + pFontMapper->m_pFontMgr = m_pFontMgr; +} diff --git a/core/src/fxge/ge/fx_ge_device.cpp b/core/src/fxge/ge/fx_ge_device.cpp index 8f7ccdb7d9..9c268b5606 100644 --- a/core/src/fxge/ge/fx_ge_device.cpp +++ b/core/src/fxge/ge/fx_ge_device.cpp @@ -1,405 +1,405 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// 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() -{ - if (m_pDeviceDriver) { - delete m_pDeviceDriver; - } -} -void CFX_RenderDevice::SetDeviceDriver(IFX_RenderDeviceDriver* pDriver) -{ - if (m_pDeviceDriver) { - 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; - } -} -FX_BOOL CFX_RenderDevice::StartRendering() -{ - return m_pDeviceDriver->StartRendering(); -} -void CFX_RenderDevice::EndRendering() -{ - m_pDeviceDriver->EndRendering(); -} -void CFX_RenderDevice::SaveState() -{ - m_pDeviceDriver->SaveState(); -} -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); -} -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); - } else if (m_RenderCaps & FXRC_BYTEMASK_OUTPUT) { - return pDIB->Create(width, height, FXDIB_8bppMask); - } else -#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); -#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_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; -} -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) -{ - FX_BYTE 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 { - 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; - } - 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; - } - } - } - 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; - } - CFX_FloatRect bbox; - if (pGraphState) { - bbox = pPathData->GetBoundingBox(pGraphState->m_LineWidth, pGraphState->m_MiterLimit); - } else { - bbox = pPathData->GetBoundingBox(); - } - if (pObject2Device) { - bbox.Transform(pObject2Device); - } - 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; - } - 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::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::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::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); -} -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; - } - 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); - } - 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::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, FX_LPVOID& 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(FX_LPVOID handle, IFX_Pause* pPause) -{ - return m_pDeviceDriver->ContinueDIBits(handle, pPause); -} -void CFX_RenderDevice::CancelDIBits(FX_LPVOID handle) -{ - m_pDeviceDriver->CancelDIBits(handle); -} +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// 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() +{ + if (m_pDeviceDriver) { + delete m_pDeviceDriver; + } +} +void CFX_RenderDevice::SetDeviceDriver(IFX_RenderDeviceDriver* pDriver) +{ + if (m_pDeviceDriver) { + 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; + } +} +FX_BOOL CFX_RenderDevice::StartRendering() +{ + return m_pDeviceDriver->StartRendering(); +} +void CFX_RenderDevice::EndRendering() +{ + m_pDeviceDriver->EndRendering(); +} +void CFX_RenderDevice::SaveState() +{ + m_pDeviceDriver->SaveState(); +} +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); +} +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); + } else if (m_RenderCaps & FXRC_BYTEMASK_OUTPUT) { + return pDIB->Create(width, height, FXDIB_8bppMask); + } else +#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); +#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_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; +} +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) +{ + FX_BYTE 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 { + 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; + } + 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; + } + } + } + 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; + } + CFX_FloatRect bbox; + if (pGraphState) { + bbox = pPathData->GetBoundingBox(pGraphState->m_LineWidth, pGraphState->m_MiterLimit); + } else { + bbox = pPathData->GetBoundingBox(); + } + if (pObject2Device) { + bbox.Transform(pObject2Device); + } + 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; + } + 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::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::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::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); +} +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; + } + 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); + } + 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::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, FX_LPVOID& 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(FX_LPVOID handle, IFX_Pause* pPause) +{ + return m_pDeviceDriver->ContinueDIBits(handle, pPause); +} +void CFX_RenderDevice::CancelDIBits(FX_LPVOID 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 e047d2ecb0..f3254ea3de 100644 --- a/core/src/fxge/ge/fx_ge_font.cpp +++ b/core/src/fxge/ge/fx_ge_font.cpp @@ -1,458 +1,458 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#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, FX_LPCBYTE& 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() -{ - if (m_pSubstFont) { - delete m_pSubstFont; - m_pSubstFont = NULL; - } -#ifdef FOXIT_CHROME_BUILD - if (m_pFontDataAllocation) { - FX_Free(m_pFontDataAllocation); - m_pFontDataAllocation = NULL; - } -#endif - if (m_Face) { -#ifdef FOXIT_CHROME_BUILD - FXFT_Library library = FXFT_Get_Face_FreeType(m_Face); - if (FXFT_Get_Face_External_Stream(m_Face)) { - FXFT_Clear_Face_External_Stream(m_Face); - } -#endif - if(m_bEmbedded) { - DeleteFace(); - } else { - CFX_GEModule::Get()->GetFontMgr()->ReleaseFace(m_Face); - } - } - 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_ && (!defined(_FPDFAPI_MINI_))) - ReleasePlatformResource(); -#endif -} -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 = FX_NEW CFX_SubstFont; - if (!m_pSubstFont) { - return FALSE; - } - 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; -} -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) - { - } -}; -FX_BOOL _LoadFile(FXFT_Library library, FXFT_Face* Face, IFX_FileRead* pFile, FXFT_Stream* stream) -{ - FXFT_Stream stream1 = (FXFT_Stream)FX_Alloc(FX_BYTE, sizeof (FXFT_StreamRec)); - if (!stream1) { - return FALSE; - } - 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; -} -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(FX_LPBYTE 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; - 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(FX_LPCBYTE data, FX_DWORD size) -{ -#ifdef FOXIT_CHROME_BUILD - m_pFontDataAllocation = FX_Alloc(FX_BYTE, size); - if (!m_pFontDataAllocation) { - return FALSE; - } - FXSYS_memcpy32(m_pFontDataAllocation, data, size); - m_Face = FT_LoadFont((FX_LPBYTE)m_pFontDataAllocation, size); - m_pFontData = (FX_LPBYTE)m_pFontDataAllocation; -#else - m_Face = FT_LoadFont((FX_LPBYTE)data, size); - m_pFontData = (FX_LPBYTE)data; -#endif - 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; -} -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; -} -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; - } - 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::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); -} -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)); - } else { - 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; - } else { - 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; -} -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::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; -} -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); - } - } - 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); - } else { - 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) -{ - CFX_UnicodeEncoding* pEncoding = NULL; - pEncoding = FX_NEW CFX_UnicodeEncoding(pFont); - return pEncoding; -} +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#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, FX_LPCBYTE& 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() +{ + if (m_pSubstFont) { + delete m_pSubstFont; + m_pSubstFont = NULL; + } +#ifdef FOXIT_CHROME_BUILD + if (m_pFontDataAllocation) { + FX_Free(m_pFontDataAllocation); + m_pFontDataAllocation = NULL; + } +#endif + if (m_Face) { +#ifdef FOXIT_CHROME_BUILD + FXFT_Library library = FXFT_Get_Face_FreeType(m_Face); + if (FXFT_Get_Face_External_Stream(m_Face)) { + FXFT_Clear_Face_External_Stream(m_Face); + } +#endif + if(m_bEmbedded) { + DeleteFace(); + } else { + CFX_GEModule::Get()->GetFontMgr()->ReleaseFace(m_Face); + } + } + 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_ && (!defined(_FPDFAPI_MINI_))) + ReleasePlatformResource(); +#endif +} +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 = FX_NEW CFX_SubstFont; + if (!m_pSubstFont) { + return FALSE; + } + 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; +} +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) + { + } +}; +FX_BOOL _LoadFile(FXFT_Library library, FXFT_Face* Face, IFX_FileRead* pFile, FXFT_Stream* stream) +{ + FXFT_Stream stream1 = (FXFT_Stream)FX_Alloc(FX_BYTE, sizeof (FXFT_StreamRec)); + if (!stream1) { + return FALSE; + } + 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; +} +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(FX_LPBYTE 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; + 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(FX_LPCBYTE data, FX_DWORD size) +{ +#ifdef FOXIT_CHROME_BUILD + m_pFontDataAllocation = FX_Alloc(FX_BYTE, size); + if (!m_pFontDataAllocation) { + return FALSE; + } + FXSYS_memcpy32(m_pFontDataAllocation, data, size); + m_Face = FT_LoadFont((FX_LPBYTE)m_pFontDataAllocation, size); + m_pFontData = (FX_LPBYTE)m_pFontDataAllocation; +#else + m_Face = FT_LoadFont((FX_LPBYTE)data, size); + m_pFontData = (FX_LPBYTE)data; +#endif + 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; +} +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; +} +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; + } + 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::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); +} +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)); + } else { + 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; + } else { + 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; +} +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::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; +} +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); + } + } + 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); + } else { + 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) +{ + CFX_UnicodeEncoding* pEncoding = NULL; + pEncoding = FX_NEW CFX_UnicodeEncoding(pFont); + return pEncoding; +} diff --git a/core/src/fxge/ge/fx_ge_fontmap.cpp b/core/src/fxge/ge/fx_ge_fontmap.cpp index 6549e8e531..8c2751d84a 100644 --- a/core/src/fxge/ge/fx_ge_fontmap.cpp +++ b/core/src/fxge/ge/fx_ge_fontmap.cpp @@ -1,1558 +1,1558 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#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; -} -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; - } - } - m_RefCount --; - if (m_RefCount) { - return FALSE; - } - delete this; - return TRUE; -} -CFX_FontMgr::CFX_FontMgr() -{ - m_pBuiltinMapper = FX_NEW CFX_FontMapper; - if (!m_pBuiltinMapper) { - return; - } - m_pBuiltinMapper->m_pFontMgr = this; - m_pExtMapper = NULL; - m_FTLibrary = NULL; - FXSYS_memset32(m_ExternalFonts, 0, sizeof m_ExternalFonts); -} -CFX_FontMgr::~CFX_FontMgr() -{ - if (m_pBuiltinMapper) { - 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::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); -} -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 == NULL) { - FXFT_Init_FreeType(&m_FTLibrary); - } - if (m_pExtMapper) { - FXFT_Face face = m_pExtMapper->FindSubstFont(face_name, bTrueType, flags, weight, italic_angle, - CharsetCP, pSubstFont); - if (face) { - return face; - } - } - 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, FX_LPBYTE& 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, FX_LPBYTE pData, FX_DWORD size, int face_index) -{ - CTTFontDesc* pFontDesc = FX_NEW CTTFontDesc; - if (!pFontDesc) { - return NULL; - } - 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_LPCSTR g_Base14FontNames[14] = { - "Courier", - "Courier-Bold", - "Courier-BoldOblique", - "Courier-Oblique", - "Helvetica", - "Helvetica-Bold", - "Helvetica-BoldOblique", - "Helvetica-Oblique", - "Times-Roman", - "Times-Bold", - "Times-BoldItalic", - "Times-Italic", - "Symbol", - "ZapfDingbats", -}; -const struct _AltFontName { - const FX_CHAR* m_pName; - int m_Index; -} -g_AltFontNames[] = { - {"Arial", 4}, - {"Arial,Bold", 5}, - {"Arial,BoldItalic", 6}, - {"Arial,Italic", 7}, - {"Arial-Bold", 5}, - {"Arial-BoldItalic", 6}, - {"Arial-BoldItalicMT", 6}, - {"Arial-BoldMT", 5}, - {"Arial-Italic", 7}, - {"Arial-ItalicMT", 7}, - {"ArialBold", 5}, - {"ArialBoldItalic", 6}, - {"ArialItalic", 7}, - {"ArialMT", 4}, - {"ArialMT,Bold", 5}, - {"ArialMT,BoldItalic", 6}, - {"ArialMT,Italic", 7}, - {"ArialRoundedMTBold", 5}, - {"Courier", 0}, - {"Courier,Bold", 1}, - {"Courier,BoldItalic", 2}, - {"Courier,Italic", 3}, - {"Courier-Bold", 1}, - {"Courier-BoldOblique", 2}, - {"Courier-Oblique", 3}, - {"CourierBold", 1}, - {"CourierBoldItalic", 2}, - {"CourierItalic", 3}, - {"CourierNew", 0}, - {"CourierNew,Bold", 1}, - {"CourierNew,BoldItalic", 2}, - {"CourierNew,Italic", 3}, - {"CourierNew-Bold", 1}, - {"CourierNew-BoldItalic", 2}, - {"CourierNew-Italic", 3}, - {"CourierNewBold", 1}, - {"CourierNewBoldItalic", 2}, - {"CourierNewItalic", 3}, - {"CourierNewPS-BoldItalicMT", 2}, - {"CourierNewPS-BoldMT", 1}, - {"CourierNewPS-ItalicMT", 3}, - {"CourierNewPSMT", 0}, - {"CourierStd", 0}, - {"CourierStd-Bold", 1}, - {"CourierStd-BoldOblique", 2}, - {"CourierStd-Oblique", 3}, - {"Helvetica", 4}, - {"Helvetica,Bold", 5}, - {"Helvetica,BoldItalic", 6}, - {"Helvetica,Italic", 7}, - {"Helvetica-Bold", 5}, - {"Helvetica-BoldItalic", 6}, - {"Helvetica-BoldOblique", 6}, - {"Helvetica-Italic", 7}, - {"Helvetica-Oblique", 7}, - {"HelveticaBold", 5}, - {"HelveticaBoldItalic", 6}, - {"HelveticaItalic", 7}, - {"Symbol", 12}, - {"SymbolMT", 12}, - {"Times-Bold", 9}, - {"Times-BoldItalic", 10}, - {"Times-Italic", 11}, - {"Times-Roman", 8}, - {"TimesBold", 9}, - {"TimesBoldItalic", 10}, - {"TimesItalic", 11}, - {"TimesNewRoman", 8}, - {"TimesNewRoman,Bold", 9}, - {"TimesNewRoman,BoldItalic", 10}, - {"TimesNewRoman,Italic", 11}, - {"TimesNewRoman-Bold", 9}, - {"TimesNewRoman-BoldItalic", 10}, - {"TimesNewRoman-Italic", 11}, - {"TimesNewRomanBold", 9}, - {"TimesNewRomanBoldItalic", 10}, - {"TimesNewRomanItalic", 11}, - {"TimesNewRomanPS", 8}, - {"TimesNewRomanPS-Bold", 9}, - {"TimesNewRomanPS-BoldItalic", 10}, - {"TimesNewRomanPS-BoldItalicMT", 10}, - {"TimesNewRomanPS-BoldMT", 9}, - {"TimesNewRomanPS-Italic", 11}, - {"TimesNewRomanPS-ItalicMT", 11}, - {"TimesNewRomanPSMT", 8}, - {"TimesNewRomanPSMT,Bold", 9}, - {"TimesNewRomanPSMT,BoldItalic", 10}, - {"TimesNewRomanPSMT,Italic", 11}, - {"ZapfDingbats", 13}, -}; -extern "C" { - static int compareString(const void* key, const void* element) - { - return FXSYS_stricmp((FX_LPCSTR)key, ((_AltFontName*)element)->m_pName); - } -} -int _PDF_GetStandardFontName(CFX_ByteString& name) -{ - _AltFontName* found = (_AltFontName*)FXSYS_bsearch((FX_LPCSTR)name, 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(FX_LPCBYTE pFontData, FX_DWORD ttc_size, FX_DWORD font_offset) -{ - int face_index = 0; - FX_LPCBYTE 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::GetCachedTTCFace(int ttc_size, FX_DWORD checksum, - int font_offset, FX_LPBYTE& 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::AddCachedTTCFace(int ttc_size, FX_DWORD checksum, - FX_LPBYTE pData, FX_DWORD size, int font_offset) -{ - CFX_ByteString key; - key.Format("%d:%d", ttc_size, checksum); - CTTFontDesc* pFontDesc = FX_NEW CTTFontDesc; - if (!pFontDesc) { - return NULL; - } - 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::GetFixedFace(FX_LPCBYTE 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::GetFileFace(FX_LPCSTR 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]; -}; -const FoxitFonts g_FoxitFonts[14] = { - {g_FoxitFixedFontData, 17597}, - {g_FoxitFixedBoldFontData, 18055}, - {g_FoxitFixedBoldItalicFontData, 19151}, - {g_FoxitFixedItalicFontData, 18746}, - {g_FoxitSansFontData, 15025}, - {g_FoxitSansBoldFontData, 16344}, - {g_FoxitSansBoldItalicFontData, 16418}, - {g_FoxitSansItalicFontData, 16339}, - {g_FoxitSerifFontData, 19469}, - {g_FoxitSerifBoldFontData, 19395}, - {g_FoxitSerifBoldItalicFontData, 20733}, - {g_FoxitSerifItalicFontData, 21227}, - {g_FoxitSymbolFontData, 16729}, - {g_FoxitDingbatsFontData, 29513}, -}; -void _FPDFAPI_GetInternalFontData(int id, FX_LPCBYTE& data, FX_DWORD& size) -{ - CFX_GEModule::Get()->GetFontMgr()->GetStandardFont(data, size, id); -} -FX_BOOL CFX_FontMgr::GetStandardFont(FX_LPCBYTE& 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; -} -CFX_FontMapper::CFX_FontMapper() -{ - FXSYS_memset32(m_FoxitFaces, 0, sizeof m_FoxitFaces); - m_MMFaces[0] = m_MMFaces[1] = NULL; - m_pFontInfo = NULL; - m_bListLoaded = FALSE; - m_pFontEnumerator = 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(); - } -} -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(FX_LPCSTR 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(FX_LPCBYTE name_table, FX_DWORD name_id) -{ - FX_LPCBYTE ptr = name_table + 2; - int name_count = GET_TT_SHORT(ptr); - int string_offset = GET_TT_SHORT(ptr + 2); - FX_LPCBYTE 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; -} -static CFX_ByteString _FPDF_ReadStringFromStreamFile(IFX_FileStream* pFile, FX_DWORD size) -{ - CFX_ByteString buffer; - if (!pFile->ReadBlock(buffer.GetBuffer(size), size)) { - return CFX_ByteString(); - } - buffer.ReleaseBuffer(size); - return buffer; -} -CFX_ByteString _FPDF_LoadTableFromTT(FXSYS_FILE* pFile, FX_LPCBYTE pTables, FX_DWORD nTables, FX_DWORD tag) -{ - for (FX_DWORD i = 0; i < nTables; i ++) { - FX_LPCBYTE 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 _FPDF_LoadTableFromTTStreamFile(IFX_FileStream* pFile, FX_LPCBYTE pTables, FX_DWORD nTables, FX_DWORD tag) -{ - for (FX_DWORD i = 0; i < nTables; i ++) { - FX_LPCBYTE 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 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) { - FX_LPBYTE buffer = FX_Alloc(FX_BYTE, size); - if (!buffer) { - return result; - } - m_pFontInfo->GetFontData(hFont, 0x6e616d65, buffer, size); - result = _FPDF_GetNameFromTT(buffer, 6); - FX_Free(buffer); - } - return result; -} -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; - } - FX_LPCBYTE 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) { - FX_BOOL bExact; - hFont = m_pFontInfo->MapFont(0, 0, FXFONT_DEFAULT_CHARSET, 0, name, bExact); - 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; -} -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_ { - FX_BYTE 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 }, -}; -FX_BYTE _GetCharsetFromCodePage(FX_WORD codepage) -{ - FX_INT32 iEnd = sizeof(g_Codepage2CharsetTable) / sizeof(CHARSET_MAP) - 1; - FXSYS_assert(iEnd >= 0); - FX_INT32 iStart = 0, iMid; - do { - iMid = (iStart + iEnd) / 2; - const CHARSET_MAP & cp = g_Codepage2CharsetTable[iMid]; - if (codepage == cp.codepage) { - return cp.charset; - } else 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; - } - return 1 << 21; -} -static int CP2CharSet(int cp) -{ - if(cp == 932) { - return FXFONT_SHIFTJIS_CHARSET; - } else if(cp == 936) { - return FXFONT_GB2312_CHARSET; - } else if(cp == 949) { - return FXFONT_HANGEUL_CHARSET; - } else if(cp == 950) { - return FXFONT_CHINESEBIG5_CHARSET; - } - return FXFONT_DEFAULT_CHARSET; -} -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]; - } - FX_LPCBYTE 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]; - } - FX_LPCBYTE 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_LPCBYTE 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 { - FX_LPCSTR m_pFontName; - FX_LPCSTR 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((FX_LPCSTR)key); - if (str_key.Find(((_AltFontFamily*)element)->m_pFontName) != -1) { - return 0; - } - return FXSYS_stricmp((FX_LPCSTR)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((FX_LPCSTR)fontName, g_AltFontFamilies, - sizeof g_AltFontFamilies / sizeof (_AltFontFamily), sizeof (_AltFontFamily), compareFontFamilyString); - if (found == NULL) { - return fontName; - } - return found->m_pFontFamily; -}; -typedef struct _FX_FontStyle { - FX_LPCSTR style; - FX_INT32 len; -} FX_FontStyle; -const FX_FontStyle g_FontStyles[] = { - "Bold", 4, - "Italic", 6, - "BoldItalic", 10, - "Reg", 3, - "Regular", 7, -}; -CFX_ByteString ParseStyle(FX_LPCSTR 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(); -} -FX_INT32 GetStyleType(const CFX_ByteString &bsStyle, FX_BOOL bRevert) -{ - FX_INT32 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; - } - } - } - return -1; -} -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]; - } - FX_LPCBYTE 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]; - } - FX_LPCBYTE 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; - FX_BOOL bFamilyStyleIsWhole = FALSE; - FX_BOOL bNextF = 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(); - FX_INT32 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 (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(); - FX_LPCSTR pStyle = style; - int i = 0; - FX_BOOL bFirstItem = TRUE; - CFX_ByteString buf; - while (i < nLen) { - buf = ParseStyle(pStyle, nLen, i); - FX_INT32 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; - } - } - 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; - FX_BOOL bExact = FALSE; - 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; - } - } 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; - } - } - } 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 (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; - } - } - bExact = !match.IsEmpty(); - void* hFont = m_pFontInfo->MapFont(weight, bItalic, Charset, PitchFamily, family, bExact); - if (bExact) { - 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 { - 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]; - } - FX_LPCBYTE 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]; - } else { - pSubstFont->m_SubstFlags |= FXFONT_SUBST_NONSYMBOL; - return FindSubstFont(family, bTrueType, flags & ~FXFONT_SYMBOLIC, weight, italic_angle, 0, pSubstFont); - } -#else - pSubstFont->m_SubstFlags |= FXFONT_SUBST_NONSYMBOL; - return FindSubstFont(family, bTrueType, flags & ~FXFONT_SYMBOLIC, weight, italic_angle, 0, pSubstFont); -#endif - } - 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); - } else { - 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) { - FX_BYTE 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]; - } - FX_LPBYTE pFontData; - face = m_pFontMgr->GetCachedTTCFace(ttc_size, checksum, ttc_size - font_size, pFontData); - if (face == NULL) { - pFontData = FX_Alloc(FX_BYTE, ttc_size); - if (pFontData) { - m_pFontInfo->GetFontData(hFont, 0x74746366, pFontData, ttc_size); - face = m_pFontMgr->AddCachedTTCFace(ttc_size, checksum, pFontData, ttc_size, - ttc_size - font_size); - } - } - } else { - FX_LPBYTE pFontData; - face = m_pFontMgr->GetCachedFace(SubstName, weight, bItalic, pFontData); - if (face == NULL) { - pFontData = FX_Alloc(FX_BYTE, font_size); - if (!pFontData) { - m_pFontInfo->DeleteFont(hFont); - return NULL; - } - 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 { - bNeedUpdateWeight = TRUE; - } - } 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; - } - 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); -}; -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; -} -extern FX_BOOL _LoadFile(FXFT_Library library, FXFT_Face* Face, IFX_FileRead* pFile, FXFT_Stream* stream); -#if defined(_FPDFAPI_MINI_) || _FX_OS_ == _FX_ANDROID_ -IFX_SystemFontInfo* IFX_SystemFontInfo::CreateDefault() -{ - return NULL; -} -#endif -#if !defined(_FPDFAPI_MINI_) -CFX_FolderFontInfo::CFX_FolderFontInfo() -{ -} -CFX_FolderFontInfo::~CFX_FolderFontInfo() -{ - FX_POSITION pos = m_FontList.GetStartPosition(); - while (pos) { - CFX_ByteString key; - FX_LPVOID value; - m_FontList.GetNextAssoc(pos, key, value); - delete (CFontFaceInfo*)value; - } -} -void CFX_FolderFontInfo::AddPath(FX_BSTR path) -{ - m_PathList.Add(path); -} -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; -} -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 += "/"; -#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); - FX_BYTE buffer[16]; - FXSYS_fseek(pFile, 0, FXSYS_SEEK_SET); - size_t readCnt = FXSYS_fread(buffer, 12, 1, pFile); - if (GET_TT_LONG(buffer) == 0x74746366) { - FX_DWORD nFaces = GET_TT_LONG(buffer + 8); - FX_LPBYTE offsets = FX_Alloc(FX_BYTE, nFaces * 4); - if (!offsets) { - FXSYS_fclose(pFile); - return; - } - readCnt = FXSYS_fread(offsets, nFaces * 4, 1, pFile); - for (FX_DWORD i = 0; i < nFaces; i ++) { - FX_LPBYTE 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::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); - 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; - } - FX_LPVOID p; - if (m_FontList.Lookup(facename, p)) { - return; - } - CFontFaceInfo* pInfo = FX_NEW CFontFaceInfo; - if (!pInfo) { - return; - } - 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) { - FX_LPCBYTE p = (FX_LPCBYTE)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, FX_LPCSTR family, FX_BOOL& bExact) -{ - return NULL; -} -void* CFX_FolderFontInfo::GetFont(FX_LPCSTR face) -{ - FX_LPVOID p; - if (!m_FontList.Lookup(face, p)) { - return NULL; - } - return p; -} -FX_DWORD CFX_FolderFontInfo::GetFontData(void* hFont, FX_DWORD table, FX_LPBYTE 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 ++) { - FX_LPCBYTE p = (FX_LPCBYTE)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); - size_t readCnt = FXSYS_fread(buffer, datasize, 1, pFile); - } - if (pFile) { - FXSYS_fclose(pFile); - } - return datasize; -} -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; -} -#endif +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#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; +} +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; + } + } + m_RefCount --; + if (m_RefCount) { + return FALSE; + } + delete this; + return TRUE; +} +CFX_FontMgr::CFX_FontMgr() +{ + m_pBuiltinMapper = FX_NEW CFX_FontMapper; + if (!m_pBuiltinMapper) { + return; + } + m_pBuiltinMapper->m_pFontMgr = this; + m_pExtMapper = NULL; + m_FTLibrary = NULL; + FXSYS_memset32(m_ExternalFonts, 0, sizeof m_ExternalFonts); +} +CFX_FontMgr::~CFX_FontMgr() +{ + if (m_pBuiltinMapper) { + 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::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); +} +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 == NULL) { + FXFT_Init_FreeType(&m_FTLibrary); + } + if (m_pExtMapper) { + FXFT_Face face = m_pExtMapper->FindSubstFont(face_name, bTrueType, flags, weight, italic_angle, + CharsetCP, pSubstFont); + if (face) { + return face; + } + } + 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, FX_LPBYTE& 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, FX_LPBYTE pData, FX_DWORD size, int face_index) +{ + CTTFontDesc* pFontDesc = FX_NEW CTTFontDesc; + if (!pFontDesc) { + return NULL; + } + 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_LPCSTR g_Base14FontNames[14] = { + "Courier", + "Courier-Bold", + "Courier-BoldOblique", + "Courier-Oblique", + "Helvetica", + "Helvetica-Bold", + "Helvetica-BoldOblique", + "Helvetica-Oblique", + "Times-Roman", + "Times-Bold", + "Times-BoldItalic", + "Times-Italic", + "Symbol", + "ZapfDingbats", +}; +const struct _AltFontName { + const FX_CHAR* m_pName; + int m_Index; +} +g_AltFontNames[] = { + {"Arial", 4}, + {"Arial,Bold", 5}, + {"Arial,BoldItalic", 6}, + {"Arial,Italic", 7}, + {"Arial-Bold", 5}, + {"Arial-BoldItalic", 6}, + {"Arial-BoldItalicMT", 6}, + {"Arial-BoldMT", 5}, + {"Arial-Italic", 7}, + {"Arial-ItalicMT", 7}, + {"ArialBold", 5}, + {"ArialBoldItalic", 6}, + {"ArialItalic", 7}, + {"ArialMT", 4}, + {"ArialMT,Bold", 5}, + {"ArialMT,BoldItalic", 6}, + {"ArialMT,Italic", 7}, + {"ArialRoundedMTBold", 5}, + {"Courier", 0}, + {"Courier,Bold", 1}, + {"Courier,BoldItalic", 2}, + {"Courier,Italic", 3}, + {"Courier-Bold", 1}, + {"Courier-BoldOblique", 2}, + {"Courier-Oblique", 3}, + {"CourierBold", 1}, + {"CourierBoldItalic", 2}, + {"CourierItalic", 3}, + {"CourierNew", 0}, + {"CourierNew,Bold", 1}, + {"CourierNew,BoldItalic", 2}, + {"CourierNew,Italic", 3}, + {"CourierNew-Bold", 1}, + {"CourierNew-BoldItalic", 2}, + {"CourierNew-Italic", 3}, + {"CourierNewBold", 1}, + {"CourierNewBoldItalic", 2}, + {"CourierNewItalic", 3}, + {"CourierNewPS-BoldItalicMT", 2}, + {"CourierNewPS-BoldMT", 1}, + {"CourierNewPS-ItalicMT", 3}, + {"CourierNewPSMT", 0}, + {"CourierStd", 0}, + {"CourierStd-Bold", 1}, + {"CourierStd-BoldOblique", 2}, + {"CourierStd-Oblique", 3}, + {"Helvetica", 4}, + {"Helvetica,Bold", 5}, + {"Helvetica,BoldItalic", 6}, + {"Helvetica,Italic", 7}, + {"Helvetica-Bold", 5}, + {"Helvetica-BoldItalic", 6}, + {"Helvetica-BoldOblique", 6}, + {"Helvetica-Italic", 7}, + {"Helvetica-Oblique", 7}, + {"HelveticaBold", 5}, + {"HelveticaBoldItalic", 6}, + {"HelveticaItalic", 7}, + {"Symbol", 12}, + {"SymbolMT", 12}, + {"Times-Bold", 9}, + {"Times-BoldItalic", 10}, + {"Times-Italic", 11}, + {"Times-Roman", 8}, + {"TimesBold", 9}, + {"TimesBoldItalic", 10}, + {"TimesItalic", 11}, + {"TimesNewRoman", 8}, + {"TimesNewRoman,Bold", 9}, + {"TimesNewRoman,BoldItalic", 10}, + {"TimesNewRoman,Italic", 11}, + {"TimesNewRoman-Bold", 9}, + {"TimesNewRoman-BoldItalic", 10}, + {"TimesNewRoman-Italic", 11}, + {"TimesNewRomanBold", 9}, + {"TimesNewRomanBoldItalic", 10}, + {"TimesNewRomanItalic", 11}, + {"TimesNewRomanPS", 8}, + {"TimesNewRomanPS-Bold", 9}, + {"TimesNewRomanPS-BoldItalic", 10}, + {"TimesNewRomanPS-BoldItalicMT", 10}, + {"TimesNewRomanPS-BoldMT", 9}, + {"TimesNewRomanPS-Italic", 11}, + {"TimesNewRomanPS-ItalicMT", 11}, + {"TimesNewRomanPSMT", 8}, + {"TimesNewRomanPSMT,Bold", 9}, + {"TimesNewRomanPSMT,BoldItalic", 10}, + {"TimesNewRomanPSMT,Italic", 11}, + {"ZapfDingbats", 13}, +}; +extern "C" { + static int compareString(const void* key, const void* element) + { + return FXSYS_stricmp((FX_LPCSTR)key, ((_AltFontName*)element)->m_pName); + } +} +int _PDF_GetStandardFontName(CFX_ByteString& name) +{ + _AltFontName* found = (_AltFontName*)FXSYS_bsearch((FX_LPCSTR)name, 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(FX_LPCBYTE pFontData, FX_DWORD ttc_size, FX_DWORD font_offset) +{ + int face_index = 0; + FX_LPCBYTE 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::GetCachedTTCFace(int ttc_size, FX_DWORD checksum, + int font_offset, FX_LPBYTE& 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::AddCachedTTCFace(int ttc_size, FX_DWORD checksum, + FX_LPBYTE pData, FX_DWORD size, int font_offset) +{ + CFX_ByteString key; + key.Format("%d:%d", ttc_size, checksum); + CTTFontDesc* pFontDesc = FX_NEW CTTFontDesc; + if (!pFontDesc) { + return NULL; + } + 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::GetFixedFace(FX_LPCBYTE 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::GetFileFace(FX_LPCSTR 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]; +}; +const FoxitFonts g_FoxitFonts[14] = { + {g_FoxitFixedFontData, 17597}, + {g_FoxitFixedBoldFontData, 18055}, + {g_FoxitFixedBoldItalicFontData, 19151}, + {g_FoxitFixedItalicFontData, 18746}, + {g_FoxitSansFontData, 15025}, + {g_FoxitSansBoldFontData, 16344}, + {g_FoxitSansBoldItalicFontData, 16418}, + {g_FoxitSansItalicFontData, 16339}, + {g_FoxitSerifFontData, 19469}, + {g_FoxitSerifBoldFontData, 19395}, + {g_FoxitSerifBoldItalicFontData, 20733}, + {g_FoxitSerifItalicFontData, 21227}, + {g_FoxitSymbolFontData, 16729}, + {g_FoxitDingbatsFontData, 29513}, +}; +void _FPDFAPI_GetInternalFontData(int id, FX_LPCBYTE& data, FX_DWORD& size) +{ + CFX_GEModule::Get()->GetFontMgr()->GetStandardFont(data, size, id); +} +FX_BOOL CFX_FontMgr::GetStandardFont(FX_LPCBYTE& 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; +} +CFX_FontMapper::CFX_FontMapper() +{ + FXSYS_memset32(m_FoxitFaces, 0, sizeof m_FoxitFaces); + m_MMFaces[0] = m_MMFaces[1] = NULL; + m_pFontInfo = NULL; + m_bListLoaded = FALSE; + m_pFontEnumerator = 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(); + } +} +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(FX_LPCSTR 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(FX_LPCBYTE name_table, FX_DWORD name_id) +{ + FX_LPCBYTE ptr = name_table + 2; + int name_count = GET_TT_SHORT(ptr); + int string_offset = GET_TT_SHORT(ptr + 2); + FX_LPCBYTE 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; +} +static CFX_ByteString _FPDF_ReadStringFromStreamFile(IFX_FileStream* pFile, FX_DWORD size) +{ + CFX_ByteString buffer; + if (!pFile->ReadBlock(buffer.GetBuffer(size), size)) { + return CFX_ByteString(); + } + buffer.ReleaseBuffer(size); + return buffer; +} +CFX_ByteString _FPDF_LoadTableFromTT(FXSYS_FILE* pFile, FX_LPCBYTE pTables, FX_DWORD nTables, FX_DWORD tag) +{ + for (FX_DWORD i = 0; i < nTables; i ++) { + FX_LPCBYTE 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 _FPDF_LoadTableFromTTStreamFile(IFX_FileStream* pFile, FX_LPCBYTE pTables, FX_DWORD nTables, FX_DWORD tag) +{ + for (FX_DWORD i = 0; i < nTables; i ++) { + FX_LPCBYTE 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 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) { + FX_LPBYTE buffer = FX_Alloc(FX_BYTE, size); + if (!buffer) { + return result; + } + m_pFontInfo->GetFontData(hFont, 0x6e616d65, buffer, size); + result = _FPDF_GetNameFromTT(buffer, 6); + FX_Free(buffer); + } + return result; +} +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; + } + FX_LPCBYTE 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) { + FX_BOOL bExact; + hFont = m_pFontInfo->MapFont(0, 0, FXFONT_DEFAULT_CHARSET, 0, name, bExact); + 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; +} +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_ { + FX_BYTE 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 }, +}; +FX_BYTE _GetCharsetFromCodePage(FX_WORD codepage) +{ + FX_INT32 iEnd = sizeof(g_Codepage2CharsetTable) / sizeof(CHARSET_MAP) - 1; + FXSYS_assert(iEnd >= 0); + FX_INT32 iStart = 0, iMid; + do { + iMid = (iStart + iEnd) / 2; + const CHARSET_MAP & cp = g_Codepage2CharsetTable[iMid]; + if (codepage == cp.codepage) { + return cp.charset; + } else 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; + } + return 1 << 21; +} +static int CP2CharSet(int cp) +{ + if(cp == 932) { + return FXFONT_SHIFTJIS_CHARSET; + } else if(cp == 936) { + return FXFONT_GB2312_CHARSET; + } else if(cp == 949) { + return FXFONT_HANGEUL_CHARSET; + } else if(cp == 950) { + return FXFONT_CHINESEBIG5_CHARSET; + } + return FXFONT_DEFAULT_CHARSET; +} +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]; + } + FX_LPCBYTE 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]; + } + FX_LPCBYTE 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_LPCBYTE 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 { + FX_LPCSTR m_pFontName; + FX_LPCSTR 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((FX_LPCSTR)key); + if (str_key.Find(((_AltFontFamily*)element)->m_pFontName) != -1) { + return 0; + } + return FXSYS_stricmp((FX_LPCSTR)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((FX_LPCSTR)fontName, g_AltFontFamilies, + sizeof g_AltFontFamilies / sizeof (_AltFontFamily), sizeof (_AltFontFamily), compareFontFamilyString); + if (found == NULL) { + return fontName; + } + return found->m_pFontFamily; +}; +typedef struct _FX_FontStyle { + FX_LPCSTR style; + FX_INT32 len; +} FX_FontStyle; +const FX_FontStyle g_FontStyles[] = { + "Bold", 4, + "Italic", 6, + "BoldItalic", 10, + "Reg", 3, + "Regular", 7, +}; +CFX_ByteString ParseStyle(FX_LPCSTR 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(); +} +FX_INT32 GetStyleType(const CFX_ByteString &bsStyle, FX_BOOL bRevert) +{ + FX_INT32 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; + } + } + } + return -1; +} +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]; + } + FX_LPCBYTE 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]; + } + FX_LPCBYTE 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; + FX_BOOL bFamilyStyleIsWhole = FALSE; + FX_BOOL bNextF = 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(); + FX_INT32 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 (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(); + FX_LPCSTR pStyle = style; + int i = 0; + FX_BOOL bFirstItem = TRUE; + CFX_ByteString buf; + while (i < nLen) { + buf = ParseStyle(pStyle, nLen, i); + FX_INT32 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; + } + } + 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; + FX_BOOL bExact = FALSE; + 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; + } + } 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; + } + } + } 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 (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; + } + } + bExact = !match.IsEmpty(); + void* hFont = m_pFontInfo->MapFont(weight, bItalic, Charset, PitchFamily, family, bExact); + if (bExact) { + 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 { + 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]; + } + FX_LPCBYTE 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]; + } else { + pSubstFont->m_SubstFlags |= FXFONT_SUBST_NONSYMBOL; + return FindSubstFont(family, bTrueType, flags & ~FXFONT_SYMBOLIC, weight, italic_angle, 0, pSubstFont); + } +#else + pSubstFont->m_SubstFlags |= FXFONT_SUBST_NONSYMBOL; + return FindSubstFont(family, bTrueType, flags & ~FXFONT_SYMBOLIC, weight, italic_angle, 0, pSubstFont); +#endif + } + 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); + } else { + 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) { + FX_BYTE 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]; + } + FX_LPBYTE pFontData; + face = m_pFontMgr->GetCachedTTCFace(ttc_size, checksum, ttc_size - font_size, pFontData); + if (face == NULL) { + pFontData = FX_Alloc(FX_BYTE, ttc_size); + if (pFontData) { + m_pFontInfo->GetFontData(hFont, 0x74746366, pFontData, ttc_size); + face = m_pFontMgr->AddCachedTTCFace(ttc_size, checksum, pFontData, ttc_size, + ttc_size - font_size); + } + } + } else { + FX_LPBYTE pFontData; + face = m_pFontMgr->GetCachedFace(SubstName, weight, bItalic, pFontData); + if (face == NULL) { + pFontData = FX_Alloc(FX_BYTE, font_size); + if (!pFontData) { + m_pFontInfo->DeleteFont(hFont); + return NULL; + } + 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 { + bNeedUpdateWeight = TRUE; + } + } 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; + } + 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); +}; +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; +} +extern FX_BOOL _LoadFile(FXFT_Library library, FXFT_Face* Face, IFX_FileRead* pFile, FXFT_Stream* stream); +#if defined(_FPDFAPI_MINI_) || _FX_OS_ == _FX_ANDROID_ +IFX_SystemFontInfo* IFX_SystemFontInfo::CreateDefault() +{ + return NULL; +} +#endif +#if !defined(_FPDFAPI_MINI_) +CFX_FolderFontInfo::CFX_FolderFontInfo() +{ +} +CFX_FolderFontInfo::~CFX_FolderFontInfo() +{ + FX_POSITION pos = m_FontList.GetStartPosition(); + while (pos) { + CFX_ByteString key; + FX_LPVOID value; + m_FontList.GetNextAssoc(pos, key, value); + delete (CFontFaceInfo*)value; + } +} +void CFX_FolderFontInfo::AddPath(FX_BSTR path) +{ + m_PathList.Add(path); +} +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; +} +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 += "/"; +#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); + FX_BYTE buffer[16]; + FXSYS_fseek(pFile, 0, FXSYS_SEEK_SET); + size_t readCnt = FXSYS_fread(buffer, 12, 1, pFile); + if (GET_TT_LONG(buffer) == 0x74746366) { + FX_DWORD nFaces = GET_TT_LONG(buffer + 8); + FX_LPBYTE offsets = FX_Alloc(FX_BYTE, nFaces * 4); + if (!offsets) { + FXSYS_fclose(pFile); + return; + } + readCnt = FXSYS_fread(offsets, nFaces * 4, 1, pFile); + for (FX_DWORD i = 0; i < nFaces; i ++) { + FX_LPBYTE 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::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); + 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; + } + FX_LPVOID p; + if (m_FontList.Lookup(facename, p)) { + return; + } + CFontFaceInfo* pInfo = FX_NEW CFontFaceInfo; + if (!pInfo) { + return; + } + 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) { + FX_LPCBYTE p = (FX_LPCBYTE)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, FX_LPCSTR family, FX_BOOL& bExact) +{ + return NULL; +} +void* CFX_FolderFontInfo::GetFont(FX_LPCSTR face) +{ + FX_LPVOID p; + if (!m_FontList.Lookup(face, p)) { + return NULL; + } + return p; +} +FX_DWORD CFX_FolderFontInfo::GetFontData(void* hFont, FX_DWORD table, FX_LPBYTE 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 ++) { + FX_LPCBYTE p = (FX_LPCBYTE)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); + size_t readCnt = FXSYS_fread(buffer, datasize, 1, pFile); + } + if (pFile) { + FXSYS_fclose(pFile); + } + return datasize; +} +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; +} +#endif diff --git a/core/src/fxge/ge/fx_ge_linux.cpp b/core/src/fxge/ge/fx_ge_linux.cpp index 33cfcfe722..735ecac0c8 100644 --- a/core/src/fxge/ge/fx_ge_linux.cpp +++ b/core/src/fxge/ge/fx_ge_linux.cpp @@ -1,259 +1,259 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "../../../include/fxge/fx_ge.h" -#include "../agg/include/fx_agg_driver.h" -#include "text_int.h" -#if !defined(_FPDFAPI_MINI_) && _FXM_PLATFORM_ == _FXM_PLATFORM_LINUX_ -#if (_FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ && (!defined(_FPDFAPI_MINI_))) -void CFX_AggDeviceDriver::InitPlatform() -{ -} -void CFX_AggDeviceDriver::DestroyPlatform() -{ -} -void CFX_FaceCache::InitPlatform() -{ -} -FX_BOOL CFX_AggDeviceDriver::DrawDeviceText(int nChars, const FXTEXT_CHARPOS* pCharPos, CFX_Font* pFont, - CFX_FontCache* pCache, const CFX_AffineMatrix* pObject2Device, - FX_FLOAT font_size, FX_DWORD argb) -{ - return FALSE; -} -CFX_GlyphBitmap* CFX_FaceCache::RenderGlyph_Nativetext(CFX_Font* pFont, FX_DWORD glyph_index, const CFX_AffineMatrix* pMatrix, - int dest_width, int anti_alias) -{ - return NULL; -} -void CFX_Font::ReleasePlatformResource() -{ -} -#endif -static const struct { - FX_LPCSTR m_pName; - FX_LPCSTR m_pSubstName; -} -Base14Substs[] = { - {"Courier", "Courier New"}, - {"Courier-Bold", "Courier New Bold"}, - {"Courier-BoldOblique", "Courier New Bold Italic"}, - {"Courier-Oblique", "Courier New Italic"}, - {"Helvetica", "Arial"}, - {"Helvetica-Bold", "Arial Bold"}, - {"Helvetica-BoldOblique", "Arial Bold Italic"}, - {"Helvetica-Oblique", "Arial Italic"}, - {"Times-Roman", "Times New Roman"}, - {"Times-Bold", "Times New Roman Bold"}, - {"Times-BoldItalic", "Times New Roman Bold Italic"}, - {"Times-Italic", "Times New Roman Italic"}, -}; -class CFX_LinuxFontInfo : public CFX_FolderFontInfo -{ -public: - virtual void* MapFont(int weight, FX_BOOL bItalic, int charset, int pitch_family, FX_LPCSTR family, FX_BOOL& bExact); - FX_BOOL ParseFontCfg(); - void* FindFont(int weight, FX_BOOL bItalic, int charset, int pitch_family, FX_LPCSTR family, FX_BOOL bMatchName); -}; -#define LINUX_GPNAMESIZE 6 -static const struct { - FX_LPCSTR 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_LPCSTR g_LinuxGbFontList[] = { - "AR PL UMing CN Light", - "WenQuanYi Micro Hei", - "AR PL UKai CN", -}; -static const FX_LPCSTR g_LinuxB5FontList[] = { - "AR PL UMing TW Light", - "WenQuanYi Micro Hei", - "AR PL UKai TW", -}; -static const FX_LPCSTR g_LinuxHGFontList[] = { - "UnDotum", -}; -static FX_INT32 GetJapanesePreference(FX_LPCSTR 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; - } else { - return 1; - } - } else 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; - } else { - 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, FX_LPCSTR cstr_face, FX_BOOL& bExact) -{ - 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; - bExact = TRUE; - break; - } - if (iBaseFont < 12) { - return GetFont(face); - } - FX_LPVOID p = NULL; - FX_BOOL bCJK = TRUE; - switch (charset) { - case FXFONT_SHIFTJIS_CHARSET: { - FX_INT32 index = GetJapanesePreference(cstr_face, weight, pitch_family); - if (index < 0) { - break; - } - for (FX_INT32 i = 0; i < LINUX_GPNAMESIZE; i++) - if (m_FontList.Lookup(LinuxGpFontList[index].NameArr[i], p)) { - return p; - } - } - break; - case FXFONT_GB2312_CHARSET: { - static FX_INT32 s_gbCount = sizeof(g_LinuxGbFontList) / sizeof(FX_LPCSTR); - for (FX_INT32 i = 0; i < s_gbCount; i++) - if (m_FontList.Lookup(g_LinuxGbFontList[i], p)) { - return p; - } - } - break; - case FXFONT_CHINESEBIG5_CHARSET: { - static FX_INT32 s_b5Count = sizeof(g_LinuxB5FontList) / sizeof(FX_LPCSTR); - for (FX_INT32 i = 0; i < s_b5Count; i++) - if (m_FontList.Lookup(g_LinuxB5FontList[i], p)) { - return p; - } - } - break; - case FXFONT_HANGEUL_CHARSET: { - static FX_INT32 s_hgCount = sizeof(g_LinuxHGFontList) / sizeof(FX_LPCSTR); - for (FX_INT32 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 0; -} -static FX_INT32 _LinuxGetSimilarValue(int weight, FX_BOOL bItalic, int pitch_family, FX_DWORD style) -{ - FX_INT32 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, FX_LPCSTR family, FX_BOOL bMatchName) -{ - CFontFaceInfo* pFind = NULL; - FX_DWORD charset_flag = _LinuxGetCharset(charset); - FX_INT32 iBestSimilar = 0; - FX_POSITION pos = m_FontList.GetStartPosition(); - while (pos) { - CFX_ByteString bsName; - CFontFaceInfo* pFont = NULL; - m_FontList.GetNextAssoc(pos, bsName, (FX_LPVOID&)pFont); - if (!(pFont->m_Charsets & charset_flag) && charset != FXFONT_DEFAULT_CHARSET) { - continue; - } - FX_INT32 iSimilarValue = 0; - FX_INT32 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 pFind; -} -IFX_SystemFontInfo* IFX_SystemFontInfo::CreateDefault() -{ - CFX_LinuxFontInfo* pInfo = FX_NEW CFX_LinuxFontInfo; - if (!pInfo) { - return NULL; - } - 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; -} -FX_BOOL CFX_LinuxFontInfo::ParseFontCfg() -{ - return FALSE; -} -void CFX_GEModule::InitPlatform() -{ - m_pFontMgr->SetSystemFontInfo(IFX_SystemFontInfo::CreateDefault()); -} -void CFX_GEModule::DestroyPlatform() -{ -} -#endif +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "../../../include/fxge/fx_ge.h" +#include "../agg/include/fx_agg_driver.h" +#include "text_int.h" +#if !defined(_FPDFAPI_MINI_) && _FXM_PLATFORM_ == _FXM_PLATFORM_LINUX_ +#if (_FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ && (!defined(_FPDFAPI_MINI_))) +void CFX_AggDeviceDriver::InitPlatform() +{ +} +void CFX_AggDeviceDriver::DestroyPlatform() +{ +} +void CFX_FaceCache::InitPlatform() +{ +} +FX_BOOL CFX_AggDeviceDriver::DrawDeviceText(int nChars, const FXTEXT_CHARPOS* pCharPos, CFX_Font* pFont, + CFX_FontCache* pCache, const CFX_AffineMatrix* pObject2Device, + FX_FLOAT font_size, FX_DWORD argb) +{ + return FALSE; +} +CFX_GlyphBitmap* CFX_FaceCache::RenderGlyph_Nativetext(CFX_Font* pFont, FX_DWORD glyph_index, const CFX_AffineMatrix* pMatrix, + int dest_width, int anti_alias) +{ + return NULL; +} +void CFX_Font::ReleasePlatformResource() +{ +} +#endif +static const struct { + FX_LPCSTR m_pName; + FX_LPCSTR m_pSubstName; +} +Base14Substs[] = { + {"Courier", "Courier New"}, + {"Courier-Bold", "Courier New Bold"}, + {"Courier-BoldOblique", "Courier New Bold Italic"}, + {"Courier-Oblique", "Courier New Italic"}, + {"Helvetica", "Arial"}, + {"Helvetica-Bold", "Arial Bold"}, + {"Helvetica-BoldOblique", "Arial Bold Italic"}, + {"Helvetica-Oblique", "Arial Italic"}, + {"Times-Roman", "Times New Roman"}, + {"Times-Bold", "Times New Roman Bold"}, + {"Times-BoldItalic", "Times New Roman Bold Italic"}, + {"Times-Italic", "Times New Roman Italic"}, +}; +class CFX_LinuxFontInfo : public CFX_FolderFontInfo +{ +public: + virtual void* MapFont(int weight, FX_BOOL bItalic, int charset, int pitch_family, FX_LPCSTR family, FX_BOOL& bExact); + FX_BOOL ParseFontCfg(); + void* FindFont(int weight, FX_BOOL bItalic, int charset, int pitch_family, FX_LPCSTR family, FX_BOOL bMatchName); +}; +#define LINUX_GPNAMESIZE 6 +static const struct { + FX_LPCSTR 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_LPCSTR g_LinuxGbFontList[] = { + "AR PL UMing CN Light", + "WenQuanYi Micro Hei", + "AR PL UKai CN", +}; +static const FX_LPCSTR g_LinuxB5FontList[] = { + "AR PL UMing TW Light", + "WenQuanYi Micro Hei", + "AR PL UKai TW", +}; +static const FX_LPCSTR g_LinuxHGFontList[] = { + "UnDotum", +}; +static FX_INT32 GetJapanesePreference(FX_LPCSTR 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; + } else { + return 1; + } + } else 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; + } else { + 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, FX_LPCSTR cstr_face, FX_BOOL& bExact) +{ + 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; + bExact = TRUE; + break; + } + if (iBaseFont < 12) { + return GetFont(face); + } + FX_LPVOID p = NULL; + FX_BOOL bCJK = TRUE; + switch (charset) { + case FXFONT_SHIFTJIS_CHARSET: { + FX_INT32 index = GetJapanesePreference(cstr_face, weight, pitch_family); + if (index < 0) { + break; + } + for (FX_INT32 i = 0; i < LINUX_GPNAMESIZE; i++) + if (m_FontList.Lookup(LinuxGpFontList[index].NameArr[i], p)) { + return p; + } + } + break; + case FXFONT_GB2312_CHARSET: { + static FX_INT32 s_gbCount = sizeof(g_LinuxGbFontList) / sizeof(FX_LPCSTR); + for (FX_INT32 i = 0; i < s_gbCount; i++) + if (m_FontList.Lookup(g_LinuxGbFontList[i], p)) { + return p; + } + } + break; + case FXFONT_CHINESEBIG5_CHARSET: { + static FX_INT32 s_b5Count = sizeof(g_LinuxB5FontList) / sizeof(FX_LPCSTR); + for (FX_INT32 i = 0; i < s_b5Count; i++) + if (m_FontList.Lookup(g_LinuxB5FontList[i], p)) { + return p; + } + } + break; + case FXFONT_HANGEUL_CHARSET: { + static FX_INT32 s_hgCount = sizeof(g_LinuxHGFontList) / sizeof(FX_LPCSTR); + for (FX_INT32 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 0; +} +static FX_INT32 _LinuxGetSimilarValue(int weight, FX_BOOL bItalic, int pitch_family, FX_DWORD style) +{ + FX_INT32 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, FX_LPCSTR family, FX_BOOL bMatchName) +{ + CFontFaceInfo* pFind = NULL; + FX_DWORD charset_flag = _LinuxGetCharset(charset); + FX_INT32 iBestSimilar = 0; + FX_POSITION pos = m_FontList.GetStartPosition(); + while (pos) { + CFX_ByteString bsName; + CFontFaceInfo* pFont = NULL; + m_FontList.GetNextAssoc(pos, bsName, (FX_LPVOID&)pFont); + if (!(pFont->m_Charsets & charset_flag) && charset != FXFONT_DEFAULT_CHARSET) { + continue; + } + FX_INT32 iSimilarValue = 0; + FX_INT32 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 pFind; +} +IFX_SystemFontInfo* IFX_SystemFontInfo::CreateDefault() +{ + CFX_LinuxFontInfo* pInfo = FX_NEW CFX_LinuxFontInfo; + if (!pInfo) { + return NULL; + } + 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; +} +FX_BOOL CFX_LinuxFontInfo::ParseFontCfg() +{ + return FALSE; +} +void CFX_GEModule::InitPlatform() +{ + m_pFontMgr->SetSystemFontInfo(IFX_SystemFontInfo::CreateDefault()); +} +void CFX_GEModule::DestroyPlatform() +{ +} +#endif diff --git a/core/src/fxge/ge/fx_ge_path.cpp b/core/src/fxge/ge/fx_ge_path.cpp index fc6ee52f1f..cd3ff0efbe 100644 --- a/core/src/fxge/ge/fx_ge_path.cpp +++ b/core/src/fxge/ge/fx_ge_path.cpp @@ -1,654 +1,654 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "../../../include/fxcrt/fx_basic.h" -#include "../../../include/fxge/fx_ge.h" -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; - return; - } else 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 ++) { - FX_LPBYTE dest_scan = new_dib->GetBuffer() + new_dib->GetPitch() * (row - m_Box.top); - FX_LPBYTE 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 ++) { - FX_LPBYTE old_scan = old_dib->GetBuffer() + (row - m_Box.top) * old_dib->GetPitch(); - FX_LPBYTE mask_scan = mask_dib->GetBuffer() + (row - top) * mask_dib->GetPitch(); - FX_LPBYTE 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); - } -} -FX_BOOL 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); - if (!m_pPoints) { - return FALSE; - } - m_AllocCount = nPoints; - } - return TRUE; -} -FX_BOOL CFX_PathData::AllocPointCount(int nPoints) -{ - if (m_AllocCount < nPoints) { - FX_PATHPOINT* pNewBuf = FX_Alloc(FX_PATHPOINT, nPoints); - if (!pNewBuf) { - return FALSE; - } - if (m_PointCount) { - FXSYS_memcpy32(pNewBuf, m_pPoints, m_PointCount * sizeof(FX_PATHPOINT)); - } - if (m_pPoints) { - FX_Free(m_pPoints); - } - m_pPoints = pNewBuf; - m_AllocCount = nPoints; - } - return TRUE; -} -CFX_PathData::CFX_PathData(const CFX_PathData& src) -{ - m_pPoints = NULL; - m_PointCount = m_AllocCount = src.m_PointCount; - m_pPoints = FX_Alloc(FX_PATHPOINT, src.m_PointCount); - if (!m_pPoints) { - return; - } - FXSYS_memcpy32(m_pPoints, src.m_pPoints, sizeof(FX_PATHPOINT) * m_PointCount); -} -void CFX_PathData::TrimPoints(int nPoints) -{ - if (m_PointCount <= nPoints) { - return; - } - SetPointCount(nPoints); -} -FX_BOOL CFX_PathData::AddPointCount(int addPoints) -{ - int new_count = m_PointCount + addPoints; - if (!AllocPointCount(new_count)) { - return FALSE; - } - m_PointCount = new_count; - return TRUE; -} -FX_BOOL CFX_PathData::Append(const CFX_PathData* pSrc, const CFX_AffineMatrix* pMatrix) -{ - int old_count = m_PointCount; - if (!AddPointCount(pSrc->m_PointCount)) { - return FALSE; - } - FXSYS_memcpy32(m_pPoints + old_count, pSrc->m_pPoints, pSrc->m_PointCount * sizeof(FX_PATHPOINT)); - if (pMatrix == NULL) { - return TRUE; - } - 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); - } - return TRUE; -} -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; -} -FX_BOOL CFX_PathData::AppendRect(FX_FLOAT left, FX_FLOAT bottom, FX_FLOAT right, FX_FLOAT top) -{ - int old_count = m_PointCount; - if (!AddPointCount(5)) { - return FALSE; - } - 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; - return TRUE; -} -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) { - 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; - } else 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; - } - 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; - } 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); - } -} -const int g_Distant[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; -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; - } - } - 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 = 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 (pRect) { - pRect->left = x[0]; - pRect->right = x[2]; - pRect->bottom = y[0]; - pRect->top = y[2]; - pRect->Normalize(); - } - return TRUE; -} -FX_BOOL CFX_PathData::Copy(const CFX_PathData &src) -{ - if (!SetPointCount(src.m_PointCount)) { - return FALSE; - } - FXSYS_memcpy32(m_pPoints, src.m_pPoints, sizeof(FX_PATHPOINT) * m_PointCount); - return TRUE; -} -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); - if (!m_DashArray) { - return; - } - FXSYS_memcpy32(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); -} +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "../../../include/fxcrt/fx_basic.h" +#include "../../../include/fxge/fx_ge.h" +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; + return; + } else 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 ++) { + FX_LPBYTE dest_scan = new_dib->GetBuffer() + new_dib->GetPitch() * (row - m_Box.top); + FX_LPBYTE 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 ++) { + FX_LPBYTE old_scan = old_dib->GetBuffer() + (row - m_Box.top) * old_dib->GetPitch(); + FX_LPBYTE mask_scan = mask_dib->GetBuffer() + (row - top) * mask_dib->GetPitch(); + FX_LPBYTE 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); + } +} +FX_BOOL 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); + if (!m_pPoints) { + return FALSE; + } + m_AllocCount = nPoints; + } + return TRUE; +} +FX_BOOL CFX_PathData::AllocPointCount(int nPoints) +{ + if (m_AllocCount < nPoints) { + FX_PATHPOINT* pNewBuf = FX_Alloc(FX_PATHPOINT, nPoints); + if (!pNewBuf) { + return FALSE; + } + if (m_PointCount) { + FXSYS_memcpy32(pNewBuf, m_pPoints, m_PointCount * sizeof(FX_PATHPOINT)); + } + if (m_pPoints) { + FX_Free(m_pPoints); + } + m_pPoints = pNewBuf; + m_AllocCount = nPoints; + } + return TRUE; +} +CFX_PathData::CFX_PathData(const CFX_PathData& src) +{ + m_pPoints = NULL; + m_PointCount = m_AllocCount = src.m_PointCount; + m_pPoints = FX_Alloc(FX_PATHPOINT, src.m_PointCount); + if (!m_pPoints) { + return; + } + FXSYS_memcpy32(m_pPoints, src.m_pPoints, sizeof(FX_PATHPOINT) * m_PointCount); +} +void CFX_PathData::TrimPoints(int nPoints) +{ + if (m_PointCount <= nPoints) { + return; + } + SetPointCount(nPoints); +} +FX_BOOL CFX_PathData::AddPointCount(int addPoints) +{ + int new_count = m_PointCount + addPoints; + if (!AllocPointCount(new_count)) { + return FALSE; + } + m_PointCount = new_count; + return TRUE; +} +FX_BOOL CFX_PathData::Append(const CFX_PathData* pSrc, const CFX_AffineMatrix* pMatrix) +{ + int old_count = m_PointCount; + if (!AddPointCount(pSrc->m_PointCount)) { + return FALSE; + } + FXSYS_memcpy32(m_pPoints + old_count, pSrc->m_pPoints, pSrc->m_PointCount * sizeof(FX_PATHPOINT)); + if (pMatrix == NULL) { + return TRUE; + } + 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); + } + return TRUE; +} +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; +} +FX_BOOL CFX_PathData::AppendRect(FX_FLOAT left, FX_FLOAT bottom, FX_FLOAT right, FX_FLOAT top) +{ + int old_count = m_PointCount; + if (!AddPointCount(5)) { + return FALSE; + } + 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; + return TRUE; +} +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) { + 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; + } else 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; + } + 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; + } 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); + } +} +const int g_Distant[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; +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; + } + } + 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 = 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 (pRect) { + pRect->left = x[0]; + pRect->right = x[2]; + pRect->bottom = y[0]; + pRect->top = y[2]; + pRect->Normalize(); + } + return TRUE; +} +FX_BOOL CFX_PathData::Copy(const CFX_PathData &src) +{ + if (!SetPointCount(src.m_PointCount)) { + return FALSE; + } + FXSYS_memcpy32(m_pPoints, src.m_pPoints, sizeof(FX_PATHPOINT) * m_PointCount); + return TRUE; +} +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); + if (!m_DashArray) { + return; + } + FXSYS_memcpy32(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 a39ab2dee0..d664b706b0 100644 --- a/core/src/fxge/ge/fx_ge_ps.cpp +++ b/core/src/fxge/ge/fx_ge_ps.cpp @@ -1,657 +1,657 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "../../../include/fxge/fx_ge.h" -#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]; -}; -class CPSFont : public CFX_Object -{ -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() -{ - 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; -} -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::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::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 ++) { - FX_BYTE 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(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; - } - } - } - m_pOutput->OutputPS((FX_LPCSTR)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"); - } -} -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((FX_LPCSTR)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, - const CFX_GraphStateData* pGraphState, - FX_DWORD fill_color, - 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((FX_LPCSTR)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; -} -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_memcmp32(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((FX_LPCSTR)buf.GetBuffer(), buf.GetSize()); - } -} -static void FaxCompressData(FX_LPBYTE src_buf, int width, int height, FX_LPBYTE& 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, FX_LPBYTE src_buf, FX_DWORD src_size, - FX_LPBYTE& output_buf, FX_DWORD& output_size, FX_LPCSTR& filter) -{ - output_buf = src_buf; - output_size = src_size; - filter = ""; - if (src_size < 1024) { - return; - } - CCodec_ModuleMgr* pEncoders = CFX_GEModule::Get()->GetCodecModule(); - FX_LPBYTE 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::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; - FX_LPBYTE src_buf = FX_Alloc(FX_BYTE, src_size); - if (!src_buf) { - return FALSE; - } - for (int row = 0; row < height; row ++) { - FX_LPCBYTE src_scan = pSource->GetScanline(row); - FXSYS_memcpy32(src_buf + row * pitch, src_scan, pitch); - } - FX_LPBYTE 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("<>/CCITTFaxDecode filter "); - if (pSource->IsAlphaMask()) { - buf << FX_BSTRC("iM\n"); - } else { - buf << FX_BSTRC("false 1 colorimage\n"); - } - m_pOutput->OutputPS((FX_LPCSTR)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; - FX_LPBYTE output_buf = NULL; - FX_STRSIZE output_size = 0; - FX_LPCSTR 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(FX_BYTE, output_size); - if (!output_buf) { - if (pConverted != pSource) { - delete pConverted; - pConverted = NULL; - } - return FALSE; - } - for (int row = 0; row < height; row ++) { - FX_LPCBYTE src_scan = pConverted->GetScanline(row); - FX_LPBYTE 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_memcpy32(dest_scan, src_scan, src_pitch); - } - } - FX_LPBYTE 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((FX_LPCSTR)buf.GetBuffer(), buf.GetSize()); - WritePSBinary(output_buf, output_size); - FX_Free(output_buf); - } - OUTPUT_PS("\nQ\n"); - 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; - } - 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); - FX_LPBYTE pColor = (FX_LPBYTE)&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; - 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; - } - m_pOutput->OutputPS((FX_LPCSTR)buf.GetBuffer(), buf.GetSize()); - } -} -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 = FX_NEW CPSFont; - if (!pPSFont) { - return; - } - 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((FX_LPCSTR)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((FX_LPCSTR)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((FX_LPCSTR)buf.GetBuffer(), buf.GetSize()); - return TRUE; -} -void CFX_PSRenderer::WritePSBinary(FX_LPCBYTE data, int len) -{ - FX_LPBYTE 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((FX_LPCSTR)dest_buf, dest_size); - FX_Free(dest_buf); - } else { - m_pOutput->OutputPS((FX_LPCSTR)data, len); - } -} +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "../../../include/fxge/fx_ge.h" +#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]; +}; +class CPSFont : public CFX_Object +{ +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() +{ + 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; +} +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::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::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 ++) { + FX_BYTE 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(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; + } + } + } + m_pOutput->OutputPS((FX_LPCSTR)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"); + } +} +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((FX_LPCSTR)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, + const CFX_GraphStateData* pGraphState, + FX_DWORD fill_color, + 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((FX_LPCSTR)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; +} +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_memcmp32(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((FX_LPCSTR)buf.GetBuffer(), buf.GetSize()); + } +} +static void FaxCompressData(FX_LPBYTE src_buf, int width, int height, FX_LPBYTE& 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, FX_LPBYTE src_buf, FX_DWORD src_size, + FX_LPBYTE& output_buf, FX_DWORD& output_size, FX_LPCSTR& filter) +{ + output_buf = src_buf; + output_size = src_size; + filter = ""; + if (src_size < 1024) { + return; + } + CCodec_ModuleMgr* pEncoders = CFX_GEModule::Get()->GetCodecModule(); + FX_LPBYTE 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::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; + FX_LPBYTE src_buf = FX_Alloc(FX_BYTE, src_size); + if (!src_buf) { + return FALSE; + } + for (int row = 0; row < height; row ++) { + FX_LPCBYTE src_scan = pSource->GetScanline(row); + FXSYS_memcpy32(src_buf + row * pitch, src_scan, pitch); + } + FX_LPBYTE 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("<>/CCITTFaxDecode filter "); + if (pSource->IsAlphaMask()) { + buf << FX_BSTRC("iM\n"); + } else { + buf << FX_BSTRC("false 1 colorimage\n"); + } + m_pOutput->OutputPS((FX_LPCSTR)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; + FX_LPBYTE output_buf = NULL; + FX_STRSIZE output_size = 0; + FX_LPCSTR 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(FX_BYTE, output_size); + if (!output_buf) { + if (pConverted != pSource) { + delete pConverted; + pConverted = NULL; + } + return FALSE; + } + for (int row = 0; row < height; row ++) { + FX_LPCBYTE src_scan = pConverted->GetScanline(row); + FX_LPBYTE 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_memcpy32(dest_scan, src_scan, src_pitch); + } + } + FX_LPBYTE 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((FX_LPCSTR)buf.GetBuffer(), buf.GetSize()); + WritePSBinary(output_buf, output_size); + FX_Free(output_buf); + } + OUTPUT_PS("\nQ\n"); + 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; + } + 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); + FX_LPBYTE pColor = (FX_LPBYTE)&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; + 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; + } + m_pOutput->OutputPS((FX_LPCSTR)buf.GetBuffer(), buf.GetSize()); + } +} +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 = FX_NEW CPSFont; + if (!pPSFont) { + return; + } + 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((FX_LPCSTR)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((FX_LPCSTR)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((FX_LPCSTR)buf.GetBuffer(), buf.GetSize()); + return TRUE; +} +void CFX_PSRenderer::WritePSBinary(FX_LPCBYTE data, int len) +{ + FX_LPBYTE 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((FX_LPCSTR)dest_buf, dest_size); + FX_Free(dest_buf); + } else { + m_pOutput->OutputPS((FX_LPCSTR)data, len); + } +} diff --git a/core/src/fxge/ge/fx_ge_text.cpp b/core/src/fxge/ge/fx_ge_text.cpp index 92f631e615..40acc5fe34 100644 --- a/core/src/fxge/ge/fx_ge_text.cpp +++ b/core/src/fxge/ge/fx_ge_text.cpp @@ -1,1774 +1,1774 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "../../../include/fxge/fx_ge.h" -#include "../../../include/fxge/fx_freetype.h" -#include "../../../include/fxcodec/fx_codec.h" -#include "text_int.h" -#undef FX_GAMMA -#undef FX_GAMMA_INVERSE -#define FX_GAMMA(value) (value) -#define FX_GAMMA_INVERSE(value) (value) -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 const FX_BYTE g_GdipGamma_bgw[9] = {0, 0, 63, 120, 0, 168, 210, 239, 255}; -static const FX_BYTE g_GdipGamma_fgw[9] = {0, 0, 16, 45, 0, 87, 135, 192, 255}; -static const FX_BYTE g_GdipGammaAdjust_47[48] = { - 0, 30, 33, 34, 35, 36, 37, 38, 38, 39, 39, 40, 40, 40, 41, 41, 41, 42, 42, 42, 42, 43, - 43, 43, 43, 43, 44, 44, 44, 44, 44, 44, 45, 45, 45, 45, 45, 45, 45, 46, - 46, 46, 46, 46, 46, 46, 46, 47 -}; -static const FX_BYTE g_GdipGammaAdjust_75[76] = { - 0, 46, 50, 52, 54, 55, 56, 57, 58, 59, 60, 60, 61, 61, 62, 62, 63, 63, 64, 64, 64, 65, - 65, 65, 66, 66, 66, 67, 67, 67, 67, 68, 68, 68, 68, 68, 69, 69, 69, 69, 69, 70, 70, 70, - 70, 70, 71, 71, 71, 71, 71, 71, 72, 72, 72, 72, 72, 72, 72, 73, 73, 73, 73, 73, 73, 73, - 73, 74, 74, 74, 74, 74, 74, 74, 74, 75 -}; -static const FX_BYTE g_GdipGammaAdjust_81[82] = { - 0, 49, 53, 56, 58, 59, 60, 61, 62, 63, 64, 65, 65, 66, 66, 67, 67, 68, 68, 69, 69, 69, 70, 70, 70, - 71, 71, 71, 72, 72, 72, 72, 73, 73, 73, 73, 74, 74, 74, 74, 74, 75, 75, 75, 75, 75, 76, 76, 76, 76, - 76, 76, 77, 77, 77, 77, 77, 77, 78, 78, 78, 78, 78, 78, 78, 79, 79, 79, 79, 79, 79, 79, 79, 80, - 80, 80, 80, 80, 80, 80, 80, 81 -}; -static void _Adjust_alpha(int background, int foreground, int& src_alpha, int text_flags, int a) -{ -} -static const FX_BYTE 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, -}; -#define ADJUST_ALPHA(background, foreground, src_alpha, text_flags, a) \ - src_alpha = g_TextGammaAdjust[(FX_BYTE)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; - } - FX_BYTE 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, (FX_LPCBYTE)&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) -#ifdef FOXIT_CHROME_BUILD - 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)) -#ifdef FOXIT_CHROME_BUILD - 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 (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); - if (!pGlyphAndPos) { - return FALSE; - } - 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_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; - FX_LPBYTE 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; - } - continue; - } - FX_BOOL bBGRStripe = text_flags & FXTEXT_BGR_STRIPE; - ncols /= 3; - int x_subpixel = (int)(glyph.m_fOriginX * 3) % 3; - FX_LPBYTE 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; - } - FX_LPBYTE src_scan = src_buf + row * src_pitch + (start_col - left) * 3; - FX_LPBYTE 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; - } - } - } 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; - FX_BYTE 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; - } - FX_BYTE 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 { - FX_BYTE back_alpha = dest_scan[3]; - if (back_alpha == 0) { - FXARGB_SETDIB(dest_scan, FXARGB_MAKE(src_alpha1, r, g, b)); - } else { - FX_BYTE 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; - FX_BYTE 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; - } - FX_BYTE 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 { - FX_BYTE back_alpha = dest_scan[3]; - if (back_alpha == 0) { - FXARGB_SETDIB(dest_scan, FXARGB_MAKE(src_alpha1, r, g, b)); - } else { - FX_BYTE 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; - FX_BYTE 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; - } - FX_BYTE 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; - } - } - } - } - } else { - for (int row = 0; row < nrows; row ++) { - int dest_row = row + top; - if (dest_row < 0 || dest_row >= bitmap.GetHeight()) { - continue; - } - FX_LPBYTE src_scan = src_buf + row * src_pitch + (start_col - left) * 3; - FX_LPBYTE 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 (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; - } - } - } - } - } - } - 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; - } - } - if (pClippingPath) { - pClippingPath->Append(&TransformedPath, pUser2Device); - } - } - return TRUE; -} -CFX_FontCache::~CFX_FontCache() -{ - FreeCache(TRUE); -} -CFX_FaceCache* CFX_FontCache::GetCachedFace(CFX_Font* pFont) -{ - FX_BOOL bExternal = pFont->GetFace() == NULL; - void* face = bExternal ? pFont->GetSubstFont()->m_ExtHandle : pFont->GetFace(); - CFX_FTCacheMap& map = bExternal ? m_ExtFaceMap : m_FTFaceMap; - CFX_CountedFaceCache* counted_face_cache = NULL; - if (map.Lookup((FXFT_Face)face, counted_face_cache)) { - counted_face_cache->m_nCount++; - return counted_face_cache->m_Obj; - } - CFX_FaceCache* face_cache = NULL; - face_cache = FX_NEW CFX_FaceCache(bExternal ? NULL : (FXFT_Face)face); - if (face_cache == NULL) { - return NULL; - } - counted_face_cache = FX_NEW CFX_CountedFaceCache; - if (!counted_face_cache) { - if (face_cache) { - delete face_cache; - face_cache = NULL; - } - return NULL; - } - counted_face_cache->m_nCount = 2; - counted_face_cache->m_Obj = face_cache; - map.SetAt((FXFT_Face)face, counted_face_cache); - return face_cache; -} -void CFX_FontCache::ReleaseCachedFace(CFX_Font* pFont) -{ - FX_BOOL bExternal = pFont->GetFace() == NULL; - void* face = bExternal ? pFont->GetSubstFont()->m_ExtHandle : pFont->GetFace(); - CFX_FTCacheMap& map = bExternal ? m_ExtFaceMap : m_FTFaceMap; - CFX_CountedFaceCache* counted_face_cache = NULL; - if (!map.Lookup((FXFT_Face)face, counted_face_cache)) { - return; - } - if (counted_face_cache->m_nCount > 1) { - counted_face_cache->m_nCount--; - } -} -void CFX_FontCache::FreeCache(FX_BOOL bRelease) -{ - { - FX_POSITION pos; - pos = m_FTFaceMap.GetStartPosition(); - while (pos) { - FXFT_Face face; - CFX_CountedFaceCache* cache; - m_FTFaceMap.GetNextAssoc(pos, face, cache); - if (bRelease || cache->m_nCount < 2) { - delete cache->m_Obj; - delete cache; - m_FTFaceMap.RemoveKey(face); - } - } - pos = m_ExtFaceMap.GetStartPosition(); - while (pos) { - FXFT_Face face; - CFX_CountedFaceCache* cache; - m_ExtFaceMap.GetNextAssoc(pos, face, cache); - if (bRelease || cache->m_nCount < 2) { - delete cache->m_Obj; - delete cache; - m_ExtFaceMap.RemoveKey(face); - } - } - } -} -CFX_FaceCache::CFX_FaceCache(FXFT_Face face) -{ - m_Face = face; - m_pBitmap = NULL; -} -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(); - FX_LPVOID key1; - CFX_PathData* pPath; - while (pos) { - m_PathMap.GetNextAssoc(pos, key1, (FX_LPVOID&)pPath); - delete pPath; - } - if (m_pBitmap) { - delete m_pBitmap; - } - m_PathMap.RemoveAll(); -} -#if ((_FXM_PLATFORM_ != _FXM_PLATFORM_APPLE_)|| defined(_FPDFAPI_MINI_)) -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 = FX_NEW CFX_SizeGlyphCache; - if (pSizeCache == NULL) { - return NULL; - } - m_SizeMap.SetAt(FaceGlyphsKey, pSizeCache); - } - CFX_GlyphBitmap* pGlyphBitmap = NULL; - if (pSizeCache->m_GlyphMap.Lookup((FX_LPVOID)(FX_UINTPTR)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((FX_LPVOID)(FX_UINTPTR)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_)|| defined(_FPDFAPI_MINI_)) - 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()); - 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_)|| defined(_FPDFAPI_MINI_)) - 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); - } else { - CFX_GlyphBitmap* pGlyphBitmap; - CFX_SizeGlyphCache* pSizeCache = NULL; - if (m_SizeMap.Lookup(FaceGlyphsKey, (void*&)pSizeCache)) { - if (pSizeCache->m_GlyphMap.Lookup((FX_LPVOID)(FX_UINTPTR)glyph_index, (void*&)pGlyphBitmap)) { - return pGlyphBitmap; - } - pGlyphBitmap = RenderGlyph_Nativetext(pFont, glyph_index, pMatrix, dest_width, anti_alias); - if (pGlyphBitmap) { - pSizeCache->m_GlyphMap.SetAt((FX_LPVOID)(FX_UINTPTR)glyph_index, pGlyphBitmap); - return pGlyphBitmap; - } - } else { - pGlyphBitmap = RenderGlyph_Nativetext(pFont, glyph_index, pMatrix, dest_width, anti_alias); - if (pGlyphBitmap) { - pSizeCache = FX_NEW CFX_SizeGlyphCache; - if (pSizeCache == NULL) { - return NULL; - } - m_SizeMap.SetAt(FaceGlyphsKey, pSizeCache); - pSizeCache->m_GlyphMap.SetAt((FX_LPVOID)(FX_UINTPTR)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 FaceGlyphsKey(keygen.m_Key, keygen.m_KeyLen); - text_flags |= FXTEXT_NO_NATIVETEXT; - return LookUpGlyphBitmap(pFont, pMatrix, FaceGlyphsKey, glyph_index, bFontStyle, dest_width, anti_alias); - } -#endif -} -CFX_SizeGlyphCache::~CFX_SizeGlyphCache() -{ - FX_POSITION pos = m_GlyphMap.GetStartPosition(); - FX_LPVOID Key; - CFX_GlyphBitmap* pGlyphBitmap = NULL; - while(pos) { - m_GlyphMap.GetNextAssoc(pos, Key, (void*&)pGlyphBitmap); - delete pGlyphBitmap; - } - m_GlyphMap.RemoveAll(); -} -#if defined(_FPDFAPI_MINI_) -#define CONTRAST_RAMP_STEP 16 -#else -#define CONTRAST_RAMP_STEP 1 -#endif -static const FX_BYTE g_adjust_contrast11[256] = { - 0, 0, 2, 3, 4, 5, 6, 8, 9, 10, 11, 13, 14, 15, 17, 18, 19, 21, 22, 24, 25, 26, 28, 29, 31, - 32, 33, 35, 36, 38, 39, 40, 42, 43, 45, 46, 48, 49, 51, 52, 54, 55, 56, 58, 59, 61, 62, 64, 65, - 67, 68, 70, 71, 72, 74, 75, 77, 78, 80, 81, 83, 84, 86, 87, 89, 90, 91, 93, 94, 96, 97, 99, 100, - 101, 103, 104, 106, 107, 109, 110, 111, 113, 114, 116, 117, 118, 120, 121, 123, 124, 125, 127, - 128, 130, 131, 132, 134, 135, 136, 138, 139, 140, 142, 143, 144, 146, 147, 148, 149, 151, 152, - 153, 155, 156, 157, 158, 160, 161, 162, 163, 165, 166, 167, 168, 169, 171, 172, 173, 174, 175, - 177, 178, 179, 180, 181, 182, 183, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, - 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, - 215, 216, 217, 218, 219, 220, 221, 221, 222, 223, 224, 224, 225, 226, 227, 227, 228, 229, 230, - 230, 231, 232, 232, 233, 234, 234, 235, 236, 236, 237, 237, 238, 239, 239, 240, 240, 241, 241, - 242, 242, 243, 243, 244, 244, 245, 245, 246, 246, 246, 247, 247, 248, 248, 248, 249, 249, 249, - 250, 250, 250, 251, 251, 251, 251, 252, 252, 252, 252, 253, 253, 253, 253, 253, 253, 254, 254, - 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 255, -}; -static const FX_BYTE g_adjust_contrast15[256] = { - 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 5, 5, 6, 7, 7, 8, 9, 10, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, - 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 34, 35, 36, 37, 38, 40, 41, 42, 43, 45, 46, 47, 48, 50, 51, - 52, 54, 55, 56, 58, 59, 60, 62, 63, 64, 66, 67, 68, 70, 71, 73, 74, 75, 77, 78, 80, 81, 82, 84, 85, 87, - 88, 90, 91, 93, 94, 95, 97, 98, 100, 101, 103, 104, 106, 107, 109, 110, 111, 113, 114, 116, 117, 119, - 120, 122, 123, 125, 126, 128, 129, 130, 132, 133, 135, 136, 138, 139, 141, 142, 143, 145, 146, 148, - 149, 150, 152, 153, 155, 156, 157, 159, 160, 161, 163, 164, 166, 167, 168, 170, 171, 172, 174, 175, - 176, 177, 179, 180, 181, 183, 184, 185, 186, 188, 189, 190, 191, 192, 194, 195, 196, 197, 198, 199, - 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, - 221, 222, 223, 224, 225, 226, 227, 227, 228, 229, 230, 231, 232, 232, 233, 234, 235, 235, 236, 237, - 237, 238, 239, 239, 240, 241, 241, 242, 242, 243, 244, 244, 245, 245, 246, 246, 247, 247, 248, 248, - 248, 249, 249, 250, 250, 250, 251, 251, 251, 252, 252, 252, 252, 253, 253, 253, 253, 253, 254, 254, - 254, 254, 254, 254, 254, 254, 254, 254, 254, 255, -}; -static void _CalcContrastRamp(FX_LPBYTE ramp, int level) -{ - int contrast_min = 0, contrast_max = 255 - level, i; - for (i = 0; i < contrast_min; i ++) { - ramp[i] = 0; - } - for (i = contrast_min; i < contrast_max; i ++) { - ramp[i] = 255 * (i - contrast_min) / (contrast_max - contrast_min); - } - for (i = contrast_max; i < 256; i ++) { - ramp[i] = 255; - } -} -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); -} -extern const char g_AngleSkew[30] = { - 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 FX_BYTE g_WeightPow[100] = { - 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, -}; -extern const FX_BYTE g_WeightPow_11[100] = { - 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, -}; -extern const FX_BYTE g_WeightPow_SHIFTJIS[100] = { - 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(FX_LPBYTE pData, int nWid, int nHei, int src_pitch, FX_LPCBYTE gammaTable) -{ - int count = nHei * src_pitch; - for(int i = 0; i < count; i++) { - pData[i] = gammaTable[pData[i]]; - } -} -static void _ContrastAdjust(FX_LPBYTE pDataIn, FX_LPBYTE 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 ++) { - FX_LPBYTE 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_memcpy32(pDataOut + row * nDstRowBytes, pDataIn + row * nSrcRowBytes, rowbytes); - } - return; - } - rate = 255.f / temp; - for (row = 0; row < nHei; row ++) { - FX_LPBYTE pSrcRow = pDataIn + row * nSrcRowBytes; - FX_LPBYTE 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 ++ = (FX_BYTE)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 <= -30 ? -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); - } - } - int transflag = FXFT_Get_Face_Internal_Flag(m_Face); - FXFT_Set_Transform(m_Face, &ft_matrix, 0); - 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) { - FXFT_Set_Face_Internal_Flag(m_Face, transflag); - 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 >= 100) { - FXFT_Set_Face_Internal_Flag(m_Face, transflag); - 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); - } - FXFT_Library_SetLcdFilter(CFX_GEModule::Get()->GetFontMgr()->m_FTLibrary, FT_LCD_FILTER_DEFAULT); - error = FXFT_Render_Glyph(m_Face, anti_alias); - if (error) { - FXFT_Set_Face_Internal_Flag(m_Face, transflag); - 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) { - FXFT_Set_Face_Internal_Flag(m_Face, transflag); - return NULL; - } - int dib_width = bmwidth; - CFX_GlyphBitmap* pGlyphBitmap = FX_NEW CFX_GlyphBitmap; - if (!pGlyphBitmap) { - return NULL; - } - 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)); - FX_BYTE* pDestBuf = pGlyphBitmap->m_Bitmap.GetBuffer(); - FX_BYTE* pSrcBuf = (FX_BYTE*)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++) { - FX_BYTE 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_memset32(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_memcpy32(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()); - } - } - FXFT_Set_Face_Internal_Flag(m_Face, transflag); - 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); - FX_LPCBYTE src_buf = (FX_LPCBYTE)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); - FX_LPBYTE dest_buf = mask.GetBuffer(); - int dest_pitch = mask.GetPitch(); - for (int row = 0; row < bmheight; row ++) { - FX_LPCBYTE src_scan = src_buf + row * src_pitch; - FX_LPBYTE dest_scan = dest_buf + row * dest_pitch; - FXSYS_memcpy32(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); - int transflag = FXFT_Get_Face_Internal_Flag(pFont->m_Face); - 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; - } - FXFT_Set_Face_Internal_Flag(pFont->m_Face, transflag); - 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); - } - int transflag = FXFT_Get_Face_Internal_Flag(pFont->m_Face); - FXFT_Set_Transform(pFont->m_Face, &ft_matrix, 0); - FX_BOOL ret = _OutputGlyph(dib, x, y, pFont, - glyph_index, argb); - FXFT_Set_Face_Internal_Flag(pFont->m_Face, transflag); - 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; - FX_LPVOID key; - if (pFont->GetSubstFont()) - key = (FX_LPVOID)(FX_UINTPTR)(glyph_index + ((pFont->GetSubstFont()->m_Weight / 16) << 15) + - ((pFont->GetSubstFont()->m_ItalicAngle / 2) << 21) + ((dest_width / 16) << 25) + - (pFont->IsVertical() << 31)); - else { - key = (FX_LPVOID)(FX_UINTPTR)glyph_index; - } - if (m_PathMap.Lookup(key, (FX_LPVOID&)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; -} 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; - } -} -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; - } -}; -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; - } -}; -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; - } -}; -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; - } -}; -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 <= -30 ? -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); - } - } - int transflag = FXFT_Get_Face_Internal_Flag(m_Face); - FXFT_Set_Transform(m_Face, &ft_matrix, 0); - 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) { - FXFT_Set_Face_Internal_Flag(m_Face, transflag); - return NULL; - } - if (m_pSubstFont && !(m_pSubstFont->m_SubstFlags & FXFONT_SUBST_MM) && m_pSubstFont->m_Weight > 400) { - int level = 0; - if (m_pSubstFont->m_Charset == FXFONT_SHIFTJIS_CHARSET) { - level = g_WeightPow_SHIFTJIS[(m_pSubstFont->m_Weight - 400) / 10] * 2 * 65536 / 36655; - } else { - level = g_WeightPow[(m_pSubstFont->m_Weight - 400) / 10] * 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) { - FXFT_Set_Face_Internal_Flag(m_Face, transflag); - return NULL; - } - CFX_PathData* pPath = FX_NEW CFX_PathData; - if (!pPath) { - return NULL; - } - 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; - } - FXFT_Set_Face_Internal_Flag(m_Face, transflag); - 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); -} +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "../../../include/fxge/fx_ge.h" +#include "../../../include/fxge/fx_freetype.h" +#include "../../../include/fxcodec/fx_codec.h" +#include "text_int.h" +#undef FX_GAMMA +#undef FX_GAMMA_INVERSE +#define FX_GAMMA(value) (value) +#define FX_GAMMA_INVERSE(value) (value) +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 const FX_BYTE g_GdipGamma_bgw[9] = {0, 0, 63, 120, 0, 168, 210, 239, 255}; +static const FX_BYTE g_GdipGamma_fgw[9] = {0, 0, 16, 45, 0, 87, 135, 192, 255}; +static const FX_BYTE g_GdipGammaAdjust_47[48] = { + 0, 30, 33, 34, 35, 36, 37, 38, 38, 39, 39, 40, 40, 40, 41, 41, 41, 42, 42, 42, 42, 43, + 43, 43, 43, 43, 44, 44, 44, 44, 44, 44, 45, 45, 45, 45, 45, 45, 45, 46, + 46, 46, 46, 46, 46, 46, 46, 47 +}; +static const FX_BYTE g_GdipGammaAdjust_75[76] = { + 0, 46, 50, 52, 54, 55, 56, 57, 58, 59, 60, 60, 61, 61, 62, 62, 63, 63, 64, 64, 64, 65, + 65, 65, 66, 66, 66, 67, 67, 67, 67, 68, 68, 68, 68, 68, 69, 69, 69, 69, 69, 70, 70, 70, + 70, 70, 71, 71, 71, 71, 71, 71, 72, 72, 72, 72, 72, 72, 72, 73, 73, 73, 73, 73, 73, 73, + 73, 74, 74, 74, 74, 74, 74, 74, 74, 75 +}; +static const FX_BYTE g_GdipGammaAdjust_81[82] = { + 0, 49, 53, 56, 58, 59, 60, 61, 62, 63, 64, 65, 65, 66, 66, 67, 67, 68, 68, 69, 69, 69, 70, 70, 70, + 71, 71, 71, 72, 72, 72, 72, 73, 73, 73, 73, 74, 74, 74, 74, 74, 75, 75, 75, 75, 75, 76, 76, 76, 76, + 76, 76, 77, 77, 77, 77, 77, 77, 78, 78, 78, 78, 78, 78, 78, 79, 79, 79, 79, 79, 79, 79, 79, 80, + 80, 80, 80, 80, 80, 80, 80, 81 +}; +static void _Adjust_alpha(int background, int foreground, int& src_alpha, int text_flags, int a) +{ +} +static const FX_BYTE 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, +}; +#define ADJUST_ALPHA(background, foreground, src_alpha, text_flags, a) \ + src_alpha = g_TextGammaAdjust[(FX_BYTE)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; + } + FX_BYTE 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, (FX_LPCBYTE)&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) +#ifdef FOXIT_CHROME_BUILD + 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)) +#ifdef FOXIT_CHROME_BUILD + 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 (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); + if (!pGlyphAndPos) { + return FALSE; + } + 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_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; + FX_LPBYTE 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; + } + continue; + } + FX_BOOL bBGRStripe = text_flags & FXTEXT_BGR_STRIPE; + ncols /= 3; + int x_subpixel = (int)(glyph.m_fOriginX * 3) % 3; + FX_LPBYTE 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; + } + FX_LPBYTE src_scan = src_buf + row * src_pitch + (start_col - left) * 3; + FX_LPBYTE 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; + } + } + } 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; + FX_BYTE 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; + } + FX_BYTE 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 { + FX_BYTE back_alpha = dest_scan[3]; + if (back_alpha == 0) { + FXARGB_SETDIB(dest_scan, FXARGB_MAKE(src_alpha1, r, g, b)); + } else { + FX_BYTE 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; + FX_BYTE 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; + } + FX_BYTE 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 { + FX_BYTE back_alpha = dest_scan[3]; + if (back_alpha == 0) { + FXARGB_SETDIB(dest_scan, FXARGB_MAKE(src_alpha1, r, g, b)); + } else { + FX_BYTE 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; + FX_BYTE 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; + } + FX_BYTE 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; + } + } + } + } + } else { + for (int row = 0; row < nrows; row ++) { + int dest_row = row + top; + if (dest_row < 0 || dest_row >= bitmap.GetHeight()) { + continue; + } + FX_LPBYTE src_scan = src_buf + row * src_pitch + (start_col - left) * 3; + FX_LPBYTE 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 (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; + } + } + } + } + } + } + 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; + } + } + if (pClippingPath) { + pClippingPath->Append(&TransformedPath, pUser2Device); + } + } + return TRUE; +} +CFX_FontCache::~CFX_FontCache() +{ + FreeCache(TRUE); +} +CFX_FaceCache* CFX_FontCache::GetCachedFace(CFX_Font* pFont) +{ + FX_BOOL bExternal = pFont->GetFace() == NULL; + void* face = bExternal ? pFont->GetSubstFont()->m_ExtHandle : pFont->GetFace(); + CFX_FTCacheMap& map = bExternal ? m_ExtFaceMap : m_FTFaceMap; + CFX_CountedFaceCache* counted_face_cache = NULL; + if (map.Lookup((FXFT_Face)face, counted_face_cache)) { + counted_face_cache->m_nCount++; + return counted_face_cache->m_Obj; + } + CFX_FaceCache* face_cache = NULL; + face_cache = FX_NEW CFX_FaceCache(bExternal ? NULL : (FXFT_Face)face); + if (face_cache == NULL) { + return NULL; + } + counted_face_cache = FX_NEW CFX_CountedFaceCache; + if (!counted_face_cache) { + if (face_cache) { + delete face_cache; + face_cache = NULL; + } + return NULL; + } + counted_face_cache->m_nCount = 2; + counted_face_cache->m_Obj = face_cache; + map.SetAt((FXFT_Face)face, counted_face_cache); + return face_cache; +} +void CFX_FontCache::ReleaseCachedFace(CFX_Font* pFont) +{ + FX_BOOL bExternal = pFont->GetFace() == NULL; + void* face = bExternal ? pFont->GetSubstFont()->m_ExtHandle : pFont->GetFace(); + CFX_FTCacheMap& map = bExternal ? m_ExtFaceMap : m_FTFaceMap; + CFX_CountedFaceCache* counted_face_cache = NULL; + if (!map.Lookup((FXFT_Face)face, counted_face_cache)) { + return; + } + if (counted_face_cache->m_nCount > 1) { + counted_face_cache->m_nCount--; + } +} +void CFX_FontCache::FreeCache(FX_BOOL bRelease) +{ + { + FX_POSITION pos; + pos = m_FTFaceMap.GetStartPosition(); + while (pos) { + FXFT_Face face; + CFX_CountedFaceCache* cache; + m_FTFaceMap.GetNextAssoc(pos, face, cache); + if (bRelease || cache->m_nCount < 2) { + delete cache->m_Obj; + delete cache; + m_FTFaceMap.RemoveKey(face); + } + } + pos = m_ExtFaceMap.GetStartPosition(); + while (pos) { + FXFT_Face face; + CFX_CountedFaceCache* cache; + m_ExtFaceMap.GetNextAssoc(pos, face, cache); + if (bRelease || cache->m_nCount < 2) { + delete cache->m_Obj; + delete cache; + m_ExtFaceMap.RemoveKey(face); + } + } + } +} +CFX_FaceCache::CFX_FaceCache(FXFT_Face face) +{ + m_Face = face; + m_pBitmap = NULL; +} +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(); + FX_LPVOID key1; + CFX_PathData* pPath; + while (pos) { + m_PathMap.GetNextAssoc(pos, key1, (FX_LPVOID&)pPath); + delete pPath; + } + if (m_pBitmap) { + delete m_pBitmap; + } + m_PathMap.RemoveAll(); +} +#if ((_FXM_PLATFORM_ != _FXM_PLATFORM_APPLE_)|| defined(_FPDFAPI_MINI_)) +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 = FX_NEW CFX_SizeGlyphCache; + if (pSizeCache == NULL) { + return NULL; + } + m_SizeMap.SetAt(FaceGlyphsKey, pSizeCache); + } + CFX_GlyphBitmap* pGlyphBitmap = NULL; + if (pSizeCache->m_GlyphMap.Lookup((FX_LPVOID)(FX_UINTPTR)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((FX_LPVOID)(FX_UINTPTR)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_)|| defined(_FPDFAPI_MINI_)) + 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()); + 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_)|| defined(_FPDFAPI_MINI_)) + 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); + } else { + CFX_GlyphBitmap* pGlyphBitmap; + CFX_SizeGlyphCache* pSizeCache = NULL; + if (m_SizeMap.Lookup(FaceGlyphsKey, (void*&)pSizeCache)) { + if (pSizeCache->m_GlyphMap.Lookup((FX_LPVOID)(FX_UINTPTR)glyph_index, (void*&)pGlyphBitmap)) { + return pGlyphBitmap; + } + pGlyphBitmap = RenderGlyph_Nativetext(pFont, glyph_index, pMatrix, dest_width, anti_alias); + if (pGlyphBitmap) { + pSizeCache->m_GlyphMap.SetAt((FX_LPVOID)(FX_UINTPTR)glyph_index, pGlyphBitmap); + return pGlyphBitmap; + } + } else { + pGlyphBitmap = RenderGlyph_Nativetext(pFont, glyph_index, pMatrix, dest_width, anti_alias); + if (pGlyphBitmap) { + pSizeCache = FX_NEW CFX_SizeGlyphCache; + if (pSizeCache == NULL) { + return NULL; + } + m_SizeMap.SetAt(FaceGlyphsKey, pSizeCache); + pSizeCache->m_GlyphMap.SetAt((FX_LPVOID)(FX_UINTPTR)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 FaceGlyphsKey(keygen.m_Key, keygen.m_KeyLen); + text_flags |= FXTEXT_NO_NATIVETEXT; + return LookUpGlyphBitmap(pFont, pMatrix, FaceGlyphsKey, glyph_index, bFontStyle, dest_width, anti_alias); + } +#endif +} +CFX_SizeGlyphCache::~CFX_SizeGlyphCache() +{ + FX_POSITION pos = m_GlyphMap.GetStartPosition(); + FX_LPVOID Key; + CFX_GlyphBitmap* pGlyphBitmap = NULL; + while(pos) { + m_GlyphMap.GetNextAssoc(pos, Key, (void*&)pGlyphBitmap); + delete pGlyphBitmap; + } + m_GlyphMap.RemoveAll(); +} +#if defined(_FPDFAPI_MINI_) +#define CONTRAST_RAMP_STEP 16 +#else +#define CONTRAST_RAMP_STEP 1 +#endif +static const FX_BYTE g_adjust_contrast11[256] = { + 0, 0, 2, 3, 4, 5, 6, 8, 9, 10, 11, 13, 14, 15, 17, 18, 19, 21, 22, 24, 25, 26, 28, 29, 31, + 32, 33, 35, 36, 38, 39, 40, 42, 43, 45, 46, 48, 49, 51, 52, 54, 55, 56, 58, 59, 61, 62, 64, 65, + 67, 68, 70, 71, 72, 74, 75, 77, 78, 80, 81, 83, 84, 86, 87, 89, 90, 91, 93, 94, 96, 97, 99, 100, + 101, 103, 104, 106, 107, 109, 110, 111, 113, 114, 116, 117, 118, 120, 121, 123, 124, 125, 127, + 128, 130, 131, 132, 134, 135, 136, 138, 139, 140, 142, 143, 144, 146, 147, 148, 149, 151, 152, + 153, 155, 156, 157, 158, 160, 161, 162, 163, 165, 166, 167, 168, 169, 171, 172, 173, 174, 175, + 177, 178, 179, 180, 181, 182, 183, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, + 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, + 215, 216, 217, 218, 219, 220, 221, 221, 222, 223, 224, 224, 225, 226, 227, 227, 228, 229, 230, + 230, 231, 232, 232, 233, 234, 234, 235, 236, 236, 237, 237, 238, 239, 239, 240, 240, 241, 241, + 242, 242, 243, 243, 244, 244, 245, 245, 246, 246, 246, 247, 247, 248, 248, 248, 249, 249, 249, + 250, 250, 250, 251, 251, 251, 251, 252, 252, 252, 252, 253, 253, 253, 253, 253, 253, 254, 254, + 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 255, +}; +static const FX_BYTE g_adjust_contrast15[256] = { + 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 5, 5, 6, 7, 7, 8, 9, 10, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 34, 35, 36, 37, 38, 40, 41, 42, 43, 45, 46, 47, 48, 50, 51, + 52, 54, 55, 56, 58, 59, 60, 62, 63, 64, 66, 67, 68, 70, 71, 73, 74, 75, 77, 78, 80, 81, 82, 84, 85, 87, + 88, 90, 91, 93, 94, 95, 97, 98, 100, 101, 103, 104, 106, 107, 109, 110, 111, 113, 114, 116, 117, 119, + 120, 122, 123, 125, 126, 128, 129, 130, 132, 133, 135, 136, 138, 139, 141, 142, 143, 145, 146, 148, + 149, 150, 152, 153, 155, 156, 157, 159, 160, 161, 163, 164, 166, 167, 168, 170, 171, 172, 174, 175, + 176, 177, 179, 180, 181, 183, 184, 185, 186, 188, 189, 190, 191, 192, 194, 195, 196, 197, 198, 199, + 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, + 221, 222, 223, 224, 225, 226, 227, 227, 228, 229, 230, 231, 232, 232, 233, 234, 235, 235, 236, 237, + 237, 238, 239, 239, 240, 241, 241, 242, 242, 243, 244, 244, 245, 245, 246, 246, 247, 247, 248, 248, + 248, 249, 249, 250, 250, 250, 251, 251, 251, 252, 252, 252, 252, 253, 253, 253, 253, 253, 254, 254, + 254, 254, 254, 254, 254, 254, 254, 254, 254, 255, +}; +static void _CalcContrastRamp(FX_LPBYTE ramp, int level) +{ + int contrast_min = 0, contrast_max = 255 - level, i; + for (i = 0; i < contrast_min; i ++) { + ramp[i] = 0; + } + for (i = contrast_min; i < contrast_max; i ++) { + ramp[i] = 255 * (i - contrast_min) / (contrast_max - contrast_min); + } + for (i = contrast_max; i < 256; i ++) { + ramp[i] = 255; + } +} +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); +} +extern const char g_AngleSkew[30] = { + 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 FX_BYTE g_WeightPow[100] = { + 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, +}; +extern const FX_BYTE g_WeightPow_11[100] = { + 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, +}; +extern const FX_BYTE g_WeightPow_SHIFTJIS[100] = { + 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(FX_LPBYTE pData, int nWid, int nHei, int src_pitch, FX_LPCBYTE gammaTable) +{ + int count = nHei * src_pitch; + for(int i = 0; i < count; i++) { + pData[i] = gammaTable[pData[i]]; + } +} +static void _ContrastAdjust(FX_LPBYTE pDataIn, FX_LPBYTE 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 ++) { + FX_LPBYTE 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_memcpy32(pDataOut + row * nDstRowBytes, pDataIn + row * nSrcRowBytes, rowbytes); + } + return; + } + rate = 255.f / temp; + for (row = 0; row < nHei; row ++) { + FX_LPBYTE pSrcRow = pDataIn + row * nSrcRowBytes; + FX_LPBYTE 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 ++ = (FX_BYTE)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 <= -30 ? -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); + } + } + int transflag = FXFT_Get_Face_Internal_Flag(m_Face); + FXFT_Set_Transform(m_Face, &ft_matrix, 0); + 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) { + FXFT_Set_Face_Internal_Flag(m_Face, transflag); + 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 >= 100) { + FXFT_Set_Face_Internal_Flag(m_Face, transflag); + 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); + } + FXFT_Library_SetLcdFilter(CFX_GEModule::Get()->GetFontMgr()->m_FTLibrary, FT_LCD_FILTER_DEFAULT); + error = FXFT_Render_Glyph(m_Face, anti_alias); + if (error) { + FXFT_Set_Face_Internal_Flag(m_Face, transflag); + 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) { + FXFT_Set_Face_Internal_Flag(m_Face, transflag); + return NULL; + } + int dib_width = bmwidth; + CFX_GlyphBitmap* pGlyphBitmap = FX_NEW CFX_GlyphBitmap; + if (!pGlyphBitmap) { + return NULL; + } + 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)); + FX_BYTE* pDestBuf = pGlyphBitmap->m_Bitmap.GetBuffer(); + FX_BYTE* pSrcBuf = (FX_BYTE*)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++) { + FX_BYTE 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_memset32(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_memcpy32(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()); + } + } + FXFT_Set_Face_Internal_Flag(m_Face, transflag); + 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); + FX_LPCBYTE src_buf = (FX_LPCBYTE)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); + FX_LPBYTE dest_buf = mask.GetBuffer(); + int dest_pitch = mask.GetPitch(); + for (int row = 0; row < bmheight; row ++) { + FX_LPCBYTE src_scan = src_buf + row * src_pitch; + FX_LPBYTE dest_scan = dest_buf + row * dest_pitch; + FXSYS_memcpy32(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); + int transflag = FXFT_Get_Face_Internal_Flag(pFont->m_Face); + 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; + } + FXFT_Set_Face_Internal_Flag(pFont->m_Face, transflag); + 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); + } + int transflag = FXFT_Get_Face_Internal_Flag(pFont->m_Face); + FXFT_Set_Transform(pFont->m_Face, &ft_matrix, 0); + FX_BOOL ret = _OutputGlyph(dib, x, y, pFont, + glyph_index, argb); + FXFT_Set_Face_Internal_Flag(pFont->m_Face, transflag); + 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; + FX_LPVOID key; + if (pFont->GetSubstFont()) + key = (FX_LPVOID)(FX_UINTPTR)(glyph_index + ((pFont->GetSubstFont()->m_Weight / 16) << 15) + + ((pFont->GetSubstFont()->m_ItalicAngle / 2) << 21) + ((dest_width / 16) << 25) + + (pFont->IsVertical() << 31)); + else { + key = (FX_LPVOID)(FX_UINTPTR)glyph_index; + } + if (m_PathMap.Lookup(key, (FX_LPVOID&)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; +} 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; + } +} +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; + } +}; +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; + } +}; +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; + } +}; +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; + } +}; +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 <= -30 ? -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); + } + } + int transflag = FXFT_Get_Face_Internal_Flag(m_Face); + FXFT_Set_Transform(m_Face, &ft_matrix, 0); + 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) { + FXFT_Set_Face_Internal_Flag(m_Face, transflag); + return NULL; + } + if (m_pSubstFont && !(m_pSubstFont->m_SubstFlags & FXFONT_SUBST_MM) && m_pSubstFont->m_Weight > 400) { + int level = 0; + if (m_pSubstFont->m_Charset == FXFONT_SHIFTJIS_CHARSET) { + level = g_WeightPow_SHIFTJIS[(m_pSubstFont->m_Weight - 400) / 10] * 2 * 65536 / 36655; + } else { + level = g_WeightPow[(m_pSubstFont->m_Weight - 400) / 10] * 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) { + FXFT_Set_Face_Internal_Flag(m_Face, transflag); + return NULL; + } + CFX_PathData* pPath = FX_NEW CFX_PathData; + if (!pPath) { + return NULL; + } + 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; + } + FXFT_Set_Face_Internal_Flag(m_Face, transflag); + 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); +} diff --git a/core/src/fxge/ge/text_int.h b/core/src/fxge/ge/text_int.h index 7608f8a2ed..a3c9417bfc 100644 --- a/core/src/fxge/ge/text_int.h +++ b/core/src/fxge/ge/text_int.h @@ -1,100 +1,100 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -struct _CFX_UniqueKeyGen { - void Generate(int count, ...); - FX_CHAR m_Key[128]; - int m_KeyLen; -}; -class CFX_SizeGlyphCache : public CFX_Object -{ -public: - CFX_SizeGlyphCache() - { - m_GlyphMap.InitHashTable(253); - } - ~CFX_SizeGlyphCache(); - CFX_MapPtrToPtr m_GlyphMap; -}; -class CTTFontDesc : public CFX_Object -{ -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; - }; - FX_BYTE* 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; - } -}; -#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_Object -{ -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 CFX_Object -{ -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; -}; +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +struct _CFX_UniqueKeyGen { + void Generate(int count, ...); + FX_CHAR m_Key[128]; + int m_KeyLen; +}; +class CFX_SizeGlyphCache : public CFX_Object +{ +public: + CFX_SizeGlyphCache() + { + m_GlyphMap.InitHashTable(253); + } + ~CFX_SizeGlyphCache(); + CFX_MapPtrToPtr m_GlyphMap; +}; +class CTTFontDesc : public CFX_Object +{ +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; + }; + FX_BYTE* 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; + } +}; +#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_Object +{ +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 CFX_Object +{ +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; +}; -- cgit v1.2.3