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