2 *******************************************************************************
4 * Copyright (C) 1999-2003, International Business Machines
5 * Corporation and others. All Rights Reserved.
7 *******************************************************************************
8 * file name: GDIFontInstance.cpp
10 * created on: 08/09/2000
11 * created by: Eric R. Mader
16 #include "layout/LETypes.h"
17 #include "layout/LESwaps.h"
18 #include "layout/LEFontInstance.h"
20 #include "GDIFontInstance.h"
24 GDISurface::GDISurface(HDC theHDC
)
25 : fHdc(theHDC
), fCurrentFont(NULL
)
30 GDISurface::~GDISurface()
35 void GDISurface::setHDC(HDC theHDC
)
41 void GDISurface::setFont(const GDIFontInstance
*font
)
44 if (fCurrentFont
!= font
) {
46 SelectObject(fHdc
, font
->getFont());
49 SelectObject(fHdc
, font
->getFont());
53 void GDISurface::drawGlyphs(const LEFontInstance
*font
, const LEGlyphID
*glyphs
, le_int32 count
, const float *positions
,
54 le_int32 x
, le_int32 y
, le_int32 width
, le_int32 height
)
56 TTGlyphID
*ttGlyphs
= LE_NEW_ARRAY(TTGlyphID
, count
);
57 le_int32
*dx
= LE_NEW_ARRAY(le_int32
, count
);
65 for (le_int32 g
= 0; g
< count
; g
+= 1) {
66 ttGlyphs
[g
] = (TTGlyphID
) LE_GET_GLYPH(glyphs
[g
]);
68 if (ttGlyphs
[g
] == 0xFFFF || ttGlyphs
[g
] == 0xFFFE) {
72 dx
[g
] = (le_int32
) (positions
[g
* 2 + 2] - positions
[g
* 2]);
75 le_int32 dyStart
, dyEnd
;
77 setFont((GDIFontInstance
*) font
);
81 while (dyEnd
< count
) {
82 float yOffset
= positions
[dyStart
* 2 + 1];
83 float xOffset
= positions
[dyStart
* 2];
85 while (dyEnd
< count
&& yOffset
== positions
[dyEnd
* 2 + 1]) {
89 ExtTextOut(fHdc
, x
+ (le_int32
) xOffset
, y
+ (le_int32
) yOffset
- font
->getAscent(), ETO_CLIPPED
| ETO_GLYPH_INDEX
, &clip
,
90 &ttGlyphs
[dyStart
], dyEnd
- dyStart
, (INT
*) &dx
[dyStart
]);
96 LE_DELETE_ARRAY(ttGlyphs
);
99 GDIFontInstance::GDIFontInstance(GDISurface
*surface
, TCHAR
*faceName
, le_int16 pointSize
, LEErrorCode
&status
)
100 : FontTableCache(), fSurface(surface
), fFont(NULL
),
101 fPointSize(pointSize
), fUnitsPerEM(0), fAscent(0), fDescent(0), fLeading(0),
102 fDeviceScaleX(1), fDeviceScaleY(1), fMapper(NULL
)
107 OUTLINETEXTMETRIC otm
;
108 HDC hdc
= surface
->getHDC();
110 if (LE_FAILURE(status
)) {
116 SetGraphicsMode(hdc
, GM_ADVANCED
);
117 ModifyWorldTransform(hdc
, NULL
, MWT_IDENTITY
);
118 SetViewportOrgEx(hdc
, 0, 0, NULL
);
119 SetWindowOrgEx(hdc
, 0, 0, NULL
);
121 dpiX
= (FLOAT
) GetDeviceCaps(hdc
, LOGPIXELSX
);
122 dpiY
= (FLOAT
) GetDeviceCaps(hdc
, LOGPIXELSY
);
125 pt
.x
= (int) (pointSize
* dpiX
/ 72);
126 pt
.y
= (int) (pointSize
* dpiY
/ 72);
130 pt
.x
= pt
.y
= pointSize
;
133 lf
.lfHeight
= - pt
.y
;
136 lf
.lfOrientation
= 0;
141 lf
.lfCharSet
= DEFAULT_CHARSET
;
142 lf
.lfOutPrecision
= 0;
143 lf
.lfClipPrecision
= 0;
145 lf
.lfPitchAndFamily
= 0;
147 lstrcpy(lf
.lfFaceName
, faceName
);
149 fFont
= CreateFontIndirect(&lf
);
152 status
= LE_FONT_FILE_NOT_FOUND_ERROR
;
156 SelectObject(hdc
, fFont
);
158 UINT ret
= GetOutlineTextMetrics(hdc
, sizeof otm
, &otm
);
161 status
= LE_MISSING_FONT_TABLE_ERROR
;
165 fUnitsPerEM
= otm
.otmEMSquare
;
166 fAscent
= otm
.otmTextMetrics
.tmAscent
;
167 fDescent
= otm
.otmTextMetrics
.tmDescent
;
168 fLeading
= otm
.otmTextMetrics
.tmExternalLeading
;
170 status
= initMapper();
172 if (LE_FAILURE(status
)) {
177 status
= initFontTableCache();
184 GDIFontInstance::GDIFontInstance(GDISurface
*surface
, const char *faceName
, le_int16 pointSize
, LEErrorCode
&status
)
185 : FontTableCache(), fSurface(surface
), fFont(NULL
),
186 fPointSize(pointSize
), fUnitsPerEM(0), fAscent(0), fDescent(0), fLeading(0),
187 fDeviceScaleX(1), fDeviceScaleY(1), fMapper(NULL
)
192 OUTLINETEXTMETRIC otm
;
193 HDC hdc
= surface
->getHDC();
195 if (LE_FAILURE(status
)) {
201 SetGraphicsMode(hdc
, GM_ADVANCED
);
202 ModifyWorldTransform(hdc
, NULL
, MWT_IDENTITY
);
203 SetViewportOrgEx(hdc
, 0, 0, NULL
);
204 SetWindowOrgEx(hdc
, 0, 0, NULL
);
206 dpiX
= (FLOAT
) GetDeviceCaps(hdc
, LOGPIXELSX
);
207 dpiY
= (FLOAT
) GetDeviceCaps(hdc
, LOGPIXELSY
);
209 fDeviceScaleX
= dpiX
/ 72;
210 fDeviceScaleY
= dpiY
/ 72;
213 pt
.x
= (int) (pointSize
* fDeviceScaleX
);
214 pt
.y
= (int) (pointSize
* fDeviceScaleY
);
218 pt
.x
= pt
.y
= pointSize
;
221 lf
.lfHeight
= - pt
.y
;
224 lf
.lfOrientation
= 0;
229 lf
.lfCharSet
= DEFAULT_CHARSET
;
230 lf
.lfOutPrecision
= 0;
231 lf
.lfClipPrecision
= 0;
233 lf
.lfPitchAndFamily
= 0;
235 strcpy(lf
.lfFaceName
, faceName
);
237 fFont
= CreateFontIndirectA(&lf
);
240 status
= LE_FONT_FILE_NOT_FOUND_ERROR
;
244 SelectObject(hdc
, fFont
);
246 UINT ret
= GetOutlineTextMetrics(hdc
, sizeof otm
, &otm
);
249 status
= LE_MISSING_FONT_TABLE_ERROR
;
253 fUnitsPerEM
= otm
.otmEMSquare
;
254 fAscent
= otm
.otmTextMetrics
.tmAscent
;
255 fDescent
= otm
.otmTextMetrics
.tmDescent
;
256 fLeading
= otm
.otmTextMetrics
.tmExternalLeading
;
258 status
= initMapper();
260 if (LE_FAILURE(status
)) {
265 status
= initFontTableCache();
272 GDIFontInstance::~GDIFontInstance()
275 flushFontTableCache();
276 delete[] fTableCache
;
280 // FIXME: call RemoveObject first?
288 LEErrorCode
GDIFontInstance::initMapper()
290 LETag cmapTag
= LE_CMAP_TABLE_TAG
;
291 const CMAPTable
*cmap
= (const CMAPTable
*) readFontTable(cmapTag
);
294 return LE_MISSING_FONT_TABLE_ERROR
;
297 fMapper
= CMAPMapper::createUnicodeMapper(cmap
);
299 if (fMapper
== NULL
) {
300 return LE_MISSING_FONT_TABLE_ERROR
;
306 const void *GDIFontInstance::getFontTable(LETag tableTag
) const
308 return FontTableCache::find(tableTag
);
311 const void *GDIFontInstance::readFontTable(LETag tableTag
) const
313 fSurface
->setFont(this);
315 HDC hdc
= fSurface
->getHDC();
316 DWORD stag
= SWAPL(tableTag
);
317 DWORD len
= GetFontData(hdc
, stag
, 0, NULL
, 0);
320 if (len
!= GDI_ERROR
) {
321 result
= LE_NEW_ARRAY(char, len
);
322 GetFontData(hdc
, stag
, 0, result
, len
);
328 void GDIFontInstance::getGlyphAdvance(LEGlyphID glyph
, LEPoint
&advance
) const
333 if (glyph
== 0xFFFE || glyph
== 0xFFFF) {
338 GLYPHMETRICS metrics
;
340 MAT2 identity
= {{0, 1}, {0, 0}, {0, 0}, {0, 1}};
341 HDC hdc
= fSurface
->getHDC();
343 fSurface
->setFont(this);
345 result
= GetGlyphOutline(hdc
, glyph
, GGO_GLYPH_INDEX
| GGO_METRICS
, &metrics
, 0, NULL
, &identity
);
347 if (result
== GDI_ERROR
) {
351 advance
.fX
= metrics
.gmCellIncX
;
355 le_bool
GDIFontInstance::getGlyphPoint(LEGlyphID glyph
, le_int32 pointNumber
, LEPoint
&point
) const
361 result
= fFontInstance
->getGlyphPoint(glyph
, pointNumber
, pt
);
364 point
.fX
= xUnitsToPoints(pt
.fX
);
365 point
.fY
= yUnitsToPoints(pt
.fY
);