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