1e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov// Copyright 2014 PDFium Authors. All rights reserved. 2e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov// Use of this source code is governed by a BSD-style license that can be 3e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov// found in the LICENSE file. 4e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 5e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com 6e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 7e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#include "../../../include/fxge/fx_ge.h" 8e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#include "../../../include/fxge/fx_freetype.h" 9e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#include "../../../include/fxcodec/fx_codec.h" 10e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#include "text_int.h" 11e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#undef FX_GAMMA 12e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#undef FX_GAMMA_INVERSE 13e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#define FX_GAMMA(value) (value) 14e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#define FX_GAMMA_INVERSE(value) (value) 15e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovFX_RECT FXGE_GetGlyphsBBox(FXTEXT_GLYPHPOS* pGlyphAndPos, int nChars, int anti_alias, FX_FLOAT retinaScaleX, FX_FLOAT retinaScaleY) 16e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 17e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_RECT rect(0, 0, 0, 0); 18e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_BOOL bStarted = FALSE; 19e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (int iChar = 0; iChar < nChars; iChar ++) { 20e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FXTEXT_GLYPHPOS& glyph = pGlyphAndPos[iChar]; 21e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov const CFX_GlyphBitmap* pGlyph = glyph.m_pGlyph; 22e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pGlyph == NULL) { 23e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov continue; 24e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 25e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int char_left = glyph.m_OriginX + pGlyph->m_Left; 26e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int char_width = (int)(pGlyph->m_Bitmap.GetWidth() / retinaScaleX); 27e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (anti_alias == FXFT_RENDER_MODE_LCD) { 28e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov char_width /= 3; 29e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 30e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int char_right = char_left + char_width; 31e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int char_top = glyph.m_OriginY - pGlyph->m_Top; 32e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int char_bottom = char_top + (int)(pGlyph->m_Bitmap.GetHeight() / retinaScaleY); 33e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (!bStarted) { 34e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov rect.left = char_left; 35e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov rect.right = char_right; 36e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov rect.top = char_top; 37e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov rect.bottom = char_bottom; 38e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov bStarted = TRUE; 39e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else { 40e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (rect.left > char_left) { 41e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov rect.left = char_left; 42e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 43e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (rect.right < char_right) { 44e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov rect.right = char_right; 45e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 46e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (rect.top > char_top) { 47e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov rect.top = char_top; 48e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 49e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (rect.bottom < char_bottom) { 50e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov rect.bottom = char_bottom; 51e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 52e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 53e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 54e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return rect; 55e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 56e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovstatic void _AdjustGlyphSpace(FXTEXT_GLYPHPOS* pGlyphAndPos, int nChars) 57e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 58e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ASSERT(nChars > 1); 59e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_BOOL bVertical = FALSE; 60e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pGlyphAndPos[nChars - 1].m_OriginX == pGlyphAndPos[0].m_OriginX) { 61e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov bVertical = TRUE; 62e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else if (pGlyphAndPos[nChars - 1].m_OriginY != pGlyphAndPos[0].m_OriginY) { 63e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return; 64e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 65e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int i = nChars - 1; 66e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int* next_origin = bVertical ? &pGlyphAndPos[i].m_OriginY : &pGlyphAndPos[i].m_OriginX; 67e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_FLOAT next_origin_f = bVertical ? pGlyphAndPos[i].m_fOriginY : pGlyphAndPos[i].m_fOriginX; 68e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (i --; i > 0; i --) { 69e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int* this_origin = bVertical ? &pGlyphAndPos[i].m_OriginY : &pGlyphAndPos[i].m_OriginX; 70e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_FLOAT this_origin_f = bVertical ? pGlyphAndPos[i].m_fOriginY : pGlyphAndPos[i].m_fOriginX; 71e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int space = (*next_origin) - (*this_origin); 72e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_FLOAT space_f = next_origin_f - this_origin_f; 73e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_FLOAT error = (FX_FLOAT)(FXSYS_fabs(space_f) - FXSYS_fabs((FX_FLOAT)(space))); 74e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (error > 0.5f) { 75e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov *this_origin += space > 0 ? -1 : 1; 76e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 77e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov next_origin = this_origin; 78e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov next_origin_f = this_origin_f; 79e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 80e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 81e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovstatic const FX_BYTE g_TextGammaAdjust[256] = { 82e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 0, 2, 3, 4, 6, 7, 8, 10, 11, 12, 13, 15, 16, 17, 18, 19, 83e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 21, 22, 23, 24, 25, 26, 27, 29, 30, 31, 32, 33, 34, 35, 36, 38, 84e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 51, 52, 53, 54, 55, 85e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 71, 72, 86e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 87e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 88e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 89e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 121, 122, 123, 124, 125, 126, 127, 128, 129, 129, 130, 131, 132, 133, 134, 135, 90e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 91e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 152, 153, 154, 155, 156, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 92e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 167, 168, 169, 170, 171, 172, 173, 174, 174, 175, 176, 177, 178, 179, 180, 181, 93e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 182, 183, 184, 185, 186, 187, 188, 189, 190, 190, 191, 192, 193, 194, 195, 196, 94e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 197, 198, 199, 200, 201, 202, 203, 204, 204, 205, 206, 207, 208, 209, 210, 211, 95e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 212, 213, 214, 215, 216, 217, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 96e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 227, 228, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 239, 240, 97e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 250, 251, 252, 253, 254, 255, 98e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}; 99e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#define ADJUST_ALPHA(background, foreground, src_alpha, text_flags, a) \ 100e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = g_TextGammaAdjust[(FX_BYTE)src_alpha]; 101e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovvoid _Color2Argb(FX_ARGB& argb, FX_DWORD color, int alpha_flag, void* pIccTransform) 102e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 103e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pIccTransform == NULL && !FXGETFLAG_COLORTYPE(alpha_flag)) { 104e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov argb = color; 105e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return; 106e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 107e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (!CFX_GEModule::Get()->GetCodecModule() || !CFX_GEModule::Get()->GetCodecModule()->GetIccModule()) { 108e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pIccTransform = NULL; 109e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 110e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_BYTE bgra[4]; 111e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pIccTransform) { 112e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ICodec_IccModule* pIccModule = CFX_GEModule::Get()->GetCodecModule()->GetIccModule(); 113e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov color = FXGETFLAG_COLORTYPE(alpha_flag) ? FXCMYK_TODIB(color) : FXARGB_TODIB(color); 114e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pIccModule->TranslateScanline(pIccTransform, bgra, (FX_LPCBYTE)&color, 1); 115e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov bgra[3] = FXGETFLAG_COLORTYPE(alpha_flag) ? 116e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov (alpha_flag >> 24) ? FXGETFLAG_ALPHA_FILL(alpha_flag) : FXGETFLAG_ALPHA_STROKE(alpha_flag) : 117e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FXARGB_A(color); 118e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov argb = FXARGB_MAKE(bgra[3], bgra[2], bgra[1], bgra[0]); 119e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return; 120e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 121e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov AdobeCMYK_to_sRGB1(FXSYS_GetCValue(color), FXSYS_GetMValue(color), 122e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FXSYS_GetYValue(color), FXSYS_GetKValue(color), 123e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov bgra[2], bgra[1], bgra[0]); 124e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov bgra[3] = (alpha_flag >> 24) ? FXGETFLAG_ALPHA_FILL(alpha_flag) : FXGETFLAG_ALPHA_STROKE(alpha_flag); 125e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov argb = FXARGB_MAKE(bgra[3], bgra[2], bgra[1], bgra[0]); 126e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 127e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovFX_BOOL CFX_RenderDevice::DrawNormalText(int nChars, const FXTEXT_CHARPOS* pCharPos, 128e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_Font* pFont, CFX_FontCache* pCache, 129e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_FLOAT font_size, const CFX_AffineMatrix* pText2Device, 130e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_DWORD fill_color, FX_DWORD text_flags, 131e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int alpha_flag, void* pIccTransform) 132e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 133e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int nativetext_flags = text_flags; 134e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (m_DeviceClass != FXDC_DISPLAY) { 135e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (!(text_flags & FXTEXT_PRINTGRAPHICTEXT)) { 136e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ 137e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (!(text_flags & FXFONT_CIDFONT) && pFont->GetPsName().Find(CFX_WideString::FromLocal("+ZJHL")) == -1) 138e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#ifdef FOXIT_CHROME_BUILD 139e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pFont->GetPsName() != CFX_WideString::FromLocal("CNAAJI+cmex10")) 140e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#endif 141e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#endif 142e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (m_pDeviceDriver->DrawDeviceText(nChars, pCharPos, pFont, pCache, pText2Device, font_size, fill_color, alpha_flag, pIccTransform)) { 143e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return TRUE; 144e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 145e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 146e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int alpha = FXGETFLAG_COLORTYPE(alpha_flag) ? FXGETFLAG_ALPHA_FILL(alpha_flag) : FXARGB_A(fill_color); 147e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (alpha < 255) { 148e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return FALSE; 149e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 150e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else if (!(text_flags & FXTEXT_NO_NATIVETEXT)) { 151e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ 152e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (!(text_flags & FXFONT_CIDFONT)) 153e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#ifdef FOXIT_CHROME_BUILD 154e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pFont->GetPsName() != CFX_WideString::FromLocal("CNAAJI+cmex10")) 155e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#endif 156e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#endif 157e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (m_pDeviceDriver->DrawDeviceText(nChars, pCharPos, pFont, pCache, pText2Device, font_size, fill_color, alpha_flag, pIccTransform)) { 158e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return TRUE; 159e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 160e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 161e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_AffineMatrix char2device, deviceCtm, text2Device; 162e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pText2Device) { 163e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov char2device = *pText2Device; 164e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov text2Device = *pText2Device; 165e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 166e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov char2device.Scale(font_size, -font_size); 167e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (FXSYS_fabs(char2device.a) + FXSYS_fabs(char2device.b) > 50 * 1.0f || 168e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ((m_DeviceClass == FXDC_PRINTER && !m_pDeviceDriver->IsPSPrintDriver()) 169e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov && !(text_flags & FXTEXT_PRINTIMAGETEXT))) { 170e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pFont->GetFace() != NULL || (pFont->GetSubstFont()->m_SubstFlags & FXFONT_SUBST_GLYPHPATH)) { 171e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int nPathFlags = (text_flags & FXTEXT_NOSMOOTH) == 0 ? 0 : FXFILL_NOPATHSMOOTH; 172e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return DrawTextPath(nChars, pCharPos, pFont, pCache, font_size, pText2Device, NULL, NULL, fill_color, 0, NULL, nPathFlags, alpha_flag, pIccTransform); 173e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 174e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 175e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int anti_alias = FXFT_RENDER_MODE_MONO; 176e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_BOOL bNormal = FALSE; 177e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if ((text_flags & FXTEXT_NOSMOOTH) == 0) { 178e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (m_DeviceClass == FXDC_DISPLAY && m_bpp > 1) { 179e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_BOOL bClearType; 180e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pFont->GetFace() == NULL && !(pFont->GetSubstFont()->m_SubstFlags & FXFONT_SUBST_CLEARTYPE)) { 181e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov bClearType = FALSE; 182e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else { 183e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov bClearType = text_flags & FXTEXT_CLEARTYPE; 184e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 185e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if ((m_RenderCaps & (FXRC_ALPHA_OUTPUT | FXRC_CMYK_OUTPUT))) { 186e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov anti_alias = FXFT_RENDER_MODE_LCD; 187e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov bNormal = TRUE; 188e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else if (m_bpp < 16) { 189e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov anti_alias = FXFT_RENDER_MODE_NORMAL; 190e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else { 191e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (bClearType == FALSE) { 192e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov anti_alias = FXFT_RENDER_MODE_LCD; 193e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov bNormal = TRUE; 194e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else { 195e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov anti_alias = FXFT_RENDER_MODE_LCD; 196e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 197e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 198e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 199e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 200e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pCache == NULL) { 201e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pCache = CFX_GEModule::Get()->GetFontCache(); 202e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 203e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_FaceCache* pFaceCache = pCache->GetCachedFace(pFont); 204e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_FONTCACHE_DEFINE(pCache, pFont); 205e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FXTEXT_GLYPHPOS* pGlyphAndPos = FX_Alloc(FXTEXT_GLYPHPOS, nChars); 206e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int iChar; 207e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov deviceCtm = char2device; 208e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_AffineMatrix matrixCTM = GetCTM(); 209e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_FLOAT scale_x = FXSYS_fabs(matrixCTM.a); 210e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_FLOAT scale_y = FXSYS_fabs(matrixCTM.d); 211e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov deviceCtm.Concat(scale_x, 0, 0, scale_y, 0, 0); 212e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov text2Device.Concat(scale_x, 0, 0, scale_y, 0, 0); 213e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (iChar = 0; iChar < nChars; iChar ++) { 214e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FXTEXT_GLYPHPOS& glyph = pGlyphAndPos[iChar]; 215e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov const FXTEXT_CHARPOS& charpos = pCharPos[iChar]; 216e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov glyph.m_fOriginX = charpos.m_OriginX; 217e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov glyph.m_fOriginY = charpos.m_OriginY; 218e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov text2Device.Transform(glyph.m_fOriginX, glyph.m_fOriginY); 219e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (anti_alias < FXFT_RENDER_MODE_LCD) { 220e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov glyph.m_OriginX = FXSYS_round(glyph.m_fOriginX); 221e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else { 222e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov glyph.m_OriginX = (int)FXSYS_floor(glyph.m_fOriginX); 223e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 224e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov glyph.m_OriginY = FXSYS_round(glyph.m_fOriginY); 225e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (charpos.m_bGlyphAdjust) { 226e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_AffineMatrix new_matrix(charpos.m_AdjustMatrix[0], charpos.m_AdjustMatrix[1], 227e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov charpos.m_AdjustMatrix[2], charpos.m_AdjustMatrix[3], 0, 0); 228e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov new_matrix.Concat(deviceCtm); 229e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov glyph.m_pGlyph = pFaceCache->LoadGlyphBitmap(pFont, charpos.m_GlyphIndex, charpos.m_bFontStyle, &new_matrix, 230e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov charpos.m_FontCharWidth, anti_alias, nativetext_flags); 231e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else 232e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov glyph.m_pGlyph = pFaceCache->LoadGlyphBitmap(pFont, charpos.m_GlyphIndex, charpos.m_bFontStyle, &deviceCtm, 233e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov charpos.m_FontCharWidth, anti_alias, nativetext_flags); 234e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 235e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (anti_alias < FXFT_RENDER_MODE_LCD && nChars > 1) { 236e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov _AdjustGlyphSpace(pGlyphAndPos, nChars); 237e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 238e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_RECT bmp_rect1 = FXGE_GetGlyphsBBox(pGlyphAndPos, nChars, anti_alias); 239e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (scale_x > 1 && scale_y > 1) { 240e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov bmp_rect1.left--; 241e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov bmp_rect1.top --; 242e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov bmp_rect1.right ++; 243e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov bmp_rect1.bottom ++; 244e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 245e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_RECT bmp_rect(FXSYS_round((FX_FLOAT)(bmp_rect1.left) / scale_x), FXSYS_round((FX_FLOAT)(bmp_rect1.top) / scale_y), 246e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FXSYS_round((FX_FLOAT)bmp_rect1.right / scale_x), FXSYS_round((FX_FLOAT)bmp_rect1.bottom / scale_y)); 247e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov bmp_rect.Intersect(m_ClipBox); 248e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (bmp_rect.IsEmpty()) { 249e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_Free(pGlyphAndPos); 250e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return TRUE; 251e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 252e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int pixel_width = FXSYS_round(bmp_rect.Width() * scale_x); 253e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int pixel_height = FXSYS_round(bmp_rect.Height() * scale_y); 254e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int pixel_left = FXSYS_round(bmp_rect.left * scale_x); 255e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int pixel_top = FXSYS_round(bmp_rect.top * scale_y); 256e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (anti_alias == FXFT_RENDER_MODE_MONO) { 257e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_DIBitmap bitmap; 258e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (!bitmap.Create(pixel_width, pixel_height, FXDIB_1bppMask)) { 259e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_Free(pGlyphAndPos); 260e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return FALSE; 261e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 262e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov bitmap.Clear(0); 263e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (iChar = 0; iChar < nChars; iChar ++) { 264e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FXTEXT_GLYPHPOS& glyph = pGlyphAndPos[iChar]; 265e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (glyph.m_pGlyph == NULL) { 266e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov continue; 267e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 268e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov const CFX_DIBitmap* pGlyph = &glyph.m_pGlyph->m_Bitmap; 269e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov bitmap.TransferBitmap(glyph.m_OriginX + glyph.m_pGlyph->m_Left - pixel_left, 270e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov glyph.m_OriginY - glyph.m_pGlyph->m_Top - pixel_top, 271e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pGlyph->GetWidth(), pGlyph->GetHeight(), pGlyph, 0, 0); 272e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 273e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_Free(pGlyphAndPos); 274e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return SetBitMask(&bitmap, bmp_rect.left, bmp_rect.top, fill_color); 275e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 276e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_DIBitmap bitmap; 277e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (m_bpp == 8) { 278e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (!bitmap.Create(pixel_width, pixel_height, FXDIB_8bppMask)) { 279e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_Free(pGlyphAndPos); 280e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return FALSE; 281e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 282e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else { 283e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (!CreateCompatibleBitmap(&bitmap, pixel_width, pixel_height)) { 284e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_Free(pGlyphAndPos); 285e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return FALSE; 286e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 287e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 288e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (!bitmap.HasAlpha() && !bitmap.IsAlphaMask()) { 289e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov bitmap.Clear(0xFFFFFFFF); 290e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (!GetDIBits(&bitmap, bmp_rect.left, bmp_rect.top)) { 291e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_Free(pGlyphAndPos); 292e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return FALSE; 293e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 294e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else { 295e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov bitmap.Clear(0); 296e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (bitmap.m_pAlphaMask) { 297e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov bitmap.m_pAlphaMask->Clear(0); 298e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 299e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 300e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int dest_width = pixel_width; 301e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_LPBYTE dest_buf = bitmap.GetBuffer(); 302e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int dest_pitch = bitmap.GetPitch(); 303e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int Bpp = bitmap.GetBPP() / 8; 304e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int a, r, g, b; 305e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (anti_alias == FXFT_RENDER_MODE_LCD) { 306e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov _Color2Argb(fill_color, fill_color, alpha_flag | (1 << 24), pIccTransform); 307e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ArgbDecode(fill_color, a, r, g, b); 308e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov r = FX_GAMMA(r); 309e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov g = FX_GAMMA(g); 310e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov b = FX_GAMMA(b); 311e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 312e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (iChar = 0; iChar < nChars; iChar ++) { 313e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FXTEXT_GLYPHPOS& glyph = pGlyphAndPos[iChar]; 314e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (glyph.m_pGlyph == NULL) { 315e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov continue; 316e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 317e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov const CFX_DIBitmap* pGlyph = &glyph.m_pGlyph->m_Bitmap; 318e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int left = glyph.m_OriginX + glyph.m_pGlyph->m_Left - pixel_left; 319e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int top = glyph.m_OriginY - glyph.m_pGlyph->m_Top - pixel_top; 320e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int ncols = pGlyph->GetWidth(); 321e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int nrows = pGlyph->GetHeight(); 322e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (anti_alias == FXFT_RENDER_MODE_NORMAL) { 323e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (!bitmap.CompositeMask(left, top, ncols, nrows, pGlyph, fill_color, 324e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 0, 0, FXDIB_BLEND_NORMAL, NULL, FALSE, alpha_flag, pIccTransform)) { 325e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_Free(pGlyphAndPos); 326e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return FALSE; 327e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 328e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov continue; 329e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 330e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_BOOL bBGRStripe = text_flags & FXTEXT_BGR_STRIPE; 331e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ncols /= 3; 332e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int x_subpixel = (int)(glyph.m_fOriginX * 3) % 3; 333e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_LPBYTE src_buf = pGlyph->GetBuffer(); 334e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int src_pitch = pGlyph->GetPitch(); 335e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int start_col = left; 336e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (start_col < 0) { 337e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov start_col = 0; 338e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 339e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int end_col = left + ncols; 340e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (end_col > dest_width) { 341e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov end_col = dest_width; 342e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 343e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (start_col >= end_col) { 344e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov continue; 345e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 346e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (bitmap.GetFormat() == FXDIB_Argb) { 347e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (int row = 0; row < nrows; row ++) { 348e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int dest_row = row + top; 349e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (dest_row < 0 || dest_row >= bitmap.GetHeight()) { 350e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov continue; 351e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 352e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_LPBYTE src_scan = src_buf + row * src_pitch + (start_col - left) * 3; 353e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_LPBYTE dest_scan = dest_buf + dest_row * dest_pitch + (start_col << 2); 354e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (bBGRStripe) { 355e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (x_subpixel == 0) { 356e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (int col = start_col; col < end_col; col ++) { 357e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int src_alpha = src_scan[2]; 358e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 359e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); 360e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_scan[1]; 361e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 362e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); 363e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_scan[0]; 364e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 365e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); 366e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[3] = 255; 367e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan += 4; 368e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_scan += 3; 369e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 370e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else if (x_subpixel == 1) { 371e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int src_alpha = src_scan[1]; 372e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[2], r, src_alpha, nativetext_flags, a); 373e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 374e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); 375e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_scan[0]; 376e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[1], g, src_alpha, nativetext_flags, a); 377e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 378e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); 379e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (start_col > left) { 380e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_scan[-1]; 381e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[0], b, src_alpha, nativetext_flags, a); 382e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 383e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); 384e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 385e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[3] = 255; 386e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan += 4; 387e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_scan += 3; 388e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (int col = start_col + 1; col < end_col - 1; col ++) { 389e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int src_alpha = src_scan[1]; 390e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[2], r, src_alpha, nativetext_flags, a); 391e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 392e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); 393e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_scan[0]; 394e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[1], g, src_alpha, nativetext_flags, a); 395e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 396e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); 397e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_scan[-1]; 398e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[0], b, src_alpha, nativetext_flags, a); 399e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 400e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); 401e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[3] = 255; 402e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan += 4; 403e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_scan += 3; 404e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 405e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else { 406e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int src_alpha = src_scan[0]; 407e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[2], r, src_alpha, nativetext_flags, a); 408e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 409e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); 410e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (start_col > left) { 411e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_scan[-1]; 412e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[1], g, src_alpha, nativetext_flags, a); 413e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 414e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); 415e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_scan[-2]; 416e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[0], b, src_alpha, nativetext_flags, a); 417e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 418e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); 419e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 420e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[3] = 255; 421e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan += 4; 422e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_scan += 3; 423e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (int col = start_col + 1; col < end_col - 1; col ++) { 424e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int src_alpha = src_scan[0]; 425e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[2], r, src_alpha, nativetext_flags, a); 426e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 427e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); 428e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_scan[-1]; 429e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[1], g, src_alpha, nativetext_flags, a); 430e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 431e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); 432e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_scan[-2]; 433e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[0], b, src_alpha, nativetext_flags, a); 434e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 435e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); 436e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[3] = 255; 437e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan += 4; 438e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_scan += 3; 439e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 440e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 441e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else { 442e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (x_subpixel == 0) { 443e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (int col = start_col; col < end_col; col ++) { 444e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (bNormal) { 445e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int src_alpha1 = (src_scan[0] + src_scan[1] + src_scan[2]) / 3; 446e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[2], r, src_alpha1, nativetext_flags, a); 447e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha1 = src_alpha1 * a / 255; 448e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_BYTE back_alpha = dest_scan[3]; 449e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (back_alpha == 0) { 450e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FXARGB_SETDIB(dest_scan, FXARGB_MAKE(src_alpha1, r, g, b)); 451e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan += 4; 452e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_scan += 3; 453e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov continue; 454e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 455e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (src_alpha1 == 0) { 456e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan += 4; 457e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_scan += 3; 458e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov continue; 459e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 460e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_BYTE dest_alpha = back_alpha + src_alpha1 - back_alpha * src_alpha1 / 255; 461e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[3] = dest_alpha; 462e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int alpha_ratio = src_alpha1 * 255 / dest_alpha; 463e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, alpha_ratio)); 464e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, alpha_ratio)); 465e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, alpha_ratio)); 466e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan += 4; 467e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_scan += 3; 468e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov continue; 469e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 470e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int src_alpha = src_scan[0]; 471e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[2], r, src_alpha, nativetext_flags, a); 472e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 473e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); 474e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_scan[1]; 475e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[1], g, src_alpha, nativetext_flags, a); 476e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 477e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); 478e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_scan[2]; 479e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[0], b, src_alpha, nativetext_flags, a); 480e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 481e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); 482e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[3] = 255; 483e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan += 4; 484e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_scan += 3; 485e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 486e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else if (x_subpixel == 1) { 487e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (bNormal) { 488e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int src_alpha1 = start_col > left ? ((src_scan[-1] + src_scan[0] + src_scan[1]) / 3) : ((src_scan[0] + src_scan[1]) / 3); 489e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[2], r, src_alpha1, nativetext_flags, a); 490e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha1 = src_alpha1 * a / 255; 491e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (src_alpha1 == 0) { 492e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan += 4; 493e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_scan += 3; 494e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else { 495e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_BYTE back_alpha = dest_scan[3]; 496e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (back_alpha == 0) { 497e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FXARGB_SETDIB(dest_scan, FXARGB_MAKE(src_alpha1, r, g, b)); 498e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else { 499e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_BYTE dest_alpha = back_alpha + src_alpha1 - back_alpha * src_alpha1 / 255; 500e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[3] = dest_alpha; 501e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int alpha_ratio = src_alpha1 * 255 / dest_alpha; 502e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, alpha_ratio)); 503e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, alpha_ratio)); 504e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, alpha_ratio)); 505e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 506e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan += 4; 507e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_scan += 3; 508e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 509e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else { 510e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (start_col > left) { 511e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int src_alpha = src_scan[-1]; 512e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[2], r, src_alpha, nativetext_flags, a); 513e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 514e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); 515e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 516e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int src_alpha = src_scan[0]; 517e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[1], g, src_alpha, nativetext_flags, a); 518e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 519e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); 520e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_scan[1]; 521e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[0], b, src_alpha, nativetext_flags, a); 522e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 523e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); 524e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[3] = 255; 525e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan += 4; 526e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_scan += 3; 527e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 528e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (int col = start_col + 1; col < end_col; col ++) { 529e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (bNormal) { 530e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int src_alpha1 = (src_scan[-1] + src_scan[0] + src_scan[1]) / 3; 531e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[2], r, src_alpha1, nativetext_flags, a); 532e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha1 = src_alpha1 * a / 255; 533e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_BYTE back_alpha = dest_scan[3]; 534e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (back_alpha == 0) { 535e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FXARGB_SETDIB(dest_scan, FXARGB_MAKE(src_alpha1, r, g, b)); 536e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan += 4; 537e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_scan += 3; 538e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov continue; 539e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 540e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (src_alpha1 == 0) { 541e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan += 4; 542e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_scan += 3; 543e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov continue; 544e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 545e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_BYTE dest_alpha = back_alpha + src_alpha1 - back_alpha * src_alpha1 / 255; 546e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[3] = dest_alpha; 547e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int alpha_ratio = src_alpha1 * 255 / dest_alpha; 548e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, alpha_ratio)); 549e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, alpha_ratio)); 550e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, alpha_ratio)); 551e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan += 4; 552e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_scan += 3; 553e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov continue; 554e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 555e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int src_alpha = src_scan[-1]; 556e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[2], r, src_alpha, nativetext_flags, a); 557e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 558e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); 559e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_scan[0]; 560e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[1], g, src_alpha, nativetext_flags, a); 561e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 562e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); 563e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_scan[1]; 564e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[0], b, src_alpha, nativetext_flags, a); 565e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 566e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); 567e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[3] = 255; 568e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan += 4; 569e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_scan += 3; 570e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 571e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else { 572e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (bNormal) { 573e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int src_alpha1 = start_col > left ? ((src_scan[-2] + src_scan[-1] + src_scan[0]) / 3) : ((src_scan[0]) / 3); 574e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[2], r, src_alpha1, nativetext_flags, a); 575e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha1 = src_alpha1 * a / 255; 576e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (src_alpha1 == 0) { 577e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan += 4; 578e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_scan += 3; 579e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else { 580e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_BYTE back_alpha = dest_scan[3]; 581e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (back_alpha == 0) { 582e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FXARGB_SETDIB(dest_scan, FXARGB_MAKE(src_alpha1, r, g, b)); 583e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else { 584e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_BYTE dest_alpha = back_alpha + src_alpha1 - back_alpha * src_alpha1 / 255; 585e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[3] = dest_alpha; 586e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int alpha_ratio = src_alpha1 * 255 / dest_alpha; 587e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, alpha_ratio)); 588e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, alpha_ratio)); 589e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, alpha_ratio)); 590e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 591e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan += 4; 592e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_scan += 3; 593e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 594e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else { 595e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (start_col > left) { 596e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int src_alpha = src_scan[-2]; 597e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[2], r, src_alpha, nativetext_flags, a); 598e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 599e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); 600e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_scan[-1]; 601e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[1], g, src_alpha, nativetext_flags, a); 602e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 603e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); 604e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 605e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int src_alpha = src_scan[0]; 606e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[0], b, src_alpha, nativetext_flags, a); 607e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 608e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); 609e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[3] = 255; 610e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan += 4; 611e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_scan += 3; 612e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 613e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (int col = start_col + 1; col < end_col; col ++) { 614e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (bNormal) { 615e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int src_alpha1 = (src_scan[-2] + src_scan[-1] + src_scan[0]) / 3; 616e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[2], r, src_alpha1, nativetext_flags, a); 617e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha1 = src_alpha1 * a / 255; 618e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_BYTE back_alpha = dest_scan[3]; 619e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (back_alpha == 0) { 620e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FXARGB_SETDIB(dest_scan, FXARGB_MAKE(src_alpha1, r, g, b)); 621e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan += 4; 622e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_scan += 3; 623e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov continue; 624e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 625e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (src_alpha1 == 0) { 626e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan += 4; 627e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_scan += 3; 628e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov continue; 629e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 630e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_BYTE dest_alpha = back_alpha + src_alpha1 - back_alpha * src_alpha1 / 255; 631e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[3] = dest_alpha; 632e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int alpha_ratio = src_alpha1 * 255 / dest_alpha; 633e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, alpha_ratio)); 634e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, alpha_ratio)); 635e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, alpha_ratio)); 636e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan += 4; 637e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_scan += 3; 638e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov continue; 639e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 640e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int src_alpha = src_scan[-2]; 641e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[2], r, src_alpha, nativetext_flags, a); 642e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 643e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); 644e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_scan[-1]; 645e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[1], g, src_alpha, nativetext_flags, a); 646e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 647e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); 648e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_scan[0]; 649e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[0], b, src_alpha, nativetext_flags, a); 650e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 651e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); 652e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[3] = 255; 653e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan += 4; 654e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_scan += 3; 655e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 656e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 657e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 658e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 659e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else { 660e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (int row = 0; row < nrows; row ++) { 661e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int dest_row = row + top; 662e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (dest_row < 0 || dest_row >= bitmap.GetHeight()) { 663e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov continue; 664e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 665e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_LPBYTE src_scan = src_buf + row * src_pitch + (start_col - left) * 3; 666e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_LPBYTE dest_scan = dest_buf + dest_row * dest_pitch + start_col * Bpp; 667e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (bBGRStripe) { 668e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (x_subpixel == 0) { 669e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (int col = start_col; col < end_col; col ++) { 670e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int src_alpha = src_scan[2]; 671e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[2], r, src_alpha, nativetext_flags, a); 672e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 673e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); 674e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_scan[1]; 675e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[1], g, src_alpha, nativetext_flags, a); 676e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 677e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); 678e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_scan[0]; 679e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[0], b, src_alpha, nativetext_flags, a); 680e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 681e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); 682e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan += Bpp; 683e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_scan += 3; 684e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 685e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else if (x_subpixel == 1) { 686e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int src_alpha = src_scan[1]; 687e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[2], r, src_alpha, nativetext_flags, a); 688e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 689e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); 690e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_scan[0]; 691e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[1], g, src_alpha, nativetext_flags, a); 692e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 693e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); 694e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (start_col > left) { 695e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_scan[-1]; 696e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[0], b, src_alpha, nativetext_flags, a); 697e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 698e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); 699e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 700e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan += Bpp; 701e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_scan += 3; 702e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (int col = start_col + 1; col < end_col - 1; col ++) { 703e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int src_alpha = src_scan[1]; 704e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[2], r, src_alpha, nativetext_flags, a); 705e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 706e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); 707e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_scan[0]; 708e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[1], g, src_alpha, nativetext_flags, a); 709e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 710e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); 711e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_scan[-1]; 712e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[0], b, src_alpha, nativetext_flags, a); 713e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 714e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); 715e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan += Bpp; 716e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_scan += 3; 717e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 718e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else { 719e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int src_alpha = src_scan[0]; 720e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[2], r, src_alpha, nativetext_flags, a); 721e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 722e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); 723e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (start_col > left) { 724e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_scan[-1]; 725e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[1], g, src_alpha, nativetext_flags, a); 726e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 727e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); 728e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_scan[-2]; 729e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[0], b, src_alpha, nativetext_flags, a); 730e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 731e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); 732e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 733e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan += Bpp; 734e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_scan += 3; 735e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (int col = start_col + 1; col < end_col - 1; col ++) { 736e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int src_alpha = src_scan[0]; 737e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[2], r, src_alpha, nativetext_flags, a); 738e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 739e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); 740e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_scan[-1]; 741e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[1], g, src_alpha, nativetext_flags, a); 742e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 743e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); 744e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_scan[-2]; 745e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[0], b, src_alpha, nativetext_flags, a); 746e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 747e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); 748e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan += Bpp; 749e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_scan += 3; 750e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 751e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 752e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else { 753e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (x_subpixel == 0) { 754e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (int col = start_col; col < end_col; col ++) { 755e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (bNormal) { 756e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int src_alpha1 = (src_scan[0] + src_scan[1] + src_scan[2]) / 3; 757e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[2], r, src_alpha1, nativetext_flags, a); 758e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha1 = src_alpha1 * a / 255; 759e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (src_alpha1 == 0) { 760e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan += Bpp; 761e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_scan += 3; 762e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov continue; 763e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 764e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha1)); 765e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha1)); 766e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha1)); 767e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan += Bpp; 768e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_scan += 3; 769e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov continue; 770e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 771e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int src_alpha = src_scan[0]; 772e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[2], r, src_alpha, nativetext_flags, a); 773e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 774e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); 775e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_scan[1]; 776e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[1], g, src_alpha, nativetext_flags, a); 777e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 778e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); 779e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_scan[2]; 780e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[0], b, src_alpha, nativetext_flags, a); 781e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 782e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); 783e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan += Bpp; 784e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_scan += 3; 785e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 786e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else if (x_subpixel == 1) { 787e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (bNormal) { 788e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int src_alpha1 = start_col > left ? (src_scan[0] + src_scan[1] + src_scan[-1]) / 3 : (src_scan[0] + src_scan[1]) / 3; 789e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[2], r, src_alpha1, nativetext_flags, a); 790e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha1 = src_alpha1 * a / 255; 791e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha1)); 792e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha1)); 793e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha1)); 794e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan += Bpp; 795e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_scan += 3; 796e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else { 797e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (start_col > left) { 798e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int src_alpha = src_scan[-1]; 799e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[2], r, src_alpha, nativetext_flags, a); 800e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 801e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); 802e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 803e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int src_alpha = src_scan[0]; 804e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[1], g, src_alpha, nativetext_flags, a); 805e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 806e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); 807e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_scan[1]; 808e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[0], b, src_alpha, nativetext_flags, a); 809e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 810e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); 811e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan += Bpp; 812e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_scan += 3; 813e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 814e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (int col = start_col + 1; col < end_col; col ++) { 815e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (bNormal) { 816e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int src_alpha1 = (src_scan[0] + src_scan[1] + src_scan[-1]) / 3; 817e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[2], r, src_alpha1, nativetext_flags, a); 818e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha1 = src_alpha1 * a / 255; 819e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (src_alpha1 == 0) { 820e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan += Bpp; 821e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_scan += 3; 822e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov continue; 823e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 824e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha1)); 825e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha1)); 826e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha1)); 827e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan += Bpp; 828e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_scan += 3; 829e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov continue; 830e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 831e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int src_alpha = src_scan[-1]; 832e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[2], r, src_alpha, nativetext_flags, a); 833e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 834e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); 835e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_scan[0]; 836e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[1], g, src_alpha, nativetext_flags, a); 837e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 838e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); 839e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_scan[1]; 840e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[0], b, src_alpha, nativetext_flags, a); 841e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 842e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); 843e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan += Bpp; 844e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_scan += 3; 845e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 846e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else { 847e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (bNormal) { 848e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int src_alpha1 = start_col > left ? (src_scan[0] + src_scan[-2] + src_scan[-1]) / 3 : src_scan[0] / 3; 849e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[2], r, src_alpha1, nativetext_flags, a); 850e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha1 = src_alpha1 * a / 255; 851e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha1)); 852e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha1)); 853e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha1)); 854e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan += Bpp; 855e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_scan += 3; 856e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else { 857e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (start_col > left) { 858e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int src_alpha = src_scan[-2]; 859e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[2], r, src_alpha, nativetext_flags, a); 860e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 861e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); 862e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_scan[-1]; 863e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[1], g, src_alpha, nativetext_flags, a); 864e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 865e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); 866e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 867e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int src_alpha = src_scan[0]; 868e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[0], b, src_alpha, nativetext_flags, a); 869e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 870e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); 871e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan += Bpp; 872e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_scan += 3; 873e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 874e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (int col = start_col + 1; col < end_col; col ++) { 875e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (bNormal) { 876e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int src_alpha1 = ((int)(src_scan[0]) + (int)(src_scan[-2]) + (int)(src_scan[-1])) / 3; 877e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[2], r, src_alpha1, nativetext_flags, a); 878e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha1 = src_alpha1 * a / 255; 879e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (src_alpha1 == 0) { 880e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan += Bpp; 881e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_scan += 3; 882e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov continue; 883e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 884e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha1)); 885e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha1)); 886e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha1)); 887e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan += Bpp; 888e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_scan += 3; 889e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov continue; 890e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 891e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int src_alpha = src_scan[-2]; 892e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[2], r, src_alpha, nativetext_flags, a); 893e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 894e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[2] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[2]), r, src_alpha)); 895e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_scan[-1]; 896e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[1], g, src_alpha, nativetext_flags, a); 897e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 898e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[1] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[1]), g, src_alpha)); 899e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_scan[0]; 900e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ADJUST_ALPHA(dest_scan[0], b, src_alpha, nativetext_flags, a); 901e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_alpha = src_alpha * a / 255; 902e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan[0] = FX_GAMMA_INVERSE(FXDIB_ALPHA_MERGE(FX_GAMMA(dest_scan[0]), b, src_alpha)); 903e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov dest_scan += Bpp; 904e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov src_scan += 3; 905e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 906e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 907e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 908e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 909e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 910e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 911e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (bitmap.IsAlphaMask()) { 912e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov SetBitMask(&bitmap, bmp_rect.left, bmp_rect.top, fill_color, alpha_flag, pIccTransform); 913e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else { 914e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov SetDIBits(&bitmap, bmp_rect.left, bmp_rect.top); 915e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 916e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_Free(pGlyphAndPos); 917e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return TRUE; 918e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 919e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovFX_BOOL CFX_RenderDevice::DrawTextPath(int nChars, const FXTEXT_CHARPOS* pCharPos, 920e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_Font* pFont, CFX_FontCache* pCache, 921e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_FLOAT font_size, const CFX_AffineMatrix* pText2User, 922e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov const CFX_AffineMatrix* pUser2Device, const CFX_GraphStateData* pGraphState, 923e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_DWORD fill_color, FX_ARGB stroke_color, CFX_PathData* pClippingPath, int nFlag, 924e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int alpha_flag, void* pIccTransform, int blend_type) 925e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 926e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pCache == NULL) { 927e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pCache = CFX_GEModule::Get()->GetFontCache(); 928e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 929e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_FaceCache* pFaceCache = pCache->GetCachedFace(pFont); 930e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_FONTCACHE_DEFINE(pCache, pFont); 931e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (int iChar = 0; iChar < nChars; iChar ++) { 932e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov const FXTEXT_CHARPOS& charpos = pCharPos[iChar]; 933e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_AffineMatrix matrix; 934e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (charpos.m_bGlyphAdjust) 935e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov matrix.Set(charpos.m_AdjustMatrix[0], charpos.m_AdjustMatrix[1], 936e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov charpos.m_AdjustMatrix[2], charpos.m_AdjustMatrix[3], 0, 0); 937e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov matrix.Concat(font_size, 0, 0, font_size, charpos.m_OriginX, charpos.m_OriginY); 938e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov const CFX_PathData* pPath = pFaceCache->LoadGlyphPath(pFont, charpos.m_GlyphIndex, charpos.m_FontCharWidth); 939e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pPath == NULL) { 940e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov continue; 941e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 942e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov matrix.Concat(*pText2User); 943e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_PathData TransformedPath(*pPath); 944e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov TransformedPath.Transform(&matrix); 945e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_BOOL bHasAlpha = FXGETFLAG_COLORTYPE(alpha_flag) ? 946e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov (FXGETFLAG_ALPHA_FILL(alpha_flag) || FXGETFLAG_ALPHA_STROKE(alpha_flag)) : 947e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov (fill_color || stroke_color); 948e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (bHasAlpha) { 949e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int fill_mode = nFlag; 950e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (FXGETFLAG_COLORTYPE(alpha_flag)) { 951e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (FXGETFLAG_ALPHA_FILL(alpha_flag)) { 952e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov fill_mode |= FXFILL_WINDING; 953e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 954e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else { 955e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (fill_color) { 956e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov fill_mode |= FXFILL_WINDING; 957e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 958e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 959e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov fill_mode |= FX_FILL_TEXT_MODE; 960e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (!DrawPath(&TransformedPath, pUser2Device, pGraphState, fill_color, stroke_color, fill_mode, alpha_flag, pIccTransform, blend_type)) { 961e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return FALSE; 962e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 963e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 964e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pClippingPath) { 965e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pClippingPath->Append(&TransformedPath, pUser2Device); 966e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 967e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 968e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return TRUE; 969e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 970e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovCFX_FontCache::~CFX_FontCache() 971e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 972e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FreeCache(TRUE); 973e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 974e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovCFX_FaceCache* CFX_FontCache::GetCachedFace(CFX_Font* pFont) 975e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 976e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_BOOL bExternal = pFont->GetFace() == NULL; 977e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov void* face = bExternal ? pFont->GetSubstFont()->m_ExtHandle : pFont->GetFace(); 978e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_FTCacheMap& map = bExternal ? m_ExtFaceMap : m_FTFaceMap; 979e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_CountedFaceCache* counted_face_cache = NULL; 980e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (map.Lookup((FXFT_Face)face, counted_face_cache)) { 981e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov counted_face_cache->m_nCount++; 982e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return counted_face_cache->m_Obj; 983e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 984e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_FaceCache* face_cache = new CFX_FaceCache(bExternal ? NULL : (FXFT_Face)face); 985e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov counted_face_cache = new CFX_CountedFaceCache; 986e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov counted_face_cache->m_nCount = 2; 987e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov counted_face_cache->m_Obj = face_cache; 988e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov map.SetAt((FXFT_Face)face, counted_face_cache); 989e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return face_cache; 990e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 991e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovvoid CFX_FontCache::ReleaseCachedFace(CFX_Font* pFont) 992e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 993e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_BOOL bExternal = pFont->GetFace() == NULL; 994e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov void* face = bExternal ? pFont->GetSubstFont()->m_ExtHandle : pFont->GetFace(); 995e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_FTCacheMap& map = bExternal ? m_ExtFaceMap : m_FTFaceMap; 996e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_CountedFaceCache* counted_face_cache = NULL; 997e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (!map.Lookup((FXFT_Face)face, counted_face_cache)) { 998e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return; 999e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1000e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (counted_face_cache->m_nCount > 1) { 1001e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov counted_face_cache->m_nCount--; 1002e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1003e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 1004e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovvoid CFX_FontCache::FreeCache(FX_BOOL bRelease) 1005e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 1006e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov { 1007e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_POSITION pos; 1008e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pos = m_FTFaceMap.GetStartPosition(); 1009e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov while (pos) { 1010e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FXFT_Face face; 1011e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_CountedFaceCache* cache; 1012e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov m_FTFaceMap.GetNextAssoc(pos, face, cache); 1013e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (bRelease || cache->m_nCount < 2) { 1014e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov delete cache->m_Obj; 1015e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov delete cache; 1016e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov m_FTFaceMap.RemoveKey(face); 1017e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1018e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1019e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pos = m_ExtFaceMap.GetStartPosition(); 1020e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov while (pos) { 1021e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FXFT_Face face; 1022e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_CountedFaceCache* cache; 1023e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov m_ExtFaceMap.GetNextAssoc(pos, face, cache); 1024e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (bRelease || cache->m_nCount < 2) { 1025e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov delete cache->m_Obj; 1026e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov delete cache; 1027e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov m_ExtFaceMap.RemoveKey(face); 1028e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1029e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1030e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1031e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 1032e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovCFX_FaceCache::CFX_FaceCache(FXFT_Face face) 1033e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 1034e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov m_Face = face; 1035e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov m_pBitmap = NULL; 1036e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 1037e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovCFX_FaceCache::~CFX_FaceCache() 1038e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 1039e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_POSITION pos = m_SizeMap.GetStartPosition(); 1040e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_ByteString Key; 1041e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_SizeGlyphCache* pSizeCache = NULL; 1042e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov while(pos) { 1043e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov m_SizeMap.GetNextAssoc( pos, Key, (void*&)pSizeCache); 1044e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov delete pSizeCache; 1045e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1046e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov m_SizeMap.RemoveAll(); 1047e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pos = m_PathMap.GetStartPosition(); 1048e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_LPVOID key1; 1049e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_PathData* pPath; 1050e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov while (pos) { 1051e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov m_PathMap.GetNextAssoc(pos, key1, (FX_LPVOID&)pPath); 1052e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov delete pPath; 1053e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1054e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (m_pBitmap) { 1055e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov delete m_pBitmap; 1056e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1057e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov m_PathMap.RemoveAll(); 1058e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 1059e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#if _FXM_PLATFORM_ != _FXM_PLATFORM_APPLE_ 1060e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovvoid CFX_FaceCache::InitPlatform() 1061e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 1062e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 1063e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#endif 1064e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovCFX_GlyphBitmap* CFX_FaceCache::LookUpGlyphBitmap(CFX_Font* pFont, const CFX_AffineMatrix* pMatrix, 1065e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_ByteStringC& FaceGlyphsKey, FX_DWORD glyph_index, FX_BOOL bFontStyle, 1066e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int dest_width, int anti_alias) 1067e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 1068e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_SizeGlyphCache* pSizeCache = NULL; 1069e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (!m_SizeMap.Lookup(FaceGlyphsKey, (void*&)pSizeCache)) { 1070e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pSizeCache = new CFX_SizeGlyphCache; 1071e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov m_SizeMap.SetAt(FaceGlyphsKey, pSizeCache); 1072e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1073e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_GlyphBitmap* pGlyphBitmap = NULL; 1074e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pSizeCache->m_GlyphMap.Lookup((FX_LPVOID)(FX_UINTPTR)glyph_index, (void*&)pGlyphBitmap)) { 1075e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return pGlyphBitmap; 1076e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1077e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pGlyphBitmap = RenderGlyph(pFont, glyph_index, bFontStyle, pMatrix, dest_width, anti_alias); 1078e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pGlyphBitmap == NULL) { 1079e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return NULL; 1080e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1081e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pSizeCache->m_GlyphMap.SetAt((FX_LPVOID)(FX_UINTPTR)glyph_index, pGlyphBitmap); 1082e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return pGlyphBitmap; 1083e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 1084e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovconst CFX_GlyphBitmap* CFX_FaceCache::LoadGlyphBitmap(CFX_Font* pFont, FX_DWORD glyph_index, FX_BOOL bFontStyle, const CFX_AffineMatrix* pMatrix, 1085e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int dest_width, int anti_alias, int& text_flags) 1086e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 1087e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (glyph_index == (FX_DWORD) - 1) { 1088e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return NULL; 1089e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1090e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov _CFX_UniqueKeyGen keygen; 1091e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#if _FXM_PLATFORM_ != _FXM_PLATFORM_APPLE_ 1092e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pFont->GetSubstFont()) 1093e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov keygen.Generate(9, (int)(pMatrix->a * 10000), (int)(pMatrix->b * 10000), 1094e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov (int)(pMatrix->c * 10000), (int)(pMatrix->d * 10000), dest_width, anti_alias, 1095e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pFont->GetSubstFont()->m_Weight, pFont->GetSubstFont()->m_ItalicAngle, pFont->IsVertical()); 1096e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov else 1097e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov keygen.Generate(6, (int)(pMatrix->a * 10000), (int)(pMatrix->b * 10000), 1098e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov (int)(pMatrix->c * 10000), (int)(pMatrix->d * 10000), dest_width, anti_alias); 1099e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#else 1100e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (text_flags & FXTEXT_NO_NATIVETEXT) { 1101e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pFont->GetSubstFont()) 1102e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov keygen.Generate(9, (int)(pMatrix->a * 10000), (int)(pMatrix->b * 10000), 1103e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov (int)(pMatrix->c * 10000), (int)(pMatrix->d * 10000), dest_width, anti_alias, 1104e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pFont->GetSubstFont()->m_Weight, pFont->GetSubstFont()->m_ItalicAngle, pFont->IsVertical()); 1105e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov else 1106e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov keygen.Generate(6, (int)(pMatrix->a * 10000), (int)(pMatrix->b * 10000), 1107e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov (int)(pMatrix->c * 10000), (int)(pMatrix->d * 10000), dest_width, anti_alias); 1108e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else { 1109e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pFont->GetSubstFont()) 1110e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov keygen.Generate(10, (int)(pMatrix->a * 10000), (int)(pMatrix->b * 10000), 1111e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov (int)(pMatrix->c * 10000), (int)(pMatrix->d * 10000), dest_width, anti_alias, 1112e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pFont->GetSubstFont()->m_Weight, pFont->GetSubstFont()->m_ItalicAngle, pFont->IsVertical(), 3); 1113e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov else 1114e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov keygen.Generate(7, (int)(pMatrix->a * 10000), (int)(pMatrix->b * 10000), 1115e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov (int)(pMatrix->c * 10000), (int)(pMatrix->d * 10000), dest_width, anti_alias, 3); 1116e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1117e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#endif 1118e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_ByteStringC FaceGlyphsKey(keygen.m_Key, keygen.m_KeyLen); 1119e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#if _FXM_PLATFORM_ != _FXM_PLATFORM_APPLE_ 1120e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return LookUpGlyphBitmap(pFont, pMatrix, FaceGlyphsKey, glyph_index, bFontStyle, dest_width, anti_alias); 1121e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#else 1122e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (text_flags & FXTEXT_NO_NATIVETEXT) { 1123e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return LookUpGlyphBitmap(pFont, pMatrix, FaceGlyphsKey, glyph_index, bFontStyle, dest_width, anti_alias); 1124e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else { 1125e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_GlyphBitmap* pGlyphBitmap; 1126e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_SizeGlyphCache* pSizeCache = NULL; 1127e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (m_SizeMap.Lookup(FaceGlyphsKey, (void*&)pSizeCache)) { 1128e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pSizeCache->m_GlyphMap.Lookup((FX_LPVOID)(FX_UINTPTR)glyph_index, (void*&)pGlyphBitmap)) { 1129e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return pGlyphBitmap; 1130e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1131e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pGlyphBitmap = RenderGlyph_Nativetext(pFont, glyph_index, pMatrix, dest_width, anti_alias); 1132e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pGlyphBitmap) { 1133e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pSizeCache->m_GlyphMap.SetAt((FX_LPVOID)(FX_UINTPTR)glyph_index, pGlyphBitmap); 1134e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return pGlyphBitmap; 1135e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1136e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else { 1137e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pGlyphBitmap = RenderGlyph_Nativetext(pFont, glyph_index, pMatrix, dest_width, anti_alias); 1138e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pGlyphBitmap) { 1139e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pSizeCache = new CFX_SizeGlyphCache; 1140e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov m_SizeMap.SetAt(FaceGlyphsKey, pSizeCache); 1141e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pSizeCache->m_GlyphMap.SetAt((FX_LPVOID)(FX_UINTPTR)glyph_index, pGlyphBitmap); 1142e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return pGlyphBitmap; 1143e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1144e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1145e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pFont->GetSubstFont()) 1146e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov keygen.Generate(9, (int)(pMatrix->a * 10000), (int)(pMatrix->b * 10000), 1147e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov (int)(pMatrix->c * 10000), (int)(pMatrix->d * 10000), dest_width, anti_alias, 1148e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pFont->GetSubstFont()->m_Weight, pFont->GetSubstFont()->m_ItalicAngle, pFont->IsVertical()); 1149e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov else 1150e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov keygen.Generate(6, (int)(pMatrix->a * 10000), (int)(pMatrix->b * 10000), 1151e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov (int)(pMatrix->c * 10000), (int)(pMatrix->d * 10000), dest_width, anti_alias); 1152e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_ByteStringC FaceGlyphsKey(keygen.m_Key, keygen.m_KeyLen); 1153e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov text_flags |= FXTEXT_NO_NATIVETEXT; 1154e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return LookUpGlyphBitmap(pFont, pMatrix, FaceGlyphsKey, glyph_index, bFontStyle, dest_width, anti_alias); 1155e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1156e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#endif 1157e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 1158e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovCFX_SizeGlyphCache::~CFX_SizeGlyphCache() 1159e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 1160e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_POSITION pos = m_GlyphMap.GetStartPosition(); 1161e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_LPVOID Key; 1162e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_GlyphBitmap* pGlyphBitmap = NULL; 1163e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov while(pos) { 1164e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov m_GlyphMap.GetNextAssoc(pos, Key, (void*&)pGlyphBitmap); 1165e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov delete pGlyphBitmap; 1166e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1167e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov m_GlyphMap.RemoveAll(); 1168e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 1169e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#define CONTRAST_RAMP_STEP 1 1170e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovvoid CFX_Font::AdjustMMParams(int glyph_index, int dest_width, int weight) 1171e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 1172e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FXFT_MM_Var pMasters = NULL; 1173e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FXFT_Get_MM_Var(m_Face, &pMasters); 1174e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pMasters == NULL) { 1175e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return; 1176e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1177e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov long coords[2]; 1178e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (weight == 0) { 1179e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov coords[0] = FXFT_Get_MM_Axis_Def(FXFT_Get_MM_Axis(pMasters, 0)) / 65536; 1180e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else { 1181e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov coords[0] = weight; 1182e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1183e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (dest_width == 0) { 1184e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov coords[1] = FXFT_Get_MM_Axis_Def(FXFT_Get_MM_Axis(pMasters, 1)) / 65536; 1185e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else { 1186e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int min_param = FXFT_Get_MM_Axis_Min(FXFT_Get_MM_Axis(pMasters, 1)) / 65536; 1187e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int max_param = FXFT_Get_MM_Axis_Max(FXFT_Get_MM_Axis(pMasters, 1)) / 65536; 1188e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov coords[1] = min_param; 1189e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int error = FXFT_Set_MM_Design_Coordinates(m_Face, 2, coords); 1190e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov error = FXFT_Load_Glyph(m_Face, glyph_index, FXFT_LOAD_NO_SCALE | FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH); 1191e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int min_width = FXFT_Get_Glyph_HoriAdvance(m_Face) * 1000 / FXFT_Get_Face_UnitsPerEM(m_Face); 1192e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov coords[1] = max_param; 1193e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov error = FXFT_Set_MM_Design_Coordinates(m_Face, 2, coords); 1194e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov error = FXFT_Load_Glyph(m_Face, glyph_index, FXFT_LOAD_NO_SCALE | FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH); 1195e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int max_width = FXFT_Get_Glyph_HoriAdvance(m_Face) * 1000 / FXFT_Get_Face_UnitsPerEM(m_Face); 1196e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (max_width == min_width) { 1197e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return; 1198e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1199e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int param = min_param + (max_param - min_param) * (dest_width - min_width) / (max_width - min_width); 1200e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov coords[1] = param; 1201e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1202e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FXFT_Free(m_Face, pMasters); 1203e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FXFT_Set_MM_Design_Coordinates(m_Face, 2, coords); 1204e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 1205e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovstatic const size_t ANGLESKEW_ARRAY_SIZE = 30; 1206e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovstatic const char g_AngleSkew[ANGLESKEW_ARRAY_SIZE] = { 1207e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 0, 2, 3, 5, 7, 9, 11, 12, 14, 16, 1208e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 18, 19, 21, 23, 25, 27, 29, 31, 32, 34, 1209e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 36, 38, 40, 42, 45, 47, 49, 51, 53, 55, 1210e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}; 1211e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovstatic const size_t WEIGHTPOW_ARRAY_SIZE = 100; 1212e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovstatic const FX_BYTE g_WeightPow[WEIGHTPOW_ARRAY_SIZE] = { 1213e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 0, 3, 6, 7, 8, 9, 11, 12, 14, 15, 16, 17, 18, 19, 20, 1214e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 35, 36, 36, 1215e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 37, 37, 37, 38, 38, 38, 39, 39, 39, 40, 40, 40, 41, 41, 41, 42, 42, 42, 1216e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 42, 43, 43, 43, 44, 44, 44, 44, 45, 45, 45, 45, 46, 46, 46, 46, 47, 47, 1217e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 47, 47, 48, 48, 48, 48, 48, 49, 49, 49, 49, 50, 50, 50, 50, 50, 51, 51, 1218e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 51, 51, 51, 52, 52, 52, 52, 52, 53, 53, 53, 53, 53, 1219e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}; 1220e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovstatic const FX_BYTE g_WeightPow_11[WEIGHTPOW_ARRAY_SIZE] = { 1221e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 0, 4, 7, 8, 9, 10, 12, 13, 15, 17, 18, 19, 20, 21, 22, 1222e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 23, 24, 25, 26, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 39, 39, 40, 40, 1223e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 41, 41, 41, 42, 42, 42, 43, 43, 43, 44, 44, 44, 45, 45, 45, 46, 46, 46, 1224e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 46, 43, 47, 47, 48, 48, 48, 48, 45, 50, 50, 50, 46, 51, 51, 51, 52, 52, 1225e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 52, 52, 53, 53, 53, 53, 53, 54, 54, 54, 54, 55, 55, 55, 55, 55, 56, 56, 1226e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 56, 56, 56, 57, 57, 57, 57, 57, 58, 58, 58, 58, 58, 1227e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}; 1228e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovstatic const FX_BYTE g_WeightPow_SHIFTJIS[WEIGHTPOW_ARRAY_SIZE] = { 1229e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 0, 0, 1, 2, 3, 4, 5, 7, 8, 10, 11, 13, 14, 16, 17, 19, 21, 22, 24, 26, 28, 1230e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 30, 32, 33, 35, 37, 39, 41, 43, 45, 48, 48, 48, 48, 49, 49, 49, 50, 50, 50, 50, 1231e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 51, 51, 51, 51, 52, 52, 52, 52, 52, 53, 53, 53, 53, 53, 54, 54, 54, 54, 54, 55, 55, 1232e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 55, 55, 55, 56, 56, 56, 56, 56 , 56, 57, 57, 57 , 57 , 57, 57, 57, 58, 58, 58, 58, 58, 1233e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 58, 58, 59, 59, 59, 59, 59, 59, 59, 60, 60, 60, 60, 60, 60, 60, 60, 1234e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}; 1235e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovstatic void _GammaAdjust(FX_LPBYTE pData, int nWid, int nHei, int src_pitch, FX_LPCBYTE gammaTable) 1236e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 1237e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int count = nHei * src_pitch; 1238e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for(int i = 0; i < count; i++) { 1239e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pData[i] = gammaTable[pData[i]]; 1240e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1241e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 1242e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovstatic void _ContrastAdjust(FX_LPBYTE pDataIn, FX_LPBYTE pDataOut, int nWid, int nHei, int nSrcRowBytes, int nDstRowBytes) 1243e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 1244e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int col, row, temp; 1245e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int max = 0, min = 255; 1246e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_FLOAT rate; 1247e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (row = 0; row < nHei; row ++) { 1248e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_LPBYTE pRow = pDataIn + row * nSrcRowBytes; 1249e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (col = 0; col < nWid; col++) { 1250e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov temp = *pRow ++; 1251e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (temp > max) { 1252e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov max = temp; 1253e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1254e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (temp < min) { 1255e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov min = temp; 1256e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1257e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1258e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1259e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov temp = max - min; 1260e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (0 == temp || 255 == temp) { 1261e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int rowbytes = FXSYS_abs(nSrcRowBytes) > nDstRowBytes ? nDstRowBytes : FXSYS_abs(nSrcRowBytes); 1262e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (row = 0; row < nHei; row ++) { 1263e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FXSYS_memcpy32(pDataOut + row * nDstRowBytes, pDataIn + row * nSrcRowBytes, rowbytes); 1264e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1265e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return; 1266e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1267e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov rate = 255.f / temp; 1268e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (row = 0; row < nHei; row ++) { 1269e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_LPBYTE pSrcRow = pDataIn + row * nSrcRowBytes; 1270e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_LPBYTE pDstRow = pDataOut + row * nDstRowBytes; 1271e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (col = 0; col < nWid; col ++) { 1272e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov temp = (int)((*(pSrcRow++) - min) * rate + 0.5); 1273e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (temp > 255) { 1274e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov temp = 255; 1275e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else if (temp < 0) { 1276e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov temp = 0; 1277e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1278e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov *pDstRow ++ = (FX_BYTE)temp; 1279e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1280e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1281e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 1282e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovCFX_GlyphBitmap* CFX_FaceCache::RenderGlyph(CFX_Font* pFont, FX_DWORD glyph_index, FX_BOOL bFontStyle, 1283e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov const CFX_AffineMatrix* pMatrix, int dest_width, int anti_alias) 1284e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 1285e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (m_Face == NULL) { 1286e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return NULL; 1287e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1288e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FXFT_Matrix ft_matrix; 1289e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ft_matrix.xx = (signed long)(pMatrix->GetA() / 64 * 65536); 1290e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ft_matrix.xy = (signed long)(pMatrix->GetC() / 64 * 65536); 1291e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ft_matrix.yx = (signed long)(pMatrix->GetB() / 64 * 65536); 1292e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ft_matrix.yy = (signed long)(pMatrix->GetD() / 64 * 65536); 1293e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_BOOL bUseCJKSubFont = FALSE; 1294e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov const CFX_SubstFont* pSubstFont = pFont->GetSubstFont(); 1295e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pSubstFont) { 1296e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov bUseCJKSubFont = pSubstFont->m_bSubstOfCJK && bFontStyle; 1297e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int skew = 0; 1298e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (bUseCJKSubFont) { 1299e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov skew = pSubstFont->m_bItlicCJK ? -15 : 0; 1300e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else { 1301e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov skew = pSubstFont->m_ItalicAngle; 1302e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1303e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (skew) { 1304e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov skew = skew <= -ANGLESKEW_ARRAY_SIZE ? -58 : -g_AngleSkew[-skew]; 1305e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pFont->IsVertical()) { 1306e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ft_matrix.yx += ft_matrix.yy * skew / 100; 1307e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else { 1308e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ft_matrix.xy += -ft_matrix.xx * skew / 100; 1309e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1310e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1311e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pSubstFont->m_SubstFlags & FXFONT_SUBST_MM) { 1312e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pFont->AdjustMMParams(glyph_index, dest_width, pFont->GetSubstFont()->m_Weight); 1313e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1314e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1315e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FXFT_Set_Transform(m_Face, &ft_matrix, 0); 1316e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int load_flags = (m_Face->face_flags & FT_FACE_FLAG_SFNT) ? FXFT_LOAD_NO_BITMAP : (FXFT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING); 1317e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int error = FXFT_Load_Glyph(m_Face, glyph_index, load_flags); 1318e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (error) { 1319e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov //if an error is returned, try to reload glyphs without hinting. 1320e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (load_flags & FT_LOAD_NO_HINTING || load_flags & FT_LOAD_NO_SCALE) { 1321e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return NULL; 1322e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1323e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 1324e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov load_flags |= FT_LOAD_NO_HINTING; 1325e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov error = FXFT_Load_Glyph(m_Face, glyph_index, load_flags); 1326e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 1327e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (error) { 1328e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return NULL; 1329e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1330e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1331e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int weight = 0; 1332e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (bUseCJKSubFont) { 1333e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov weight = pSubstFont->m_WeightCJK; 1334e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else { 1335e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov weight = pSubstFont ? pSubstFont->m_Weight : 0; 1336e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1337e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pSubstFont && !(pSubstFont->m_SubstFlags & FXFONT_SUBST_MM) && weight > 400) { 1338e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int index = (weight - 400) / 10; 1339e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (index >= WEIGHTPOW_ARRAY_SIZE) { 1340e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return NULL; 1341e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1342e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int level = 0; 1343e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pSubstFont->m_Charset == FXFONT_SHIFTJIS_CHARSET) { 1344e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov level = g_WeightPow_SHIFTJIS[index] * 2 * (FXSYS_abs((int)(ft_matrix.xx)) + FXSYS_abs((int)(ft_matrix.xy))) / 36655; 1345e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else { 1346e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov level = g_WeightPow_11[index] * (FXSYS_abs((int)(ft_matrix.xx)) + FXSYS_abs((int)(ft_matrix.xy))) / 36655; 1347e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1348e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FXFT_Outline_Embolden(FXFT_Get_Glyph_Outline(m_Face), level); 1349e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1350e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FXFT_Library_SetLcdFilter(CFX_GEModule::Get()->GetFontMgr()->m_FTLibrary, FT_LCD_FILTER_DEFAULT); 1351e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov error = FXFT_Render_Glyph(m_Face, anti_alias); 1352e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (error) { 1353e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return NULL; 1354e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1355e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int bmwidth = FXFT_Get_Bitmap_Width(FXFT_Get_Glyph_Bitmap(m_Face)); 1356e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int bmheight = FXFT_Get_Bitmap_Rows(FXFT_Get_Glyph_Bitmap(m_Face)); 1357e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (bmwidth > 2048 || bmheight > 2048) { 1358e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return NULL; 1359e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1360e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int dib_width = bmwidth; 1361e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_GlyphBitmap* pGlyphBitmap = new CFX_GlyphBitmap; 1362e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pGlyphBitmap->m_Bitmap.Create(dib_width, bmheight, 1363e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov anti_alias == FXFT_RENDER_MODE_MONO ? FXDIB_1bppMask : FXDIB_8bppMask); 1364e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pGlyphBitmap->m_Left = FXFT_Get_Glyph_BitmapLeft(m_Face); 1365e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pGlyphBitmap->m_Top = FXFT_Get_Glyph_BitmapTop(m_Face); 1366e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int dest_pitch = pGlyphBitmap->m_Bitmap.GetPitch(); 1367e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int src_pitch = FXFT_Get_Bitmap_Pitch(FXFT_Get_Glyph_Bitmap(m_Face)); 1368e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_BYTE* pDestBuf = pGlyphBitmap->m_Bitmap.GetBuffer(); 1369e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_BYTE* pSrcBuf = (FX_BYTE*)FXFT_Get_Bitmap_Buffer(FXFT_Get_Glyph_Bitmap(m_Face)); 1370e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (anti_alias != FXFT_RENDER_MODE_MONO && FXFT_Get_Bitmap_PixelMode(FXFT_Get_Glyph_Bitmap(m_Face)) == FXFT_PIXEL_MODE_MONO) { 1371e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int bytes = anti_alias == FXFT_RENDER_MODE_LCD ? 3 : 1; 1372e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for(int i = 0; i < bmheight; i++) 1373e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for(int n = 0; n < bmwidth; n++) { 1374e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_BYTE data = (pSrcBuf[i * src_pitch + n / 8] & (0x80 >> (n % 8))) ? 255 : 0; 1375e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (int b = 0; b < bytes; b ++) { 1376e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pDestBuf[i * dest_pitch + n * bytes + b] = data; 1377e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1378e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1379e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else { 1380e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FXSYS_memset32(pDestBuf, 0, dest_pitch * bmheight); 1381e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (anti_alias == FXFT_RENDER_MODE_MONO && FXFT_Get_Bitmap_PixelMode(FXFT_Get_Glyph_Bitmap(m_Face)) == FXFT_PIXEL_MODE_MONO) { 1382e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int rowbytes = FXSYS_abs(src_pitch) > dest_pitch ? dest_pitch : FXSYS_abs(src_pitch); 1383e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (int row = 0; row < bmheight; row ++) { 1384e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FXSYS_memcpy32(pDestBuf + row * dest_pitch, pSrcBuf + row * src_pitch, rowbytes); 1385e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1386e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else { 1387e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov _ContrastAdjust(pSrcBuf, pDestBuf, bmwidth, bmheight, src_pitch, dest_pitch); 1388e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov _GammaAdjust(pDestBuf, bmwidth, bmheight, dest_pitch, CFX_GEModule::Get()->GetTextGammaTable()); 1389e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1390e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1391e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return pGlyphBitmap; 1392e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 1393e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovFX_BOOL _OutputGlyph(void* dib, int x, int y, CFX_Font* pFont, 1394e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int glyph_index, FX_ARGB argb) 1395e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 1396e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_DIBitmap* pDib = (CFX_DIBitmap*)dib; 1397e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FXFT_Face face = pFont->GetFace(); 1398e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int error = FXFT_Load_Glyph(face, glyph_index, FXFT_LOAD_NO_BITMAP); 1399e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (error) { 1400e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return FALSE; 1401e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1402e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov error = FXFT_Render_Glyph(face, FXFT_RENDER_MODE_NORMAL); 1403e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (error) { 1404e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return FALSE; 1405e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1406e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int bmwidth = FXFT_Get_Bitmap_Width(FXFT_Get_Glyph_Bitmap(face)); 1407e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int bmheight = FXFT_Get_Bitmap_Rows(FXFT_Get_Glyph_Bitmap(face)); 1408e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int left = FXFT_Get_Glyph_BitmapLeft(face); 1409e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int top = FXFT_Get_Glyph_BitmapTop(face); 1410e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_LPCBYTE src_buf = (FX_LPCBYTE)FXFT_Get_Bitmap_Buffer(FXFT_Get_Glyph_Bitmap(face)); 1411e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int src_pitch = FXFT_Get_Bitmap_Pitch(FXFT_Get_Glyph_Bitmap(face)); 1412e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_DIBitmap mask; 1413e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov mask.Create(bmwidth, bmheight, FXDIB_8bppMask); 1414e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_LPBYTE dest_buf = mask.GetBuffer(); 1415e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int dest_pitch = mask.GetPitch(); 1416e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (int row = 0; row < bmheight; row ++) { 1417e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_LPCBYTE src_scan = src_buf + row * src_pitch; 1418e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_LPBYTE dest_scan = dest_buf + row * dest_pitch; 1419e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FXSYS_memcpy32(dest_scan, src_scan, dest_pitch); 1420e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1421e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pDib->CompositeMask(x + left, y - top, bmwidth, bmheight, &mask, argb, 0, 0); 1422e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return TRUE; 1423e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 1424e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovFX_BOOL OutputText(void* dib, int x, int y, CFX_Font* pFont, double font_size, 1425e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_AffineMatrix* pText_matrix, unsigned short const* text, unsigned long argb) 1426e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 1427e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (!pFont) { 1428e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return FALSE; 1429e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1430e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FXFT_Face face = pFont->GetFace(); 1431e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FXFT_Select_Charmap(pFont->m_Face, FXFT_ENCODING_UNICODE); 1432e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pText_matrix) { 1433e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FXFT_Matrix ft_matrix; 1434e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ft_matrix.xx = (signed long)(pText_matrix->a / 64 * 65536); 1435e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ft_matrix.xy = (signed long)(pText_matrix->c / 64 * 65536); 1436e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ft_matrix.yx = (signed long)(pText_matrix->b / 64 * 65536); 1437e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ft_matrix.yy = (signed long)(pText_matrix->d / 64 * 65536); 1438e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FXFT_Set_Transform(face, &ft_matrix, 0); 1439e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1440e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_FLOAT x_pos = 0; 1441e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (; *text != 0; text ++) { 1442e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_WCHAR unicode = *text; 1443e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int glyph_index = FXFT_Get_Char_Index(pFont->m_Face, unicode); 1444e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (glyph_index <= 0) { 1445e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov continue; 1446e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1447e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int err = FXFT_Load_Glyph(pFont->m_Face, glyph_index, FXFT_LOAD_NO_SCALE | FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH); 1448e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (err) { 1449e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov continue; 1450e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1451e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int w = FXFT_Get_Glyph_HoriAdvance(pFont->m_Face); 1452e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int em = FXFT_Get_Face_UnitsPerEM(pFont->m_Face); 1453e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_FLOAT x1, y1; 1454e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pText_matrix->Transform(x_pos, 0, x1, y1); 1455e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov _OutputGlyph(dib, (int)x1 + x, (int) - y1 + y, pFont, 1456e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov glyph_index, argb); 1457e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov x_pos += (FX_FLOAT)w / em; 1458e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1459e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return TRUE; 1460e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 1461e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovFX_BOOL OutputGlyph(void* dib, int x, int y, CFX_Font* pFont, double font_size, 1462e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_AffineMatrix* pMatrix, unsigned long glyph_index, unsigned long argb) 1463e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 1464e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FXFT_Matrix ft_matrix; 1465e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pMatrix) { 1466e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ft_matrix.xx = (signed long)(pMatrix->a * font_size / 64 * 65536); 1467e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ft_matrix.xy = (signed long)(pMatrix->c * font_size / 64 * 65536); 1468e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ft_matrix.yx = (signed long)(pMatrix->b * font_size / 64 * 65536); 1469e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ft_matrix.yy = (signed long)(pMatrix->d * font_size / 64 * 65536); 1470e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else { 1471e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ft_matrix.xx = (signed long)(font_size / 64 * 65536); 1472e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ft_matrix.xy = ft_matrix.yx = 0; 1473e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ft_matrix.yy = (signed long)(font_size / 64 * 65536); 1474e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1475e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FXFT_Set_Transform(pFont->m_Face, &ft_matrix, 0); 1476e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_BOOL ret = _OutputGlyph(dib, x, y, pFont, 1477e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov glyph_index, argb); 1478e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return ret; 1479e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 1480e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovconst CFX_PathData* CFX_FaceCache::LoadGlyphPath(CFX_Font* pFont, FX_DWORD glyph_index, int dest_width) 1481e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 1482e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (m_Face == NULL || glyph_index == (FX_DWORD) - 1) { 1483e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return NULL; 1484e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1485e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_PathData* pGlyphPath = NULL; 1486e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_LPVOID key; 1487e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pFont->GetSubstFont()) 1488e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov key = (FX_LPVOID)(FX_UINTPTR)(glyph_index + ((pFont->GetSubstFont()->m_Weight / 16) << 15) + 1489e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ((pFont->GetSubstFont()->m_ItalicAngle / 2) << 21) + ((dest_width / 16) << 25) + 1490e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov (pFont->IsVertical() << 31)); 1491e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov else { 1492e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov key = (FX_LPVOID)(FX_UINTPTR)glyph_index; 1493e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1494e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (m_PathMap.Lookup(key, (FX_LPVOID&)pGlyphPath)) { 1495e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return pGlyphPath; 1496e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1497e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pGlyphPath = pFont->LoadGlyphPath(glyph_index, dest_width); 1498e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov m_PathMap.SetAt(key, pGlyphPath); 1499e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return pGlyphPath; 1500e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 1501e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovtypedef struct { 1502e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_BOOL m_bCount; 1503e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int m_PointCount; 1504e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_PATHPOINT* m_pPoints; 1505e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int m_CurX; 1506e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int m_CurY; 1507e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_FLOAT m_CoordUnit; 1508e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} OUTLINE_PARAMS; 1509e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovvoid _Outline_CheckEmptyContour(OUTLINE_PARAMS* param) 1510e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 1511e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (param->m_PointCount >= 2 && param->m_pPoints[param->m_PointCount - 2].m_Flag == FXPT_MOVETO && 1512e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov param->m_pPoints[param->m_PointCount - 2].m_PointX == param->m_pPoints[param->m_PointCount - 1].m_PointX && 1513e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov param->m_pPoints[param->m_PointCount - 2].m_PointY == param->m_pPoints[param->m_PointCount - 1].m_PointY) { 1514e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov param->m_PointCount -= 2; 1515e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1516e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (param->m_PointCount >= 4 && param->m_pPoints[param->m_PointCount - 4].m_Flag == FXPT_MOVETO && 1517e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov param->m_pPoints[param->m_PointCount - 3].m_Flag == FXPT_BEZIERTO && 1518e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov param->m_pPoints[param->m_PointCount - 3].m_PointX == param->m_pPoints[param->m_PointCount - 4].m_PointX && 1519e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov param->m_pPoints[param->m_PointCount - 3].m_PointY == param->m_pPoints[param->m_PointCount - 4].m_PointY && 1520e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov param->m_pPoints[param->m_PointCount - 2].m_PointX == param->m_pPoints[param->m_PointCount - 4].m_PointX && 1521e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov param->m_pPoints[param->m_PointCount - 2].m_PointY == param->m_pPoints[param->m_PointCount - 4].m_PointY && 1522e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov param->m_pPoints[param->m_PointCount - 1].m_PointX == param->m_pPoints[param->m_PointCount - 4].m_PointX && 1523e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov param->m_pPoints[param->m_PointCount - 1].m_PointY == param->m_pPoints[param->m_PointCount - 4].m_PointY) { 1524e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov param->m_PointCount -= 4; 1525e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1526e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 1527e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovextern "C" { 1528e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov static int _Outline_MoveTo(const FXFT_Vector* to, void* user) 1529e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov { 1530e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov OUTLINE_PARAMS* param = (OUTLINE_PARAMS*)user; 1531e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (!param->m_bCount) { 1532e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov _Outline_CheckEmptyContour(param); 1533e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov param->m_pPoints[param->m_PointCount].m_PointX = to->x / param->m_CoordUnit; 1534e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov param->m_pPoints[param->m_PointCount].m_PointY = to->y / param->m_CoordUnit; 1535e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov param->m_pPoints[param->m_PointCount].m_Flag = FXPT_MOVETO; 1536e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov param->m_CurX = to->x; 1537e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov param->m_CurY = to->y; 1538e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (param->m_PointCount) { 1539e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov param->m_pPoints[param->m_PointCount - 1].m_Flag |= FXPT_CLOSEFIGURE; 1540e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1541e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1542e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov param->m_PointCount ++; 1543e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return 0; 1544e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1545e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}; 1546e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovextern "C" { 1547e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov static int _Outline_LineTo(const FXFT_Vector* to, void* user) 1548e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov { 1549e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov OUTLINE_PARAMS* param = (OUTLINE_PARAMS*)user; 1550e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (!param->m_bCount) { 1551e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov param->m_pPoints[param->m_PointCount].m_PointX = to->x / param->m_CoordUnit; 1552e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov param->m_pPoints[param->m_PointCount].m_PointY = to->y / param->m_CoordUnit; 1553e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov param->m_pPoints[param->m_PointCount].m_Flag = FXPT_LINETO; 1554e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov param->m_CurX = to->x; 1555e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov param->m_CurY = to->y; 1556e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1557e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov param->m_PointCount ++; 1558e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return 0; 1559e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1560e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}; 1561e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovextern "C" { 1562e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov static int _Outline_ConicTo(const FXFT_Vector* control, const FXFT_Vector* to, void* user) 1563e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov { 1564e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov OUTLINE_PARAMS* param = (OUTLINE_PARAMS*)user; 1565e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (!param->m_bCount) { 1566e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov param->m_pPoints[param->m_PointCount].m_PointX = (param->m_CurX + (control->x - param->m_CurX) * 2 / 3) / param->m_CoordUnit; 1567e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov param->m_pPoints[param->m_PointCount].m_PointY = (param->m_CurY + (control->y - param->m_CurY) * 2 / 3) / param->m_CoordUnit; 1568e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov param->m_pPoints[param->m_PointCount].m_Flag = FXPT_BEZIERTO; 1569e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov param->m_pPoints[param->m_PointCount + 1].m_PointX = (control->x + (to->x - control->x) / 3) / param->m_CoordUnit; 1570e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov param->m_pPoints[param->m_PointCount + 1].m_PointY = (control->y + (to->y - control->y) / 3) / param->m_CoordUnit; 1571e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov param->m_pPoints[param->m_PointCount + 1].m_Flag = FXPT_BEZIERTO; 1572e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov param->m_pPoints[param->m_PointCount + 2].m_PointX = to->x / param->m_CoordUnit; 1573e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov param->m_pPoints[param->m_PointCount + 2].m_PointY = to->y / param->m_CoordUnit; 1574e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov param->m_pPoints[param->m_PointCount + 2].m_Flag = FXPT_BEZIERTO; 1575e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov param->m_CurX = to->x; 1576e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov param->m_CurY = to->y; 1577e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1578e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov param->m_PointCount += 3; 1579e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return 0; 1580e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1581e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}; 1582e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovextern "C" { 1583e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov static int _Outline_CubicTo(const FXFT_Vector* control1, const FXFT_Vector* control2, const FXFT_Vector* to, void* user) 1584e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov { 1585e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov OUTLINE_PARAMS* param = (OUTLINE_PARAMS*)user; 1586e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (!param->m_bCount) { 1587e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov param->m_pPoints[param->m_PointCount].m_PointX = control1->x / param->m_CoordUnit; 1588e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov param->m_pPoints[param->m_PointCount].m_PointY = control1->y / param->m_CoordUnit; 1589e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov param->m_pPoints[param->m_PointCount].m_Flag = FXPT_BEZIERTO; 1590e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov param->m_pPoints[param->m_PointCount + 1].m_PointX = control2->x / param->m_CoordUnit; 1591e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov param->m_pPoints[param->m_PointCount + 1].m_PointY = control2->y / param->m_CoordUnit; 1592e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov param->m_pPoints[param->m_PointCount + 1].m_Flag = FXPT_BEZIERTO; 1593e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov param->m_pPoints[param->m_PointCount + 2].m_PointX = to->x / param->m_CoordUnit; 1594e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov param->m_pPoints[param->m_PointCount + 2].m_PointY = to->y / param->m_CoordUnit; 1595e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov param->m_pPoints[param->m_PointCount + 2].m_Flag = FXPT_BEZIERTO; 1596e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov param->m_CurX = to->x; 1597e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov param->m_CurY = to->y; 1598e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1599e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov param->m_PointCount += 3; 1600e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return 0; 1601e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1602e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}; 1603e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovCFX_PathData* CFX_Font::LoadGlyphPath(FX_DWORD glyph_index, int dest_width) 1604e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 1605e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (m_Face == NULL) { 1606e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return NULL; 1607e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1608e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FXFT_Set_Pixel_Sizes(m_Face, 0, 64); 1609e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FXFT_Matrix ft_matrix = {65536, 0, 0, 65536}; 1610e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (m_pSubstFont) { 1611e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (m_pSubstFont->m_ItalicAngle) { 1612e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int skew = m_pSubstFont->m_ItalicAngle; 1613e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov skew = skew <= -ANGLESKEW_ARRAY_SIZE ? -58 : -g_AngleSkew[-skew]; 1614e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (m_bVertical) { 1615e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ft_matrix.yx += ft_matrix.yy * skew / 100; 1616e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else { 1617e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ft_matrix.xy += -ft_matrix.xx * skew / 100; 1618e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1619e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1620e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (m_pSubstFont->m_SubstFlags & FXFONT_SUBST_MM) { 1621e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov AdjustMMParams(glyph_index, dest_width, m_pSubstFont->m_Weight); 1622e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1623e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1624e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FXFT_Set_Transform(m_Face, &ft_matrix, 0); 1625e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int load_flags = (m_Face->face_flags & FT_FACE_FLAG_SFNT) ? FXFT_LOAD_NO_BITMAP : FXFT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING; 1626e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int error = FXFT_Load_Glyph(m_Face, glyph_index, load_flags); 1627e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (error) { 1628e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return NULL; 1629e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1630e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (m_pSubstFont && !(m_pSubstFont->m_SubstFlags & FXFONT_SUBST_MM) && m_pSubstFont->m_Weight > 400) { 1631e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int index = (m_pSubstFont->m_Weight - 400) / 10; 1632e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (index >= WEIGHTPOW_ARRAY_SIZE) 1633e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov index = WEIGHTPOW_ARRAY_SIZE - 1; 1634e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int level = 0; 1635e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (m_pSubstFont->m_Charset == FXFONT_SHIFTJIS_CHARSET) { 1636e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov level = g_WeightPow_SHIFTJIS[index] * 2 * 65536 / 36655; 1637e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else { 1638e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov level = g_WeightPow[index] * 2; 1639e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1640e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FXFT_Outline_Embolden(FXFT_Get_Glyph_Outline(m_Face), level); 1641e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1642e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FXFT_Outline_Funcs funcs; 1643e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov funcs.move_to = _Outline_MoveTo; 1644e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov funcs.line_to = _Outline_LineTo; 1645e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov funcs.conic_to = _Outline_ConicTo; 1646e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov funcs.cubic_to = _Outline_CubicTo; 1647e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov funcs.shift = 0; 1648e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov funcs.delta = 0; 1649e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov OUTLINE_PARAMS params; 1650e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov params.m_bCount = TRUE; 1651e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov params.m_PointCount = 0; 1652e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FXFT_Outline_Decompose(FXFT_Get_Glyph_Outline(m_Face), &funcs, ¶ms); 1653e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (params.m_PointCount == 0) { 1654e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return NULL; 1655e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1656e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_PathData* pPath = new CFX_PathData; 1657e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pPath->SetPointCount(params.m_PointCount); 1658e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov params.m_bCount = FALSE; 1659e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov params.m_PointCount = 0; 1660e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov params.m_pPoints = pPath->GetPoints(); 1661e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov params.m_CurX = params.m_CurY = 0; 1662e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov params.m_CoordUnit = 64 * 64.0; 1663e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FXFT_Outline_Decompose(FXFT_Get_Glyph_Outline(m_Face), &funcs, ¶ms); 1664e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov _Outline_CheckEmptyContour(¶ms); 1665e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pPath->TrimPoints(params.m_PointCount); 1666e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (params.m_PointCount) { 1667e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pPath->GetPoints()[params.m_PointCount - 1].m_Flag |= FXPT_CLOSEFIGURE; 1668e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1669e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return pPath; 1670e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 1671e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovvoid _CFX_UniqueKeyGen::Generate(int count, ...) 1672e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 1673e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov va_list argList; 1674e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov va_start(argList, count); 1675e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (int i = 0; i < count; i ++) { 1676e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int p = va_arg(argList, int); 1677e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ((FX_DWORD*)m_Key)[i] = p; 1678e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 1679e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov va_end(argList); 1680e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov m_KeyLen = count * sizeof(FX_DWORD); 1681e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 1682