This source file includes following definitions.
- IsValid
- Describe
- GetFontData
- GetTableTags
- GetTable
- Create
#include "content/renderer/pepper/pepper_truetype_font.h"
#include <windows.h>
#include <set>
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
#include "base/strings/utf_string_conversions.h"
#include "base/sys_byteorder.h"
#include "base/win/scoped_hdc.h"
#include "base/win/scoped_select_object.h"
#include "content/public/renderer/render_thread.h"
#include "ppapi/c/dev/ppb_truetype_font_dev.h"
#include "ppapi/c/pp_errors.h"
namespace content {
namespace {
class PepperTrueTypeFontWin : public PepperTrueTypeFont {
public:
explicit PepperTrueTypeFontWin(
const ppapi::proxy::SerializedTrueTypeFontDesc& desc);
virtual ~PepperTrueTypeFontWin();
virtual bool IsValid() OVERRIDE;
virtual int32_t Describe(
ppapi::proxy::SerializedTrueTypeFontDesc* desc) OVERRIDE;
virtual int32_t GetTableTags(std::vector<uint32_t>* tags) OVERRIDE;
virtual int32_t GetTable(uint32_t table_tag,
int32_t offset,
int32_t max_data_length,
std::string* data) OVERRIDE;
private:
DWORD GetFontData(HDC hdc,
DWORD table,
DWORD offset,
LPVOID buffer,
DWORD length);
HFONT font_;
DISALLOW_COPY_AND_ASSIGN(PepperTrueTypeFontWin);
};
PepperTrueTypeFontWin::PepperTrueTypeFontWin(
const ppapi::proxy::SerializedTrueTypeFontDesc& desc) {
DWORD pitch_and_family = DEFAULT_PITCH;
switch (desc.generic_family) {
case PP_TRUETYPEFONTFAMILY_SERIF:
pitch_and_family |= FF_ROMAN;
break;
case PP_TRUETYPEFONTFAMILY_SANSSERIF:
pitch_and_family |= FF_SWISS;
break;
case PP_TRUETYPEFONTFAMILY_CURSIVE:
pitch_and_family |= FF_SCRIPT;
break;
case PP_TRUETYPEFONTFAMILY_FANTASY:
pitch_and_family |= FF_DECORATIVE;
break;
case PP_TRUETYPEFONTFAMILY_MONOSPACE:
pitch_and_family |= FF_MODERN;
break;
}
font_ = CreateFont(0 ,
0 ,
0 ,
0 ,
desc.weight,
(desc.style & PP_TRUETYPEFONTSTYLE_ITALIC) ? 1 : 0,
0 ,
0 ,
desc.charset,
OUT_OUTLINE_PRECIS,
CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY,
pitch_and_family,
base::UTF8ToUTF16(desc.family).c_str());
}
PepperTrueTypeFontWin::~PepperTrueTypeFontWin() {
}
bool PepperTrueTypeFontWin::IsValid() {
return font_ != NULL;
}
int32_t PepperTrueTypeFontWin::Describe(
ppapi::proxy::SerializedTrueTypeFontDesc* desc) {
LOGFONT font_desc;
if (!::GetObject(font_, sizeof(LOGFONT), &font_desc))
return PP_ERROR_FAILED;
switch (font_desc.lfPitchAndFamily & 0xF0) {
case FF_ROMAN:
desc->generic_family = PP_TRUETYPEFONTFAMILY_SERIF;
break;
case FF_SWISS:
desc->generic_family = PP_TRUETYPEFONTFAMILY_SANSSERIF;
break;
case FF_SCRIPT:
desc->generic_family = PP_TRUETYPEFONTFAMILY_CURSIVE;
break;
case FF_DECORATIVE:
desc->generic_family = PP_TRUETYPEFONTFAMILY_FANTASY;
break;
case FF_MODERN:
desc->generic_family = PP_TRUETYPEFONTFAMILY_MONOSPACE;
break;
}
desc->style = font_desc.lfItalic ? PP_TRUETYPEFONTSTYLE_ITALIC :
PP_TRUETYPEFONTSTYLE_NORMAL;
desc->weight = static_cast<PP_TrueTypeFontWeight_Dev>(font_desc.lfWeight);
desc->width = PP_TRUETYPEFONTWIDTH_NORMAL;
desc->charset =
static_cast<PP_TrueTypeFontCharset_Dev>(font_desc.lfCharSet);
base::win::ScopedCreateDC hdc(::CreateCompatibleDC(NULL));
if (hdc) {
base::win::ScopedSelectObject select_object(hdc, font_);
WCHAR name[LF_FACESIZE];
GetTextFace(hdc, LF_FACESIZE, name);
desc->family = base::UTF16ToUTF8(name);
}
return PP_OK;
}
DWORD PepperTrueTypeFontWin::GetFontData(HDC hdc,
DWORD table,
DWORD offset,
void* buffer,
DWORD length) {
if (buffer && !length)
return 0;
DWORD result = ::GetFontData(hdc, table, offset, buffer, length);
if (result == GDI_ERROR) {
LOGFONTW logfont;
if (!::GetObject(font_, sizeof(LOGFONTW), &logfont))
return GDI_ERROR;
RenderThread* render_thread = RenderThread::Get();
if (!render_thread)
return GDI_ERROR;
render_thread->PreCacheFont(logfont);
result = ::GetFontData(hdc, table, offset, buffer, length);
}
return result;
}
int32_t PepperTrueTypeFontWin::GetTableTags(std::vector<uint32_t>* tags) {
base::win::ScopedCreateDC hdc(::CreateCompatibleDC(NULL));
if (!hdc)
return PP_ERROR_FAILED;
base::win::ScopedSelectObject select_object(hdc, font_);
static const DWORD kFontHeaderSize = 12;
uint8_t header_buf[kFontHeaderSize];
if (GetFontData(hdc, 0, 0, header_buf, kFontHeaderSize) == GDI_ERROR)
return PP_ERROR_FAILED;
DWORD num_tables = (header_buf[4] << 8) | header_buf[5];
static const DWORD kDirectoryEntrySize = 16;
DWORD directory_size = num_tables * kDirectoryEntrySize;
scoped_ptr<uint8_t[]> directory(new uint8_t[directory_size]);
if (GetFontData(hdc, 0 , kFontHeaderSize,
directory.get(),
directory_size) == GDI_ERROR)
return PP_ERROR_FAILED;
tags->resize(num_tables);
for (DWORD i = 0; i < num_tables; i++) {
const uint8_t* entry = directory.get() + i * kDirectoryEntrySize;
uint32_t tag = static_cast<uint32_t>(entry[0]) << 24 |
static_cast<uint32_t>(entry[1]) << 16 |
static_cast<uint32_t>(entry[2]) << 8 |
static_cast<uint32_t>(entry[3]);
(*tags)[i] = tag;
}
return num_tables;
}
int32_t PepperTrueTypeFontWin::GetTable(uint32_t table_tag,
int32_t offset,
int32_t max_data_length,
std::string* data) {
base::win::ScopedCreateDC hdc(::CreateCompatibleDC(NULL));
if (!hdc)
return PP_ERROR_FAILED;
base::win::ScopedSelectObject select_object(hdc, font_);
table_tag = base::ByteSwap(table_tag);
DWORD table_size = GetFontData(hdc, table_tag, 0, NULL, 0);
if (table_size == GDI_ERROR)
return PP_ERROR_FAILED;
DWORD safe_offset = std::min(static_cast<DWORD>(offset), table_size);
DWORD safe_length = std::min(table_size - safe_offset,
static_cast<DWORD>(max_data_length));
data->resize(safe_length);
if (safe_length == 0) {
table_size = 0;
} else {
table_size = GetFontData(hdc, table_tag, safe_offset,
reinterpret_cast<uint8_t*>(&(*data)[0]),
safe_length);
if (table_size == GDI_ERROR)
return PP_ERROR_FAILED;
}
return static_cast<int32_t>(table_size);
}
}
PepperTrueTypeFont* PepperTrueTypeFont::Create(
const ppapi::proxy::SerializedTrueTypeFontDesc& desc) {
return new PepperTrueTypeFontWin(desc);
}
}