| Index: Source/platform/fonts/mac/SimpleFontDataCoreText.cpp
|
| diff --git a/Source/platform/fonts/mac/SimpleFontDataCoreText.cpp b/Source/platform/fonts/mac/SimpleFontDataCoreText.cpp
|
| index a9563507d33b96d912f586dba39bdc4ade2ea95f..b1940d0effecfa753f4b8322551cc131a3145a70 100644
|
| --- a/Source/platform/fonts/mac/SimpleFontDataCoreText.cpp
|
| +++ b/Source/platform/fonts/mac/SimpleFontDataCoreText.cpp
|
| @@ -27,8 +27,17 @@
|
| #include "config.h"
|
| #include "platform/fonts/SimpleFontData.h"
|
|
|
| +#include "platform/fonts/Character.h"
|
| +#include "platform/fonts/Font.h"
|
| +#include "platform/fonts/GlyphPage.h"
|
| #include <ApplicationServices/ApplicationServices.h>
|
|
|
| +// Forward declare Mac SPIs.
|
| +// Request for public API: rdar://13787589
|
| +extern "C" {
|
| +void CGFontGetGlyphsForUnichars(CGFontRef, const UniChar chars[], CGGlyph glyphs[], size_t length);
|
| +}
|
| +
|
| namespace WebCore {
|
|
|
| CFDictionaryRef SimpleFontData::getCFStringAttributes(TypesettingFeatures typesettingFeatures, FontOrientation orientation) const
|
| @@ -63,4 +72,138 @@ CFDictionaryRef SimpleFontData::getCFStringAttributes(TypesettingFeatures typese
|
| return attributesDictionary.get();
|
| }
|
|
|
| +static bool shouldUseCoreText(UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData)
|
| +{
|
| + if (fontData->platformData().isCompositeFontReference())
|
| + return true;
|
| +
|
| + // CoreText doesn't have vertical glyphs of surrogate pair characters.
|
| + // Therefore, we should not use CoreText, but this always returns horizontal glyphs.
|
| + // FIXME: We should use vertical glyphs. https://code.google.com/p/chromium/issues/detail?id=340173
|
| + if (bufferLength >= 2 && U_IS_SURROGATE(buffer[0]) && fontData->hasVerticalGlyphs()) {
|
| + ASSERT(U_IS_SURROGATE_LEAD(buffer[0]));
|
| + ASSERT(U_IS_TRAIL(buffer[1]));
|
| + return false;
|
| + }
|
| +
|
| + if (fontData->platformData().widthVariant() != RegularWidth || fontData->hasVerticalGlyphs()) {
|
| + // Ideographs don't have a vertical variant or width variants.
|
| + for (unsigned i = 0; i < bufferLength; ++i) {
|
| + if (!Character::isCJKIdeograph(buffer[i]))
|
| + return true;
|
| + }
|
| + }
|
| +
|
| + return false;
|
| +}
|
| +
|
| +bool SimpleFontData::fillGlyphPage(GlyphPage* pageToFill, unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength) const
|
| +{
|
| + bool haveGlyphs = false;
|
| +
|
| + Vector<CGGlyph, 512> glyphs(bufferLength);
|
| + if (!shouldUseCoreText(buffer, bufferLength, this)) {
|
| + CGFontGetGlyphsForUnichars(platformData().cgFont(), buffer, glyphs.data(), bufferLength);
|
| + for (unsigned i = 0; i < length; ++i) {
|
| + if (!glyphs[i]) {
|
| + pageToFill->setGlyphDataForIndex(offset + i, 0, 0);
|
| + } else {
|
| + pageToFill->setGlyphDataForIndex(offset + i, glyphs[i], this);
|
| + haveGlyphs = true;
|
| + }
|
| + }
|
| + } else if (!platformData().isCompositeFontReference() && platformData().widthVariant() != RegularWidth
|
| + && CTFontGetGlyphsForCharacters(platformData().ctFont(), buffer, glyphs.data(), bufferLength)) {
|
| + // When buffer consists of surrogate pairs, CTFontGetGlyphsForCharacters
|
| + // places the glyphs at indices corresponding to the first character of each pair.
|
| + unsigned glyphStep = bufferLength / length;
|
| + for (unsigned i = 0; i < length; ++i) {
|
| + if (!glyphs[i * glyphStep]) {
|
| + pageToFill->setGlyphDataForIndex(offset + i, 0, 0);
|
| + } else {
|
| + pageToFill->setGlyphDataForIndex(offset + i, glyphs[i * glyphStep], this);
|
| + haveGlyphs = true;
|
| + }
|
| + }
|
| + } else {
|
| + // We ask CoreText for possible vertical variant glyphs
|
| + RetainPtr<CFStringRef> string(AdoptCF, CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, buffer, bufferLength, kCFAllocatorNull));
|
| + RetainPtr<CFAttributedStringRef> attributedString(AdoptCF, CFAttributedStringCreate(kCFAllocatorDefault, string.get(), getCFStringAttributes(0, hasVerticalGlyphs() ? Vertical : Horizontal)));
|
| + RetainPtr<CTLineRef> line(AdoptCF, CTLineCreateWithAttributedString(attributedString.get()));
|
| +
|
| + CFArrayRef runArray = CTLineGetGlyphRuns(line.get());
|
| + CFIndex runCount = CFArrayGetCount(runArray);
|
| +
|
| + // Initialize glyph entries
|
| + for (unsigned index = 0; index < length; ++index)
|
| + pageToFill->setGlyphDataForIndex(offset + index, 0, 0);
|
| +
|
| + Vector<CGGlyph, 512> glyphVector;
|
| + Vector<CFIndex, 512> indexVector;
|
| + bool done = false;
|
| +
|
| + // For the CGFont comparison in the loop, use the CGFont that Core Text assigns to the CTFont. This may
|
| + // be non-CFEqual to platformData().cgFont().
|
| + RetainPtr<CGFontRef> cgFont(AdoptCF, CTFontCopyGraphicsFont(platformData().ctFont(), 0));
|
| +
|
| + for (CFIndex r = 0; r < runCount && !done ; ++r) {
|
| + // CTLine could map characters over multiple fonts using its own font fallback list.
|
| + // We need to pick runs that use the exact font we need, i.e., platformData().ctFont().
|
| + CTRunRef ctRun = static_cast<CTRunRef>(CFArrayGetValueAtIndex(runArray, r));
|
| + ASSERT(CFGetTypeID(ctRun) == CTRunGetTypeID());
|
| +
|
| + CFDictionaryRef attributes = CTRunGetAttributes(ctRun);
|
| + CTFontRef runFont = static_cast<CTFontRef>(CFDictionaryGetValue(attributes, kCTFontAttributeName));
|
| + RetainPtr<CGFontRef> runCGFont(AdoptCF, CTFontCopyGraphicsFont(runFont, 0));
|
| + // Use CGFont here as CFEqual for CTFont counts all attributes for font.
|
| + bool gotBaseFont = CFEqual(cgFont.get(), runCGFont.get());
|
| + if (gotBaseFont || platformData().isCompositeFontReference()) {
|
| + // This run uses the font we want. Extract glyphs.
|
| + CFIndex glyphCount = CTRunGetGlyphCount(ctRun);
|
| + const CGGlyph* glyphs = CTRunGetGlyphsPtr(ctRun);
|
| + if (!glyphs) {
|
| + glyphVector.resize(glyphCount);
|
| + CTRunGetGlyphs(ctRun, CFRangeMake(0, 0), glyphVector.data());
|
| + glyphs = glyphVector.data();
|
| + }
|
| + const CFIndex* stringIndices = CTRunGetStringIndicesPtr(ctRun);
|
| + if (!stringIndices) {
|
| + indexVector.resize(glyphCount);
|
| + CTRunGetStringIndices(ctRun, CFRangeMake(0, 0), indexVector.data());
|
| + stringIndices = indexVector.data();
|
| + }
|
| +
|
| + if (gotBaseFont) {
|
| + for (CFIndex i = 0; i < glyphCount; ++i) {
|
| + if (stringIndices[i] >= static_cast<CFIndex>(length)) {
|
| + done = true;
|
| + break;
|
| + }
|
| + if (glyphs[i]) {
|
| + pageToFill->setGlyphDataForIndex(offset + stringIndices[i], glyphs[i], this);
|
| + haveGlyphs = true;
|
| + }
|
| + }
|
| + } else {
|
| + const SimpleFontData* runSimple = getCompositeFontReferenceFontData((NSFont *)runFont);
|
| + if (runSimple) {
|
| + for (CFIndex i = 0; i < glyphCount; ++i) {
|
| + if (stringIndices[i] >= static_cast<CFIndex>(length)) {
|
| + done = true;
|
| + break;
|
| + }
|
| + if (glyphs[i]) {
|
| + pageToFill->setGlyphDataForIndex(offset + stringIndices[i], glyphs[i], runSimple);
|
| + haveGlyphs = true;
|
| + }
|
| + }
|
| + }
|
| + }
|
| + }
|
| + }
|
| + }
|
| +
|
| + return haveGlyphs;
|
| +}
|
| +
|
| } // namespace WebCore
|
|
|