8 #define IsFontBold(lf) ((lf).lfWeight > FW_NORMAL)
9 #define FT_FixedToInt(x) (FT_RoundFix(x) >> 16)
10 #define FT_PosToInt(x) (((x) + (1 << 5)) >> 6)
11 #define RESOLUTION_X 72
12 #define RESOLUTION_Y 72
13 FT_Error
New_FT_Outline_Embolden( FT_Outline
* outline
, FT_Pos str_h
, FT_Pos str_v
);
14 FT_Error
Old_FT_Outline_Embolden( FT_Outline
* outline
, FT_Pos strength
);
15 FT_Error
Vert_FT_Outline_Embolden( FT_Outline
* outline
, FT_Pos strength
);
17 class CGGOKerning
: public CMap
<DWORD
, int>
20 DWORD
makekey(WORD first
, WORD second
) {
21 return ((DWORD
)first
<< 16) | second
;
25 int get(WORD first
, WORD second
) {
26 DWORD key
= makekey(first
, second
);
28 return (x
>= 0) ? GetValueAt(x
) : 0;
33 CGGOKerning::init(HDC hdc
)
36 rc
= GetKerningPairs(hdc
, 0, NULL
);
39 LPKERNINGPAIR kpp
= (LPKERNINGPAIR
)calloc(kpcnt
, sizeof *kpp
);
41 rc
= GetKerningPairs(hdc
, kpcnt
, kpp
);
42 for (DWORD i
= 0; i
< rc
; ++i
) {
43 Add(makekey(kpp
[i
].wFirst
, kpp
[i
].wSecond
), kpp
[i
].iKernAmount
);
48 struct FreeTypeDrawInfo
50 FT_FaceRec_ dummy_freetype_face
;
52 //FreeTypePrepare‚ª�Ý’è‚·‚é
53 FT_Face freetype_face
;
55 FT_Render_Mode render_mode
;
56 FTC_ImageTypeRec font_type
;
57 FreeTypeFontInfo
* pfi
;
58 const CFontSettings
* pfs
;
59 FreeTypeFontCache
* pftCache
;
60 FTC_FaceID face_id_list
[CFontLinkInfo::FONTMAX
* 2 + 1];
61 FT_Int cmap_list
[CFontLinkInfo::FONTMAX
* 2 + 1];
64 //ŒÄ‚Ñ�o‚µ‘O‚ÉŽ©•ª‚Å�Ý’è‚·‚é
71 FREETYPE_PARAMS params
;
73 FreeTypeDrawInfo(const FREETYPE_PARAMS
& fp
, HDC dc
, LOGFONTW
* lf
= NULL
, CBitmapCache
* ca
= NULL
, const int* dx
= NULL
)
74 : freetype_face(&dummy_freetype_face
), useKerning(0)
75 , pfi(NULL
), pfs(NULL
), pftCache(NULL
), face_id_list_num(0)
76 , hdc(dc
), x(0), yBase(0), yTop(0)
78 render_mode
= FT_RENDER_MODE_NORMAL
;
79 ZeroMemory(&font_type
, sizeof(font_type
));
80 ZeroMemory(&face_id_list
, sizeof face_id_list
);
81 ZeroMemory(&cmap_list
, sizeof cmap_list
);
85 if(lf
) params
.lplf
= lf
;
86 memset(&dummy_freetype_face
, 0, sizeof dummy_freetype_face
);
89 const LOGFONTW
& LogFont() const { return *params
.lplf
; }
90 COLORREF
Color() const { return params
.color
; }
91 UINT
GetETO() const { return params
.etoOptions
; }
92 bool IsGlyphIndex() const { return !!(params
.etoOptions
& ETO_GLYPH_INDEX
); }
93 bool IsMono() const { return !!(params
.ftOptions
& FTO_MONO
); }
94 bool IsSizeOnly() const { return !!(params
.ftOptions
& FTO_SIZE_ONLY
); }
95 CGGOKerning ggokerning
;
99 extern FT_Library freetype_library
;
100 extern FTC_Manager cache_man
;
101 extern FTC_CMapCache cmap_cache
;
102 extern FTC_ImageCache image_cache
;
109 BYTE tbl2
[256 * 16 + 1];
110 // ’Ê�í‚̃Aƒ‹ƒtƒ@’l•â�³
115 // ‰e•¶Žš—p‚̃Aƒ‹ƒtƒ@’l•â�³
121 static const int BASE
;
126 BYTE
doAB(BYTE fg
, BYTE bg
, int alpha
);
127 void gettunetbl(int paramalpha
, bool lcd
, const int * &tblR
, const int * &tblG
, const int * &tblB
) const;
128 inline int conv1(BYTE n
) {
131 inline BYTE
conv2(int n
) {
132 return tbl2
[n
/ (BASE
* BASE
/ (sizeof tbl2
- 1))];
135 inline int convalpha(int alpha
) {
136 return alphatbl
[alpha
];
138 inline BYTE
rconv1(int n
);
140 const int CAlphaBlend::BASE
= 0x4000;
142 static CAlphaBlend s_AlphaBlendTable
;
144 void CAlphaBlend::gettunetbl(int paramalpha
, bool lcd
, const int * &tblR
, const int * &tblG
, const int * &tblB
) const
146 if (paramalpha
== 1) {
152 tblR
= tblG
= tblB
= tunetbl
;
160 tblR
= tblG
= tblB
= tunetblS
;
165 void CAlphaBlend::init()
167 const CGdippSettings
* pSettings
= CGdippSettings::GetInstance();
168 const float gamma
= pSettings
->GammaValue();
169 const float weight
= pSettings
->RenderWeight();
170 const float contrast
= pSettings
->Contrast();
171 const int mode
= pSettings
->GammaMode();
176 for (i
= 0; i
< 256; ++i
) {
177 temp
= pow((1.0f
/ 255.0f
) * i
, 1.0f
/ weight
);
180 alpha
= pow(temp
* 2, contrast
) / 2.0f
;
182 alpha
= 1.0f
- pow((1.0f
- temp
) * 2, contrast
) / 2.0f
;
184 alphatbl
[i
] = (int)(alpha
* BASE
);
187 temp
= (1.0f
/ 255.0f
) * i
;
191 temp
= (float)i
/ (12.92f
* 255.0f
);
193 temp
= pow(((1.0f
/ 255.0f
) * i
+ 0.055f
) / 1.055f
, 2.4f
);
195 } else if (mode
== 2) {
197 temp
= ((float)i
/ (12.92f
* 255.0f
) + (float)i
/ 255.0f
) / 2;
199 temp
= (pow(((1.0f
/ 255.0f
) * i
+ 0.055f
) / 1.055f
, 2.4f
) + (float)i
/ 255.0f
) / 2;
202 temp
= pow((1.0f
/ 255.0f
) * i
, gamma
);
205 tbl1
[i
] = (int)(temp
* BASE
);
210 for (i
= 0; i
<= sizeof tbl2
- 1; ++i
) {
211 tbl2
[i
] = rconv1(i
* (BASE
/ (sizeof tbl2
- 1)));
214 const int* table
= pSettings
->GetTuneTable();
215 const int* tableR
= pSettings
->GetTuneTableR();
216 const int* tableG
= pSettings
->GetTuneTableG();
217 const int* tableB
= pSettings
->GetTuneTableB();
218 const int* shadow
= pSettings
->GetShadowParams();
219 const int paramalpha
= Max(shadow
[2], 1);
221 for (i
= 0; i
< 256; ++i
) {
222 tunetbl
[i
] = alphatbl
[Bound(table
[i
], 0, 255)];
223 tunetblR
[i
] = alphatbl
[Bound(tableR
[i
], 0, 255)];
224 tunetblG
[i
] = alphatbl
[Bound(tableG
[i
], 0, 255)];
225 tunetblB
[i
] = alphatbl
[Bound(tableB
[i
], 0, 255)];
226 tunetblS
[i
] = alphatbl
[Bound(table
[i
] / paramalpha
, 0, 255)];
227 tunetblRS
[i
] = alphatbl
[Bound(tableR
[i
] / paramalpha
, 0, 255)];
228 tunetblGS
[i
] = alphatbl
[Bound(tableG
[i
] / paramalpha
, 0, 255)];
229 tunetblBS
[i
] = alphatbl
[Bound(tableB
[i
] / paramalpha
, 0, 255)];
233 BYTE
CAlphaBlend::rconv1(int n
)
238 if (n
>= tbl1
[pos
]) {
245 if (n
>= tbl1
[pos
]) {
248 return (BYTE
)(pos
- 1);
251 class CAlphaBlendColorOne
261 CAlphaBlendColorOne()
262 : fg(0), temp_fg(0), tunetbl(NULL
), bg0(0), alpha0(0), c0(0) {}
263 void init(BYTE f
, const int *tbl
);
264 ~CAlphaBlendColorOne() {};
265 BYTE
doAB(BYTE bg
, int alpha
);
268 FORCEINLINE
void CAlphaBlendColorOne::init(BYTE f
, const int *tbl
)
271 temp_fg
= s_AlphaBlendTable
.conv1(fg
);
275 FORCEINLINE BYTE
CAlphaBlendColorOne::doAB(BYTE bg
, int alpha
)
277 if (bg0
== bg
&& alpha0
== alpha
) return c0
;
278 int temp_alpha
= tunetbl
[alpha
];
279 if (fg
== bg
|| temp_alpha
<= 0) return bg
;
280 if (temp_alpha
>= s_AlphaBlendTable
.BASE
) return fg
;
281 int temp_bg
= s_AlphaBlendTable
.conv1(bg
);
282 int temp
= temp_bg
* (s_AlphaBlendTable
.BASE
- temp_alpha
) +
283 temp_fg
* temp_alpha
;
286 return c0
= s_AlphaBlendTable
.conv2(temp
);
289 class CAlphaBlendColor
292 CAlphaBlendColorOne r
;
293 CAlphaBlendColorOne g
;
294 CAlphaBlendColorOne b
;
296 CAlphaBlendColor(COLORREF newColor
, int paramalpha
, bool lcd
, bool gbr
= false);
297 ~CAlphaBlendColor() { }
298 BYTE
doABsub(BYTE fg
, int temp_fg
, BYTE bg
, int temp_alpha
) const;
299 COLORREF
doAB(COLORREF baseColor
, int alphaR
, int alphaG
, int alphaB
);
300 COLORREF
doAB(COLORREF baseColor
, int alpha
) {
301 return doAB(baseColor
, alpha
, alpha
, alpha
);
304 CAlphaBlendColor() { }
307 FORCEINLINE
CAlphaBlendColor::CAlphaBlendColor(COLORREF newColor
, int paramalpha
, bool lcd
, bool gbr
)
312 s_AlphaBlendTable
.gettunetbl(paramalpha
, lcd
, tblR
, tblG
, tblB
);
314 r
.init(GetRValue(newColor
), tblR
);
315 b
.init(GetBValue(newColor
), tblB
);
317 r
.init(GetBValue(newColor
), tblB
);
318 b
.init(GetRValue(newColor
), tblR
);
320 g
.init(GetGValue(newColor
), tblG
);
323 FORCEINLINE COLORREF
CAlphaBlendColor::doAB(COLORREF baseColor
, int alphaR
, int alphaG
, int alphaB
)
325 return RGB( r
.doAB(GetRValue(baseColor
), alphaR
),
326 g
.doAB(GetGValue(baseColor
), alphaG
),
327 b
.doAB(GetBValue(baseColor
), alphaB
));
330 FORCEINLINE BYTE
CAlphaBlend::doAB(BYTE fg
, BYTE bg
, int alpha
)
332 if (fg
== bg
|| alpha
<= 0) return bg
;
333 if (alpha
>= 255) return fg
;
334 int temp_alpha
= convalpha(alpha
);
335 int temp_bg
= conv1(bg
);
336 int temp_fg
= conv1(fg
);
337 int temp
= temp_bg
* (BASE
- temp_alpha
) +
338 temp_fg
* temp_alpha
;
342 FORCEINLINE BYTE
DoAlphaBlend(BYTE fg
, BYTE bg
, int alpha
)
344 return s_AlphaBlendTable
.doAB(fg
, bg
, alpha
);
347 // LCD(‰t�»)—p‚̃Aƒ‹ƒtƒ@ƒuƒŒƒ“ƒh(ƒTƒuƒsƒNƒZƒ‹ƒŒƒ“ƒ_ƒŠƒ“ƒO)
349 COLORREF
AlphaBlendColorLCD(
352 int alphaR
, int alphaG
, int alphaB
,
353 const int* tableR
, const int* tableG
, const int* tableB
,
354 const FreeTypeDrawInfo
& ftdi
)
356 const BYTE rs
= GetRValue(baseColor
);
357 const BYTE gs
= GetGValue(baseColor
);
358 const BYTE bs
= GetBValue(baseColor
);
359 BYTE rd
= GetRValue(newColor
);
360 BYTE gd
= GetGValue(newColor
);
361 BYTE bd
= GetBValue(newColor
);
363 alphaR
= tableR
[alphaR
] / ftdi
.params
.alpha
;
364 alphaG
= tableG
[alphaG
] / ftdi
.params
.alpha
;
365 alphaB
= tableB
[alphaB
] / ftdi
.params
.alpha
;
366 // rd = (((rd - rs) * alphaR) / 255) + rs;
367 // gd = (((gd - gs) * alphaG) / 255) + gs;
368 // bd = (((bd - bs) * alphaB) / 255) + bs;
369 rd
= DoAlphaBlend(rd
, rs
, alphaR
);
370 gd
= DoAlphaBlend(gd
, gs
, alphaG
);
371 bd
= DoAlphaBlend(bd
, bs
, alphaB
);
372 return RGB(rd
, gd
, bd
);
375 // ƒAƒ‹ƒtƒ@ƒuƒŒƒ“ƒh(256ŠK’²)
377 COLORREF
AlphaBlendColor(
380 int alpha
, const int* table
,
381 const FreeTypeDrawInfo
& ftdi
)
383 const BYTE rs
= GetRValue(baseColor
);
384 const BYTE gs
= GetGValue(baseColor
);
385 const BYTE bs
= GetBValue(baseColor
);
386 BYTE rd
= GetRValue(newColor
);
387 BYTE gd
= GetGValue(newColor
);
388 BYTE bd
= GetBValue(newColor
);
390 alpha
= table
[alpha
] / ftdi
.params
.alpha
;
391 // rd = (rs * (255 - alpha) + rd * alpha) / 255;
392 // gd = (gs * (255 - alpha) + gd * alpha) / 255;
393 // bd = (bs * (255 - alpha) + bd * alpha) / 255;
395 // rd = (((rd - rs) * alpha) / 255) + rs;
396 // gd = (((gd - gs) * alpha) / 255) + gs;
397 // bd = (((bd - bs) * alpha) / 255) + bs;
398 rd
= DoAlphaBlend(rd
, rs
, alpha
);
399 gd
= DoAlphaBlend(gd
, gs
, alpha
);
400 bd
= DoAlphaBlend(bd
, bs
, alpha
);
401 return RGB(rd
, gd
, bd
);
405 static void FreeTypeDrawBitmapPixelModeMono(
407 const FT_Bitmap
*bitmap
,
409 const FreeTypeDrawInfo
& ftdi
)
412 int dx
, dy
; // display
415 if(bitmap
->pixel_mode
!= FT_PIXEL_MODE_MONO
){
419 const COLORREF color
= RGB2DIB(ftdi
.Color());
421 const SIZE cachebufsize
= cache
.Size();
422 DWORD
* const cachebufp
= (DWORD
*)cache
.GetPixels();
423 DWORD
* cachebufrowp
;
425 int left
, top
, width
, height
;
432 width
= Min(bitmap
->width
, (int)(cachebufsize
.cx
- x
));
434 height
= bitmap
->rows
;
436 for(j
= top
, dy
= y
; j
< height
; ++j
, ++dy
){
437 if ((unsigned int)dy
>= (unsigned int)cachebufsize
.cy
) continue;
438 p
= bitmap
->pitch
< 0 ?
439 &bitmap
->buffer
[(-bitmap
->pitch
* bitmap
->rows
) - bitmap
->pitch
* j
] : // up-flow
440 &bitmap
->buffer
[bitmap
->pitch
* j
]; // down-flow
441 cachebufrowp
= &cachebufp
[dy
* cachebufsize
.cx
];
442 for(i
= left
, dx
= x
; i
< width
; ++i
, ++dx
){
443 if((p
[i
/ 8] & (1 << (7 - (i
% 8)))) != 0){
444 cachebufrowp
[dx
] = color
;
450 // LCD(‰t�»)—p•`‰æ(ƒTƒuƒsƒNƒZƒ‹ƒŒƒ“ƒ_ƒŠƒ“ƒO)
452 static void FreeTypeDrawBitmapPixelModeLCD(
454 const FT_Bitmap
*bitmap
,
456 const FreeTypeDrawInfo
& ftdi
)
459 int dx
, dy
; // display
463 if(bitmap
->pixel_mode
!= FT_PIXEL_MODE_LCD
){
467 const COLORREF color
= ftdi
.Color();
468 const int AAMode
= ftdi
.pfs
->GetAntiAliasMode();
470 const SIZE cachebufsize
= cache
.Size();
471 DWORD
* const cachebufp
= (DWORD
*)cache
.GetPixels();
472 DWORD
* cachebufrowp
;
474 // LCD‚Í3ƒTƒuƒsƒNƒZƒ‹•ª‚ ‚é
475 int left
, top
, width
, height
;
482 width
= Min(bitmap
->width
, (int)(cachebufsize
.cx
- x
) * 3);
484 height
= bitmap
->rows
;
486 CAlphaBlendColor
ab(color
, ftdi
.params
.alpha
, true, true);
489 int alphaR
, alphaG
, alphaB
;
491 for(j
= 0, dy
= y
; j
< height
; ++j
, ++dy
){
492 if ((unsigned int)dy
>= (unsigned int)cachebufsize
.cy
) continue;
494 p
= bitmap
->pitch
< 0 ?
495 &bitmap
->buffer
[(-bitmap
->pitch
* bitmap
->rows
) - bitmap
->pitch
* j
] : // up-flow
496 &bitmap
->buffer
[bitmap
->pitch
* j
]; // down-flow
498 cachebufrowp
= &cachebufp
[dy
* cachebufsize
.cx
];
500 for(i
= left
, dx
= x
; i
< width
; i
+= 3, ++dx
){
501 if(AAMode
== 2 || AAMode
== 4){
502 // ‚±‚ê‚ÍRGB‚Ì�‡‚ɃTƒuƒsƒNƒZƒ‹‚ª‚ ‚éƒfƒBƒXƒvƒŒƒC—p
512 backColor
= cachebufrowp
[dx
];
513 c
= ab
.doAB(backColor
, alphaB
, alphaG
, alphaR
);
514 cachebufrowp
[dx
] = c
;
519 // ƒOƒŠƒtƒrƒbƒgƒ}ƒbƒv‚̃Œƒ“ƒ_ƒŠƒ“ƒO
520 static void FreeTypeDrawBitmap(
522 const FT_Bitmap
*bitmap
,
524 const FreeTypeDrawInfo
& ftdi
)
527 int dx
, dy
; // display
531 if(bitmap
->pixel_mode
!= FT_PIXEL_MODE_GRAY
){
532 // ‚±‚ÌŠÖ�”Ž©‘Ì‚ÍFT_PIXEL_MODE_GRAY‚ɂ̂ݑΉž‚µ‘¼‚ɈÏ�÷‚·‚é
533 switch(bitmap
->pixel_mode
){
534 case FT_PIXEL_MODE_MONO
:
535 FreeTypeDrawBitmapPixelModeMono(
536 cache
, bitmap
, x
, y
, ftdi
);
538 case FT_PIXEL_MODE_LCD
:
539 FreeTypeDrawBitmapPixelModeLCD(
540 cache
, bitmap
, x
, y
, ftdi
);
548 const COLORREF color
= ftdi
.Color();
549 const SIZE cachebufsize
= cache
.Size();
550 DWORD
* const cachebufp
= (DWORD
*)cache
.GetPixels();
551 DWORD
* cachebufrowp
;
553 int left
, top
, width
, height
;
560 width
= Min(bitmap
->width
, (int)(cachebufsize
.cx
- x
));
562 height
= bitmap
->rows
;
564 CAlphaBlendColor
ab(color
, ftdi
.params
.alpha
, false, true);
569 for(j
= top
, dy
= y
; j
< height
; ++j
, ++dy
){
570 if ((unsigned int)dy
>= (unsigned int)cachebufsize
.cy
) continue;
571 p
= bitmap
->pitch
< 0 ?
572 &bitmap
->buffer
[(-bitmap
->pitch
* bitmap
->rows
) - bitmap
->pitch
* j
] : // up-flow
573 &bitmap
->buffer
[bitmap
->pitch
* j
]; // down-flow
574 cachebufrowp
= &cachebufp
[dy
* cachebufsize
.cx
];
575 for(i
= left
, dx
= x
; i
< width
; ++i
, ++dx
){
577 backColor
= cachebufrowp
[dx
];
578 c
= ab
.doAB(backColor
, alpha
);
579 cachebufrowp
[dx
] = c
;
584 // �c�‘‚«—p‚̃Œƒ“ƒ_ƒŠƒ“ƒO(ƒRƒsƒyŽè”²‚«)
586 static void FreeTypeDrawBitmapPixelModeMonoV(
588 const FT_Bitmap
*bitmap
,
589 const int x
, const int y
,
590 const FreeTypeDrawInfo
& ftdi
)
593 int dx
, dy
; // display
596 if(bitmap
->pixel_mode
!= FT_PIXEL_MODE_MONO
){
600 const COLORREF color
= ftdi
.Color();
602 const int width
= bitmap
->width
;
603 const int height
= bitmap
->rows
;
605 for(j
= 0, dy
= x
; j
< height
; ++j
, ++dy
){
606 p
= bitmap
->pitch
< 0 ?
607 &bitmap
->buffer
[(-bitmap
->pitch
* bitmap
->rows
) - bitmap
->pitch
* j
] : // up-flow
608 &bitmap
->buffer
[bitmap
->pitch
* j
]; // down-flow
609 for(i
= 0, dx
= y
+width
; i
< width
; ++i
, --dx
){
610 if((p
[i
/ 8] & (1 << (7 - (i
% 8)))) != 0){
611 if (cache
.GetPixel(dx
, dy
) != CLR_INVALID
) { // dx dy ƒGƒ‰�[ƒ`ƒFƒbƒN
612 cache
.SetCurrentPixel(color
);
619 // LCD(‰t�»)—p•`‰æ(ƒTƒuƒsƒNƒZƒ‹ƒŒƒ“ƒ_ƒŠƒ“ƒO)
621 static void FreeTypeDrawBitmapPixelModeLCDV(
623 const FT_Bitmap
*bitmap
,
624 const int x
, const int y
,
625 const FreeTypeDrawInfo
& ftdi
)
628 int dx
, dy
; // display
632 if(bitmap
->pixel_mode
!= FT_PIXEL_MODE_LCD_V
){
636 const COLORREF color
= ftdi
.Color();
637 const int AAMode
= ftdi
.pfs
->GetAntiAliasMode();
639 // LCD‚Í3ƒTƒuƒsƒNƒZƒ‹•ª‚ ‚é
640 const int width
= bitmap
->width
;
641 const int height
= bitmap
->rows
;
642 const int pitch
= bitmap
->pitch
;
643 const int pitchabs
= pitch
< 0 ? -pitch
: pitch
;
645 CAlphaBlendColor
ab(color
, ftdi
.params
.alpha
, true);
647 for(j
= 0, dy
= x
; j
< height
; j
+= 3, ++dy
){
649 &bitmap
->buffer
[(pitchabs
* bitmap
->rows
) + pitchabs
* j
] : // up-flow
650 &bitmap
->buffer
[pitchabs
* j
]; // down-flow
652 int alphaR
, alphaG
, alphaB
;
653 for(i
= 0, dx
= y
+width
; i
< width
; ++i
, --dx
){
654 const COLORREF backColor
= cache
.GetPixel(dy
, dx
);
656 if (backColor
== color
|| backColor
== CLR_INVALID
) continue;
657 if(AAMode
== 2 || AAMode
== 4){
658 // ‚±‚ê‚ÍRGB‚Ì�‡‚ɃTƒuƒsƒNƒZƒ‹‚ª‚ ‚éƒfƒBƒXƒvƒŒƒC—p
660 alphaG
= p
[i
+ pitch
];
661 alphaB
= p
[i
+ pitch
* 2];
664 alphaR
= p
[i
+ pitch
* 2];
665 alphaG
= p
[i
+ pitch
];
668 c
= ab
.doAB(backColor
, alphaR
, alphaG
, alphaB
);
669 cache
.SetCurrentPixel(c
);
677 static void FreeTypeDrawBitmapV(
679 const FT_Bitmap
*bitmap
,
680 const int x
, const int y
,
681 const FreeTypeDrawInfo
& ftdi
)
684 int dx
, dy
; // display
689 if(bitmap
->pixel_mode
!= FT_PIXEL_MODE_GRAY
){
690 // ‚±‚ÌŠÖ�”Ž©‘Ì‚ÍFT_PIXEL_MODE_GRAY‚ɂ̂ݑΉž‚µ‘¼‚ɈÏ�÷‚·‚é
691 switch(bitmap
->pixel_mode
){
692 case FT_PIXEL_MODE_MONO
:
693 FreeTypeDrawBitmapPixelModeMonoV(
694 cache
, bitmap
, x
, y
, ftdi
);
696 case FT_PIXEL_MODE_LCD_V
:
697 FreeTypeDrawBitmapPixelModeLCDV(
698 cache
, bitmap
, x
, y
, ftdi
);
706 const COLORREF color
= ftdi
.Color();
707 const CGdippSettings
* pSettings
= CGdippSettings::GetInstance();
708 const int* table
= pSettings
->GetTuneTable();
709 width
= bitmap
->width
;
710 height
= bitmap
->rows
;
712 CAlphaBlendColor
ab(color
, ftdi
.params
.alpha
, false);
714 for(j
= 0, dy
= x
; j
< height
; ++j
, ++dy
){
715 p
= bitmap
->pitch
< 0 ?
716 &bitmap
->buffer
[(-bitmap
->pitch
* bitmap
->rows
) - bitmap
->pitch
* j
] : // up-flow
717 &bitmap
->buffer
[bitmap
->pitch
* j
]; // down-flow
718 for(i
= 0, dx
= y
+width
; i
< width
; ++i
, --dx
){
719 const COLORREF backColor
= cache
.GetPixel(dy
, dx
);
720 if (backColor
== color
|| backColor
== CLR_INVALID
) continue;
721 c
= ab
.doAB(backColor
, p
[i
]);
722 cache
.SetPixelV(dy
, dx
, c
);
727 class CGGOGlyphLoader
731 const FT_Glyph_Class
*m_clazz
;
733 static int CALLBACK
EnumFontFamProc(const LOGFONT
* lplf
, const TEXTMETRIC
* lptm
, DWORD FontType
, LPARAM lParam
);
735 CGGOGlyphLoader() : m_lib(NULL
), m_clazz(NULL
) {}
736 ~CGGOGlyphLoader() {}
737 bool init(FT_Library freetype_library
);
738 FT_Library
getlib() { return m_lib
; }
739 const FT_Glyph_Class
* getclazz() { return m_clazz
; }
740 BYTE
convbgpixel(BYTE val
) { return bgtbl
[val
]; }
742 static CGGOGlyphLoader s_GGOGlyphLoader
;
744 int CALLBACK
CGGOGlyphLoader::EnumFontFamProc(const LOGFONT
* lplf
, const TEXTMETRIC
* lptm
, DWORD FontType
, LPARAM lParam
)
746 CGGOGlyphLoader
* pThis
= reinterpret_cast<CGGOGlyphLoader
*>(lParam
);
747 if (FontType
!= TRUETYPE_FONTTYPE
/*|| lplf->lfCharSet == SYMBOL_CHARSET*/) {
751 FreeTypeSysFontData
* pFont
= FreeTypeSysFontData::CreateInstance(lplf
->lfFaceName
, 0, false);
756 const FT_Glyph_Class
*clazz
= NULL
;
757 FT_Face face
= pFont
->GetFace();
758 FT_Error err
= FT_Set_Pixel_Sizes(face
, 0, 12);
760 err
= FT_Load_Char(face
, lptm
->tmDefaultChar
, FT_LOAD_DEFAULT
);
763 err
= FT_Get_Glyph(face
->glyph
, &glyph
);
765 if (glyph
->format
== FT_GLYPH_FORMAT_OUTLINE
) {
766 clazz
= glyph
->clazz
;
768 FT_Done_Glyph(glyph
);
776 pThis
->m_clazz
= clazz
;
784 CGGOGlyphLoader::init(FT_Library freetype_library
)
790 if (!freetype_library
) {
794 for (BYTE val
= 0; val
<= 0x40; ++val
) {
795 BYTE t
= (BYTE
)(((DWORD
)val
* 256) / 65);
796 bgtbl
[val
] = t
+ (t
>> 6);
799 m_lib
= freetype_library
;
802 //‘O‚Ì•û–@‚¾‚Æ�Aarial.ttf‚ª–³‚¢‚Æ‚Ü‚¸‚»‚¤‚È‚Ì‚Å
803 //“K“–‚ÉŽg‚¦‚éƒAƒEƒgƒ‰ƒCƒ“ƒtƒHƒ“ƒg‚ð’T‚·
804 HDC hdc
= CreateCompatibleDC(NULL
);
805 EnumFontFamilies(hdc
, NULL
, EnumFontFamProc
, reinterpret_cast<LPARAM
>(this));
808 if (m_clazz
!= NULL
) {
815 class CGGOOutlineGlyph
818 FT_OutlineGlyph m_ptr
;
819 static FT_F26Dot6
toF26Dot6(const FIXED
& fx
) {
820 return *(LONG
*)(&fx
) >> 10;
822 static FT_Fixed
toFixed(const short n
) {
823 return (FT_Fixed
)n
<< 16;
825 static char getTag(char tag
, const FT_Vector
& point
) {
826 if ((point
.x
& 0x0f) != 0) {
827 tag
|= FT_CURVE_TAG_TOUCH_X
;
829 if ((point
.y
& 0x0f) != 0) {
830 tag
|= FT_CURVE_TAG_TOUCH_Y
;
835 CGGOOutlineGlyph() : m_ptr(NULL
) { _ASSERTE(s_GGOGlyphLoader
.getlib()); }
836 ~CGGOOutlineGlyph() { done(); };
837 bool init(DWORD bufsize
, PVOID bufp
, const GLYPHMETRICS
& gm
);
839 operator FT_Glyph () { return (FT_Glyph
)m_ptr
; }
843 CGGOOutlineGlyph::done()
846 free(m_ptr
->outline
.points
);
847 free(m_ptr
->outline
.tags
);
848 free(m_ptr
->outline
.contours
);
855 CGGOOutlineGlyph::init(DWORD bufsize
, PVOID bufp
, const GLYPHMETRICS
& gm
)
858 m_ptr
= (FT_OutlineGlyph
)calloc(1, sizeof *m_ptr
);
863 FT_GlyphRec
& root
= m_ptr
->root
;
864 FT_Outline
& outline
= m_ptr
->outline
;
866 root
.library
= s_GGOGlyphLoader
.getlib();
867 root
.clazz
= s_GGOGlyphLoader
.getclazz();
868 root
.format
= FT_GLYPH_FORMAT_OUTLINE
;
869 root
.advance
.x
= toFixed(gm
.gmCellIncX
);
870 root
.advance
.y
= toFixed(gm
.gmCellIncY
);
872 outline
.n_contours
= 0;
873 outline
.n_points
= 0;
874 outline
.flags
= 0; //FT_OUTLINE_HIGH_PRECISION;
876 LPTTPOLYGONHEADER ttphp
= (LPTTPOLYGONHEADER
)bufp
;
877 LPTTPOLYGONHEADER ttphpend
= (LPTTPOLYGONHEADER
)((PBYTE
)ttphp
+ bufsize
);
879 while (ttphp
< ttphpend
) {
880 LPTTPOLYCURVE ttpcp
= (LPTTPOLYCURVE
)(ttphp
+ 1);
881 LPTTPOLYCURVE ttpcpend
= (LPTTPOLYCURVE
)((PBYTE
)ttphp
+ ttphp
->cb
);
882 if ((PVOID
)ttpcpend
> (PVOID
)ttphpend
) {
886 ++outline
.n_contours
;
887 while (ttpcp
< ttpcpend
) {
888 LPPOINTFX pfxp
= &ttpcp
->apfx
[0];
889 outline
.n_points
+= ttpcp
->cpfx
;
890 ttpcp
= (LPTTPOLYCURVE
)(pfxp
+ ttpcp
->cpfx
);
892 ttphp
= (LPTTPOLYGONHEADER
)ttpcp
;
895 if (ttphp
!= ttphpend
) {
898 outline
.points
= (FT_Vector
*)calloc(outline
.n_points
, sizeof *outline
.points
);
899 outline
.tags
= (char *)calloc(outline
.n_points
, sizeof *outline
.tags
);
900 outline
.contours
= (short *)calloc(outline
.n_contours
, sizeof *outline
.contours
);
901 if (!outline
.points
|| !outline
.tags
|| !outline
.contours
) {
906 short *cp
= outline
.contours
;
909 ttphp
= (LPTTPOLYGONHEADER
)bufp
;
910 while (ttphp
< ttphpend
) {
911 LPTTPOLYCURVE ttpcp
= (LPTTPOLYCURVE
)(ttphp
+ 1);
912 LPTTPOLYCURVE ttpcpend
= (LPTTPOLYCURVE
)((PBYTE
)ttphp
+ ttphp
->cb
);
914 LPPOINTFX pfxp0
= &ttpcp
->apfx
[0];
915 while (ttpcp
< ttpcpend
) {
916 LPPOINTFX pfxp
= &ttpcp
->apfx
[0];
917 pfxp0
= pfxp
+ (ttpcp
->cpfx
- 1);
918 ttpcp
= (LPTTPOLYCURVE
)(pfxp
+ ttpcp
->cpfx
);
920 ttpcp
= (LPTTPOLYCURVE
)(ttphp
+ 1);
922 if (pfxp0
->x
.value
!= ttphp
->pfxStart
.x
.value
|| pfxp0
->x
.fract
!= ttphp
->pfxStart
.x
.fract
||
923 pfxp0
->y
.value
!= ttphp
->pfxStart
.y
.value
|| pfxp0
->y
.fract
!= ttphp
->pfxStart
.y
.fract
) {
924 outline
.points
[ppos
].x
= toF26Dot6(ttphp
->pfxStart
.x
);
925 outline
.points
[ppos
].y
= toF26Dot6(ttphp
->pfxStart
.y
);
926 outline
.tags
[ppos
] = getTag(FT_CURVE_TAG_ON
, outline
.points
[ppos
]);
929 while (ttpcp
< ttpcpend
) {
931 switch (ttpcp
->wType
) {
933 tag
= FT_CURVE_TAG_ON
;
935 case TT_PRIM_QSPLINE
:
936 tag
= FT_CURVE_TAG_CONIC
;
938 case TT_PRIM_CSPLINE
:
939 tag
= FT_CURVE_TAG_CONIC
;
945 LPPOINTFX pfxp
= &ttpcp
->apfx
[0];
946 for (WORD cnt
= 0; cnt
< ttpcp
->cpfx
; ++cnt
) {
947 outline
.points
[ppos
].x
= toF26Dot6(pfxp
->x
);
948 outline
.points
[ppos
].y
= toF26Dot6(pfxp
->y
);
949 outline
.tags
[ppos
] = tag
;
953 outline
.tags
[ppos
- 1] = getTag(FT_CURVE_TAG_ON
, outline
.points
[ppos
- 1]);
954 ttpcp
= (LPTTPOLYCURVE
)pfxp
;
957 ttphp
= (LPTTPOLYGONHEADER
)ttpcp
;
959 outline
.n_points
= ppos
;
967 char m_localbuf
[0x0f80];
971 CTempMem() : m_size(sizeof m_localbuf
), m_ptr((T
)m_localbuf
) {
980 m_ptr
= (T
)malloc(m_size
);
985 if (m_ptr
!= (T
)m_localbuf
) {
988 m_size
= sizeof m_localbuf
;
989 m_ptr
= (T
)m_localbuf
;
991 operator T () { return m_ptr
; }
992 bool operator ! () { return !m_ptr
; }
993 DWORD
getsize() { return m_size
; }
996 BOOL
FreeTypeSetDrawSettings(FreeTypeDrawInfo
& FTInfo
, FTC_FaceID face_id
);
998 BOOL
FreeTypePrepare(FreeTypeDrawInfo
& FTInfo
)
1000 FT_Face
& freetype_face
= FTInfo
.freetype_face
;
1001 FT_Render_Mode
& render_mode
= FTInfo
.render_mode
;
1002 FTC_ImageTypeRec
& font_type
= FTInfo
.font_type
;
1003 FreeTypeFontInfo
*& pfi
= FTInfo
.pfi
;
1004 const CFontSettings
*& pfs
= FTInfo
.pfs
;
1005 FreeTypeFontCache
*& pftCache
= FTInfo
.pftCache
;
1007 FTC_FaceID face_id
= NULL
;
1010 const LOGFONTW
& lf
= FTInfo
.LogFont();
1011 if (lf
.lfFaceName
== NULL
)
1014 render_mode
= FT_RENDER_MODE_NORMAL
;
1015 if (FTInfo
.params
.alpha
< 1)
1016 FTInfo
.params
.alpha
= 1;
1018 if (! (pfi
= g_pFTEngine
->FindFont(lf
.lfFaceName
, lf
.lfWeight
, !!lf
.lfItalic
)) )
1021 face_id
= (FTC_FaceID
)pfi
->GetId();
1022 FTInfo
.face_id_list
[0] = face_id
;
1023 FTInfo
.face_id_list_num
= 1;
1025 if(FTC_Manager_LookupFace(cache_man
, face_id
, &freetype_face
)) {
1030 FTInfo
.cmap_list
[0] = FT_Get_Charmap_Index(freetype_face
->charmap
);
1032 if (freetype_face
->charmap
->encoding
!= FT_ENCODING_MS_SYMBOL
) {
1033 CFontFaceNamesEnumerator
fn(lf
.lfFaceName
);
1034 for (; !fn
.atend(); fn
.next()) {
1035 FreeTypeFontInfo
* pfitemp
= g_pFTEngine
->FindFont(fn
, lf
.lfWeight
, !!lf
.lfItalic
);
1041 FTInfo
.face_id_list
[FTInfo
.face_id_list_num
] = (FTC_FaceID
)pfitemp
->GetId();
1042 FTInfo
.cmap_list
[FTInfo
.face_id_list_num
] = -1;
1043 ++FTInfo
.face_id_list_num
;
1047 const CGdippSettings
* pSettings
= CGdippSettings::GetInstance();
1048 pfs
= &pfi
->GetFontSettings();
1049 switch (pSettings
->FontLoader()) {
1050 case SETTING_FONTLOADER_FREETYPE
:
1052 FTC_ScalerRec scaler
= { 0 };
1053 scaler
.face_id
= face_id
;
1054 // scaler.width = lf.lfWidth;
1055 TT_OS2
*os2_table
= (TT_OS2
*)FT_Get_Sfnt_Table(freetype_face
, ft_sfnt_os2
);
1056 scaler
.width
= FT_MulDiv(lf
.lfWidth
, freetype_face
->units_per_EM
, os2_table
->xAvgCharWidth
);
1058 if(lf
.lfHeight
> 0){
1060 scaler
.height
= FT_MulDiv(lf
.lfHeight
, freetype_face
->units_per_EM
, freetype_face
->height
);
1064 scaler
.height
= -lf
.lfHeight
;
1071 if(FTC_Manager_LookupSize(cache_man
, &scaler
, &font_size
))
1073 height
= scaler
.height
;
1076 case SETTING_FONTLOADER_WIN32
:
1078 OUTLINETEXTMETRIC otm
;
1079 if (GetOutlineTextMetrics(FTInfo
.hdc
, sizeof otm
, &otm
) != sizeof otm
) {
1082 height
= lf
.lfHeight
;
1089 pftCache
= pfi
->GetCache(height
, lf
);
1093 return FreeTypeSetDrawSettings(FTInfo
, face_id
);
1096 BOOL
FreeTypeSetDrawSettings(FreeTypeDrawInfo
& FTInfo
, FTC_FaceID face_id
)
1098 FT_Face
& freetype_face
= FTInfo
.freetype_face
;
1099 FT_Render_Mode
& render_mode
= FTInfo
.render_mode
;
1100 FTC_ImageTypeRec
& font_type
= FTInfo
.font_type
;
1102 FreeTypeFontInfo
* pfi
= g_pFTEngine
->FindFont((int)face_id
);
1106 const CFontSettings
* pfs
= &pfi
->GetFontSettings();
1110 const CGdippSettings
* pSettings
= CGdippSettings::GetInstance();
1112 /*FT_Size_RequestRec size_request;
1113 size_request.width = lf.lfWidth;
1114 size_request.horiResolution = 0;
1115 size_request.vertResolution = 0;
1116 if(lf.lfHeight > 0){
1118 size_request.type = FT_SIZE_REQUEST_TYPE_CELL;
1119 size_request.height = lf.lfHeight * 64;
1123 size_request.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
1124 size_request.height = (-lf.lfHeight) * 64;
1126 if(FT_Request_Size(freetype_face, &size_request))
1129 switch (pSettings
->FontLoader()) {
1130 case SETTING_FONTLOADER_FREETYPE
:
1132 font_type
.face_id
= face_id
;
1133 font_type
.width
= freetype_face
->size
->metrics
.x_ppem
;
1134 font_type
.height
= freetype_face
->size
->metrics
.y_ppem
;
1136 /* ƒrƒbƒgƒ}ƒbƒv‚܂ŃLƒƒƒbƒVƒ…‚·‚é�ê�‡‚ÍFT_LOAD_RENDER | FT_LOAD_TARGET_*
1137 * ‚Æ‚·‚é�B‚½‚¾‚µ“r’†‚ÅTARGET‚ð•Ï�X‚µ‚½�ê�‡“™‚̓LƒƒƒbƒVƒ…‚ªŽ×–‚‚·‚é�B
1138 * ‚»‚¤‚¢‚¤Žž‚ÍFT_LOAD_DEFAULT‚É‚µ‚ÄFTC_ImageCache_LookupŒã‚É
1139 * FT_Glyph_To_Bitmap‚µ‚½‚Ù‚¤‚ª“s�‡‚ª‚¢‚¢‚ÆŽv‚¤�B
1141 // Bold‚Í‘¾‚è‹ï�‡‚Æ‚¢‚¤‚à‚Ì‚ª‚ ‚é‚Ì‚Å–{“–‚Í‚±‚ꂾ‚¯‚Å‚Í‘«‚è‚È‚¢‹C‚ª‚·‚é�B
1142 /*if(IsFontBold(lf) && !(freetype_face->style_flags & FT_STYLE_FLAG_BOLD) ||
1143 lf.lfItalic && !(freetype_face->style_flags & FT_STYLE_FLAG_ITALIC)){
1144 // ƒ{�[ƒ‹ƒh�AƒCƒ^ƒŠƒbƒN‚ÍŒã‚ŃŒƒ“ƒ_ƒŠƒ“ƒO‚·‚é
1145 // ‘½�‘¬“x‚Í—ò‰»‚·‚邾‚낤‚¯‚ÇŽd•û‚È‚¢�B
1146 font_type.flags = FT_LOAD_NO_BITMAP;
1149 font_type.flags = FT_LOAD_RENDER | FT_LOAD_NO_BITMAP;
1152 case SETTING_FONTLOADER_WIN32
:
1153 font_type
.face_id
= (FTC_FaceID
) - 1;
1154 font_type
.width
= -1;
1155 font_type
.height
= -1;
1158 DEFAULT_UNREACHABLE
;
1160 font_type
.flags
= FT_LOAD_NO_BITMAP
| FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH
;
1163 switch (pfs
->GetHintingMode()) {
1168 font_type
.flags
|= FT_LOAD_NO_HINTING
;
1171 font_type
.flags
|= FT_LOAD_FORCE_AUTOHINT
;
1175 if (FTInfo
.IsMono()) {
1176 font_type
.flags
|= FT_LOAD_TARGET_MONO
;
1177 render_mode
= FT_RENDER_MODE_MONO
;
1179 switch (pfs
->GetAntiAliasMode()) {
1181 font_type
.flags
|= FT_LOAD_TARGET_MONO
;
1182 render_mode
= FT_RENDER_MODE_MONO
;
1185 font_type
.flags
|= FT_LOAD_TARGET_NORMAL
;
1186 render_mode
= FT_RENDER_MODE_NORMAL
;
1189 font_type
.flags
|= FT_LOAD_TARGET_LIGHT
;
1190 render_mode
= FT_RENDER_MODE_LIGHT
;
1194 font_type
.flags
|= FT_LOAD_TARGET_LCD
;
1195 render_mode
= FT_RENDER_MODE_LCD
;
1199 font_type
.flags
|= FT_LOAD_TARGET_LIGHT
;
1200 render_mode
= FT_RENDER_MODE_LCD
;
1205 FTInfo
.useKerning
= FALSE
;
1206 if (pfs
->GetKerning()) {
1207 switch (pSettings
->FontLoader()) {
1208 case SETTING_FONTLOADER_FREETYPE
:
1209 FTInfo
.useKerning
= !!FT_HAS_KERNING(freetype_face
);
1211 case SETTING_FONTLOADER_WIN32
:
1213 DWORD rc
= GetFontLanguageInfo(FTInfo
.hdc
);
1214 if (rc
!= GCP_ERROR
) {
1215 FTInfo
.useKerning
= !!(rc
& GCP_USEKERNING
);
1216 FTInfo
.ggokerning
.init(FTInfo
.hdc
);
1221 DEFAULT_UNREACHABLE
;
1227 // �c‚É‚·‚é‚â‚‚Ítrue(ASCII‚Æ”¼ŠpƒJƒi‚Ífalse)
1228 inline bool IsVerticalChar(WCHAR wch
){
1231 if(0xFF61 <= wch
&& wch
<= 0xFF9F)
1233 // –{“–‚Í‚à‚Á‚Æ�^–Ê–Ú‚É‚â‚ç‚È‚¢‚Æ‚Ü‚¸‚¢‚ª�B
1242 CGGOFont(HDC hdc
, const LOGFONT
& olf
) : m_hdc(hdc
), m_hfont(NULL
), m_hprevfont(NULL
) {
1244 lf
.lfWeight
= FW_REGULAR
;
1245 lf
.lfItalic
= FALSE
;
1246 lf
.lfStrikeOut
= FALSE
;
1247 m_hfont
= CreateFontIndirect(&lf
);
1251 SelectFont(m_hdc
, m_hprevfont
);
1253 DeleteFont(m_hfont
);
1256 m_hprevfont
= SelectFont(m_hdc
, m_hfont
);
1259 SelectFont(m_hdc
, m_hprevfont
);
1262 operator HFONT () { return m_hfont
; }
1271 ClpDx(const INT
*lpDx
, UINT etoOptions
) : p(lpDx
), step((etoOptions
& ETO_PDY
) ? 2 : 1) {
1287 BOOL
ForEachGetGlyph(FreeTypeDrawInfo
& FTInfo
, LPCTSTR lpString
, int cbString
, BOOL (CALLBACK
*pfnCallback
)(FreeTypeDrawInfo
&, const WCHAR wch
, const FT_BitmapGlyph
))
1289 const CGdippSettings
* pSettings
= CGdippSettings::GetInstance();
1290 const FT_Face freetype_face
= FTInfo
.freetype_face
;
1291 const FT_Bool useKerning
= FTInfo
.useKerning
;
1292 FT_Render_Mode render_mode
= FTInfo
.render_mode
;
1293 const int AAMode
= FTInfo
.pfs
->GetAntiAliasMode();
1294 const LOGFONTW
& lf
= FTInfo
.LogFont();
1295 FreeTypeFontCache
* pftCache
= FTInfo
.pftCache
;
1296 const bool bGlyphIndex
= FTInfo
.IsGlyphIndex();
1297 const bool bSizeOnly
= FTInfo
.IsSizeOnly();
1298 //const bool bOwnCache = !(FTInfo.font_type.flags & FT_LOAD_RENDER);
1299 const LPCTSTR lpStart
= lpString
;
1300 const LPCTSTR lpEnd
= lpString
+ cbString
;
1301 FT_UInt previous
= 0;
1302 WCHAR previouswch
= 0;
1303 const bool bVertical
= lf
.lfFaceName
[0] == _T('@');
1304 const bool bLcdMode
= render_mode
== FT_RENDER_MODE_LCD
;
1305 const bool bLightLcdMode
= (AAMode
== 4) || (AAMode
== 5);
1306 ClpDx
clpdx(FTInfo
.lpDx
, FTInfo
.params
.etoOptions
);
1307 const bool bWidthGDI32
= pSettings
->WidthMode() == SETTING_WIDTHMODE_GDI32
;
1308 const int ggoformatbase
= (FTInfo
.font_type
.flags
& FT_LOAD_NO_HINTING
) ? GGO_UNHINTED
| GGO_NATIVE
: GGO_NATIVE
;
1310 if (!s_GGOGlyphLoader
.init(freetype_library
)) {
1314 for ( ; lpString
< lpEnd
; ++lpString
){
1315 const WCHAR wch
= *lpString
;
1318 if (!ORIG_GetCharWidth32W(FTInfo
.hdc
, wch
, wch
, &gdi32x
)) return FALSE
;
1320 FTInfo
.font_type
.face_id
= FTInfo
.face_id_list
[0];
1322 FreeTypeCharData
* chData
= NULL
;
1323 FT_BitmapGlyph glyph_bitmap
= NULL
;
1324 FT_Glyph copy_glyph
= NULL
;
1325 FT_UInt glyph_index
= 0;
1327 //if (bSizeOnly || bOwnCache) {
1328 chData
= bGlyphIndex
1329 ? pftCache
->FindGlyphIndex(wch
)
1330 : pftCache
->FindChar(wch
);
1335 int cx
= chData
->GetWidth();
1336 FTInfo
.x
+= (bWidthGDI32
? gdi32x
: cx
) + FTInfo
.params
.charExtra
;
1339 glyph_bitmap
= (FT_BitmapGlyph
)chData
->GetGlyph(render_mode
);
1341 if (!glyph_bitmap
) {
1342 FT_Glyph glyph
= NULL
;
1344 // �‡�¬‚âBMPŠO‚Ì•¶Žš‚ÍUniscribe‚ª�ˆ—�‚·‚é‚Ì‚Å‚±‚±‚Å�l—¶‚·‚é•K—v‚Í‚È‚¢�B
1345 bool f_glyph
= false;
1347 const MAT2 mat2
= {{0, 1}, {0, 0}, {0, 0}, {0, 1}};
1348 UINT ggoformat
= ggoformatbase
;
1349 CTempMem
<PVOID
> ggobuf
;
1350 DWORD outlinesize
= 0;
1352 switch (pSettings
->FontLoader()) {
1353 case SETTING_FONTLOADER_FREETYPE
:
1358 for (int i
= 0; i
< FTInfo
.face_id_list_num
; ++i
) {
1359 if (-1 == FTInfo
.cmap_list
[i
]) {
1361 if(FTC_Manager_LookupFace(cache_man
, FTInfo
.face_id_list
[i
], &temp_face
))
1363 FTInfo
.cmap_list
[i
] = FT_Get_Charmap_Index(temp_face
->charmap
);
1366 glyph_index
= FTC_CMapCache_Lookup(
1368 FTInfo
.face_id_list
[i
],
1369 FTInfo
.cmap_list
[i
],
1371 if (glyph_index
!= 0) {
1373 FTInfo
.font_type
.face_id
= FTInfo
.face_id_list
[i
];
1374 FreeTypeSetDrawSettings(FTInfo
, FTInfo
.font_type
.face_id
);
1380 case SETTING_FONTLOADER_WIN32
:
1384 ggoformat
|= GGO_GLYPH_INDEX
;
1386 // ƒOƒŠƒtƒCƒ“ƒfƒbƒNƒXŽæ“¾
1388 if (GetGlyphIndices(FTInfo
.hdc
, &wch
, 1, &gi
, GGI_MARK_NONEXISTING_GLYPHS
) == 1) {
1395 if (lpString
== lpStart
&& FTInfo
.font_type
.flags
& FT_LOAD_FORCE_AUTOHINT
) {
1396 // FORCE_AUTOHINT ‚ÆŠÖŒW‚È‚¢•¶Žš‰»‚¯‘Î�ô
1397 GetGlyphOutline(FTInfo
.hdc
, 0, GGO_METRICS
| GGO_GLYPH_INDEX
| GGO_NATIVE
| GGO_UNHINTED
, &gm
, 0, NULL
, &mat2
);
1399 outlinesize
= GetGlyphOutline(FTInfo
.hdc
, wch
, ggoformat
, &gm
, ggobuf
.getsize(), ggobuf
, &mat2
);
1400 if (outlinesize
== GDI_ERROR
|| outlinesize
== 0) {
1404 // ƒOƒŠƒtƒCƒ“ƒfƒbƒNƒX‚ªŽæ‚ê‚È‚¢‚̂ɃAƒEƒgƒ‰ƒCƒ“‚ªŽæ‚ꂽ
1415 if (wch
&& FTInfo
.params
.alpha
== 1) {
1416 ORIG_ExtTextOutW(FTInfo
.hdc
, FTInfo
.x
, FTInfo
.yTop
, FTInfo
.GetETO(), NULL
, &wch
, 1, NULL
);
1418 if (lpString
< lpEnd
- 1) {
1419 FTInfo
.x
+= clpdx
.get(cx
);
1421 ABC abc
= {0, gdi32x
, 0};
1422 GetCharABCWidths(FTInfo
.hdc
, wch
, wch
, &abc
);
1423 FTInfo
.x
+= Max(clpdx
.get(cx
), abc
.abcA
+ (int)abc
.abcB
);
1426 FTInfo
.x
+= FTInfo
.params
.charExtra
;
1430 switch (pSettings
->FontLoader()) {
1431 case SETTING_FONTLOADER_FREETYPE
:
1434 glyph_index
= ft2vert_get_gid(
1435 (struct ft2vert_st
*)freetype_face
->generic
.data
,
1441 if(previous
!= 0 && glyph_index
){
1443 FT_Get_Kerning(freetype_face
,
1444 previous
, glyph_index
,
1445 ft_kerning_default
, &delta
);
1446 FTInfo
.x
+= FT_PosToInt(delta
.x
);
1448 previous
= glyph_index
;
1451 case SETTING_FONTLOADER_WIN32
:
1452 if(useKerning
&& !bGlyphIndex
){
1453 if (previouswch
&& wch
) {
1454 FTInfo
.x
+= FTInfo
.ggokerning
.get(previouswch
, wch
);
1462 if(bVertical
&& IsVerticalChar(wch
)){
1463 FTInfo
.font_type
.flags
|= FT_LOAD_VERTICAL_LAYOUT
;
1466 FTInfo
.font_type
.flags
&= ~FT_LOAD_TARGET_LCD
;
1467 FTInfo
.font_type
.flags
|= FT_LOAD_TARGET_LCD_V
;
1469 render_mode
= FT_RENDER_MODE_LCD_V
;
1472 FTInfo
.font_type
.flags
&=~FT_LOAD_VERTICAL_LAYOUT
;
1475 FTInfo
.font_type
.flags
&= ~FT_LOAD_TARGET_LCD_V
;
1476 FTInfo
.font_type
.flags
|= FT_LOAD_TARGET_LCD
;
1478 render_mode
= FT_RENDER_MODE_LCD
;
1482 CGGOOutlineGlyph ggoog
;
1483 switch (pSettings
->FontLoader()) {
1484 case SETTING_FONTLOADER_FREETYPE
:
1485 if(FTC_ImageCache_Lookup(
1494 case SETTING_FONTLOADER_WIN32
:
1495 if (outlinesize
> ggobuf
.getsize()) {
1496 if (!ggobuf
.init(outlinesize
)) {
1500 outlinesize
= GetGlyphOutline(FTInfo
.hdc
, wch
, ggoformat
, &gm
, ggobuf
.getsize(), ggobuf
, &mat2
);
1501 //ggofont.restore();
1503 if (outlinesize
> ggobuf
.getsize()) {
1506 if (!ggoog
.init(outlinesize
, ggobuf
, gm
)) {
1512 /* font_type.flags‚ÅFT_LOAD_RENDER‚ð‘I‘ð‚µ‚È‚¢‚Æ
1513 * ƒOƒŠƒtƒCƒ��[ƒW‚ðŽæ“¾‚µ‚Ä‚‚é‚̂Ńrƒbƒgƒ}ƒbƒv‚É•ÏŠ·‚·‚é�B
1515 if(glyph
->format
== FT_GLYPH_FORMAT_BITMAP
){
1516 glyph_bitmap
= (FT_BitmapGlyph
)glyph
;
1519 //FT_Glyph copy_glyph = NULL;
1520 if(FT_Glyph_Copy(glyph
, ©_glyph
))
1523 // ƒAƒEƒgƒ‰ƒCƒ“‚ð•ÏŒ`‚³‚¹‚é(�ã‹LƒTƒCƒg‚©‚ç)�B
1527 str_h
= str_v
= FTInfo
.pfi
->CalcNormalWeight();
1528 if (IsFontBold(lf
) &&
1529 pSettings
->FontLoader() == SETTING_FONTLOADER_FREETYPE
&&
1530 !(freetype_face
->style_flags
& FT_STYLE_FLAG_BOLD
)) {
1532 str_h
= FTInfo
.pfi
->GetFTWeight();
1534 if((str_h
|| str_v
) && New_FT_Outline_Embolden(
1535 &((FT_OutlineGlyph
)copy_glyph
)->outline
,
1538 FT_Done_Glyph(copy_glyph
);
1539 return FALSE
; // •ÏŠ·Ž¸”s
1541 /*if (copy_glyph->advance.x) {
1543 matrix.xx = (1 << 16) + (0x80000000 / (copy_glyph->advance.x >> 1));
1546 matrix.yy = 1 << 16;
1547 FT_Outline_Transform(
1548 &((FT_OutlineGlyph)copy_glyph)->outline,
1552 ((FT_BitmapGlyph
)copy_glyph
)->root
.advance
.x
+= 0x10000;
1555 pSettings
->FontLoader() == SETTING_FONTLOADER_FREETYPE
&&
1556 !(freetype_face
->style_flags
& FT_STYLE_FLAG_ITALIC
)){
1560 FTInfo
.pfi
->CalcItalicSlant(matrix
);
1561 FT_Outline_Transform(
1562 &((FT_OutlineGlyph
)copy_glyph
)->outline
,
1566 //// •¶Žš‚Ì•�‚ðGDI32‚É�‡‚킹‚é
1567 //FT_Fixed& ftx = (bVertical && IsVerticalChar(wch)) ?
1568 // copy_glyph->advance.y : copy_glyph->advance.x;
1569 //FT_Fixed targetx = gdi32x << 16;
1570 //if (ftx != targetx) {
1571 // if (ftx > targetx) {
1572 // // ‘å‚«‚¢‚Ȃ當Žš�k�¬ (�¬‚³‚‚Ä‚àŠg‘å‚Í‚µ‚È‚¢)
1573 // FT_Matrix matrix = {FT_DivFix(targetx, ftx) , 0, 0, 1 << 16};
1574 // FT_Outline_Transform(&((FT_OutlineGlyph)copy_glyph)->outline, &matrix);
1577 // ftx = targetx; // ‘å‚«‚‚Ä‚à�¬‚³‚‚Ä‚àƒTƒCƒY‚ ‚킹
1580 /* FT_RENDER_MODE_NORMAL‚Å•�’Ê‚Ì(256ŠK’²)ƒAƒ“ƒ`ƒGƒCƒŠƒAƒX
1581 * FT_RENDER_MODE_LCD‚ʼnt�»—pƒAƒ“ƒ`ƒGƒCƒŠƒAƒX(ƒTƒuƒsƒNƒZƒ‹ƒŒƒ“ƒ_ƒŠƒ“ƒO)
1584 if(FT_Glyph_To_Bitmap(©_glyph
, render_mode
, 0, 1)){
1585 FT_Done_Glyph(copy_glyph
);
1588 glyph_bitmap
= (FT_BitmapGlyph
)copy_glyph
;
1592 int cx
= (bVertical
&& IsVerticalChar(wch
)) ?
1593 FT_FixedToInt(glyph_bitmap
->root
.advance
.y
) :
1594 FT_FixedToInt(glyph_bitmap
->root
.advance
.x
);
1595 pfnCallback(FTInfo
, wch
, glyph_bitmap
);
1597 FTInfo
.x
+= bWidthGDI32
? gdi32x
: cx
;
1599 int dx
= clpdx
.get(bWidthGDI32
? gdi32x
: cx
);
1600 if (lpString
< lpEnd
- 1) {
1603 int bx
= glyph_bitmap
->bitmap
.width
;
1604 if (render_mode
== FT_RENDER_MODE_LCD
) bx
/= 3;
1605 bx
+= glyph_bitmap
->left
;
1606 FTInfo
.x
+= Max(Max(dx
, bx
), cx
);
1609 FTInfo
.x
+= FTInfo
.params
.charExtra
;
1611 //if (bSizeOnly || bOwnCache) {
1615 pftCache
->AddGlyphData(glyph_index
, cx
, glyph_bitmap
, render_mode
);
1617 pftCache
->AddCharData(wch
, glyph_index
, cx
, glyph_bitmap
, render_mode
);
1623 FT_Done_Glyph(copy_glyph
);
1629 BOOL
GetLogFontFromDC(HDC hdc
, LOGFONT
& lf
)
1631 LOGFONTW lfForce
= { 0 };
1632 HFONT hf
= GetCurrentFont(hdc
);
1633 if (!GetObject(hf
, sizeof(LOGFONTW
), &lf
))
1636 const CGdippSettings
* pSettings
= CGdippSettings::GetInstance();
1637 if (pSettings
->CopyForceFont(lfForce
, lf
))
1640 if(pSettings
->LoadOnDemand()) {
1641 AddFontToFT(lf
.lfFaceName
, lf
.lfWeight
, !!lf
.lfItalic
);
1646 BOOL CALLBACK
TextOutCallback(FreeTypeDrawInfo
& FTInfo
, const WCHAR wch
, const FT_BitmapGlyph glyph_bitmap
)
1648 const bool bVertical
= FTInfo
.LogFont().lfFaceName
[0] == _T('@');
1650 if (!glyph_bitmap
->bitmap
.buffer
) {
1651 if (FTInfo
.params
.alpha
== 1) {
1652 ORIG_ExtTextOutW(FTInfo
.hdc
, FTInfo
.x
, FTInfo
.yTop
, FTInfo
.GetETO(), NULL
, &wch
, 1, NULL
);
1655 const CGdippSettings
* pSettings
= CGdippSettings::GetInstance();
1656 if (bVertical
&& IsVerticalChar(wch
) &&
1657 pSettings
->FontLoader() == SETTING_FONTLOADER_FREETYPE
) {
1658 FreeTypeDrawBitmapV(*FTInfo
.pCache
,
1659 &glyph_bitmap
->bitmap
,
1660 FTInfo
.x
+ FTInfo
.yBase
- glyph_bitmap
->top
,
1661 FTInfo
.yTop
+ FT_PosToInt(FTInfo
.freetype_face
->size
->metrics
.height
) -
1662 (glyph_bitmap
->left
+glyph_bitmap
->bitmap
.width
) - 1,
1665 FreeTypeDrawBitmap(*FTInfo
.pCache
,
1666 &glyph_bitmap
->bitmap
,
1667 FTInfo
.x
+ glyph_bitmap
->left
,
1668 FTInfo
.yBase
- glyph_bitmap
->top
,
1673 //if (FTInfo.lpDx) {
1674 // FTInfo.x += *FTInfo.lpDx++;
1680 BOOL CALLBACK
GetTextExtentCallback(FreeTypeDrawInfo
& /*FTInfo*/, const WCHAR
/*wch*/, const FT_BitmapGlyph
/*glyph_bitmap*/)
1685 // FreeType‚ð—p‚¢‚½TextOut API‚à‚Ç‚«
1686 BOOL
FreeTypeTextOut(
1687 const HDC hdc
, // ƒfƒoƒCƒXƒRƒ“ƒeƒLƒXƒg‚̃nƒ“ƒhƒ‹
1688 CBitmapCache
& cache
,
1689 const int nXStart
, // ŠJŽnˆÊ’u�iŠî�€“_�j‚Ì x �À•W
1690 const int nYStart
, // ŠJŽnˆÊ’u�iŠî�€“_�j‚Ì y �À•W
1691 LPCWSTR lpString
, // •¶Žš—ñ
1692 int cbString
, // •¶Žš�”
1693 const int* lpDx
, // •`‰æˆÊ’u
1694 const FREETYPE_PARAMS
* params
,
1698 CCriticalSectionLock __lock
;
1700 // Unicode‚Å“n‚·‚悤‚É‚·‚é(FT_Select_Charmap‚Å•Ï�X‰Â”\)
1701 if(cbString
<= 0 || lpString
== NULL
)
1704 LOGFONTW
* lplf
= NULL
;
1705 LOGFONTW lfForce
= { 0 };
1706 const CGdippSettings
* pSettings
= CGdippSettings::GetInstance();
1707 if (!(params
->etoOptions
& ETO_GLYPH_INDEX
))
1709 if (pSettings
->CopyForceFont(lfForce
, *params
->lplf
))
1713 FreeTypeDrawInfo
FTInfo(*params
, hdc
, lplf
, &cache
, lpDx
);
1714 if(!FreeTypePrepare(FTInfo
))
1717 FT_Face freetype_face
= FTInfo
.freetype_face
;
1718 const LOGFONT
& lf
= FTInfo
.LogFont();
1721 FTInfo
.yTop
= nYStart
;
1723 const TEXTMETRIC
& tm
= FTInfo
.pftCache
->GetTextMetric(hdc
);
1724 FTInfo
.yBase
= nYStart
+ tm
.tmAscent
;
1725 if(!ForEachGetGlyph(FTInfo
, lpString
, cbString
, TextOutCallback
))
1729 const int x
= FTInfo
.x
;
1730 const int y
= FTInfo
.yBase
;
1732 // ‰º�ü‚ð(‚ ‚ê‚Î)ˆø‚
1733 if(lf
.lfUnderline
|| lf
.lfStrikeOut
) {
1734 OUTLINETEXTMETRIC otm
= { sizeof(OUTLINETEXTMETRIC
) };
1735 GetOutlineTextMetrics(hdc
, otm
.otmSize
, &otm
);
1737 int yPos
= 0; //‰º�ü‚̈ʒu
1739 int thickness
= 0; // “K“–‚È‘¾‚³
1740 switch (pSettings
->FontLoader()) {
1741 case SETTING_FONTLOADER_FREETYPE
:
1743 height
= FT_PosToInt(freetype_face
->size
->metrics
.height
);
1745 FT_MulDiv(freetype_face
->underline_thickness
,
1746 freetype_face
->size
->metrics
.y_ppem
,
1747 freetype_face
->units_per_EM
);
1749 case SETTING_FONTLOADER_WIN32
:
1750 yPos
= y
- otm
.otmsUnderscorePosition
;
1751 height
= otm
.otmTextMetrics
.tmHeight
;
1752 thickness
= otm
.otmsUnderscoreSize
;
1755 if (yPos
>= height
) {
1758 cache
.DrawHorizontalLine(nXStart
, yPos
, x
, FTInfo
.Color(), thickness
);
1761 // Žæ�Á�ü‚ð(‚ ‚ê‚Î)ˆø‚
1763 // Žæ�Á�ü‚̈ʒu(FreeType‚Ŏ擾‚Å‚«‚»‚¤‚É‚È‚¢‚Ì‚ÅWin32API—˜—p)
1764 int yPos
= y
- otm
.otmsStrikeoutPosition
; //Žæ�Á�ü‚̈ʒu
1765 int thickness
= 0; // “K“–‚È‘¾‚³
1766 switch (pSettings
->FontLoader()) {
1767 case SETTING_FONTLOADER_FREETYPE
:
1769 MulDiv(freetype_face
->underline_thickness
,
1770 freetype_face
->size
->metrics
.y_ppem
,
1771 freetype_face
->units_per_EM
);
1773 case SETTING_FONTLOADER_WIN32
:
1774 thickness
= otm
.otmsStrikeoutSize
;
1777 cache
.DrawHorizontalLine(nXStart
, yPos
, x
, FTInfo
.Color(), thickness
);
1781 //PatBlt(hdc, 0, y, 9999, y + 1, DSTINVERT);
1782 //PatBlt(hdc, 0, 0, 9999, 0 + 1, DSTINVERT);
1786 BOOL
FreeTypeGetTextExtentPoint(
1791 const FREETYPE_PARAMS
* params
1795 * FIXME: there should be a replaced version of GetTextExtentPointI for WidthMode=1
1796 * but there isn't now, so we call the original one when GLYPH_INDEX is specified
1797 * and obviously calling GetTextExtentPoint32W in this circumstance is wrong
1799 if (params
->etoOptions
& ETO_GLYPH_INDEX
)
1800 return GetTextExtentPointI(hdc
, (LPWORD
)lpString
, cbString
, lpSize
);
1802 const CGdippSettings
* pSettings
= CGdippSettings::GetInstance();
1803 if (pSettings
->WidthMode() == SETTING_WIDTHMODE_GDI32
) {
1804 return ORIG_GetTextExtentPoint32W(hdc
, lpString
, cbString
, lpSize
);
1807 CCriticalSectionLock __lock
;
1811 lpSize
->cx
= lpSize
->cy
= 0;
1814 // Unicode‚Å“n‚·‚悤‚É‚·‚é(FT_Select_Charmap‚Å•Ï�X‰Â”\)
1815 if(cbString
<= 0 || lpString
== NULL
|| lpSize
== NULL
) {
1819 Assert(params
!= NULL
);
1821 if (!GetLogFontFromDC(hdc
, lf
))
1824 FreeTypeDrawInfo
FTInfo(*params
, hdc
, &lf
);
1825 if(!FreeTypePrepare(FTInfo
))
1829 if(!ForEachGetGlyph(FTInfo
, lpString
, cbString
, GetTextExtentCallback
)) {
1835 lpSize
->cx
= FTInfo
.x
;
1836 lpSize
->cy
= FTInfo
.pftCache
->GetTextMetric(hdc
).tmHeight
;
1840 BOOL
FreeTypeGetCharWidth(const HDC hdc
, UINT iFirstChar
, UINT iLastChar
, LPINT lpBuffer
)
1842 const CGdippSettings
* pSettings
= CGdippSettings::GetInstance();
1843 if (pSettings
->WidthMode() == SETTING_WIDTHMODE_GDI32
) {
1844 return ORIG_GetCharWidth32W(hdc
, iFirstChar
, iLastChar
, lpBuffer
);
1847 CCriticalSectionLock __lock
;
1849 if (!lpBuffer
|| iFirstChar
> iLastChar
|| iFirstChar
> 0xffff || iLastChar
> 0xffff) {
1850 SetLastError(ERROR_INVALID_PARAMETER
);
1855 ZeroMemory(lpBuffer
, sizeof(INT
) * (iLastChar
- iFirstChar
));
1858 if (!GetLogFontFromDC(hdc
, lf
))
1861 FREETYPE_PARAMS
params(0, hdc
);
1862 FreeTypeDrawInfo
FTInfo(params
, hdc
, &lf
);
1863 if(!FreeTypePrepare(FTInfo
))
1866 WCHAR wch
= (WORD
)iFirstChar
;
1867 const WCHAR wend
= (WORD
)iLastChar
;
1869 while (wch
<= wend
) {
1871 if(!ForEachGetGlyph(FTInfo
, &wch
, 1, GetTextExtentCallback
))
1873 *lpBuffer
++ = FTInfo
.x
;
1879 void VertFinalizer(void *object
){
1880 FT_Face face
= (FT_Face
)object
;
1881 ft2vert_final(face
, (struct ft2vert_st
*)face
->generic
.data
);
1884 FT_Error
face_requester(
1886 FT_Library
/*library*/,
1887 FT_Pointer
/*request_data*/,
1893 FreeTypeFontInfo
* pfi
= g_pFTEngine
->FindFont((int)face_id
);
1896 return FT_Err_Invalid_Argument
;
1898 LPCTSTR fontname
= pfi
->GetName();
1900 // –¼�Ì‚ðŽw’肵‚ătƒHƒ“ƒg‚ðŽæ“¾
1901 FreeTypeSysFontData
* pData
= FreeTypeSysFontData::CreateInstance(fontname
, pfi
->GetFontWeight(), pfi
->IsItalic());
1903 return FT_Err_Cannot_Open_Resource
;
1906 face
= pData
->GetFace();
1907 Assert(face
!= NULL
);
1909 // Charmap‚ð�ݒ肵‚Ä‚¨‚
1910 ret
= FT_Select_Charmap(face
, FT_ENCODING_UNICODE
);
1911 if(ret
!= FT_Err_Ok
){
1912 ret
= FT_Select_Charmap(face
, FT_ENCODING_MS_SYMBOL
);
1913 if(ret
!= FT_Err_Ok
)
1920 if(fontname
[0] == _T('@')){
1921 struct ft2vert_st
*vert
= ft2vert_init(face
);
1922 face
->generic
.data
= vert
;
1923 face
->generic
.finalizer
= VertFinalizer
;
1926 // ƒOƒŠƒt’uŠ·‚Ì‚½‚ß�í‚É•K—v
1927 struct ft2vert_st
*vert
= ft2vert_init(face
);
1928 face
->generic
.data
= vert
;
1929 face
->generic
.finalizer
= VertFinalizer
;
1937 DWORD FreeTypeGetVersion()
1939 int major = 0, minor = 0, patch = 0;
1940 FT_Library_Version(freetype_library, &major, &minor, &patch);
1941 //–Ê“|‚È‚Ì‚ÅRGBƒ}ƒNƒ�Žg—p
1942 return RGB(major, minor, patch);
1946 //�V‘¾ŽšƒAƒ‹ƒSƒŠƒYƒ€
1947 FT_Error
New_FT_Outline_Embolden( FT_Outline
* outline
, FT_Pos str_h
, FT_Pos str_v
)
1949 const CGdippSettings
* pSettings
= CGdippSettings::GetInstance();
1950 int orientation
= 0;
1951 switch (pSettings
->BolderMode()) {
1953 return Old_FT_Outline_Embolden( outline
, str_h
);
1956 return FT_Outline_Embolden( outline
, str_h
);
1960 if ( !outline
) return FT_Err_Invalid_Argument
;
1961 orientation
= FT_Outline_Get_Orientation( outline
);
1962 if ( orientation
== FT_ORIENTATION_NONE
)
1963 if ( outline
->n_contours
) return FT_Err_Invalid_Argument
;
1964 Vert_FT_Outline_Embolden( outline
, str_v
);
1965 Old_FT_Outline_Embolden( outline
, str_h
);
1971 //‰¡•ûŒü‚¾‚¯‘¾‚点‚éFT_Outline_Embolden
1972 FT_Error
Old_FT_Outline_Embolden( FT_Outline
* outline
, FT_Pos strength
)
1975 FT_Vector v_prev
, v_first
, v_next
, v_cur
;
1976 FT_Angle rotate
, angle_in
, angle_out
;
1981 return FT_Err_Invalid_Argument
;
1984 if ( strength
== 0 )
1987 orientation
= FT_Outline_Get_Orientation( outline
);
1988 if ( orientation
== FT_ORIENTATION_NONE
)
1990 if ( outline
->n_contours
)
1991 return FT_Err_Invalid_Argument
;
1996 if ( orientation
== FT_ORIENTATION_TRUETYPE
)
1997 rotate
= -FT_ANGLE_PI2
;
1999 rotate
= FT_ANGLE_PI2
;
2001 points
= outline
->points
;
2004 for ( c
= 0; c
< outline
->n_contours
; c
++ )
2006 int last
= outline
->contours
[c
];
2008 v_first
= points
[first
];
2009 v_prev
= points
[last
];
2012 for ( n
= first
; n
<= last
; n
++ )
2015 FT_Angle angle_diff
;
2020 v_next
= points
[n
+ 1];
2024 /* compute the in and out vectors */
2025 in
.x
= v_cur
.x
- v_prev
.x
;
2026 in
.y
= v_cur
.y
- v_prev
.y
;
2028 out
.x
= v_next
.x
- v_cur
.x
;
2029 out
.y
= v_next
.y
- v_cur
.y
;
2031 angle_in
= FT_Atan2( in
.x
, in
.y
);
2032 angle_out
= FT_Atan2( out
.x
, out
.y
);
2033 angle_diff
= FT_Angle_Diff( angle_in
, angle_out
);
2034 scale
= FT_Cos( angle_diff
/ 2 );
2036 if ( scale
< 0x4000L
&& scale
> -0x4000L
)
2040 d
= FT_DivFix( strength
, scale
);
2042 FT_Vector_From_Polar( &in
, d
, angle_in
+ angle_diff
/ 2 - rotate
);
2045 outline
->points
[n
].x
= v_cur
.x
+ strength
+ in
.x
;
2046 //�«‚±‚ê‚ðƒRƒ�ƒ“ƒgƒAƒEƒg‚µ‚½‚¾‚¯
2047 //outline->points[n].y = v_cur.y + strength + in.y;
2060 FT_Error
Vert_FT_Outline_Embolden( FT_Outline
* outline
, FT_Pos strength
)
2063 FT_Vector v_prev
, v_first
, v_next
, v_cur
;
2064 FT_Angle rotate
, angle_in
, angle_out
;
2069 return FT_Err_Invalid_Argument
;
2072 if ( strength
== 0 )
2075 orientation
= FT_Outline_Get_Orientation( outline
);
2076 if ( orientation
== FT_ORIENTATION_NONE
)
2078 if ( outline
->n_contours
)
2079 return FT_Err_Invalid_Argument
;
2084 if ( orientation
== FT_ORIENTATION_TRUETYPE
)
2085 rotate
= -FT_ANGLE_PI2
;
2087 rotate
= FT_ANGLE_PI2
;
2089 points
= outline
->points
;
2092 for ( c
= 0; c
< outline
->n_contours
; c
++ )
2094 int last
= outline
->contours
[c
];
2096 v_first
= points
[first
];
2097 v_prev
= points
[last
];
2100 for ( n
= first
; n
<= last
; n
++ )
2103 FT_Angle angle_diff
;
2108 v_next
= points
[n
+ 1];
2112 /* compute the in and out vectors */
2113 in
.x
= v_cur
.x
- v_prev
.x
;
2114 in
.y
= v_cur
.y
- v_prev
.y
;
2116 out
.x
= v_next
.x
- v_cur
.x
;
2117 out
.y
= v_next
.y
- v_cur
.y
;
2119 angle_in
= FT_Atan2( in
.x
, in
.y
);
2120 angle_out
= FT_Atan2( out
.x
, out
.y
);
2121 angle_diff
= FT_Angle_Diff( angle_in
, angle_out
);
2122 scale
= FT_Cos( angle_diff
/ 2 );
2124 if ( scale
< 0x4000L
&& scale
> -0x4000L
)
2128 d
= FT_DivFix( strength
, scale
);
2130 FT_Vector_From_Polar( &in
, d
, angle_in
+ angle_diff
/ 2 - rotate
);
2133 //outline->points[n].x = v_cur.x + strength + in.x;
2134 //�ª‚±‚ê‚ðƒRƒ�ƒ“ƒgƒAƒEƒg‚µ‚½‚¾‚¯
2135 outline
->points
[n
].y
= v_cur
.y
+ strength
+ in
.y
;
2148 FT_EXPORT( FT_Error
)
2149 FT_Library_SetLcdFilter_Dummy( FT_Library
/*library*/,
2150 FT_LcdFilter
/*filter*/ )
2155 BOOL
FontLInit(void){
2156 CCriticalSectionLock __lock
;
2158 if(FT_Init_FreeType(&freetype_library
)){
2161 const CGdippSettings
* pSettings
= CGdippSettings::GetInstance();
2162 if(FTC_Manager_New(freetype_library
,
2163 pSettings
->CacheMaxFaces(),
2164 pSettings
->CacheMaxSizes(),
2165 pSettings
->CacheMaxBytes(),
2166 face_requester
, NULL
,
2172 if(FTC_CMapCache_New(cache_man
, &cmap_cache
)){
2176 if(FTC_ImageCache_New(cache_man
, &image_cache
)){
2181 const int nLcdFilter
= pSettings
->LcdFilter();
2182 if ((int)FT_LCD_FILTER_NONE
< nLcdFilter
&& nLcdFilter
< (int)FT_LCD_FILTER_MAX
) {
2183 FT_Library_SetLcdFilter(freetype_library
, (FT_LcdFilter
)nLcdFilter
);
2186 s_AlphaBlendTable
.init();
2190 void FontLFree(void){
2191 CCriticalSectionLock __lock
;
2193 if(cache_man
!= NULL
)
2194 FTC_Manager_Done(cache_man
);
2195 if(freetype_library
!= NULL
)
2196 FT_Done_FreeType(freetype_library
);
2198 freetype_library
= NULL
;