diff options
author | John Abd-El-Malek <jabdelmalek@google.com> | 2014-05-23 17:28:10 -0700 |
---|---|---|
committer | John Abd-El-Malek <jabdelmalek@google.com> | 2014-05-23 17:41:56 -0700 |
commit | 3f3b45cc74b0499912409f766a595945dbbfc4c5 (patch) | |
tree | ec400b6965477b88ea7f0d335f7e5c52044c346c /core/src/fxge/ge | |
parent | 6fe4aed948337175f6f7f81bb03c37b9c7f535da (diff) | |
download | pdfium-3f3b45cc74b0499912409f766a595945dbbfc4c5.tar.xz |
Convert all line endings to LF.
Diffstat (limited to 'core/src/fxge/ge')
-rw-r--r-- | core/src/fxge/ge/fx_ge.cpp | 158 | ||||
-rw-r--r-- | core/src/fxge/ge/fx_ge_device.cpp | 810 | ||||
-rw-r--r-- | core/src/fxge/ge/fx_ge_font.cpp | 916 | ||||
-rw-r--r-- | core/src/fxge/ge/fx_ge_fontmap.cpp | 3116 | ||||
-rw-r--r-- | core/src/fxge/ge/fx_ge_linux.cpp | 518 | ||||
-rw-r--r-- | core/src/fxge/ge/fx_ge_path.cpp | 1308 | ||||
-rw-r--r-- | core/src/fxge/ge/fx_ge_ps.cpp | 1314 | ||||
-rw-r--r-- | core/src/fxge/ge/fx_ge_text.cpp | 3548 | ||||
-rw-r--r-- | core/src/fxge/ge/text_int.h | 200 |
9 files changed, 5944 insertions, 5944 deletions
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("<</K -1/EndOfBlock false/Columns ") << width << FX_BSTRC("/Rows ") << height <<
- FX_BSTRC(">>/CCITTFaxDecode filter ");
- if (pSource->IsAlphaMask()) {
- buf << FX_BSTRC("iM\n");
- } else {
- buf << FX_BSTRC("false 1 colorimage\n");
- }
- m_pOutput->OutputPS((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("<</K -1/EndOfBlock false/Columns ") << width << FX_BSTRC("/Rows ") << height << + FX_BSTRC(">>/CCITTFaxDecode filter "); + if (pSource->IsAlphaMask()) { + buf << FX_BSTRC("iM\n"); + } else { + buf << FX_BSTRC("false 1 colorimage\n"); + } + m_pOutput->OutputPS((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; +}; |