summaryrefslogtreecommitdiffstats
path: root/WebCore/platform/graphics/mac
diff options
context:
space:
mode:
authorFeng Qian <fqian@google.com>2009-06-17 12:12:20 -0700
committerFeng Qian <fqian@google.com>2009-06-17 12:12:20 -0700
commit5f1ab04193ad0130ca8204aadaceae083aca9881 (patch)
tree5a92cd389e2cfe7fb67197ce14b38469462379f8 /WebCore/platform/graphics/mac
parent194315e5a908cc8ed67d597010544803eef1ac59 (diff)
downloadexternal_webkit-5f1ab04193ad0130ca8204aadaceae083aca9881.zip
external_webkit-5f1ab04193ad0130ca8204aadaceae083aca9881.tar.gz
external_webkit-5f1ab04193ad0130ca8204aadaceae083aca9881.tar.bz2
Get WebKit r44544.
Diffstat (limited to 'WebCore/platform/graphics/mac')
-rw-r--r--WebCore/platform/graphics/mac/ColorMac.h2
-rw-r--r--WebCore/platform/graphics/mac/ColorMac.mm48
-rw-r--r--WebCore/platform/graphics/mac/CoreTextController.cpp32
-rw-r--r--WebCore/platform/graphics/mac/CoreTextController.h4
-rw-r--r--WebCore/platform/graphics/mac/FontCacheMac.mm16
-rw-r--r--WebCore/platform/graphics/mac/FontMac.mm16
-rw-r--r--WebCore/platform/graphics/mac/FontMacATSUI.mm49
-rw-r--r--WebCore/platform/graphics/mac/FontMacCoreText.cpp4
-rw-r--r--WebCore/platform/graphics/mac/FontPlatformData.h2
-rw-r--r--WebCore/platform/graphics/mac/GraphicsContextMac.mm11
-rw-r--r--WebCore/platform/graphics/mac/GraphicsLayerCA.h3
-rw-r--r--WebCore/platform/graphics/mac/GraphicsLayerCA.mm98
-rw-r--r--WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h6
-rw-r--r--WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm294
-rw-r--r--WebCore/platform/graphics/mac/SimpleFontDataMac.mm105
-rw-r--r--WebCore/platform/graphics/mac/WebLayer.mm1
16 files changed, 459 insertions, 232 deletions
diff --git a/WebCore/platform/graphics/mac/ColorMac.h b/WebCore/platform/graphics/mac/ColorMac.h
index 830e9d9..8a5ce31 100644
--- a/WebCore/platform/graphics/mac/ColorMac.h
+++ b/WebCore/platform/graphics/mac/ColorMac.h
@@ -41,7 +41,7 @@ namespace WebCore {
// These functions assume NSColors are in DeviceRGB colorspace
Color colorFromNSColor(NSColor *);
- NSColor* nsColor(const Color&);
+ NSColor *nsColor(const Color&);
bool usesTestModeFocusRingColor();
void setUsesTestModeFocusRingColor(bool);
diff --git a/WebCore/platform/graphics/mac/ColorMac.mm b/WebCore/platform/graphics/mac/ColorMac.mm
index 1c4350c..05dd78d 100644
--- a/WebCore/platform/graphics/mac/ColorMac.mm
+++ b/WebCore/platform/graphics/mac/ColorMac.mm
@@ -24,13 +24,10 @@
*/
#import "config.h"
-#import "Color.h"
#import "ColorMac.h"
-#import <AppKit/AppKit.h>
-#import <wtf/Assertions.h>
-#import <wtf/StdLibExtras.h>
#import <wtf/RetainPtr.h>
+#import <wtf/StdLibExtras.h>
@interface WebCoreControlTintObserver : NSObject
+ (void)controlTintDidChange;
@@ -47,7 +44,13 @@ static bool useOldAquaFocusRingColor;
static RGBA32 makeRGBAFromNSColor(NSColor *c)
{
- return makeRGBA((int)(255 * [c redComponent]), (int)(255 * [c greenComponent]), (int)(255 * [c blueComponent]), (int)(255 * [c alphaComponent]));
+ CGFloat redComponent;
+ CGFloat greenComponent;
+ CGFloat blueComponent;
+ CGFloat alpha;
+ [c getRed:&redComponent green:&greenComponent blue:&blueComponent alpha:&alpha];
+
+ return makeRGBA(255 * redComponent, 255 * greenComponent, 255 * blueComponent, 255 * alpha);
}
Color colorFromNSColor(NSColor *c)
@@ -55,21 +58,21 @@ Color colorFromNSColor(NSColor *c)
return Color(makeRGBAFromNSColor(c));
}
-NSColor* nsColor(const Color& color)
+NSColor *nsColor(const Color& color)
{
- unsigned c = color.rgb();
+ RGBA32 c = color.rgb();
switch (c) {
case 0: {
// Need this to avoid returning nil because cachedRGBAValues will default to 0.
- DEFINE_STATIC_LOCAL(RetainPtr<NSColor>, clearColor, ([NSColor colorWithDeviceRed:0.0f green:0.0f blue:0.0f alpha:0.0f]));
+ DEFINE_STATIC_LOCAL(RetainPtr<NSColor>, clearColor, ([NSColor colorWithDeviceRed:0 green:0 blue:0 alpha:0]));
return clearColor.get();
}
case Color::black: {
- DEFINE_STATIC_LOCAL(RetainPtr<NSColor>, blackColor, ([NSColor colorWithDeviceRed:0.0f green:0.0f blue:0.0f alpha:1.0f]));
+ DEFINE_STATIC_LOCAL(RetainPtr<NSColor>, blackColor, ([NSColor colorWithDeviceRed:0 green:0 blue:0 alpha:1]));
return blackColor.get();
}
case Color::white: {
- DEFINE_STATIC_LOCAL(RetainPtr<NSColor>, whiteColor, ([NSColor colorWithDeviceRed:1.0f green:1.0f blue:1.0f alpha:1.0f]));
+ DEFINE_STATIC_LOCAL(RetainPtr<NSColor>, whiteColor, ([NSColor colorWithDeviceRed:1 green:1 blue:1 alpha:1]));
return whiteColor.get();
}
default: {
@@ -81,10 +84,10 @@ NSColor* nsColor(const Color& color)
if (cachedRGBAValues[i] == c)
return cachedColors[i].get();
- NSColor* result = [NSColor colorWithDeviceRed:color.red() / 255.0f
- green:color.green() / 255.0f
- blue:color.blue() / 255.0f
- alpha:color.alpha() /255.0f];
+ NSColor *result = [NSColor colorWithDeviceRed:static_cast<CGFloat>(color.red()) / 255
+ green:static_cast<CGFloat>(color.green()) / 255
+ blue:static_cast<CGFloat>(color.blue()) / 255
+ alpha:static_cast<CGFloat>(color.alpha()) /255];
static int cursor;
cachedRGBAValues[cursor] = c;
@@ -96,16 +99,13 @@ NSColor* nsColor(const Color& color)
}
}
-static CGColorRef CGColorFromNSColor(NSColor* color)
+static CGColorRef CGColorFromNSColor(NSColor *color)
{
// This needs to always use device colorspace so it can de-calibrate the color for
// CGColor to possibly recalibrate it.
- NSColor* deviceColor = [color colorUsingColorSpaceName:NSDeviceRGBColorSpace];
- CGFloat red = [deviceColor redComponent];
- CGFloat green = [deviceColor greenComponent];
- CGFloat blue = [deviceColor blueComponent];
- CGFloat alpha = [deviceColor alphaComponent];
- const CGFloat components[4] = { red, green, blue, alpha };
+ CGFloat components[4];
+ NSColor *deviceColor = [color colorUsingColorSpaceName:NSDeviceRGBColorSpace];
+ [deviceColor getRed:&components[0] green:&components[1] blue:&components[2] alpha:&components[3]];
static CGColorSpaceRef deviceRGBColorSpace = CGColorSpaceCreateDeviceRGB();
CGColorRef cgColor = CGColorCreate(deviceRGBColorSpace, components);
return cgColor;
@@ -130,10 +130,10 @@ Color focusRingColor()
[WebCoreControlTintObserver controlTintDidChange];
tintIsKnown = true;
}
-
+
if (usesTestModeFocusRingColor())
return oldAquaFocusRingColor;
-
+
return systemFocusRingColor;
}
@@ -153,7 +153,7 @@ void setUsesTestModeFocusRingColor(bool newValue)
+ (void)controlTintDidChange
{
- NSColor* color = [[NSColor keyboardFocusIndicatorColor] colorUsingColorSpaceName:NSDeviceRGBColorSpace];
+ NSColor *color = [[NSColor keyboardFocusIndicatorColor] colorUsingColorSpaceName:NSDeviceRGBColorSpace];
WebCore::systemFocusRingColor = WebCore::makeRGBAFromNSColor(color);
}
diff --git a/WebCore/platform/graphics/mac/CoreTextController.cpp b/WebCore/platform/graphics/mac/CoreTextController.cpp
index 49e83c4..05f29b5 100644
--- a/WebCore/platform/graphics/mac/CoreTextController.cpp
+++ b/WebCore/platform/graphics/mac/CoreTextController.cpp
@@ -100,7 +100,7 @@ CoreTextController::CoreTextRun::CoreTextRun(const SimpleFontData* fontData, con
m_indices = reinterpret_cast<const CFIndex*>(CFDataGetBytePtr(m_indicesData.get()));
}
-CoreTextController::CoreTextController(const Font* font, const TextRun& run, bool mayUseNaturalWritingDirection)
+CoreTextController::CoreTextController(const Font* font, const TextRun& run, bool mayUseNaturalWritingDirection, HashSet<const SimpleFontData*>* fallbackFonts)
: m_font(*font)
, m_run(run)
, m_mayUseNaturalWritingDirection(mayUseNaturalWritingDirection)
@@ -112,6 +112,7 @@ CoreTextController::CoreTextController(const Font* font, const TextRun& run, boo
, m_currentRun(0)
, m_glyphInCurrentRun(0)
, m_finalRoundingWidth(0)
+ , m_fallbackFonts(fallbackFonts)
, m_lastRoundingGlyph(0)
{
m_padding = m_run.padding();
@@ -156,12 +157,12 @@ int CoreTextController::offsetForPosition(int h, bool includePartialGlyphs)
if (x <= adjustedAdvance) {
CFIndex hitIndex = coreTextRun.indexAt(j);
int stringLength = coreTextRun.stringLength();
- TextBreakIterator* characterIterator = characterBreakIterator(coreTextRun.characters(), stringLength);
+ TextBreakIterator* cursorPositionIterator = cursorMovementIterator(coreTextRun.characters(), stringLength);
int clusterStart;
- if (isTextBreak(characterIterator, hitIndex))
+ if (isTextBreak(cursorPositionIterator, hitIndex))
clusterStart = hitIndex;
else {
- clusterStart = textBreakPreceding(characterIterator, hitIndex);
+ clusterStart = textBreakPreceding(cursorPositionIterator, hitIndex);
if (clusterStart == TextBreakDone)
clusterStart = 0;
}
@@ -169,7 +170,7 @@ int CoreTextController::offsetForPosition(int h, bool includePartialGlyphs)
if (!includePartialGlyphs)
return coreTextRun.stringLocation() + clusterStart;
- int clusterEnd = textBreakFollowing(characterIterator, hitIndex);
+ int clusterEnd = textBreakFollowing(cursorPositionIterator, hitIndex);
if (clusterEnd == TextBreakDone)
clusterEnd = stringLength;
@@ -179,7 +180,7 @@ int CoreTextController::offsetForPosition(int h, bool includePartialGlyphs)
// reordering and on font fallback should occur within a CTLine.
if (clusterEnd - clusterStart > 1) {
int firstGlyphBeforeCluster = j - 1;
- while (firstGlyphBeforeCluster && coreTextRun.indexAt(firstGlyphBeforeCluster) >= clusterStart && coreTextRun.indexAt(firstGlyphBeforeCluster) < clusterEnd) {
+ while (firstGlyphBeforeCluster >= 0 && coreTextRun.indexAt(firstGlyphBeforeCluster) >= clusterStart && coreTextRun.indexAt(firstGlyphBeforeCluster) < clusterEnd) {
CGFloat width = m_adjustedAdvances[offsetIntoAdjustedGlyphs + firstGlyphBeforeCluster].width;
clusterWidth += width;
x += width;
@@ -359,6 +360,9 @@ void CoreTextController::collectCoreTextRunsForCharacters(const UChar* cp, unsig
return;
}
+ if (m_fallbackFonts && fontData != m_font.primaryFont())
+ m_fallbackFonts->add(fontData);
+
RetainPtr<CFStringRef> string(AdoptCF, CFStringCreateWithCharactersNoCopy(NULL, cp, length, kCFAllocatorNull));
RetainPtr<CFAttributedStringRef> attributedString(AdoptCF, CFAttributedStringCreate(NULL, string.get(), fontData->getCFStringAttributes()));
@@ -426,7 +430,7 @@ void CoreTextController::adjustGlyphsAndAdvances()
bool lastRun = r + 1 == runCount;
const UChar* cp = coreTextRun.characters();
- CGFloat roundedSpaceWidth = roundCGFloat(fontData->m_spaceWidth);
+ CGFloat roundedSpaceWidth = roundCGFloat(fontData->spaceWidth());
bool roundsAdvances = !m_font.isPrinterFont() && fontData->platformData().roundsGlyphAdvances();
bool hasExtraSpacing = (m_font.letterSpacing() || m_font.wordSpacing() || m_padding) && !m_run.spacingDisabled();
@@ -444,29 +448,29 @@ void CoreTextController::adjustGlyphsAndAdvances()
nextCh = *(m_coreTextRuns[r + 1].characters() + m_coreTextRuns[r + 1].indexAt(0));
bool treatAsSpace = Font::treatAsSpace(ch);
- CGGlyph glyph = treatAsSpace ? fontData->m_spaceGlyph : glyphs[i];
- CGSize advance = treatAsSpace ? CGSizeMake(fontData->m_spaceWidth, advances[i].height) : advances[i];
+ CGGlyph glyph = treatAsSpace ? fontData->spaceGlyph() : glyphs[i];
+ CGSize advance = treatAsSpace ? CGSizeMake(fontData->spaceWidth(), advances[i].height) : advances[i];
if (ch == '\t' && m_run.allowTabs()) {
float tabWidth = m_font.tabWidth();
advance.width = tabWidth - fmodf(m_run.xPos() + m_totalWidth, tabWidth);
} else if (ch == zeroWidthSpace || Font::treatAsZeroWidthSpace(ch) && !treatAsSpace) {
advance.width = 0;
- glyph = fontData->m_spaceGlyph;
+ glyph = fontData->spaceGlyph();
}
float roundedAdvanceWidth = roundf(advance.width);
if (roundsAdvances)
advance.width = roundedAdvanceWidth;
- advance.width += fontData->m_syntheticBoldOffset;
+ advance.width += fontData->syntheticBoldOffset();
// We special case spaces in two ways when applying word rounding.
// First, we round spaces to an adjusted width in all fonts.
// Second, in fixed-pitch fonts we ensure that all glyphs that
// match the width of the space glyph have the same width as the space glyph.
- if (roundedAdvanceWidth == roundedSpaceWidth && (fontData->m_treatAsFixedPitch || glyph == fontData->m_spaceGlyph) && m_run.applyWordRounding())
- advance.width = fontData->m_adjustedSpaceWidth;
+ if (roundedAdvanceWidth == roundedSpaceWidth && (fontData->pitch() == FixedPitch || glyph == fontData->spaceGlyph()) && m_run.applyWordRounding())
+ advance.width = fontData->adjustedSpaceWidth();
if (hasExtraSpacing) {
// If we're a glyph with an advance, go ahead and add in letter-spacing.
@@ -475,7 +479,7 @@ void CoreTextController::adjustGlyphsAndAdvances()
advance.width += m_font.letterSpacing();
// Handle justification and word-spacing.
- if (glyph == fontData->m_spaceGlyph) {
+ if (glyph == fontData->spaceGlyph()) {
// Account for padding. WebCore uses space padding to justify text.
// We distribute the specified padding over the available spaces in the run.
if (m_padding) {
diff --git a/WebCore/platform/graphics/mac/CoreTextController.h b/WebCore/platform/graphics/mac/CoreTextController.h
index 8dbb7fb..4dd6f93 100644
--- a/WebCore/platform/graphics/mac/CoreTextController.h
+++ b/WebCore/platform/graphics/mac/CoreTextController.h
@@ -37,7 +37,7 @@ namespace WebCore {
class CoreTextController {
public:
- CoreTextController(const Font*, const TextRun&, bool mayUseNaturalWritingDirection = false);
+ CoreTextController(const Font*, const TextRun&, bool mayUseNaturalWritingDirection = false, HashSet<const SimpleFontData*>* fallbackFonts = 0);
// Advance and emit glyphs up to the specified character.
void advance(unsigned to, GlyphBuffer* = 0);
@@ -106,6 +106,8 @@ private:
float m_padding;
float m_padPerSpace;
+ HashSet<const SimpleFontData*>* m_fallbackFonts;
+
unsigned m_lastRoundingGlyph;
};
diff --git a/WebCore/platform/graphics/mac/FontCacheMac.mm b/WebCore/platform/graphics/mac/FontCacheMac.mm
index 2202459..2730d5a 100644
--- a/WebCore/platform/graphics/mac/FontCacheMac.mm
+++ b/WebCore/platform/graphics/mac/FontCacheMac.mm
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
* Copyright (C) 2007 Nicholas Shanks <webkit@nickshanks.com>
*
* Redistribution and use in source and binary forms, with or without
@@ -44,16 +44,30 @@ typedef int NSInteger;
namespace WebCore {
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+static void fontCacheRegisteredFontsChangedNotificationCallback(CFNotificationCenterRef, void* observer, CFStringRef name, const void *, CFDictionaryRef)
+{
+ ASSERT_UNUSED(observer, observer == fontCache());
+ ASSERT_UNUSED(name, CFEqual(name, kCTFontManagerRegisteredFontsChangedNotification));
+ fontCache()->invalidate();
+}
+#else
static void fontCacheATSNotificationCallback(ATSFontNotificationInfoRef, void*)
{
fontCache()->invalidate();
}
+#endif
void FontCache::platformInit()
{
wkSetUpFontCache();
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+ CFNotificationCenterAddObserver(CFNotificationCenterGetLocalCenter(), this, fontCacheRegisteredFontsChangedNotificationCallback, kCTFontManagerRegisteredFontsChangedNotification, 0, CFNotificationSuspensionBehaviorDeliverImmediately);
+#else
+ // kCTFontManagerRegisteredFontsChangedNotification does not exist on Leopard and earlier.
// FIXME: Passing kATSFontNotifyOptionReceiveWhileSuspended may be an overkill and does not seem to work anyway.
ATSFontNotificationSubscribe(fontCacheATSNotificationCallback, kATSFontNotifyOptionReceiveWhileSuspended, 0, 0);
+#endif
}
static int toAppKitFontWeight(FontWeight fontWeight)
diff --git a/WebCore/platform/graphics/mac/FontMac.mm b/WebCore/platform/graphics/mac/FontMac.mm
index dc86c4b..df9494a 100644
--- a/WebCore/platform/graphics/mac/FontMac.mm
+++ b/WebCore/platform/graphics/mac/FontMac.mm
@@ -28,7 +28,6 @@
#import "Logging.h"
#import "SimpleFontData.h"
#import "WebCoreSystemInterface.h"
-#import "WebCoreTextRenderer.h"
#import <AppKit/AppKit.h>
#define SYNTHETIC_OBLIQUE_ANGLE 14
@@ -43,12 +42,17 @@ using namespace std;
namespace WebCore {
+bool Font::canReturnFallbackFontsForComplexText()
+{
+ return true;
+}
+
void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, const GlyphBuffer& glyphBuffer, int from, int numGlyphs, const FloatPoint& point) const
{
CGContextRef cgContext = context->platformContext();
bool originalShouldUseFontSmoothing = wkCGContextGetShouldSmoothFonts(cgContext);
- bool newShouldUseFontSmoothing = WebCoreShouldUseFontSmoothing();
+ bool newShouldUseFontSmoothing = shouldUseSmoothing();
if (originalShouldUseFontSmoothing != newShouldUseFontSmoothing)
CGContextSetShouldSmoothFonts(cgContext, newShouldUseFontSmoothing);
@@ -99,8 +103,8 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons
context->setFillColor(shadowFillColor);
CGContextSetTextPosition(cgContext, point.x() + shadowSize.width(), point.y() + shadowSize.height());
CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs);
- if (font->m_syntheticBoldOffset) {
- CGContextSetTextPosition(cgContext, point.x() + shadowSize.width() + font->m_syntheticBoldOffset, point.y() + shadowSize.height());
+ if (font->syntheticBoldOffset()) {
+ CGContextSetTextPosition(cgContext, point.x() + shadowSize.width() + font->syntheticBoldOffset(), point.y() + shadowSize.height());
CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs);
}
context->setFillColor(fillColor);
@@ -108,8 +112,8 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons
CGContextSetTextPosition(cgContext, point.x(), point.y());
CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs);
- if (font->m_syntheticBoldOffset) {
- CGContextSetTextPosition(cgContext, point.x() + font->m_syntheticBoldOffset, point.y());
+ if (font->syntheticBoldOffset()) {
+ CGContextSetTextPosition(cgContext, point.x() + font->syntheticBoldOffset(), point.y());
CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs);
}
diff --git a/WebCore/platform/graphics/mac/FontMacATSUI.mm b/WebCore/platform/graphics/mac/FontMacATSUI.mm
index 3794149..051abb7 100644
--- a/WebCore/platform/graphics/mac/FontMacATSUI.mm
+++ b/WebCore/platform/graphics/mac/FontMacATSUI.mm
@@ -47,13 +47,15 @@ namespace WebCore {
struct ATSULayoutParameters : Noncopyable
{
- ATSULayoutParameters(const TextRun& run)
+ ATSULayoutParameters(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts = 0)
: m_run(run)
, m_font(0)
, m_hasSyntheticBold(false)
, m_syntheticBoldPass(false)
, m_padPerSpace(0)
- {}
+ , m_fallbackFonts(fallbackFonts)
+ {
+ }
~ATSULayoutParameters()
{
@@ -73,6 +75,7 @@ struct ATSULayoutParameters : Noncopyable
bool m_hasSyntheticBold;
bool m_syntheticBoldPass;
float m_padPerSpace;
+ HashSet<const SimpleFontData*>* m_fallbackFonts;
};
static TextRun copyRunForDirectionalOverrideIfNecessary(const TextRun& run, OwnArrayPtr<UChar>& charactersWithOverride)
@@ -124,7 +127,7 @@ static void initializeATSUStyle(const SimpleFontData* fontData)
ATSUFontID fontID = fontData->platformData().m_atsuFontID;
if (!fontID) {
- LOG_ERROR("unable to get ATSUFontID for %@", fontData->m_font.font());
+ LOG_ERROR("unable to get ATSUFontID for %@", fontData->platformData().font());
return;
}
@@ -134,7 +137,7 @@ static void initializeATSUStyle(const SimpleFontData* fontData)
LOG_ERROR("ATSUCreateStyle failed (%d)", status);
CGAffineTransform transform = CGAffineTransformMakeScale(1, -1);
- if (fontData->m_font.m_syntheticOblique)
+ if (fontData->platformData().m_syntheticOblique)
transform = CGAffineTransformConcat(transform, CGAffineTransformMake(1, 0, -tanf(SYNTHETIC_OBLIQUE_ANGLE * acosf(0) / 90), 1, 0, 0));
Fixed fontSize = FloatToFixed(fontData->platformData().m_size);
ByteCount styleSizes[4] = { sizeof(Fixed), sizeof(ATSUFontID), sizeof(CGAffineTransform), sizeof(Fract) };
@@ -180,7 +183,6 @@ static OSStatus overrideLayoutOperation(ATSULayoutOperationSelector, ATSULineRef
bool shouldRound = false;
bool syntheticBoldPass = params->m_syntheticBoldPass;
Fixed syntheticBoldOffset = 0;
- ATSGlyphRef spaceGlyph = 0;
bool hasExtraSpacing = (params->m_font->letterSpacing() || params->m_font->wordSpacing() || params->m_run.padding()) && !params->m_run.spacingDisabled();
float padding = params->m_run.padding();
// In the CoreGraphics code path, the rounding hack is applied in logical order.
@@ -190,27 +192,28 @@ static OSStatus overrideLayoutOperation(ATSULayoutOperationSelector, ATSULineRef
for (i = 1; i < count; i++) {
bool isLastChar = i == count - 1;
renderer = renderers[offset / 2];
- if (renderer != lastRenderer) {
- lastRenderer = renderer;
- spaceGlyph = renderer->m_spaceGlyph;
- // The CoreGraphics interpretation of NSFontAntialiasedIntegerAdvancementsRenderingMode seems
- // to be "round each glyph's width to the nearest integer". This is not the same as ATSUI
- // does in any of its device-metrics modes.
- shouldRound = renderer->platformData().roundsGlyphAdvances();
- if (syntheticBoldPass)
- syntheticBoldOffset = FloatToFixed(renderer->m_syntheticBoldOffset);
- }
float width;
if (nextCh == zeroWidthSpace || Font::treatAsZeroWidthSpace(nextCh) && !Font::treatAsSpace(nextCh)) {
width = 0;
- layoutRecords[i-1].glyphID = spaceGlyph;
+ layoutRecords[i-1].glyphID = renderer->spaceGlyph();
} else {
width = FixedToFloat(layoutRecords[i].realPos - lastNativePos);
+ if (renderer != lastRenderer && width) {
+ lastRenderer = renderer;
+ // The CoreGraphics interpretation of NSFontAntialiasedIntegerAdvancementsRenderingMode seems
+ // to be "round each glyph's width to the nearest integer". This is not the same as ATSUI
+ // does in any of its device-metrics modes.
+ shouldRound = renderer->platformData().roundsGlyphAdvances();
+ if (syntheticBoldPass)
+ syntheticBoldOffset = FloatToFixed(renderer->syntheticBoldOffset());
+ if (params->m_fallbackFonts && renderer != params->m_font->primaryFont())
+ params->m_fallbackFonts->add(renderer);
+ }
if (shouldRound)
width = roundf(width);
- width += renderer->m_syntheticBoldOffset;
- if (renderer->m_treatAsFixedPitch ? width == renderer->m_spaceWidth : (layoutRecords[i-1].flags & kATSGlyphInfoIsWhiteSpace))
- width = renderer->m_adjustedSpaceWidth;
+ width += renderer->syntheticBoldOffset();
+ if (renderer->pitch() == FixedPitch ? width == renderer->spaceWidth() : (layoutRecords[i-1].flags & kATSGlyphInfoIsWhiteSpace))
+ width = renderer->adjustedSpaceWidth();
}
lastNativePos = layoutRecords[i].realPos;
@@ -258,7 +261,7 @@ static OSStatus overrideLayoutOperation(ATSULayoutOperationSelector, ATSULineRef
if (syntheticBoldOffset)
layoutRecords[i-1].realPos += syntheticBoldOffset;
else
- layoutRecords[i-1].glyphID = spaceGlyph;
+ layoutRecords[i-1].glyphID = renderer->spaceGlyph();
}
layoutRecords[i].realPos = FloatToFixed(lastAdjustedPos);
}
@@ -460,7 +463,7 @@ void ATSULayoutParameters::initialize(const Font* font, const GraphicsContext* g
}
} else
m_fonts[i] = r;
- if (m_fonts[i]->m_syntheticBoldOffset)
+ if (m_fonts[i]->syntheticBoldOffset())
m_hasSyntheticBold = true;
}
substituteOffset += substituteLength;
@@ -570,12 +573,12 @@ void Font::drawComplexText(GraphicsContext* graphicsContext, const TextRun& run,
graphicsContext->setShadow(shadowSize, shadowBlur, shadowColor);
}
-float Font::floatWidthForComplexText(const TextRun& run) const
+float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts) const
{
if (run.length() == 0)
return 0;
- ATSULayoutParameters params(run);
+ ATSULayoutParameters params(run, fallbackFonts);
params.initialize(this);
OSStatus status;
diff --git a/WebCore/platform/graphics/mac/FontMacCoreText.cpp b/WebCore/platform/graphics/mac/FontMacCoreText.cpp
index 5fb9d5d..9dffc7a 100644
--- a/WebCore/platform/graphics/mac/FontMacCoreText.cpp
+++ b/WebCore/platform/graphics/mac/FontMacCoreText.cpp
@@ -86,9 +86,9 @@ void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const F
drawGlyphBuffer(context, glyphBuffer, run, startPoint);
}
-float Font::floatWidthForComplexText(const TextRun& run) const
+float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts) const
{
- CoreTextController controller(this, run, true);
+ CoreTextController controller(this, run, true, fallbackFonts);
return controller.totalWidth();
}
diff --git a/WebCore/platform/graphics/mac/FontPlatformData.h b/WebCore/platform/graphics/mac/FontPlatformData.h
index e911867..1b7b884 100644
--- a/WebCore/platform/graphics/mac/FontPlatformData.h
+++ b/WebCore/platform/graphics/mac/FontPlatformData.h
@@ -82,6 +82,8 @@ struct FontPlatformData {
bool isHashTableDeletedValue() const { return m_font == hashTableDeletedFontValue(); }
float size() const { return m_size; }
+ bool syntheticBold() const { return m_syntheticBold; }
+ bool syntheticOblique() const { return m_syntheticOblique; }
bool m_syntheticBold;
bool m_syntheticOblique;
diff --git a/WebCore/platform/graphics/mac/GraphicsContextMac.mm b/WebCore/platform/graphics/mac/GraphicsContextMac.mm
index 4e11602..2404319 100644
--- a/WebCore/platform/graphics/mac/GraphicsContextMac.mm
+++ b/WebCore/platform/graphics/mac/GraphicsContextMac.mm
@@ -96,27 +96,28 @@ static NSColor* createPatternColor(NSString* name, NSColor* defaultColor, bool&
color = defaultColor;
return color;
}
-
+
+// WebKit on Mac is a standard platform component, so it must use the standard platform artwork for underline.
void GraphicsContext::drawLineForMisspellingOrBadGrammar(const IntPoint& point, int width, bool grammar)
{
if (paintingDisabled())
return;
- // These are the same for misspelling or bad grammar
+ // These are the same for misspelling or bad grammar.
int patternHeight = cMisspellingLineThickness;
int patternWidth = cMisspellingLinePatternWidth;
bool usingDot;
NSColor *patternColor;
if (grammar) {
- // Constants for grammar pattern color
+ // Constants for grammar pattern color.
static bool usingDotForGrammar = false;
DEFINE_STATIC_LOCAL(RetainPtr<NSColor>, grammarPatternColor, (createPatternColor(@"GrammarDot", [NSColor greenColor], usingDotForGrammar)));
usingDot = usingDotForGrammar;
patternColor = grammarPatternColor.get();
} else {
- // Constants for spelling pattern color
+ // Constants for spelling pattern color.
static bool usingDotForSpelling = false;
DEFINE_STATIC_LOCAL(RetainPtr<NSColor>, spellingPatternColor, (createPatternColor(@"SpellingDot", [NSColor redColor], usingDotForSpelling)));
@@ -141,7 +142,7 @@ void GraphicsContext::drawLineForMisspellingOrBadGrammar(const IntPoint& point,
// FIXME: This code should not be using wkSetPatternPhaseInUserSpace, as this approach is wrong
// for transforms.
- // Draw underline
+ // Draw underline.
NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
CGContextRef context = (CGContextRef)[currentContext graphicsPort];
CGContextSaveGState(context);
diff --git a/WebCore/platform/graphics/mac/GraphicsLayerCA.h b/WebCore/platform/graphics/mac/GraphicsLayerCA.h
index 3a692d3..50138d5 100644
--- a/WebCore/platform/graphics/mac/GraphicsLayerCA.h
+++ b/WebCore/platform/graphics/mac/GraphicsLayerCA.h
@@ -117,9 +117,8 @@ private:
bool requiresTiledLayer(const FloatSize&) const;
void swapFromOrToTiledLayer(bool useTiledLayer);
- void setHasContentsLayer(bool);
void setContentsLayer(WebLayer*);
- void setContentsLayerFlipped(bool);
+ WebLayer* contentsLayer() const { return m_contentsLayer.get(); }
RetainPtr<WebLayer> m_layer;
RetainPtr<WebLayer> m_transformLayer;
diff --git a/WebCore/platform/graphics/mac/GraphicsLayerCA.mm b/WebCore/platform/graphics/mac/GraphicsLayerCA.mm
index f3f2d7f..f361437 100644
--- a/WebCore/platform/graphics/mac/GraphicsLayerCA.mm
+++ b/WebCore/platform/graphics/mac/GraphicsLayerCA.mm
@@ -271,9 +271,9 @@ static bool forceSoftwareAnimation()
return forceSoftwareAnimation;
}
-bool GraphicsLayer::graphicsContextsFlipped()
+GraphicsLayer::CompositingCoordinatesOrientation GraphicsLayer::compositingCoordinatesOrientation()
{
- return true;
+ return CompositingCoordinatesBottomUp;
}
#ifndef NDEBUG
@@ -746,8 +746,10 @@ void GraphicsLayerCA::setDrawsContent(bool drawsContent)
swapFromOrToTiledLayer(needTiledLayer);
BEGIN_BLOCK_OBJC_EXCEPTIONS
- // Clobber any existing content. If necessary, CA will create backing store on the next display.
- [m_layer.get() setContents:nil];
+ if (m_drawsContent)
+ [m_layer.get() setNeedsDisplay];
+ else
+ [m_layer.get() setContents:nil];
#ifndef NDEBUG
updateDebugIndicators();
@@ -761,7 +763,14 @@ void GraphicsLayerCA::setBackgroundColor(const Color& color, const Animation* tr
GraphicsLayer::setBackgroundColor(color, transition, beginTime);
BEGIN_BLOCK_OBJC_EXCEPTIONS
- setHasContentsLayer(true);
+
+ if (!m_contentsLayer.get()) {
+ WebLayer* colorLayer = [WebLayer layer];
+#ifndef NDEBUG
+ [colorLayer setName:@"Color Layer"];
+#endif
+ setContentsLayer(colorLayer);
+ }
if (transition && !transition->isEmptyOrZeroDuration()) {
CALayer* presLayer = [m_contentsLayer.get() presentationLayer];
@@ -777,7 +786,6 @@ void GraphicsLayerCA::setBackgroundColor(const Color& color, const Animation* tr
CGColorRelease(bgColor);
} else {
removeAllAnimationsForProperty(AnimatedPropertyBackgroundColor);
- setHasContentsLayer(true);
setLayerBackgroundColor(m_contentsLayer.get(), m_backgroundColor);
}
@@ -787,7 +795,7 @@ void GraphicsLayerCA::setBackgroundColor(const Color& color, const Animation* tr
void GraphicsLayerCA::clearBackgroundColor()
{
if (!m_contentLayerForImageOrVideo)
- setHasContentsLayer(false);
+ setContentsLayer(0);
else
clearLayerBackgroundColor(m_contentsLayer.get());
}
@@ -1082,35 +1090,27 @@ bool GraphicsLayerCA::animateFloat(AnimatedPropertyID property, const FloatValue
void GraphicsLayerCA::setContentsToImage(Image* image)
{
if (image) {
- setHasContentsLayer(true);
-
- // FIXME: is image flipping really a property of the graphics context?
- bool needToFlip = GraphicsLayer::graphicsContextsFlipped();
- CGPoint anchorPoint = needToFlip ? CGPointMake(0.0f, 1.0f) : CGPointZero;
-
BEGIN_BLOCK_OBJC_EXCEPTIONS
{
- CGImageRef theImage = image->nativeImageForCurrentFrame();
+ if (!m_contentsLayer.get()) {
+ WebLayer* imageLayer = [WebLayer layer];
+#ifndef NDEBUG
+ [imageLayer setName:@"Image Layer"];
+#endif
+ setContentsLayer(imageLayer);
+ }
+
// FIXME: maybe only do trilinear if the image is being scaled down,
// but then what if the layer size changes?
-#if HAVE_MODERN_QUARTZCORE
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
[m_contentsLayer.get() setMinificationFilter:kCAFilterTrilinear];
#endif
- if (needToFlip) {
- CATransform3D flipper = {
- 1.0f, 0.0f, 0.0f, 0.0f,
- 0.0f, -1.0f, 0.0f, 0.0f,
- 0.0f, 0.0f, 1.0f, 0.0f,
- 0.0f, 0.0f, 0.0f, 1.0f};
- [m_contentsLayer.get() setTransform:flipper];
- }
-
- [m_contentsLayer.get() setAnchorPoint:anchorPoint];
+ CGImageRef theImage = image->nativeImageForCurrentFrame();
[m_contentsLayer.get() setContents:(id)theImage];
}
END_BLOCK_OBJC_EXCEPTIONS
} else
- setHasContentsLayer(false);
+ setContentsLayer(0);
m_contentLayerForImageOrVideo = (image != 0);
}
@@ -1124,7 +1124,7 @@ void GraphicsLayerCA::setContentsToVideo(PlatformLayer* videoLayer)
void GraphicsLayerCA::clearContents()
{
if (m_contentLayerForImageOrVideo) {
- setHasContentsLayer(false);
+ setContentsLayer(0);
m_contentLayerForImageOrVideo = false;
}
}
@@ -1431,7 +1431,7 @@ void GraphicsLayerCA::swapFromOrToTiledLayer(bool userTiledLayer)
[tiledLayer setLevelsOfDetail:1];
[tiledLayer setLevelsOfDetailBias:0];
- if (GraphicsLayer::graphicsContextsFlipped())
+ if (GraphicsLayer::compositingCoordinatesOrientation() == GraphicsLayer::CompositingCoordinatesBottomUp)
[tiledLayer setContentsGravity:@"bottomLeft"];
else
[tiledLayer setContentsGravity:@"topLeft"];
@@ -1476,24 +1476,6 @@ void GraphicsLayerCA::swapFromOrToTiledLayer(bool userTiledLayer)
#endif
}
-void GraphicsLayerCA::setHasContentsLayer(bool hasLayer)
-{
- BEGIN_BLOCK_OBJC_EXCEPTIONS
-
- if (hasLayer && !m_contentsLayer) {
- // create the inner layer
- WebLayer* contentsLayer = [WebLayer layer];
-#ifndef NDEBUG
- [contentsLayer setName:@"Contents Layer"];
-#endif
- setContentsLayer(contentsLayer);
-
- } else if (!hasLayer && m_contentsLayer)
- setContentsLayer(0);
-
- END_BLOCK_OBJC_EXCEPTIONS
-}
-
void GraphicsLayerCA::setContentsLayer(WebLayer* contentsLayer)
{
if (contentsLayer == m_contentsLayer)
@@ -1511,14 +1493,26 @@ void GraphicsLayerCA::setContentsLayer(WebLayer* contentsLayer)
[contentsLayer setStyle:[NSDictionary dictionaryWithObject:nullActionsDictionary() forKey:@"actions"]];
m_contentsLayer.adoptNS([contentsLayer retain]);
- [m_contentsLayer.get() setAnchorPoint:CGPointZero];
- [m_layer.get() addSublayer:m_contentsLayer.get()];
- updateContentsRect();
+ bool needToFlip = GraphicsLayer::compositingCoordinatesOrientation() == GraphicsLayer::CompositingCoordinatesBottomUp;
+ CGPoint anchorPoint = needToFlip ? CGPointMake(0.0f, 1.0f) : CGPointZero;
- // Set contents to nil if the layer does not draw its own content.
- if (m_client && !drawsContent())
- [m_layer.get() setContents:nil];
+ // If the layer world is flipped, we need to un-flip the contents layer
+ if (needToFlip) {
+ CATransform3D flipper = {
+ 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, -1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+ [m_contentsLayer.get() setTransform:flipper];
+ }
+ [m_contentsLayer.get() setAnchorPoint:anchorPoint];
+
+ // Insert the content layer first. Video elements require this, because they have
+ // shadow content that must display in front of the video.
+ [m_layer.get() insertSublayer:m_contentsLayer.get() atIndex:0];
+
+ updateContentsRect();
#ifndef NDEBUG
if (showDebugBorders()) {
diff --git a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h
index 677c31a..f90f258 100644
--- a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h
+++ b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h
@@ -30,6 +30,7 @@
#include "MediaPlayerPrivate.h"
#include "Timer.h"
+#include "FloatSize.h"
#include <wtf/RetainPtr.h>
#ifdef __OBJC__
@@ -127,6 +128,8 @@ private:
float maxTimeLoaded() const;
void disableUnsupportedTracks();
+ void sawUnsupportedTracks();
+ void cacheMovieScale();
bool metaDataAvailable() const { return m_qtMovie && m_readyState >= MediaPlayer::HaveMetadata; }
MediaPlayer* m_player;
@@ -142,7 +145,10 @@ private:
bool m_isStreaming;
bool m_visible;
IntRect m_rect;
+ FloatSize m_scaleFactor;
unsigned m_enabledTrackCount;
+ unsigned m_totalTrackCount;
+ bool m_hasUnsupportedTracks;
float m_duration;
#if DRAW_FRAME_RATE
int m_frameCountWhilePlaying;
diff --git a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm
index 74a9ff9..dd41ed3 100644
--- a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm
+++ b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm
@@ -37,6 +37,7 @@
#import "FrameView.h"
#import "GraphicsContext.h"
#import "KURL.h"
+#import "MIMETypeRegistry.h"
#import "SoftLinking.h"
#import "WebCoreSystemInterface.h"
#import <QTKit/QTKit.h>
@@ -67,6 +68,7 @@ SOFT_LINK(QTKit, QTMakeTime, QTTime, (long long timeValue, long timeScale), (tim
SOFT_LINK_CLASS(QTKit, QTMovie)
SOFT_LINK_CLASS(QTKit, QTMovieView)
+SOFT_LINK_POINTER(QTKit, QTTrackMediaTypeAttribute, NSString *)
SOFT_LINK_POINTER(QTKit, QTMediaTypeAttribute, NSString *)
SOFT_LINK_POINTER(QTKit, QTMediaTypeBase, NSString *)
SOFT_LINK_POINTER(QTKit, QTMediaTypeMPEG, NSString *)
@@ -81,6 +83,7 @@ SOFT_LINK_POINTER(QTKit, QTMovieIsActiveAttribute, NSString *)
SOFT_LINK_POINTER(QTKit, QTMovieLoadStateAttribute, NSString *)
SOFT_LINK_POINTER(QTKit, QTMovieLoadStateDidChangeNotification, NSString *)
SOFT_LINK_POINTER(QTKit, QTMovieNaturalSizeAttribute, NSString *)
+SOFT_LINK_POINTER(QTKit, QTMovieCurrentSizeAttribute, NSString *)
SOFT_LINK_POINTER(QTKit, QTMoviePreventExternalURLLinksAttribute, NSString *)
SOFT_LINK_POINTER(QTKit, QTMovieRateDidChangeNotification, NSString *)
SOFT_LINK_POINTER(QTKit, QTMovieSizeDidChangeNotification, NSString *)
@@ -90,10 +93,15 @@ SOFT_LINK_POINTER(QTKit, QTMovieURLAttribute, NSString *)
SOFT_LINK_POINTER(QTKit, QTMovieVolumeDidChangeNotification, NSString *)
SOFT_LINK_POINTER(QTKit, QTSecurityPolicyNoCrossSiteAttribute, NSString *)
SOFT_LINK_POINTER(QTKit, QTVideoRendererWebKitOnlyNewImageAvailableNotification, NSString *)
+#ifndef BUILDING_ON_TIGER
+SOFT_LINK_POINTER(QTKit, QTMovieApertureModeClean, NSString *)
+SOFT_LINK_POINTER(QTKit, QTMovieApertureModeAttribute, NSString *)
+#endif
#define QTMovie getQTMovieClass()
#define QTMovieView getQTMovieViewClass()
+#define QTTrackMediaTypeAttribute getQTTrackMediaTypeAttribute()
#define QTMediaTypeAttribute getQTMediaTypeAttribute()
#define QTMediaTypeBase getQTMediaTypeBase()
#define QTMediaTypeMPEG getQTMediaTypeMPEG()
@@ -108,6 +116,7 @@ SOFT_LINK_POINTER(QTKit, QTVideoRendererWebKitOnlyNewImageAvailableNotification,
#define QTMovieLoadStateAttribute getQTMovieLoadStateAttribute()
#define QTMovieLoadStateDidChangeNotification getQTMovieLoadStateDidChangeNotification()
#define QTMovieNaturalSizeAttribute getQTMovieNaturalSizeAttribute()
+#define QTMovieCurrentSizeAttribute getQTMovieCurrentSizeAttribute()
#define QTMoviePreventExternalURLLinksAttribute getQTMoviePreventExternalURLLinksAttribute()
#define QTMovieRateDidChangeNotification getQTMovieRateDidChangeNotification()
#define QTMovieSizeDidChangeNotification getQTMovieSizeDidChangeNotification()
@@ -117,6 +126,10 @@ SOFT_LINK_POINTER(QTKit, QTVideoRendererWebKitOnlyNewImageAvailableNotification,
#define QTMovieVolumeDidChangeNotification getQTMovieVolumeDidChangeNotification()
#define QTSecurityPolicyNoCrossSiteAttribute getQTSecurityPolicyNoCrossSiteAttribute()
#define QTVideoRendererWebKitOnlyNewImageAvailableNotification getQTVideoRendererWebKitOnlyNewImageAvailableNotification()
+#ifndef BUILDING_ON_TIGER
+#define QTMovieApertureModeClean getQTMovieApertureModeClean()
+#define QTMovieApertureModeAttribute getQTMovieApertureModeAttribute()
+#endif
// Older versions of the QTKit header don't have these constants.
#if !defined QTKIT_VERSION_MAX_ALLOWED || QTKIT_VERSION_MAX_ALLOWED <= QTKIT_VERSION_7_0
@@ -184,7 +197,10 @@ MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player)
, m_isStreaming(false)
, m_visible(false)
, m_rect()
+ , m_scaleFactor(1, 1)
, m_enabledTrackCount(0)
+ , m_totalTrackCount(0)
+ , m_hasUnsupportedTracks(false)
, m_duration(-1.0f)
#if DRAW_FRAME_RATE
, m_frameCountWhilePlaying(0)
@@ -221,10 +237,15 @@ void MediaPlayerPrivate::createQTMovie(const String& url)
[NSNumber numberWithBool:YES], QTMoviePreventExternalURLLinksAttribute,
[NSNumber numberWithBool:YES], QTSecurityPolicyNoCrossSiteAttribute,
[NSNumber numberWithBool:NO], QTMovieAskUnresolvedDataRefsAttribute,
- [NSNumber numberWithBool:YES], @"QTMovieOpenForPlaybackAttribute", // FIXME: Use defined attribute when required version of QT supports this attribute
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+ [NSNumber numberWithBool:YES], @"QTMovieOpenForPlaybackAttribute",
+#endif
+#ifndef BUILDING_ON_TIGER
+ QTMovieApertureModeClean, QTMovieApertureModeAttribute,
+#endif
nil];
- NSError* error = nil;
+ NSError *error = nil;
m_qtMovie.adoptNS([[QTMovie alloc] initWithAttributes:movieAttributes error:&error]);
// FIXME: Find a proper way to detect streaming content.
@@ -239,6 +260,17 @@ void MediaPlayerPrivate::createQTMovie(const String& url)
selector:@selector(loadStateChanged:)
name:QTMovieLoadStateDidChangeNotification
object:m_qtMovie.get()];
+
+ // In updateState(), we track when maxTimeLoaded() == duration().
+ // In newer version of QuickTime, a notification is emitted when maxTimeLoaded changes.
+ // In older version of QuickTime, QTMovieLoadStateDidChangeNotification be fired.
+ if (NSString *maxTimeLoadedChangeNotification = wkQTMovieMaxTimeLoadedChangeNotification()) {
+ [[NSNotificationCenter defaultCenter] addObserver:m_objcObserver.get()
+ selector:@selector(loadStateChanged:)
+ name:maxTimeLoadedChangeNotification
+ object:m_qtMovie.get()];
+ }
+
[[NSNotificationCenter defaultCenter] addObserver:m_objcObserver.get()
selector:@selector(rateChanged:)
name:QTMovieRateDidChangeNotification
@@ -545,7 +577,16 @@ IntSize MediaPlayerPrivate::naturalSize() const
{
if (!metaDataAvailable())
return IntSize();
- return IntSize([[m_qtMovie.get() attributeForKey:QTMovieNaturalSizeAttribute] sizeValue]);
+
+ // In spite of the name of this method, return QTMovieNaturalSizeAttribute transformed by the
+ // initial movie scale because the spec says intrinsic size is:
+ //
+ // ... the dimensions of the resource in CSS pixels after taking into account the resource's
+ // dimensions, aspect ratio, clean aperture, resolution, and so forth, as defined for the
+ // format used by the resource
+
+ NSSize naturalSize = [[m_qtMovie.get() attributeForKey:QTMovieNaturalSizeAttribute] sizeValue];
+ return IntSize(naturalSize.width * m_scaleFactor.width(), naturalSize.height * m_scaleFactor.height());
}
bool MediaPlayerPrivate::hasVideo() const
@@ -586,8 +627,14 @@ float MediaPlayerPrivate::maxTimeBuffered() const
float MediaPlayerPrivate::maxTimeSeekable() const
{
+ if (!metaDataAvailable())
+ return 0;
+
// infinite duration means live stream
- return isinf(duration()) ? 0 : maxTimeLoaded();
+ if (isinf(duration()))
+ return 0;
+
+ return wkQTMovieMaxTimeSeekable(m_qtMovie.get());
}
float MediaPlayerPrivate::maxTimeLoaded() const
@@ -629,6 +676,31 @@ void MediaPlayerPrivate::cancelLoad()
updateStates();
}
+void MediaPlayerPrivate::cacheMovieScale()
+{
+ NSSize initialSize = NSZeroSize;
+ NSSize naturalSize = [[m_qtMovie.get() attributeForKey:QTMovieNaturalSizeAttribute] sizeValue];
+
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+ // QTMovieCurrentSizeAttribute is not allowed with instances of QTMovie that have been
+ // opened with QTMovieOpenForPlaybackAttribute, so ask for the display transform attribute instead.
+ NSAffineTransform *displayTransform = [m_qtMovie.get() attributeForKey:@"QTMoviePreferredTransformAttribute"];
+ if (displayTransform)
+ initialSize = [displayTransform transformSize:naturalSize];
+ else {
+ initialSize.width = naturalSize.width;
+ initialSize.height = naturalSize.height;
+ }
+#else
+ initialSize = [[m_qtMovie.get() attributeForKey:QTMovieCurrentSizeAttribute] sizeValue];
+#endif
+
+ if (naturalSize.width)
+ m_scaleFactor.setWidth(initialSize.width / naturalSize.width);
+ if (naturalSize.height)
+ m_scaleFactor.setHeight(initialSize.height / naturalSize.height);
+}
+
void MediaPlayerPrivate::updateStates()
{
MediaPlayer::NetworkState oldNetworkState = m_networkState;
@@ -636,18 +708,37 @@ void MediaPlayerPrivate::updateStates()
long loadState = m_qtMovie ? [[m_qtMovie.get() attributeForKey:QTMovieLoadStateAttribute] longValue] : static_cast<long>(QTMovieLoadStateError);
- if (loadState >= QTMovieLoadStateLoaded && m_readyState < MediaPlayer::HaveMetadata && !m_player->inMediaDocument()) {
+ if (loadState >= QTMovieLoadStateLoaded && m_readyState < MediaPlayer::HaveMetadata) {
disableUnsupportedTracks();
- if (!m_enabledTrackCount)
+ if (m_player->inMediaDocument()) {
+ if (!m_enabledTrackCount || m_enabledTrackCount != m_totalTrackCount) {
+ // This is a type of media that we do not handle directly with a <video>
+ // element, likely streamed media or QuickTime VR. Tell the MediaPlayerClient
+ // that we noticed.
+ sawUnsupportedTracks();
+ return;
+ }
+ } else if (!m_enabledTrackCount) {
loadState = QTMovieLoadStateError;
+ }
+
+ if (loadState != QTMovieLoadStateError)
+ cacheMovieScale();
}
- if (loadState >= QTMovieLoadStateComplete && !m_isStreaming) {
+ BOOL completelyLoaded = !m_isStreaming && (loadState >= QTMovieLoadStateComplete);
+
+ // Note: QT indicates that we are fully loaded with QTMovieLoadStateComplete.
+ // However newer versions of QT do not, so we check maxTimeLoaded against duration.
+ if (!completelyLoaded && !m_isStreaming && metaDataAvailable())
+ completelyLoaded = maxTimeLoaded() == duration();
+
+ if (completelyLoaded) {
// "Loaded" is reserved for fully buffered movies, never the case when streaming
m_networkState = MediaPlayer::Loaded;
m_readyState = MediaPlayer::HaveEnoughData;
} else if (loadState >= QTMovieLoadStatePlaythroughOK) {
- m_readyState = MediaPlayer::HaveFutureData;
+ m_readyState = MediaPlayer::HaveEnoughData;
m_networkState = MediaPlayer::Loading;
} else if (loadState >= QTMovieLoadStatePlayable) {
// FIXME: This might not work correctly in streaming case, <rdar://problem/5693967>
@@ -657,11 +748,17 @@ void MediaPlayerPrivate::updateStates()
m_readyState = MediaPlayer::HaveMetadata;
m_networkState = MediaPlayer::Loading;
} else if (loadState > QTMovieLoadStateError) {
- m_readyState = MediaPlayer::HaveNothing;
+ m_readyState = MediaPlayer::HaveNothing;
m_networkState = MediaPlayer::Loading;
} else {
- float loaded = maxTimeLoaded();
+ if (m_player->inMediaDocument()) {
+ // Something went wrong in the loading of media within a standalone file.
+ // This can occur with chained refmovies pointing to streamed media.
+ sawUnsupportedTracks();
+ return;
+ }
+ float loaded = maxTimeLoaded();
if (!loaded)
m_readyState = MediaPlayer::HaveNothing;
@@ -684,7 +781,7 @@ void MediaPlayerPrivate::updateStates()
if (m_readyState != oldReadyState)
m_player->readyStateChanged();
- if (loadState >= QTMovieLoadStateLoaded && oldReadyState < MediaPlayer::HaveMetadata && m_player->visible())
+ if (loadState >= QTMovieLoadStateLoaded && (!m_qtMovieView && !m_qtVideoRenderer) && m_player->visible())
setUpVideoRendering();
if (loadState >= QTMovieLoadStateLoaded) {
@@ -699,28 +796,39 @@ void MediaPlayerPrivate::updateStates()
void MediaPlayerPrivate::loadStateChanged()
{
- updateStates();
+ if (!m_hasUnsupportedTracks)
+ updateStates();
}
void MediaPlayerPrivate::rateChanged()
{
+ if (m_hasUnsupportedTracks)
+ return;
+
updateStates();
m_player->rateChanged();
}
void MediaPlayerPrivate::sizeChanged()
{
- m_player->sizeChanged();
+ if (!m_hasUnsupportedTracks)
+ m_player->sizeChanged();
}
void MediaPlayerPrivate::timeChanged()
{
+ if (m_hasUnsupportedTracks)
+ return;
+
updateStates();
m_player->timeChanged();
}
void MediaPlayerPrivate::didEnd()
{
+ if (m_hasUnsupportedTracks)
+ return;
+
m_startedPlaying = false;
#if DRAW_FRAME_RATE
m_timeStoppedPlaying = [NSDate timeIntervalSinceReferenceDate];
@@ -729,22 +837,15 @@ void MediaPlayerPrivate::didEnd()
m_player->timeChanged();
}
-void MediaPlayerPrivate::setSize(const IntSize& size)
+void MediaPlayerPrivate::setSize(const IntSize&)
{
- if (!m_qtMovieView)
- return;
-
- m_rect.setSize(size);
- if (m_player->inMediaDocument())
- // We need the QTMovieView to be placed in the proper location for document mode.
- [m_qtMovieView.get() setFrame:m_rect];
- else {
- // We don't really need the QTMovieView in any specific location so let's just get it out of the way
- // where it won't intercept events or try to bring up the context menu.
- IntRect farAwayButCorrectSize(m_rect);
- farAwayButCorrectSize.move(-1000000, -1000000);
- [m_qtMovieView.get() setFrame:farAwayButCorrectSize];
- }
+ // Don't resize the view now because [view setFrame] also resizes the movie itself, and because
+ // the renderer calls this function immediately when we report a size change (QTMovieSizeDidChangeNotification)
+ // we can get into a feedback loop observing the size change and resetting the size, and this can cause
+ // QuickTime to miss resetting a movie's size when the media size changes (as happens with an rtsp movie
+ // once the rtsp server sends the track sizes). Instead we remember the size passed to paint() and resize
+ // the view when it changes.
+ // <rdar://problem/6336092> REGRESSION: rtsp movie does not resize correctly
}
void MediaPlayerPrivate::setVisible(bool b)
@@ -761,6 +862,9 @@ void MediaPlayerPrivate::setVisible(bool b)
void MediaPlayerPrivate::repaint()
{
+ if (m_hasUnsupportedTracks)
+ return;
+
#if DRAW_FRAME_RATE
if (m_startedPlaying) {
m_frameCountWhilePlaying++;
@@ -775,7 +879,7 @@ void MediaPlayerPrivate::repaint()
void MediaPlayerPrivate::paint(GraphicsContext* context, const IntRect& r)
{
- if (context->paintingDisabled())
+ if (context->paintingDisabled() || m_hasUnsupportedTracks)
return;
NSView *view = m_qtMovieView.get();
id qtVideoRenderer = m_qtVideoRenderer.get();
@@ -802,12 +906,28 @@ void MediaPlayerPrivate::paint(GraphicsContext* context, const IntRect& r)
[(id<WebKitVideoRenderingDetails>)qtVideoRenderer drawInRect:paintRect];
[NSGraphicsContext restoreGraphicsState];
} else {
- if (m_player->inMediaDocument() && r != m_rect) {
- // the QTMovieView needs to be placed in the proper location for document mode
- m_rect = r;
- [view setFrame:m_rect];
+ if (m_rect != r) {
+ m_rect = r;
+ if (m_player->inMediaDocument()) {
+ // the QTMovieView needs to be placed in the proper location for document mode
+ [view setFrame:m_rect];
+ }
+ else {
+ // We don't really need the QTMovieView in any specific location so let's just get it out of the way
+ // where it won't intercept events or try to bring up the context menu.
+ IntRect farAwayButCorrectSize(m_rect);
+ farAwayButCorrectSize.move(-1000000, -1000000);
+ [view setFrame:farAwayButCorrectSize];
+ }
}
- [view displayRectIgnoringOpacity:paintRect inContext:newContext];
+
+ if (m_player->inMediaDocument()) {
+ // If we're using a QTMovieView in a media document, the view may get layer-backed. AppKit won't update
+ // the layer hosting correctly if we call displayRectIgnoringOpacity:inContext:, so use displayRectIgnoringOpacity:
+ // in this case. See <rdar://problem/6702882>.
+ [view displayRectIgnoringOpacity:paintRect];
+ } else
+ [view displayRectIgnoringOpacity:paintRect inContext:newContext];
}
#if DRAW_FRAME_RATE
@@ -839,25 +959,57 @@ void MediaPlayerPrivate::paint(GraphicsContext* context, const IntRect& r)
[m_objcObserver.get() setDelayCallbacks:NO];
}
-static HashSet<String> mimeTypeCache()
+static void addFileTypesToCache(NSArray * fileTypes, HashSet<String> &cache)
+{
+ int count = [fileTypes count];
+ for (int n = 0; n < count; n++) {
+ CFStringRef ext = reinterpret_cast<CFStringRef>([fileTypes objectAtIndex:n]);
+ RetainPtr<CFStringRef> uti(AdoptCF, UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, ext, NULL));
+ if (!uti)
+ continue;
+ RetainPtr<CFStringRef> mime(AdoptCF, UTTypeCopyPreferredTagWithClass(uti.get(), kUTTagClassMIMEType));
+
+ // UTI types are missing many media related MIME types supported by QTKit, see rdar://6434168,
+ // and not all third party movie importers register their types, so if we didn't find a type for
+ // this extension look it up in the hard coded table in the MIME type regsitry.
+ if (!mime) {
+ // -movieFileTypes: returns both file extensions and OSTypes. The later are surrounded by single
+ // quotes, eg. 'MooV', so don't bother looking at those.
+ if (CFStringGetCharacterAtIndex(ext, 0) != '\'') {
+ String mediaType = MIMETypeRegistry::getMediaMIMETypeForExtension(String(ext));
+ if (!mediaType.isEmpty())
+ mime.adoptCF(mediaType.createCFString());
+ }
+ }
+ if (!mime)
+ continue;
+ cache.add(mime.get());
+ }
+}
+
+static HashSet<String> mimeCommonTypesCache()
{
DEFINE_STATIC_LOCAL(HashSet<String>, cache, ());
static bool typeListInitialized = false;
if (!typeListInitialized) {
+ typeListInitialized = true;
NSArray* fileTypes = [QTMovie movieFileTypes:QTIncludeCommonTypes];
- int count = [fileTypes count];
- for (int n = 0; n < count; n++) {
- CFStringRef ext = reinterpret_cast<CFStringRef>([fileTypes objectAtIndex:n]);
- RetainPtr<CFStringRef> uti(AdoptCF, UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, ext, NULL));
- if (!uti)
- continue;
- RetainPtr<CFStringRef> mime(AdoptCF, UTTypeCopyPreferredTagWithClass(uti.get(), kUTTagClassMIMEType));
- if (!mime)
- continue;
- cache.add(mime.get());
- }
+ addFileTypesToCache(fileTypes, cache);
+ }
+
+ return cache;
+}
+
+static HashSet<String> mimeModernTypesCache()
+{
+ DEFINE_STATIC_LOCAL(HashSet<String>, cache, ());
+ static bool typeListInitialized = false;
+
+ if (!typeListInitialized) {
typeListInitialized = true;
+ NSArray* fileTypes = [QTMovie movieFileTypes:(QTMovieFileTypeOptions)wkQTIncludeOnlyModernMediaFileTypes()];
+ addFileTypesToCache(fileTypes, cache);
}
return cache;
@@ -865,14 +1017,21 @@ static HashSet<String> mimeTypeCache()
void MediaPlayerPrivate::getSupportedTypes(HashSet<String>& types)
{
- types = mimeTypeCache();
+ // Note: this method starts QTKitServer if it isn't already running when in 64-bit because it has to return the list
+ // of every MIME type supported by QTKit.
+ types = mimeCommonTypesCache();
}
MediaPlayer::SupportsType MediaPlayerPrivate::supportsType(const String& type, const String& codecs)
{
- // only return "IsSupported" if there is no codecs parameter for now as there is no way to ask QT if it supports an
- // extended MIME type yet
- return mimeTypeCache().contains(type) ? (codecs && !codecs.isEmpty() ? MediaPlayer::MayBeSupported : MediaPlayer::IsSupported) : MediaPlayer::IsNotSupported;
+ // Only return "IsSupported" if there is no codecs parameter for now as there is no way to ask QT if it supports an
+ // extended MIME type yet.
+
+ // We check the "modern" type cache first, as it doesn't require QTKitServer to start.
+ if (mimeModernTypesCache().contains(type) || mimeCommonTypesCache().contains(type))
+ return (codecs && !codecs.isEmpty() ? MediaPlayer::MayBeSupported : MediaPlayer::IsSupported);
+
+ return MediaPlayer::IsNotSupported;
}
bool MediaPlayerPrivate::isAvailable()
@@ -900,6 +1059,7 @@ void MediaPlayerPrivate::disableUnsupportedTracks()
{
if (!m_qtMovie) {
m_enabledTrackCount = 0;
+ m_totalTrackCount = 0;
return;
}
@@ -911,15 +1071,19 @@ void MediaPlayerPrivate::disableUnsupportedTracks()
allowedTrackTypes->add(QTMediaTypeText);
allowedTrackTypes->add(QTMediaTypeBase);
allowedTrackTypes->add(QTMediaTypeMPEG);
- allowedTrackTypes->add("clcp");
- allowedTrackTypes->add("sbtl");
+ allowedTrackTypes->add("clcp"); // Closed caption
+ allowedTrackTypes->add("sbtl"); // Subtitle
+ allowedTrackTypes->add("odsm"); // MPEG-4 object descriptor stream
+ allowedTrackTypes->add("sdsm"); // MPEG-4 scene description stream
+ allowedTrackTypes->add("tmcd"); // timecode
+ allowedTrackTypes->add("tc64"); // timcode-64
}
NSArray *tracks = [m_qtMovie.get() tracks];
- unsigned trackCount = [tracks count];
- m_enabledTrackCount = trackCount;
- for (unsigned trackIndex = 0; trackIndex < trackCount; trackIndex++) {
+ m_totalTrackCount = [tracks count];
+ m_enabledTrackCount = m_totalTrackCount;
+ for (unsigned trackIndex = 0; trackIndex < m_totalTrackCount; trackIndex++) {
// Grab the track at the current index. If there isn't one there, then
// we can move onto the next one.
QTTrack *track = [tracks objectAtIndex:trackIndex];
@@ -931,24 +1095,18 @@ void MediaPlayerPrivate::disableUnsupportedTracks()
if (![track isEnabled])
continue;
- // Grab the track's media. We're going to check to see if we need to
- // disable the tracks. They could be unsupported.
- QTMedia *trackMedia = [track media];
- if (!trackMedia)
- continue;
-
- // Grab the media type for this track.
- NSString *mediaType = [trackMedia attributeForKey:QTMediaTypeAttribute];
+ // Get the track's media type.
+ NSString *mediaType = [track attributeForKey:QTTrackMediaTypeAttribute];
if (!mediaType)
continue;
-
+
// Test whether the media type is in our white list.
if (!allowedTrackTypes->contains(mediaType)) {
// If this track type is not allowed, then we need to disable it.
[track setEnabled:NO];
--m_enabledTrackCount;
}
-
+
// Disable chapter tracks. These are most likely to lead to trouble, as
// they will be composited under the video tracks, forcing QT to do extra
// work.
@@ -982,6 +1140,12 @@ void MediaPlayerPrivate::disableUnsupportedTracks()
}
}
+void MediaPlayerPrivate::sawUnsupportedTracks()
+{
+ m_hasUnsupportedTracks = true;
+ m_player->mediaPlayerClient()->mediaPlayerSawUnsupportedTracks(m_player);
+}
+
}
@implementation WebCoreMovieObserver
diff --git a/WebCore/platform/graphics/mac/SimpleFontDataMac.mm b/WebCore/platform/graphics/mac/SimpleFontDataMac.mm
index a3c10fa..cdde7cf 100644
--- a/WebCore/platform/graphics/mac/SimpleFontDataMac.mm
+++ b/WebCore/platform/graphics/mac/SimpleFontDataMac.mm
@@ -58,7 +58,7 @@ static inline float scaleEmToUnits(float x, unsigned unitsPerEm) { return x * (c
static bool initFontData(SimpleFontData* fontData)
{
- if (!fontData->m_font.cgFont())
+ if (!fontData->platformData().cgFont())
return false;
#ifdef BUILDING_ON_TIGER
@@ -66,7 +66,7 @@ static bool initFontData(SimpleFontData* fontData)
if (ATSUCreateStyle(&fontStyle) != noErr)
return false;
- ATSUFontID fontId = fontData->m_font.m_atsuFontID;
+ ATSUFontID fontId = fontData->platformData().m_atsuFontID;
if (!fontId) {
ATSUDisposeStyle(fontStyle);
return false;
@@ -153,7 +153,7 @@ void SimpleFontData::platformInit()
m_shapesArabic = false;
#endif
- m_syntheticBoldOffset = m_font.m_syntheticBold ? 1.0f : 0.f;
+ m_syntheticBoldOffset = m_platformData.m_syntheticBold ? 1.0f : 0.f;
bool failedSetup = false;
if (!initFontData(this)) {
@@ -165,7 +165,7 @@ void SimpleFontData::platformInit()
// It overrides the normal "Times" family font.
// It also appears to have a corrupt regular variant.
NSString *fallbackFontFamily;
- if ([[m_font.font() familyName] isEqual:@"Times"])
+ if ([[m_platformData.font() familyName] isEqual:@"Times"])
fallbackFontFamily = @"Times New Roman";
else
fallbackFontFamily = webFallbackFontFamily();
@@ -173,12 +173,12 @@ void SimpleFontData::platformInit()
// Try setting up the alternate font.
// This is a last ditch effort to use a substitute font when something has gone wrong.
#if !ERROR_DISABLED
- RetainPtr<NSFont> initialFont = m_font.font();
+ RetainPtr<NSFont> initialFont = m_platformData.font();
#endif
- if (m_font.font())
- m_font.setFont([[NSFontManager sharedFontManager] convertFont:m_font.font() toFamily:fallbackFontFamily]);
+ if (m_platformData.font())
+ m_platformData.setFont([[NSFontManager sharedFontManager] convertFont:m_platformData.font() toFamily:fallbackFontFamily]);
else
- m_font.setFont([NSFont fontWithName:fallbackFontFamily size:m_font.size()]);
+ m_platformData.setFont([NSFont fontWithName:fallbackFontFamily size:m_platformData.size()]);
#if !ERROR_DISABLED
NSString *filePath = pathFromFont(initialFont.get());
if (!filePath)
@@ -188,7 +188,7 @@ void SimpleFontData::platformInit()
if ([fallbackFontFamily isEqual:@"Times New Roman"]) {
// OK, couldn't setup Times New Roman as an alternate to Times, fallback
// on the system font. If this fails we have no alternative left.
- m_font.setFont([[NSFontManager sharedFontManager] convertFont:m_font.font() toFamily:webFallbackFontFamily()]);
+ m_platformData.setFont([[NSFontManager sharedFontManager] convertFont:m_platformData.font() toFamily:webFallbackFontFamily()]);
if (!initFontData(this)) {
// We tried, Times, Times New Roman, and the system font. No joy. We have to give up.
LOG_ERROR("unable to initialize with font %@ at %@", initialFont.get(), filePath);
@@ -203,14 +203,14 @@ void SimpleFontData::platformInit()
// Report the problem.
LOG_ERROR("Corrupt font detected, using %@ in place of %@ located at \"%@\".",
- [m_font.font() familyName], [initialFont.get() familyName], filePath);
+ [m_platformData.font() familyName], [initialFont.get() familyName], filePath);
}
// If all else fails, try to set up using the system font.
// This is probably because Times and Times New Roman are both unavailable.
if (failedSetup) {
- m_font.setFont([NSFont systemFontOfSize:[m_font.font() pointSize]]);
- LOG_ERROR("failed to set up font, using system font %s", m_font.font());
+ m_platformData.setFont([NSFont systemFontOfSize:[m_platformData.font() pointSize]]);
+ LOG_ERROR("failed to set up font, using system font %s", m_platformData.font());
initFontData(this);
}
@@ -218,15 +218,15 @@ void SimpleFontData::platformInit()
int iDescent;
int iLineGap;
#ifdef BUILDING_ON_TIGER
- wkGetFontMetrics(m_font.cgFont(), &iAscent, &iDescent, &iLineGap, &m_unitsPerEm);
+ wkGetFontMetrics(m_platformData.cgFont(), &iAscent, &iDescent, &iLineGap, &m_unitsPerEm);
#else
- iAscent = CGFontGetAscent(m_font.cgFont());
- iDescent = CGFontGetDescent(m_font.cgFont());
- iLineGap = CGFontGetLeading(m_font.cgFont());
- m_unitsPerEm = CGFontGetUnitsPerEm(m_font.cgFont());
+ iAscent = CGFontGetAscent(m_platformData.cgFont());
+ iDescent = CGFontGetDescent(m_platformData.cgFont());
+ iLineGap = CGFontGetLeading(m_platformData.cgFont());
+ m_unitsPerEm = CGFontGetUnitsPerEm(m_platformData.cgFont());
#endif
- float pointSize = m_font.m_size;
+ float pointSize = m_platformData.m_size;
float fAscent = scaleEmToUnits(iAscent, m_unitsPerEm) * pointSize;
float fDescent = -scaleEmToUnits(iDescent, m_unitsPerEm) * pointSize;
float fLineGap = scaleEmToUnits(iLineGap, m_unitsPerEm) * pointSize;
@@ -236,7 +236,7 @@ void SimpleFontData::platformInit()
// web standard. The AppKit adjustment of 20% is too big and is
// incorrectly added to line spacing, so we use a 15% adjustment instead
// and add it to the ascent.
- NSString *familyName = [m_font.font() familyName];
+ NSString *familyName = [m_platformData.font() familyName];
if ([familyName isEqualToString:@"Times"] || [familyName isEqualToString:@"Helvetica"] || [familyName isEqualToString:@"Courier"])
fAscent += floorf(((fAscent + fDescent) * 0.15f) + 0.5f);
else if ([familyName isEqualToString:@"Geeza Pro"]) {
@@ -264,14 +264,49 @@ void SimpleFontData::platformInit()
GlyphPage* glyphPageZero = GlyphPageTreeNode::getRootChild(this, 0)->page();
NSGlyph xGlyph = glyphPageZero ? glyphPageZero->glyphDataForCharacter('x').glyph : 0;
if (xGlyph) {
- NSRect xBox = [m_font.font() boundingRectForGlyph:xGlyph];
+ NSRect xBox = [m_platformData.font() boundingRectForGlyph:xGlyph];
// Use the maximum of either width or height because "x" is nearly square
// and web pages that foolishly use this metric for width will be laid out
// poorly if we return an accurate height. Classic case is Times 13 point,
// which has an "x" that is 7x6 pixels.
m_xHeight = MAX(NSMaxX(xBox), NSMaxY(xBox));
} else
- m_xHeight = [m_font.font() xHeight];
+ m_xHeight = [m_platformData.font() xHeight];
+}
+
+void SimpleFontData::platformCharWidthInit()
+{
+ m_avgCharWidth = 0.f;
+
+ // Calculate avgCharWidth according to http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6OS2.html
+ // We can try grabbing it out of the OS/2 table or via ATSFontGetHorizontalMetrics, but
+ // ATSFontGetHorizontalMetrics never seems to return a non-zero value and the OS/2 table
+ // contains zero for a large number of fonts.
+ GlyphPage* glyphPageZero = GlyphPageTreeNode::getRootChild(this, 0)->page();
+ if (glyphPageZero) {
+ static int weights[] = { 64, 14, 27, 35, 100, 20, 14, 42, 63, 3, 6, 35, 20, 56, 56, 17, 4, 49, 56, 71, 31, 10, 18, 3, 18, 2, 166 };
+ int numGlyphs = 27;
+ ASSERT(numGlyphs == sizeof(weights) / sizeof(int));
+ // Compute the weighted sum of the space character and the lowercase letters in the Latin alphabet.
+ float sum = 0.f;
+ int totalWeight = 0;
+ for (int i = 0; i < numGlyphs; i++) {
+ Glyph glyph = glyphPageZero->glyphDataForCharacter((i < 26 ? i + 'a' : ' ')).glyph;
+ if (glyph) {
+ totalWeight += weights[i];
+ sum += widthForGlyph(glyph) * weights[i];
+ }
+ }
+ if (sum > 0.f && totalWeight > 0)
+ m_avgCharWidth = sum / totalWeight;
+ }
+
+ m_maxCharWidth = 0.f;
+ if (m_platformData.font())
+ m_maxCharWidth = [m_platformData.font() maximumAdvancement].width;
+
+ // Fallback to a cross-platform estimate, which will populate these values if they are non-positive.
+ initCharWidths();
}
void SimpleFontData::platformDestroy()
@@ -290,13 +325,13 @@ SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDes
{
if (!m_smallCapsFontData) {
if (isCustomFont()) {
- FontPlatformData smallCapsFontData(m_font);
+ FontPlatformData smallCapsFontData(m_platformData);
smallCapsFontData.m_size = smallCapsFontData.m_size * smallCapsFontSizeMultiplier;
m_smallCapsFontData = new SimpleFontData(smallCapsFontData, true, false);
} else {
BEGIN_BLOCK_OBJC_EXCEPTIONS;
- float size = [m_font.font() pointSize] * smallCapsFontSizeMultiplier;
- FontPlatformData smallCapsFont([[NSFontManager sharedFontManager] convertFont:m_font.font() toSize:size]);
+ float size = [m_platformData.font() pointSize] * smallCapsFontSizeMultiplier;
+ FontPlatformData smallCapsFont([[NSFontManager sharedFontManager] convertFont:m_platformData.font() toSize:size]);
// AppKit resets the type information (screen/printer) when you convert a font to a different size.
// We have to fix up the font that we're handed back.
@@ -304,11 +339,11 @@ SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDes
if (smallCapsFont.font()) {
NSFontManager *fontManager = [NSFontManager sharedFontManager];
- NSFontTraitMask fontTraits = [fontManager traitsOfFont:m_font.font()];
+ NSFontTraitMask fontTraits = [fontManager traitsOfFont:m_platformData.font()];
- if (m_font.m_syntheticBold)
+ if (m_platformData.m_syntheticBold)
fontTraits |= NSBoldFontMask;
- if (m_font.m_syntheticOblique)
+ if (m_platformData.m_syntheticOblique)
fontTraits |= NSItalicFontMask;
NSFontTraitMask smallCapsFontTraits = [fontManager traitsOfFont:smallCapsFont.font()];
@@ -326,7 +361,7 @@ SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDes
bool SimpleFontData::containsCharacters(const UChar* characters, int length) const
{
NSString *string = [[NSString alloc] initWithCharactersNoCopy:const_cast<unichar*>(characters) length:length freeWhenDone:NO];
- NSCharacterSet *set = [[m_font.font() coveredCharacterSet] invertedSet];
+ NSCharacterSet *set = [[m_platformData.font() coveredCharacterSet] invertedSet];
bool result = set && [string rangeOfCharacterFromSet:set].location == NSNotFound;
[string release];
return result;
@@ -334,7 +369,7 @@ bool SimpleFontData::containsCharacters(const UChar* characters, int length) con
void SimpleFontData::determinePitch()
{
- NSFont* f = m_font.font();
+ NSFont* f = m_platformData.font();
// Special case Osaka-Mono.
// According to <rdar://problem/3999467>, we should treat Osaka-Mono as fixed pitch.
// Note that the AppKit does not report Osaka-Mono as fixed pitch.
@@ -356,11 +391,11 @@ void SimpleFontData::determinePitch()
float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
{
- NSFont* font = m_font.font();
- float pointSize = m_font.m_size;
+ NSFont* font = m_platformData.font();
+ float pointSize = m_platformData.m_size;
CGAffineTransform m = CGAffineTransformMakeScale(pointSize, pointSize);
CGSize advance;
- if (!wkGetGlyphTransformedAdvances(m_font.cgFont(), font, &m, &glyph, &advance)) {
+ if (!wkGetGlyphTransformedAdvances(m_platformData.cgFont(), font, &m, &glyph, &advance)) {
LOG_ERROR("Unable to cache glyph widths for %@ %f", [font displayName], pointSize);
advance.width = 0;
}
@@ -374,9 +409,9 @@ void SimpleFontData::checkShapesArabic() const
m_checkedShapesArabic = true;
- ATSUFontID fontID = m_font.m_atsuFontID;
+ ATSUFontID fontID = m_platformData.m_atsuFontID;
if (!fontID) {
- LOG_ERROR("unable to get ATSUFontID for %@", m_font.font());
+ LOG_ERROR("unable to get ATSUFontID for %@", m_platformData.font());
return;
}
@@ -404,7 +439,7 @@ CTFontRef SimpleFontData::getCTFont() const
if (getNSFont())
return toCTFontRef(getNSFont());
if (!m_CTFont)
- m_CTFont.adoptCF(CTFontCreateWithGraphicsFont(m_font.cgFont(), m_font.size(), NULL, NULL));
+ m_CTFont.adoptCF(CTFontCreateWithGraphicsFont(m_platformData.cgFont(), m_platformData.size(), NULL, NULL));
return m_CTFont.get();
}
diff --git a/WebCore/platform/graphics/mac/WebLayer.mm b/WebCore/platform/graphics/mac/WebLayer.mm
index 267b5bc..fad3916 100644
--- a/WebCore/platform/graphics/mac/WebLayer.mm
+++ b/WebCore/platform/graphics/mac/WebLayer.mm
@@ -32,7 +32,6 @@
#import "GraphicsContext.h"
#import "GraphicsLayer.h"
#import <QuartzCore/QuartzCore.h>
-#import "WebCoreTextRenderer.h"
#import <wtf/UnusedParam.h>
using namespace WebCore;