From 901baddfb80f62f14ea9b19fdb1852ba7b0c89b9 Mon Sep 17 00:00:00 2001 From: "brettw@chromium.org" Date: Thu, 29 Jul 2010 21:59:26 +0000 Subject: Hook up the new font API to WebKit. This moves the existing GetFontTable API to the private font interface. TEST=none BUG=none Review URL: http://codereview.chromium.org/3044029 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@54203 0039d316-1c4b-4281-b951-d872f2087c98 --- DEPS | 2 +- webkit/glue/plugins/pepper_font.cc | 280 ++++++++++++++++++++++++++++------ webkit/glue/plugins/pepper_font.h | 28 +++- webkit/glue/plugins/pepper_private.cc | 73 +++++++++ webkit/glue/plugins/pepper_resource.h | 2 + webkit/glue/plugins/pepper_var.h | 3 +- webkit/glue/plugins/ppb_private.h | 56 +++++++ 7 files changed, 389 insertions(+), 55 deletions(-) diff --git a/DEPS b/DEPS index bbac946..7f1b21c 100644 --- a/DEPS +++ b/DEPS @@ -158,7 +158,7 @@ deps = { Var("libvpx_revision"), "src/third_party/ppapi": - "http://ppapi.googlecode.com/svn/trunk@174", + "http://ppapi.googlecode.com/svn/trunk@180", "src/third_party/libjingle/source": "http://libjingle.googlecode.com/svn/branches/nextsnap@" + diff --git a/webkit/glue/plugins/pepper_font.cc b/webkit/glue/plugins/pepper_font.cc index 378842a..3b5e661 100644 --- a/webkit/glue/plugins/pepper_font.cc +++ b/webkit/glue/plugins/pepper_font.cc @@ -2,79 +2,188 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "build/build_config.h" - #include "webkit/glue/plugins/pepper_font.h" -#if defined(OS_LINUX) -#include -#endif - #include "base/logging.h" +#include "base/utf_string_conversions.h" +#include "third_party/ppapi/c/pp_rect.h" #include "third_party/ppapi/c/ppb_font.h" +#include "third_party/WebKit/WebKit/chromium/public/WebFont.h" +#include "third_party/WebKit/WebKit/chromium/public/WebFontDescription.h" +#include "third_party/WebKit/WebKit/chromium/public/WebRect.h" +#include "third_party/WebKit/WebKit/chromium/public/WebFloatPoint.h" +#include "third_party/WebKit/WebKit/chromium/public/WebFloatRect.h" +#include "third_party/WebKit/WebKit/chromium/public/WebTextRun.h" +#include "webkit/glue/plugins/pepper_image_data.h" #include "webkit/glue/plugins/pepper_plugin_module.h" +#include "webkit/glue/plugins/pepper_string.h" +#include "webkit/glue/plugins/pepper_var.h" #include "webkit/glue/webkit_glue.h" +using WebKit::WebFloatPoint; +using WebKit::WebFloatRect; +using WebKit::WebFont; +using WebKit::WebFontDescription; +using WebKit::WebRect; +using WebKit::WebTextRun; + namespace pepper { namespace { -PP_Resource MatchFontWithFallback(PP_Module module_id, - const PP_FontDescription* description) { -#if defined(OS_LINUX) +bool IsPPFontDescriptionValid(const PP_FontDescription& desc) { + // Check validity of UTF-8. + if (desc.face.type != PP_VARTYPE_STRING && desc.face.type != PP_VARTYPE_VOID) + return false; + + if (static_cast(desc.family) < PP_FONTFAMILY_DEFAULT || + static_cast(desc.family) > PP_FONTFAMILY_MONOSPACE) + return false; + if (static_cast(desc.weight) < PP_FONTWEIGHT_100 || + static_cast(desc.weight) > PP_FONTWEIGHT_900) + return false; + + return true; +} + +// The PP_* version lacks "None", so is just one value shifted from the +// WebFontDescription version. These values are checked in +// PPFontDescToWebFontDesc to make sure the conversion is correct. This is a +// macro so it can also be used in the COMPILE_ASSERTS. +#define PP_FONTFAMILY_TO_WEB_FONTFAMILY(f) \ + static_cast(f + 1) + +// Assumes the given PP_FontDescription has been validated. +WebFontDescription PPFontDescToWebFontDesc(const PP_FontDescription& font) { + // Verify that the enums match so we can just static cast. + COMPILE_ASSERT(static_cast(WebFontDescription::Weight100) == + static_cast(PP_FONTWEIGHT_100), + FontWeight100); + COMPILE_ASSERT(static_cast(WebFontDescription::Weight900) == + static_cast(PP_FONTWEIGHT_900), + FontWeight900); + COMPILE_ASSERT(WebFontDescription::GenericFamilyStandard == + PP_FONTFAMILY_TO_WEB_FONTFAMILY(PP_FONTFAMILY_DEFAULT), + StandardFamily); + COMPILE_ASSERT(WebFontDescription::GenericFamilySerif == + PP_FONTFAMILY_TO_WEB_FONTFAMILY(PP_FONTFAMILY_SERIF), + SerifFamily); + COMPILE_ASSERT(WebFontDescription::GenericFamilySansSerif == + PP_FONTFAMILY_TO_WEB_FONTFAMILY(PP_FONTFAMILY_SANSSERIF), + SansSerifFamily); + COMPILE_ASSERT(WebFontDescription::GenericFamilyMonospace == + PP_FONTFAMILY_TO_WEB_FONTFAMILY(PP_FONTFAMILY_MONOSPACE), + MonospaceFamily); + + WebFontDescription result; + String* face_name = GetString(font.face); + if (face_name) + result.family = UTF8ToUTF16(face_name->value()); + result.genericFamily = PP_FONTFAMILY_TO_WEB_FONTFAMILY(font.family); + result.size = static_cast(font.size); + result.italic = font.italic; + result.smallCaps = font.small_caps; + result.weight = static_cast(font.weight); + result.letterSpacing = static_cast(font.letter_spacing); + result.wordSpacing = static_cast(font.word_spacing); + return result; +} + +// Converts the given PP_TextRun to a WebTextRun, returning true on success. +// False means the input was invalid. +bool PPTextRunToWebTextRun(const PP_TextRun* run, WebTextRun* output) { + String* text_string = GetString(run->text); + if (!text_string) + return false; + *output = WebTextRun(UTF8ToUTF16(text_string->value()), + run->rtl, run->override_direction); + return true; +} + +PP_Resource Create(PP_Module module_id, + const PP_FontDescription* description) { PluginModule* module = PluginModule::FromPPModule(module_id); if (!module) return 0; - int fd = webkit_glue::MatchFontWithFallback(description->face, - description->weight >= 700, - description->italic, - description->charset); - if (fd == -1) + if (!IsPPFontDescriptionValid(*description)) return 0; - scoped_refptr font(new Font(module, fd)); - + scoped_refptr font(new Font(module, *description)); return font->GetReference(); -#else - // For trusted pepper plugins, this is only needed in Linux since font loading - // on Windows and Mac works through the renderer sandbox. - return false; -#endif } bool IsFont(PP_Resource resource) { - return !!Resource::GetAs(resource); + return !!Resource::GetAs(resource).get(); +} + +bool Describe(PP_Resource font_id, + PP_FontDescription* description, + PP_FontMetrics* metrics) { + scoped_refptr font(Resource::GetAs(font_id)); + if (!font.get()) + return false; + return font->Describe(description, metrics); } -bool GetFontTable(PP_Resource font_id, - uint32_t table, - void* output, - uint32_t* output_length) { +bool DrawTextAt(PP_Resource font_id, + PP_Resource image_data, + const PP_TextRun* text, + const PP_Point* position, + uint32_t color, + const PP_Rect* clip, + bool image_data_is_opaque) { scoped_refptr font(Resource::GetAs(font_id)); if (!font.get()) return false; + return font->DrawTextAt(image_data, text, position, color, clip, + image_data_is_opaque); +} - return font->GetFontTable(table, output, output_length); +int32_t MeasureText(PP_Resource font_id, const PP_TextRun* text) { + scoped_refptr font(Resource::GetAs(font_id)); + if (!font.get()) + return -1; + return font->MeasureText(text); +} + +uint32_t CharacterOffsetForPixel(PP_Resource font_id, + const PP_TextRun* text, + int32_t pixel_position) { + scoped_refptr font(Resource::GetAs(font_id)); + if (!font.get()) + return false; + return font->CharacterOffsetForPixel(text, pixel_position); +} + +int32_t PixelOffsetForCharacter(PP_Resource font_id, + const PP_TextRun* text, + uint32_t char_offset) { + scoped_refptr font(Resource::GetAs(font_id)); + if (!font.get()) + return false; + return font->PixelOffsetForCharacter(text, char_offset); } const PPB_Font ppb_font = { - &MatchFontWithFallback, + &Create, &IsFont, - &GetFontTable, + &Describe, + &DrawTextAt, + &MeasureText, + &CharacterOffsetForPixel, + &PixelOffsetForCharacter }; } // namespace -Font::Font(PluginModule* module, int fd) - : Resource(module), - fd_(fd) { +Font::Font(PluginModule* module, const PP_FontDescription& desc) + : Resource(module) { + WebFontDescription web_font_desc = PPFontDescToWebFontDesc(desc); + font_.reset(WebFont::create(web_font_desc)); } Font::~Font() { -#if defined (OS_LINUX) - close(fd_); -#endif } // static @@ -82,18 +191,95 @@ const PPB_Font* Font::GetInterface() { return &ppb_font; } -bool Font::GetFontTable(uint32_t table, - void* output, - uint32_t* output_length) { -#if defined(OS_LINUX) - size_t temp_size = static_cast(*output_length); - bool rv = webkit_glue::GetFontTable( - fd_, table, static_cast(output), &temp_size); - *output_length = static_cast(temp_size); - return rv; -#else - return false; -#endif +bool Font::Describe(PP_FontDescription* description, + PP_FontMetrics* metrics) { + if (description->face.type != PP_VARTYPE_VOID) + return false; + + WebFontDescription web_desc = font_->fontDescription(); + + // While converting the other way in PPFontDescToWebFontDesc we validated + // that the enums can be casted. + description->face = StringToPPVar(UTF16ToUTF8(web_desc.family)); + description->family = static_cast(web_desc.genericFamily); + description->size = static_cast(web_desc.size); + description->weight = static_cast(web_desc.weight); + description->italic = web_desc.italic; + description->small_caps = web_desc.smallCaps; + + metrics->height = font_->height(); + metrics->ascent = font_->ascent(); + metrics->descent = font_->descent(); + metrics->line_spacing = font_->lineSpacing(); + metrics->x_height = static_cast(font_->xHeight()); + + return true; +} + +bool Font::DrawTextAt(PP_Resource image_data, + const PP_TextRun* text, + const PP_Point* position, + uint32_t color, + const PP_Rect* clip, + bool image_data_is_opaque) { + WebTextRun run; + if (!PPTextRunToWebTextRun(text, &run)) + return false; + + // Get and map the image data we're painting to. + scoped_refptr image_resource( + Resource::GetAs(image_data)); + if (!image_resource.get()) + return false; + ImageDataAutoMapper mapper(image_resource); + if (!mapper.is_valid()) + return false; + + // Convert position and clip. + WebFloatPoint web_position(static_cast(position->x), + static_cast(position->y)); + WebRect web_clip; + if (!clip) { + // Use entire canvas. + web_clip = WebRect(0, 0, image_resource->width(), image_resource->height()); + } else { + web_clip = WebRect(clip->point.x, clip->point.y, + clip->size.width, clip->size.height); + } + + font_->drawText(webkit_glue::ToWebCanvas(image_resource->mapped_canvas()), + run, web_position, color, web_clip, image_data_is_opaque); + return true; +} + +int32_t Font::MeasureText(const PP_TextRun* text) { + WebTextRun run; + if (!PPTextRunToWebTextRun(text, &run)) + return -1; + return font_->calculateWidth(run); +} + +uint32_t Font::CharacterOffsetForPixel(const PP_TextRun* text, + int32_t pixel_position) { + WebTextRun run; + if (!PPTextRunToWebTextRun(text, &run)) + return -1; + + return static_cast(font_->offsetForPosition( + run, static_cast(pixel_position))); +} + +int32_t Font::PixelOffsetForCharacter(const PP_TextRun* text, + uint32_t char_offset) { + WebTextRun run; + if (!PPTextRunToWebTextRun(text, &run)) + return -1; + if (char_offset >= run.text.length()) + return -1; + + WebFloatRect rect = font_->selectionRectForText( + run, WebFloatPoint(0.0f, 0.0f), font_->height(), 0, char_offset); + return static_cast(rect.width); } } // namespace pepper diff --git a/webkit/glue/plugins/pepper_font.h b/webkit/glue/plugins/pepper_font.h index ad1abba..347800d 100644 --- a/webkit/glue/plugins/pepper_font.h +++ b/webkit/glue/plugins/pepper_font.h @@ -5,9 +5,15 @@ #ifndef WEBKIT_GLUE_PLUGINS_PEPPER_FONT_H_ #define WEBKIT_GLUE_PLUGINS_PEPPER_FONT_H_ +#include + +#include "base/scoped_ptr.h" +#include "third_party/ppapi/c/ppb_font.h" #include "webkit/glue/plugins/pepper_resource.h" -typedef struct _ppb_Font PPB_Font; +namespace WebKit { +class WebFont; +} namespace pepper { @@ -15,7 +21,7 @@ class PluginInstance; class Font : public Resource { public: - Font(PluginModule* module, int fd); + Font(PluginModule* module, const PP_FontDescription& desc); virtual ~Font(); // Returns a pointer to the interface implementing PPB_Font that is exposed to @@ -26,12 +32,22 @@ class Font : public Resource { Font* AsFont() { return this; } // PPB_Font implementation. - bool GetFontTable(uint32_t table, - void* output, - uint32_t* output_length); + bool Describe(PP_FontDescription* description, + PP_FontMetrics* metrics); + bool DrawTextAt(PP_Resource image_data, + const PP_TextRun* text, + const PP_Point* position, + uint32_t color, + const PP_Rect* clip, + bool image_data_is_opaque); + int32_t MeasureText(const PP_TextRun* text); + uint32_t CharacterOffsetForPixel(const PP_TextRun* text, + int32_t pixel_position); + int32_t PixelOffsetForCharacter(const PP_TextRun* text, + uint32_t char_offset); private: - int fd_; + scoped_ptr font_; }; } // namespace pepper diff --git a/webkit/glue/plugins/pepper_private.cc b/webkit/glue/plugins/pepper_private.cc index 8d5182f..e88eb61 100644 --- a/webkit/glue/plugins/pepper_private.cc +++ b/webkit/glue/plugins/pepper_private.cc @@ -9,11 +9,30 @@ #include "base/utf_string_conversions.h" #include "grit/webkit_strings.h" #include "webkit/glue/webkit_glue.h" +#include "webkit/glue/plugins/pepper_plugin_module.h" #include "webkit/glue/plugins/pepper_var.h" #include "webkit/glue/plugins/ppb_private.h" namespace pepper { +#if defined(OS_LINUX) +class PrivateFontFile : public Resource { + public: + PrivateFontFile(PluginModule* module, int fd) : Resource(module), fd_(fd) {} + virtual ~PrivateFontFile() {} + + // Resource overrides. + PrivateFontFile* AsPrivateFontFile() { return this; } + + bool GetFontTable(uint32_t table, + void* output, + uint32_t* output_length); + + private: + int fd_; +}; +#endif + namespace { PP_Var GetLocalizedString(PP_ResourceString string_id) { @@ -24,8 +43,50 @@ PP_Var GetLocalizedString(PP_ResourceString string_id) { return StringToPPVar(rv); } +PP_Resource GetFontFileWithFallback( + PP_Module module_id, + const PP_PrivateFontFileDescription* description) { +#if defined(OS_LINUX) + PluginModule* module = PluginModule::FromPPModule(module_id); + if (!module) + return NULL; + + int fd = webkit_glue::MatchFontWithFallback(description->face, + description->weight >= 700, + description->italic, + description->charset); + if (fd == -1) + return NULL; + + scoped_refptr font(new PrivateFontFile(module, fd)); + + return font->GetReference(); +#else + // For trusted pepper plugins, this is only needed in Linux since font loading + // on Windows and Mac works through the renderer sandbox. + return false; +#endif +} + +bool GetFontTableForPrivateFontFile(PP_Resource font_file, + uint32_t table, + void* output, + uint32_t* output_length) { +#if defined(OS_LINUX) + scoped_refptr font( + Resource::GetAs(font_file)); + if (!font.get()) + return false; + return font->GetFontTable(table, output, output_length); +#else + return false; +#endif +} + const PPB_Private ppb_private = { &GetLocalizedString, + &GetFontFileWithFallback, + &GetFontTableForPrivateFontFile, }; } // namespace @@ -35,4 +96,16 @@ const PPB_Private* Private::GetInterface() { return &ppb_private; } +#if defined(OS_LINUX) +bool PrivateFontFile::GetFontTable(uint32_t table, + void* output, + uint32_t* output_length) { + size_t temp_size = static_cast(*output_length); + bool rv = webkit_glue::GetFontTable( + fd_, table, static_cast(output), &temp_size); + *output_length = static_cast(temp_size); + return rv; +} +#endif + } // namespace pepper diff --git a/webkit/glue/plugins/pepper_resource.h b/webkit/glue/plugins/pepper_resource.h index 417a06b..1acaddcb 100644 --- a/webkit/glue/plugins/pepper_resource.h +++ b/webkit/glue/plugins/pepper_resource.h @@ -22,6 +22,7 @@ class FileRef; class Font; class ImageData; class PluginModule; +class PrivateFontFile; class Scrollbar; class URLLoader; class URLRequestInfo; @@ -80,6 +81,7 @@ class Resource : public base::RefCountedThreadSafe { virtual FileRef* AsFileRef() { return NULL; } virtual Font* AsFont() { return NULL; } virtual ImageData* AsImageData() { return NULL; } + virtual PrivateFontFile* AsPrivateFontFile() { return NULL; } virtual Scrollbar* AsScrollbar() { return NULL; } virtual URLLoader* AsURLLoader() { return NULL; } virtual URLRequestInfo* AsURLRequestInfo() { return NULL; } diff --git a/webkit/glue/plugins/pepper_var.h b/webkit/glue/plugins/pepper_var.h index b8c31cc..7b95b33 100644 --- a/webkit/glue/plugins/pepper_var.h +++ b/webkit/glue/plugins/pepper_var.h @@ -33,7 +33,8 @@ PP_Var NPObjectToPPVar(NPObject* object); NPObject* GetNPObject(PP_Var var); // Returns a PP_Var of type string that contains a copy of the given string. -// The input data must be valid UTF-8 encoded text. +// The input data must be valid UTF-8 encoded text. The return value will +// have a reference count of 1. PP_Var StringToPPVar(const std::string& str); // Returns the String corresponding to the PP_Var. This pointer has not been diff --git a/webkit/glue/plugins/ppb_private.h b/webkit/glue/plugins/ppb_private.h index a0956f0..24831c1 100644 --- a/webkit/glue/plugins/ppb_private.h +++ b/webkit/glue/plugins/ppb_private.h @@ -5,6 +5,7 @@ #ifndef WEBKIT_GLUE_PLUGINS_PPB_PRIVATE_H_ #define WEBKIT_GLUE_PLUGINS_PPB_PRIVATE_H_ +#include "third_party/ppapi/c/pp_module.h" #include "third_party/ppapi/c/pp_var.h" #define PPB_PRIVATE_INTERFACE "PPB_Private;1" @@ -13,9 +14,64 @@ typedef enum _pp_ResourceString { PP_RESOURCESTRING_PDFGETPASSWORD = 0, } PP_ResourceString; +typedef enum _pp_PrivateFontPitch { + PP_PRIVATEFONTPITCH_DEFAULT = 0, + PP_PRIVATEFONTPITCH_FIXED = 1 +} PP_PrivateFontPitch; + +typedef enum _pp_PrivateFontFamily { + PP_PRIVATEFONTFAMILY_DEFAULT = 0, + PP_PRIVATEFONTFAMILY_ROMAN = 1, + PP_PRIVATEFONTFAMILY_SCRIPT = 2 +} PP_PrivateFontFamily; + +typedef enum _pp_PrivateFontCharset { + PP_PRIVATEFONTCHARSET_ANSI = 0, + PP_PRIVATEFONTCHARSET_DEFAULT = 1, + PP_PRIVATEFONTCHARSET_SYMBOL = 2, + PP_PRIVATEFONTCHARSET_MAC = 77, + PP_PRIVATEFONTCHARSET_SHIFTJIS = 128, + PP_PRIVATEFONTCHARSET_HANGUL = 129, + PP_PRIVATEFONTCHARSET_JOHAB = 130, + PP_PRIVATEFONTCHARSET_GB2312 =134, + PP_PRIVATEFONTCHARSET_CHINESEBIG5 = 136, + PP_PRIVATEFONTCHARSET_GREEK = 161, + PP_PRIVATEFONTCHARSET_TURKISH = 162, + PP_PRIVATEFONTCHARSET_VIETNAMESE = 163, + PP_PRIVATEFONTCHARSET_HEBREW = 177, + PP_PRIVATEFONTCHARSET_ARABIC = 178, + PP_PRIVATEFONTCHARSET_BALTIC = 186, + PP_PRIVATEFONTCHARSET_RUSSIAN = 204, + PP_PRIVATEFONTCHARSET_THAI = 222, + PP_PRIVATEFONTCHARSET_EASTEUROPE = 238, + PP_PRIVATEFONTCHARSET_OEM = 255 +} PP_PrivateFontCharset; + +typedef struct _pp_PrivateFontFileDescription { + const char* face; + uint32_t weight; + bool italic; + PP_PrivateFontPitch pitch; + PP_PrivateFontFamily family; + PP_PrivateFontCharset charset; +} PP_PrivateFontFileDescription; + typedef struct _ppb_Private { // Returns a localized string. PP_Var (*GetLocalizedString)(PP_ResourceString string_id); + + // Returns a resource identifying a font file corresponding to the given font + // request after applying the browser-specific fallback. Linux only. + PP_Resource (*GetFontFileWithFallback)( + PP_Module module, + const PP_PrivateFontFileDescription* description); + + // Given a resource previously returned by GetFontFileWithFallback, returns + // a pointer to the requested font table. Linux only. + bool (*GetFontTableForPrivateFontFile)(PP_Resource font_file, + uint32_t table, + void* output, + uint32_t* output_length); } PPB_Private; #endif // WEBKIT_GLUE_PLUGINS_PPB_PRIVATE_H_ -- cgit v1.1