3 #include "gdipp_lib/scoped_rw_lock.h"
4 #include "gdipp_server/freetype.h"
5 #include "gdipp_server/global.h"
6 #include "gdipp_server/helper.h"
8 #define TTCF_TABLE_TAG mmioFOURCC('t', 't', 'c', 'f')
10 // little-endian <-> big-endian
11 #define SWAPWORD(x) MAKEWORD(HIBYTE(x), LOBYTE(x))
12 #define SWAPLONG(x) MAKELONG(SWAPWORD(HIWORD(x)), SWAPWORD(LOWORD(x)))
17 DWORD
font_mgr::get_font_size(HDC font_holder
, DWORD
*table_header
)
19 *table_header
= TTCF_TABLE_TAG
;
22 try to get font file size with ttcf tag first
23 if succeeds, the font face is part of a TTC file
24 otherwise, the font face is a standalone TrueType font file
26 DWORD font_size
= GetFontData(font_holder
, *table_header
, 0, NULL
, 0);
27 if (font_size
== GDI_ERROR
)
30 font_size
= GetFontData(font_holder
, *table_header
, 0, NULL
, 0);
31 assert(font_size
!= GDI_ERROR
);
37 ULONG
font_mgr::get_ttc_face_index(HDC font_holder
, DWORD ttc_file_size
)
39 // get the index of the current face in its TTC file
40 // by comparing its start offset retrieved from GetFontData and from the TTC header
42 // pre-condition: the font file contains TTC header
46 // start offset of the current face
47 DWORD face_start
= GetFontData(font_holder
, 0, 0, NULL
, 0);
48 assert(face_start
!= GDI_ERROR
);
49 face_start
= ttc_file_size
- face_start
;
51 DWORD read_offset
= sizeof(DWORD
) + sizeof(FIXED
);
53 DWORD buffer_len
= sizeof(face_count
);
55 // number of face records in the TTC header
56 read_size
= GetFontData(font_holder
, TTCF_TABLE_TAG
, read_offset
, &face_count
, buffer_len
);
57 assert(read_size
== buffer_len
);
59 // TrueType font data uses big-endian, while mainstream Windows uses little-endian platforms
60 face_count
= SWAPLONG(face_count
);
61 read_offset
+= buffer_len
;
63 for (ULONG i
= 0; i
< face_count
; i
++)
65 // start offset of the current record
67 buffer_len
= sizeof(curr_start
);
68 read_size
= GetFontData(font_holder
, TTCF_TABLE_TAG
, read_offset
, &curr_start
, buffer_len
);
69 assert(read_size
== buffer_len
);
70 curr_start
= SWAPLONG(curr_start
);
72 if (curr_start
== face_start
)
75 read_offset
+= buffer_len
;
83 _font_holder_tls_index
= TlsAlloc();
84 assert(_font_holder_tls_index
!= TLS_OUT_OF_INDEXES
);
89 for (std::map
<std::wstring
, _font_entry
>::const_iterator iter
= _font_registry
.begin(); iter
!= _font_registry
.end(); ++iter
)
90 DeleteObject(iter
->second
.font_handle
);
92 TlsFree(_font_holder_tls_index
);
95 void *font_mgr::register_font(HDC font_holder
, const LOGFONTW
*log_font
, BYTE
**outline_metrics_buf
, unsigned long *outline_metrics_size
)
97 // create a font with supplied LOGFONT and retrieve related information
101 const HFONT hfont
= CreateFontIndirectW(log_font
);
105 SelectObject(font_holder
, hfont
);
107 *outline_metrics_size
= get_dc_outline_metrics(font_holder
, outline_metrics_buf
);
108 if (*outline_metrics_size
== 0)
114 const OUTLINETEXTMETRICW
*outline_metrics
= reinterpret_cast<const OUTLINETEXTMETRICW
*>(*outline_metrics_buf
);
115 const std::wstring font_face
= metric_face_name(outline_metrics
);
116 std::map
<std::wstring
, _font_entry
>::iterator font_iter
= _font_registry
.find(font_face
);
117 if (font_iter
== _font_registry
.end())
119 const scoped_rw_lock
lock_w(scoped_rw_lock::SERVER_FONT_MGR
, false);
120 font_iter
= _font_registry
.find(font_face
);
121 if (font_iter
== _font_registry
.end())
124 b_ret
= os2
.init(font_holder
);
132 DWORD font_size
= get_font_size(font_holder
, &table_header
);
133 if (font_size
== GDI_ERROR
)
139 DWORD face_index
= 0;
140 if (table_header
!= 0)
142 face_index
= get_ttc_face_index(font_holder
, font_size
);
143 if (face_index
== ULONG_MAX
)
150 const std::pair
<std::map
<std::wstring
, _font_entry
>::iterator
, bool> insert_ret
= _font_registry
.insert(std::pair
<std::wstring
, _font_entry
>(font_face
, _font_entry()));
151 assert(insert_ret
.second
);
152 font_iter
= insert_ret
.first
;
154 font_iter
->second
.font_handle
= hfont
;
155 font_iter
->second
.os2
= os2
;
156 font_iter
->second
.face_index
= face_index
;
157 font_iter
->second
.table_header
= table_header
;
159 font_iter
->second
.stream
.size
= font_size
;
160 // need the table header to retrieve font data (see stream_io())
161 font_iter
->second
.stream
.descriptor
.value
= table_header
;
162 font_iter
->second
.stream
.read
= font_mgr::stream_io
;
163 font_iter
->second
.stream
.close
= font_mgr::stream_close
;
165 return &font_iter
->second
;
169 // font has been created before
171 return &font_iter
->second
;
174 HFONT
font_mgr::select_font(void *font_id
, HDC hdc
) const
176 const _font_entry
*curr_font
= reinterpret_cast<const _font_entry
*>(font_id
);
177 return reinterpret_cast<HFONT
>(SelectObject(hdc
, curr_font
->font_handle
));
180 ULONG
font_mgr::lookup_face_index(void *font_id
) const
182 const _font_entry
*curr_font
= reinterpret_cast<const _font_entry
*>(font_id
);
183 return curr_font
->face_index
;
186 const os2_metrics
*font_mgr::lookup_os2_metrics(void *font_id
) const
188 const _font_entry
*curr_font
= reinterpret_cast<const _font_entry
*>(font_id
);
189 return &curr_font
->os2
;
192 FT_Stream
font_mgr::lookup_stream(void *font_id
) const
194 _font_entry
*curr_font
= reinterpret_cast<_font_entry
*>(font_id
);
195 return &curr_font
->stream
;
198 HDC
font_mgr::get_thread_font_holder() const
200 return reinterpret_cast<HDC
>(TlsGetValue(_font_holder_tls_index
));
203 BOOL
font_mgr::set_thread_font_holder(HDC font_holder
) const
205 return TlsSetValue(_font_holder_tls_index
, font_holder
);
208 unsigned long font_mgr::get_dc_outline_metrics(HDC hdc
, BYTE
**outline_metrics_buf
)
210 // get outline metrics of the DC, which also include the text metrics
212 unsigned long outline_metrics_size
= GetOutlineTextMetricsW(hdc
, 0, NULL
);
213 if (outline_metrics_size
== 0)
214 return outline_metrics_size
;
216 *outline_metrics_buf
= new BYTE
[outline_metrics_size
];
217 outline_metrics_size
= GetOutlineTextMetricsW(hdc
, outline_metrics_size
, reinterpret_cast<OUTLINETEXTMETRICW
*>(*outline_metrics_buf
));
218 assert(outline_metrics_size
!= 0);
220 return outline_metrics_size
;
223 unsigned long font_mgr::stream_io(FT_Stream stream
, unsigned long offset
, unsigned char *buffer
, unsigned long count
)
225 // callback function, called when freetype requests font data
227 // count == 0 means seek operation
231 const DWORD read_size
= GetFontData(font_mgr_instance
.get_thread_font_holder(), stream
->descriptor
.value
, offset
, buffer
, count
);
232 assert(read_size
!= GDI_ERROR
);
233 assert(read_size
== count
);
238 void font_mgr::stream_close(FT_Stream stream
)
240 // GetFontData() needs no close