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