diff options
Diffstat (limited to 'Source/WebCore/platform/graphics/mac')
18 files changed, 213 insertions, 106 deletions
diff --git a/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp b/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp index 1a56664..07bc3ec 100644 --- a/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp +++ b/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp @@ -63,7 +63,8 @@ ComplexTextController::ComplexTextController(const Font* font, const TextRun& ru , m_glyphInCurrentRun(0) , m_characterInCurrentGlyph(0) , m_expansion(run.expansion()) - , m_afterExpansion(true) + , m_leadingExpansion(0) + , m_afterExpansion(!run.allowsLeadingExpansion()) , m_fallbackFonts(fallbackFonts) , m_minGlyphBoundingBoxX(numeric_limits<float>::max()) , m_maxGlyphBoundingBoxX(numeric_limits<float>::min()) @@ -73,7 +74,7 @@ ComplexTextController::ComplexTextController(const Font* font, const TextRun& ru if (!m_expansion) m_expansionPerOpportunity = 0; else { - bool isAfterExpansion = true; + bool isAfterExpansion = m_afterExpansion; unsigned expansionOpportunityCount = Font::expansionOpportunityCount(m_run.characters(), m_end, m_run.ltr() ? LTR : RTL, isAfterExpansion); if (isAfterExpansion && !m_run.allowsTrailingExpansion()) expansionOpportunityCount--; @@ -86,12 +87,16 @@ ComplexTextController::ComplexTextController(const Font* font, const TextRun& ru collectComplexTextRuns(); adjustGlyphsAndAdvances(); + + m_runWidthSoFar = m_leadingExpansion; } int ComplexTextController::offsetForPosition(float h, bool includePartialGlyphs) { if (h >= m_totalWidth) return m_run.ltr() ? m_end : 0; + + h -= m_leadingExpansion; if (h < 0) return m_run.ltr() ? 0 : m_end; @@ -472,16 +477,21 @@ void ComplexTextController::adjustGlyphsAndAdvances() // Handle justification and word-spacing. if (treatAsSpace || Font::isCJKIdeographOrSymbol(ch)) { // Distribute the run's total expansion evenly over all expansion opportunities in the run. - if (m_expansion && (!lastGlyph || m_run.allowsTrailingExpansion())) { + if (m_expansion) { if (!treatAsSpace && !m_afterExpansion) { // Take the expansion opportunity before this ideograph. m_expansion -= m_expansionPerOpportunity; m_totalWidth += m_expansionPerOpportunity; - m_adjustedAdvances.last().width += m_expansionPerOpportunity; + if (m_adjustedAdvances.isEmpty()) + m_leadingExpansion = m_expansionPerOpportunity; + else + m_adjustedAdvances.last().width += m_expansionPerOpportunity; + } + if (!lastGlyph || m_run.allowsTrailingExpansion()) { + m_expansion -= m_expansionPerOpportunity; + advance.width += m_expansionPerOpportunity; + m_afterExpansion = true; } - m_expansion -= m_expansionPerOpportunity; - advance.width += m_expansionPerOpportunity; - m_afterExpansion = true; } else m_afterExpansion = false; diff --git a/Source/WebCore/platform/graphics/mac/ComplexTextController.h b/Source/WebCore/platform/graphics/mac/ComplexTextController.h index 7373bfe..44a7994 100644 --- a/Source/WebCore/platform/graphics/mac/ComplexTextController.h +++ b/Source/WebCore/platform/graphics/mac/ComplexTextController.h @@ -175,6 +175,7 @@ private: unsigned m_characterInCurrentGlyph; float m_expansion; float m_expansionPerOpportunity; + float m_leadingExpansion; bool m_afterExpansion; HashSet<const SimpleFontData*>* m_fallbackFonts; diff --git a/Source/WebCore/platform/graphics/mac/ComplexTextControllerATSUI.cpp b/Source/WebCore/platform/graphics/mac/ComplexTextControllerATSUI.cpp index b367fdf..d965ada 100644 --- a/Source/WebCore/platform/graphics/mac/ComplexTextControllerATSUI.cpp +++ b/Source/WebCore/platform/graphics/mac/ComplexTextControllerATSUI.cpp @@ -264,7 +264,7 @@ static void disableLigatures(const SimpleFontData* fontData, ATSUStyle atsuStyle // Don't be too aggressive: if the font doesn't contain 'a', then assume that any ligatures it contains are // in characters that always go through ATSUI, and therefore allow them. Geeza Pro is an example. // See bugzilla 5166. - if ((typesettingFeatures & Ligatures) || (fontData->orientation() == Horizontal && fontData->platformData().allowsLigatures())) + if ((typesettingFeatures & Ligatures) || (fontData->platformData().orientation() == Horizontal && fontData->platformData().allowsLigatures())) return; ATSUFontFeatureType featureTypes[] = { kLigaturesType }; diff --git a/Source/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.cpp b/Source/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.cpp index 239113f..d2fbaf5 100644 --- a/Source/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.cpp +++ b/Source/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.cpp @@ -144,17 +144,17 @@ void ComplexTextController::collectComplexTextRunsForCharactersCoreText(const UC static CFDictionaryRef rtlTypesetterOptions = CFDictionaryCreate(kCFAllocatorDefault, optionKeys, rtlOptionValues, WTF_ARRAY_LENGTH(optionKeys), &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) - ProviderInfo info = { cp, length, fontData->getCFStringAttributes(m_font.typesettingFeatures()) }; + ProviderInfo info = { cp, length, fontData->getCFStringAttributes(m_font.typesettingFeatures(), fontData->platformData().orientation()) }; RetainPtr<CTTypesetterRef> typesetter(AdoptCF, wkCreateCTTypesetterWithUniCharProviderAndOptions(&provideStringAndAttributes, 0, &info, m_run.ltr() ? ltrTypesetterOptions : rtlTypesetterOptions)); #else RetainPtr<CFStringRef> string(AdoptCF, CFStringCreateWithCharactersNoCopy(kCFAllocatorDefault, cp, length, kCFAllocatorNull)); - RetainPtr<CFAttributedStringRef> attributedString(AdoptCF, CFAttributedStringCreate(kCFAllocatorDefault, string.get(), fontData->getCFStringAttributes(m_font.typesettingFeatures()))); + RetainPtr<CFAttributedStringRef> attributedString(AdoptCF, CFAttributedStringCreate(kCFAllocatorDefault, string.get(), fontData->getCFStringAttributes(m_font.typesettingFeatures(), fontData->platformData().orientation()))); RetainPtr<CTTypesetterRef> typesetter(AdoptCF, CTTypesetterCreateWithAttributedStringAndOptions(attributedString.get(), m_run.ltr() ? ltrTypesetterOptions : rtlTypesetterOptions)); #endif line.adoptCF(CTTypesetterCreateLine(typesetter.get(), CFRangeMake(0, 0))); } else { - ProviderInfo info = { cp, length, fontData->getCFStringAttributes(m_font.typesettingFeatures()) }; + ProviderInfo info = { cp, length, fontData->getCFStringAttributes(m_font.typesettingFeatures(), fontData->platformData().orientation()) }; line.adoptCF(wkCreateCTLineWithUniCharProvider(&provideStringAndAttributes, 0, &info)); } diff --git a/Source/WebCore/platform/graphics/mac/FontCacheMac.mm b/Source/WebCore/platform/graphics/mac/FontCacheMac.mm index c254906..f7ae6b7 100644 --- a/Source/WebCore/platform/graphics/mac/FontCacheMac.mm +++ b/Source/WebCore/platform/graphics/mac/FontCacheMac.mm @@ -211,7 +211,7 @@ FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontD bool syntheticBold = isAppKitFontWeightBold(weight) && !isAppKitFontWeightBold(actualWeight); bool syntheticOblique = (traits & NSFontItalicTrait) && !(actualTraits & NSFontItalicTrait); - return new FontPlatformData(platformFont, size, syntheticBold, syntheticOblique, fontDescription.orientation(), fontDescription.widthVariant()); + return new FontPlatformData(platformFont, size, syntheticBold, syntheticOblique, fontDescription.orientation(), fontDescription.textOrientation(), fontDescription.widthVariant()); } } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/mac/FontComplexTextMac.cpp b/Source/WebCore/platform/graphics/mac/FontComplexTextMac.cpp index eed49a5..fe2a22c 100644 --- a/Source/WebCore/platform/graphics/mac/FontComplexTextMac.cpp +++ b/Source/WebCore/platform/graphics/mac/FontComplexTextMac.cpp @@ -111,8 +111,8 @@ float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon { ComplexTextController controller(this, run, true, fallbackFonts); if (glyphOverflow) { - glyphOverflow->top = max<int>(glyphOverflow->top, ceilf(-controller.minGlyphBoundingBoxY()) - fontMetrics().ascent()); - glyphOverflow->bottom = max<int>(glyphOverflow->bottom, ceilf(controller.maxGlyphBoundingBoxY()) - fontMetrics().descent()); + glyphOverflow->top = max<int>(glyphOverflow->top, ceilf(-controller.minGlyphBoundingBoxY()) - (glyphOverflow->computeBounds ? 0 : fontMetrics().ascent())); + glyphOverflow->bottom = max<int>(glyphOverflow->bottom, ceilf(controller.maxGlyphBoundingBoxY()) - (glyphOverflow->computeBounds ? 0 : fontMetrics().descent())); glyphOverflow->left = max<int>(0, ceilf(-controller.minGlyphBoundingBoxX())); glyphOverflow->right = max<int>(0, ceilf(controller.maxGlyphBoundingBoxX() - controller.totalWidth())); } diff --git a/Source/WebCore/platform/graphics/mac/FontCustomPlatformData.cpp b/Source/WebCore/platform/graphics/mac/FontCustomPlatformData.cpp index f2bc33d..383adef 100644 --- a/Source/WebCore/platform/graphics/mac/FontCustomPlatformData.cpp +++ b/Source/WebCore/platform/graphics/mac/FontCustomPlatformData.cpp @@ -38,9 +38,9 @@ FontCustomPlatformData::~FontCustomPlatformData() CGFontRelease(m_cgFont); } -FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation orientation, FontWidthVariant widthVariant, FontRenderingMode) +FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation orientation, TextOrientation textOrientation, FontWidthVariant widthVariant, FontRenderingMode) { - return FontPlatformData(m_cgFont, size, bold, italic, orientation, widthVariant); + return FontPlatformData(m_cgFont, size, bold, italic, orientation, textOrientation, widthVariant); } FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer) diff --git a/Source/WebCore/platform/graphics/mac/FontCustomPlatformData.h b/Source/WebCore/platform/graphics/mac/FontCustomPlatformData.h index c7ae1ca..c625304 100644 --- a/Source/WebCore/platform/graphics/mac/FontCustomPlatformData.h +++ b/Source/WebCore/platform/graphics/mac/FontCustomPlatformData.h @@ -24,6 +24,7 @@ #include "FontOrientation.h" #include "FontRenderingMode.h" #include "FontWidthVariant.h" +#include "TextOrientation.h" #include <CoreFoundation/CFBase.h> #include <wtf/Forward.h> #include <wtf/Noncopyable.h> @@ -48,7 +49,7 @@ public: ~FontCustomPlatformData(); - FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, FontWidthVariant = RegularWidth, FontRenderingMode = NormalRenderingMode); + FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, TextOrientation = TextOrientationVerticalRight, FontWidthVariant = RegularWidth, FontRenderingMode = NormalRenderingMode); static bool supportsFormat(const String&); diff --git a/Source/WebCore/platform/graphics/mac/FontMac.mm b/Source/WebCore/platform/graphics/mac/FontMac.mm index acd7562..4c28ead 100644 --- a/Source/WebCore/platform/graphics/mac/FontMac.mm +++ b/Source/WebCore/platform/graphics/mac/FontMac.mm @@ -52,28 +52,72 @@ bool Font::canExpandAroundIdeographsInComplexText() return true; } -static void showGlyphsWithAdvances(const SimpleFontData* font, CGContextRef context, const CGGlyph* glyphs, const CGSize* advances, size_t count) +// CTFontGetVerticalTranslationsForGlyphs is different on Snow Leopard. It returns values for a font-size of 1 +// without unitsPerEm applied. We have to apply a transform that scales up to the point size and that also +// divides by unitsPerEm. +static bool hasBrokenCTFontGetVerticalTranslationsForGlyphs() { +// Chromium runs the same binary on both Leopard and Snow Leopard, so the check has to happen at runtime. +#if PLATFORM(CHROMIUM) + static bool isCached = false; + static bool result; + + if (!isCached) { + SInt32 majorVersion = 0; + SInt32 minorVersion = 0; + Gestalt(gestaltSystemVersionMajor, &majorVersion); + Gestalt(gestaltSystemVersionMinor, &minorVersion); + result = majorVersion == 10 && minorVersion == 6; + isCached = true; + } + return result; +#elif defined(BUILDING_ON_SNOW_LEOPARD) + return true; +#else + return false; +#endif +} + +static void showGlyphsWithAdvances(const FloatPoint& point, const SimpleFontData* font, CGContextRef context, const CGGlyph* glyphs, const CGSize* advances, size_t count) +{ + CGContextSetTextPosition(context, point.x(), point.y()); + const FontPlatformData& platformData = font->platformData(); if (!platformData.isColorBitmapFont()) { CGAffineTransform savedMatrix; - bool isVertical = font->orientation() == Vertical; - + bool isVertical = font->platformData().orientation() == Vertical; if (isVertical) { CGAffineTransform rotateLeftTransform = CGAffineTransformMake(0, -1, 1, 0, 0, 0); - savedMatrix = CGContextGetTextMatrix(context); CGAffineTransform runMatrix = CGAffineTransformConcat(savedMatrix, rotateLeftTransform); - // Move start point to put glyphs into original region. - runMatrix.tx = savedMatrix.tx + font->fontMetrics().ascent(); - runMatrix.ty = savedMatrix.ty + font->fontMetrics().descent(); CGContextSetTextMatrix(context, runMatrix); - } - - CGContextShowGlyphsWithAdvances(context, glyphs, advances, count); - - if (isVertical) + + CGAffineTransform translationsTransform; + if (hasBrokenCTFontGetVerticalTranslationsForGlyphs()) { + translationsTransform = CGAffineTransformMake(platformData.m_size, 0, 0, platformData.m_size, 0, 0); + translationsTransform = CGAffineTransformConcat(translationsTransform, rotateLeftTransform); + CGFloat unitsPerEm = CGFontGetUnitsPerEm(platformData.cgFont()); + translationsTransform = CGAffineTransformConcat(translationsTransform, CGAffineTransformMakeScale(1 / unitsPerEm, 1 / unitsPerEm)); + } else { + translationsTransform = rotateLeftTransform; + } + Vector<CGSize, 256> translations(count); + CTFontGetVerticalTranslationsForGlyphs(platformData.ctFont(), glyphs, translations.data(), count); + + CGAffineTransform transform = CGAffineTransformInvert(CGContextGetTextMatrix(context)); + + CGPoint position = FloatPoint(point.x(), point.y() + font->fontMetrics().floatAscent(IdeographicBaseline) - font->fontMetrics().floatAscent()); + Vector<CGPoint, 256> positions(count); + for (size_t i = 0; i < count; ++i) { + CGSize translation = CGSizeApplyAffineTransform(translations[i], translationsTransform); + positions[i] = CGPointApplyAffineTransform(CGPointMake(position.x - translation.width, position.y + translation.height), transform); + position.x += advances[i].width; + position.y += advances[i].height; + } + CGContextShowGlyphsAtPositions(context, glyphs, positions.data(), count); CGContextSetTextMatrix(context, savedMatrix); + } else + CGContextShowGlyphsWithAdvances(context, glyphs, advances, count); } #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) else { @@ -188,21 +232,15 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons float shadowTextX = point.x() + shadowOffset.width(); // If shadows are ignoring transforms, then we haven't applied the Y coordinate flip yet, so down is negative. float shadowTextY = point.y() + shadowOffset.height() * (context->shadowsIgnoreTransforms() ? -1 : 1); - CGContextSetTextPosition(cgContext, shadowTextX, shadowTextY); - showGlyphsWithAdvances(font, cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); - if (font->syntheticBoldOffset()) { - CGContextSetTextPosition(cgContext, shadowTextX + font->syntheticBoldOffset(), shadowTextY); - showGlyphsWithAdvances(font, cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); - } + showGlyphsWithAdvances(FloatPoint(shadowTextX, shadowTextY), font, cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); + if (font->syntheticBoldOffset()) + showGlyphsWithAdvances(FloatPoint(shadowTextX + font->syntheticBoldOffset(), shadowTextY), font, cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); context->setFillColor(fillColor, fillColorSpace); } - CGContextSetTextPosition(cgContext, point.x(), point.y()); - showGlyphsWithAdvances(font, cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); - if (font->syntheticBoldOffset()) { - CGContextSetTextPosition(cgContext, point.x() + font->syntheticBoldOffset(), point.y()); - showGlyphsWithAdvances(font, cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); - } + showGlyphsWithAdvances(point, font, cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); + if (font->syntheticBoldOffset()) + showGlyphsWithAdvances(FloatPoint(point.x() + font->syntheticBoldOffset(), point.y()), font, cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs); if (hasSimpleShadow) context->setShadow(shadowOffset, shadowBlur, shadowColor, shadowColorSpace); diff --git a/Source/WebCore/platform/graphics/mac/GlyphPageTreeNodeMac.cpp b/Source/WebCore/platform/graphics/mac/GlyphPageTreeNodeMac.cpp index fe2b33a..18d0dc5 100644 --- a/Source/WebCore/platform/graphics/mac/GlyphPageTreeNodeMac.cpp +++ b/Source/WebCore/platform/graphics/mac/GlyphPageTreeNodeMac.cpp @@ -39,7 +39,7 @@ namespace WebCore { #ifndef BUILDING_ON_TIGER static bool shouldUseCoreText(UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData) { - if (fontData->platformData().widthVariant() != RegularWidth || (fontData->orientation() == Vertical && !fontData->isBrokenIdeographFont())) { + 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 (!Font::isCJKIdeograph(buffer[i])) @@ -70,7 +70,7 @@ bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned b } 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(), fontData->getCFStringAttributes(0))); + RetainPtr<CFAttributedStringRef> attributedString(AdoptCF, CFAttributedStringCreate(kCFAllocatorDefault, string.get(), fontData->getCFStringAttributes(0, fontData->hasVerticalGlyphs() ? Vertical : Horizontal))); RetainPtr<CTLineRef> line(AdoptCF, CTLineCreateWithAttributedString(attributedString.get())); CFArrayRef runArray = CTLineGetGlyphRuns(line.get()); diff --git a/Source/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm b/Source/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm index aaa250b..997c976 100644 --- a/Source/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm +++ b/Source/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm @@ -93,9 +93,14 @@ GraphicsContext3D::GraphicsContext3D(GraphicsContext3D::Attributes attrs, HostWi , m_attrs(attrs) , m_contextObj(0) , m_texture(0) + , m_compositorTexture(0) , m_fbo(0) , m_depthStencilBuffer(0) + , m_layerComposited(false) + , m_internalColorFormat(0) , m_boundFBO(0) + , m_activeTexture(0) + , m_boundTexture0(0) , m_multisampleFBO(0) , m_multisampleDepthStencilBuffer(0) , m_multisampleColorBuffer(0) @@ -166,6 +171,12 @@ GraphicsContext3D::GraphicsContext3D(GraphicsContext3D::Attributes attrs, HostWi ::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + ::glGenTextures(1, &m_compositorTexture); + ::glBindTexture(GL_TEXTURE_2D, m_compositorTexture); + ::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + ::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); ::glBindTexture(GL_TEXTURE_2D, 0); // create an FBO @@ -215,6 +226,7 @@ GraphicsContext3D::~GraphicsContext3D() if (m_contextObj) { CGLSetCurrentContext(m_contextObj); ::glDeleteTextures(1, &m_texture); + ::glDeleteTextures(1, &m_compositorTexture); if (m_attrs.antialias) { ::glDeleteRenderbuffersEXT(1, &m_multisampleColorBuffer); if (m_attrs.stencil || m_attrs.depth) diff --git a/Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h b/Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h index 80bc94e..7bdc064 100644 --- a/Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h +++ b/Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.h @@ -54,6 +54,8 @@ class WebCoreMovieObserver; #endif namespace WebCore { + +class ApplicationCacheResource; class MediaPlayerPrivateQTKit : public MediaPlayerPrivateInterface { public: @@ -139,6 +141,7 @@ private: void createQTMovie(const String& url); void createQTMovie(NSURL *, NSDictionary *movieAttributes); + void createQTMovie(ApplicationCacheResource*); enum MediaRenderingMode { MediaRenderingNone, MediaRenderingMovieView, MediaRenderingSoftwareRenderer, MediaRenderingMovieLayer }; MediaRenderingMode currentRenderingMode() const; @@ -178,6 +181,8 @@ private: virtual double maximumDurationToCacheMediaTime() const { return 5; } virtual void setPrivateBrowsingMode(bool); + + NSMutableDictionary* commonMovieAttributes(); MediaPlayer* m_player; RetainPtr<QTMovie> m_qtMovie; @@ -211,6 +216,7 @@ private: double m_timeStartedPlaying; double m_timeStoppedPlaying; #endif + mutable FloatSize m_cachedNaturalSize; }; } diff --git a/Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm b/Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm index ecb7d9f..400fdfb 100644 --- a/Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm +++ b/Source/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm @@ -29,11 +29,18 @@ #import "MediaPlayerPrivateQTKit.h" +#if ENABLE(OFFLINE_WEB_APPLICATIONS) +#include "ApplicationCacheHost.h" +#include "ApplicationCacheResource.h" +#include "DocumentLoader.h" +#endif + #ifdef BUILDING_ON_TIGER #import "AutodrainedPool.h" #endif #import "BlockExceptions.h" +#import "DocumentLoader.h" #import "FrameView.h" #import "GraphicsContext.h" #import "KURL.h" @@ -83,6 +90,7 @@ SOFT_LINK_POINTER(QTKit, QTMediaTypeText, NSString *) SOFT_LINK_POINTER(QTKit, QTMediaTypeVideo, NSString *) SOFT_LINK_POINTER(QTKit, QTMovieAskUnresolvedDataRefsAttribute, NSString *) SOFT_LINK_POINTER(QTKit, QTMovieLoopsAttribute, NSString *) +SOFT_LINK_POINTER(QTKit, QTMovieDataAttribute, NSString *) SOFT_LINK_POINTER(QTKit, QTMovieDataSizeAttribute, NSString *) SOFT_LINK_POINTER(QTKit, QTMovieDidEndNotification, NSString *) SOFT_LINK_POINTER(QTKit, QTMovieHasVideoAttribute, NSString *) @@ -120,6 +128,7 @@ SOFT_LINK_POINTER(QTKit, QTMovieApertureModeAttribute, NSString *) #define QTMediaTypeVideo getQTMediaTypeVideo() #define QTMovieAskUnresolvedDataRefsAttribute getQTMovieAskUnresolvedDataRefsAttribute() #define QTMovieLoopsAttribute getQTMovieLoopsAttribute() +#define QTMovieDataAttribute getQTMovieDataAttribute() #define QTMovieDataSizeAttribute getQTMovieDataSizeAttribute() #define QTMovieDidEndNotification getQTMovieDidEndNotification() #define QTMovieHasVideoAttribute getQTMovieHasVideoAttribute() @@ -241,21 +250,26 @@ MediaPlayerPrivateQTKit::~MediaPlayerPrivateQTKit() [m_objcObserver.get() disconnect]; } -void MediaPlayerPrivateQTKit::createQTMovie(const String& url) +NSMutableDictionary* MediaPlayerPrivateQTKit::commonMovieAttributes() { - NSURL *cocoaURL = KURL(ParsedURLString, url); - NSMutableDictionary *movieAttributes = [NSMutableDictionary dictionaryWithObjectsAndKeys: - cocoaURL, QTMovieURLAttribute, - [NSNumber numberWithBool:m_player->preservesPitch()], QTMovieRateChangesPreservePitchAttribute, - [NSNumber numberWithBool:YES], QTMoviePreventExternalURLLinksAttribute, - [NSNumber numberWithBool:YES], QTSecurityPolicyNoCrossSiteAttribute, - [NSNumber numberWithBool:NO], QTMovieAskUnresolvedDataRefsAttribute, - [NSNumber numberWithBool:NO], QTMovieLoopsAttribute, - [NSNumber numberWithBool:!m_privateBrowsing], @"QTMovieAllowPersistentCacheAttribute", + return [NSMutableDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithBool:m_player->preservesPitch()], QTMovieRateChangesPreservePitchAttribute, + [NSNumber numberWithBool:YES], QTMoviePreventExternalURLLinksAttribute, + [NSNumber numberWithBool:YES], QTSecurityPolicyNoCrossSiteAttribute, + [NSNumber numberWithBool:NO], QTMovieAskUnresolvedDataRefsAttribute, + [NSNumber numberWithBool:NO], QTMovieLoopsAttribute, + [NSNumber numberWithBool:!m_privateBrowsing], @"QTMovieAllowPersistentCacheAttribute", #ifndef BUILDING_ON_TIGER - QTMovieApertureModeClean, QTMovieApertureModeAttribute, + QTMovieApertureModeClean, QTMovieApertureModeAttribute, #endif - nil]; + nil]; +} + +void MediaPlayerPrivateQTKit::createQTMovie(const String& url) +{ + NSURL *cocoaURL = KURL(ParsedURLString, url); + NSMutableDictionary *movieAttributes = commonMovieAttributes(); + [movieAttributes setValue:cocoaURL forKey:QTMovieURLAttribute]; #if !defined(BUILDING_ON_LEOPARD) CFDictionaryRef proxySettings = CFNetworkCopySystemProxySettings(); @@ -291,6 +305,33 @@ void MediaPlayerPrivateQTKit::createQTMovie(const String& url) createQTMovie(cocoaURL, movieAttributes); } +void MediaPlayerPrivateQTKit::createQTMovie(ApplicationCacheResource* resource) +{ +#if ENABLE(OFFLINE_WEB_APPLICATIONS) + ASSERT(resource); + + NSMutableDictionary *movieAttributes = commonMovieAttributes(); + [movieAttributes setObject:[NSNumber numberWithBool:YES] forKey:@"QTMovieOpenForPlaybackAttribute"]; + + // ApplicationCacheResources can supply either a data pointer, or a path to a locally cached + // flat file. We would prefer the path over the data, but QTKit can handle either: + String localPath = resource->path(); + NSURL* cocoaURL = !localPath.isEmpty() ? [NSURL fileURLWithPath:localPath isDirectory:NO] : nil; + if (cocoaURL) + [movieAttributes setValue:cocoaURL forKey:QTMovieURLAttribute]; + else { + NSData* movieData = resource->data()->createNSData(); + [movieAttributes setValue:movieData forKey:QTMovieDataAttribute]; + [movieData release]; + } + + createQTMovie(cocoaURL, movieAttributes); + +#else + ASSERT_NOT_REACHED(); +#endif +} + static void disableComponentsOnce() { static bool sComponentsDisabled = false; @@ -658,6 +699,14 @@ void MediaPlayerPrivateQTKit::loadInternal(const String& url) [m_objcObserver.get() setDelayCallbacks:YES]; +#if ENABLE(OFFLINE_WEB_APPLICATIONS) + Frame* frame = m_player->frameView() ? m_player->frameView()->frame() : NULL; + ApplicationCacheHost* cacheHost = frame ? frame->loader()->documentLoader()->applicationCacheHost() : NULL; + ApplicationCacheResource* resource = NULL; + if (cacheHost && cacheHost->shouldLoadResourceFromApplicationCache(ResourceRequest(url), resource) && resource) + createQTMovie(resource); + else +#endif createQTMovie(url); [m_objcObserver.get() loadStateChanged:nil]; @@ -827,8 +876,19 @@ IntSize MediaPlayerPrivateQTKit::naturalSize() const // 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()); + FloatSize naturalSize([[m_qtMovie.get() attributeForKey:QTMovieNaturalSizeAttribute] sizeValue]); + if (naturalSize.isEmpty() && m_isStreaming) { + // HTTP Live Streams will occasionally return {0,0} natural sizes while scrubbing. + // Work around this problem (<rdar://problem/9078563>) by returning the last valid + // cached natural size: + naturalSize = m_cachedNaturalSize; + } else { + // Unfortunately, due to another QTKit bug (<rdar://problem/9082071>) we won't get a sizeChanged + // event when this happens, so we must cache the last valid naturalSize here: + m_cachedNaturalSize = naturalSize; + } + + return IntSize(naturalSize.width() * m_scaleFactor.width(), naturalSize.height() * m_scaleFactor.height()); } bool MediaPlayerPrivateQTKit::hasVideo() const diff --git a/Source/WebCore/platform/graphics/mac/SimpleFontDataCoreText.cpp b/Source/WebCore/platform/graphics/mac/SimpleFontDataCoreText.cpp index 452bd54..832bb9d 100644 --- a/Source/WebCore/platform/graphics/mac/SimpleFontDataCoreText.cpp +++ b/Source/WebCore/platform/graphics/mac/SimpleFontDataCoreText.cpp @@ -39,15 +39,17 @@ using namespace std; namespace WebCore { -CFDictionaryRef SimpleFontData::getCFStringAttributes(TypesettingFeatures typesettingFeatures) const +CFDictionaryRef SimpleFontData::getCFStringAttributes(TypesettingFeatures typesettingFeatures, FontOrientation orientation) const { unsigned key = typesettingFeatures + 1; pair<HashMap<unsigned, RetainPtr<CFDictionaryRef> >::iterator, bool> addResult = m_CFStringAttributes.add(key, RetainPtr<CFDictionaryRef>()); RetainPtr<CFDictionaryRef>& attributesDictionary = addResult.first->second; if (!addResult.second) return attributesDictionary.get(); + + bool treatLineAsVertical = orientation == Vertical; - bool allowLigatures = (orientation() == Horizontal && platformData().allowsLigatures()) || (typesettingFeatures & Ligatures); + bool allowLigatures = (!treatLineAsVertical && platformData().allowsLigatures()) || (typesettingFeatures & Ligatures); static const int ligaturesNotAllowedValue = 0; static CFNumberRef ligaturesNotAllowed = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &ligaturesNotAllowedValue); @@ -60,13 +62,13 @@ CFDictionaryRef SimpleFontData::getCFStringAttributes(TypesettingFeatures typese static CFNumberRef kerningAdjustment = CFNumberCreate(kCFAllocatorDefault, kCFNumberFloatType, &kerningAdjustmentValue); static const void* keysWithKerningDisabled[] = { kCTFontAttributeName, kCTKernAttributeName, kCTLigatureAttributeName, kCTVerticalFormsAttributeName }; const void* valuesWithKerningDisabled[] = { platformData().ctFont(), kerningAdjustment, allowLigatures - ? ligaturesAllowed : ligaturesNotAllowed, orientation() == Vertical ? kCFBooleanTrue : kCFBooleanFalse }; + ? ligaturesAllowed : ligaturesNotAllowed, treatLineAsVertical ? kCFBooleanTrue : kCFBooleanFalse }; attributesDictionary.adoptCF(CFDictionaryCreate(0, keysWithKerningDisabled, valuesWithKerningDisabled, WTF_ARRAY_LENGTH(keysWithKerningDisabled), &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); } else { // By omitting the kCTKernAttributeName attribute, we get Core Text's standard kerning. static const void* keysWithKerningEnabled[] = { kCTFontAttributeName, kCTLigatureAttributeName, kCTVerticalFormsAttributeName }; - const void* valuesWithKerningEnabled[] = { platformData().ctFont(), allowLigatures ? ligaturesAllowed : ligaturesNotAllowed, orientation() == Vertical ? kCFBooleanTrue : kCFBooleanFalse }; + const void* valuesWithKerningEnabled[] = { platformData().ctFont(), allowLigatures ? ligaturesAllowed : ligaturesNotAllowed, treatLineAsVertical ? kCFBooleanTrue : kCFBooleanFalse }; attributesDictionary.adoptCF(CFDictionaryCreate(0, keysWithKerningEnabled, valuesWithKerningEnabled, WTF_ARRAY_LENGTH(keysWithKerningEnabled), &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); } diff --git a/Source/WebCore/platform/graphics/mac/SimpleFontDataMac.mm b/Source/WebCore/platform/graphics/mac/SimpleFontDataMac.mm index 3094498..cd34000 100644 --- a/Source/WebCore/platform/graphics/mac/SimpleFontDataMac.mm +++ b/Source/WebCore/platform/graphics/mac/SimpleFontDataMac.mm @@ -259,49 +259,32 @@ void SimpleFontData::platformInit() descent = 3; } - if (m_orientation == Vertical) { - // Ignore vertical orientation when the font doesn't support vertical metrics. + if (platformData().orientation() == Vertical && !isTextOrientationFallback()) { // The check doesn't look neat but this is what AppKit does for vertical writing... RetainPtr<CFArrayRef> tableTags(AdoptCF, CTFontCopyAvailableTables(m_platformData.ctFont(), kCTFontTableOptionExcludeSynthetic)); CFIndex numTables = CFArrayGetCount(tableTags.get()); - bool found = false; for (CFIndex index = 0; index < numTables; ++index) { CTFontTableTag tag = (CTFontTableTag)(uintptr_t)CFArrayGetValueAtIndex(tableTags.get(), index); if (tag == kCTFontTableVhea || tag == kCTFontTableVORG) { - found = true; + m_hasVerticalGlyphs = true; break; } } - - if (found == false) - m_orientation = Horizontal; } float xHeight; - // Measure the actual character "x", because AppKit synthesizes X height rather than getting it from the font. - // Unfortunately, NSFont will round this for us so we don't quite get the right value. - GlyphPage* glyphPageZero = GlyphPageTreeNode::getRootChild(this, 0)->page(); - NSGlyph xGlyph = glyphPageZero ? glyphPageZero->glyphDataForCharacter('x').glyph : 0; - if (xGlyph) { - CGRect xBox = platformBoundsForGlyph(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. - xHeight = static_cast<float>(max(CGRectGetMaxX(xBox), -CGRectGetMinY(xBox))); - } else { -#ifndef BUILDING_ON_TIGER - xHeight = static_cast<float>(CGFontGetXHeight(m_platformData.cgFont())) / unitsPerEm; -#else - xHeight = m_platformData.font() ? [m_platformData.font() xHeight] : 0; -#endif - // CGFontGetXHeight() returns a wrong value for "Apple Symbols" font (a float close to 0, but not strictly 0). - // The following code makes a guess for xHeight in that case. - // The int cast is a workaround for the "almost" zero value returned by CGFontGetXHeight(). - if (!static_cast<int>(xHeight) && ascent) - xHeight = 2 * ascent / 3; - } + if (platformData().orientation() == Horizontal) { + // Measure the actual character "x", since it's possible for it to extend below the baseline, and we need the + // reported x-height to only include the portion of the glyph that is above the baseline. + GlyphPage* glyphPageZero = GlyphPageTreeNode::getRootChild(this, 0)->page(); + NSGlyph xGlyph = glyphPageZero ? glyphPageZero->glyphDataForCharacter('x').glyph : 0; + if (xGlyph) + xHeight = -CGRectGetMinY(platformBoundsForGlyph(xGlyph)); + else + xHeight = scaleEmToUnits(CGFontGetXHeight(m_platformData.cgFont()), unitsPerEm) * pointSize; + } else + xHeight = verticalRightOrientationFontData()->fontMetrics().xHeight(); m_fontMetrics.setUnitsPerEm(unitsPerEm); m_fontMetrics.setAscent(ascent); @@ -474,17 +457,8 @@ void SimpleFontData::determinePitch() FloatRect SimpleFontData::platformBoundsForGlyph(Glyph glyph) const { FloatRect boundingBox; -#ifndef BUILDING_ON_TIGER - boundingBox = CTFontGetBoundingRectsForGlyphs(m_platformData.ctFont(), - orientation() == Vertical ? kCTFontVerticalOrientation : kCTFontHorizontalOrientation, &glyph, 0, 1); + boundingBox = CTFontGetBoundingRectsForGlyphs(m_platformData.ctFont(), platformData().orientation() == Vertical ? kCTFontVerticalOrientation : kCTFontHorizontalOrientation, &glyph, 0, 1); boundingBox.setY(-boundingBox.maxY()); -#else - // FIXME: Custom fonts don't have NSFonts, so this function doesn't compute correct bounds for these on Tiger. - if (!m_platformData.font()) - return boundingBox; - boundingBox = [m_platformData.font() boundingRectForGlyph:glyph]; - boundingBox.setY(-boundingBox.maxY()); -#endif if (m_syntheticBoldOffset) boundingBox.setWidth(boundingBox.width() + m_syntheticBoldOffset); @@ -494,7 +468,7 @@ FloatRect SimpleFontData::platformBoundsForGlyph(Glyph glyph) const float SimpleFontData::platformWidthForGlyph(Glyph glyph) const { CGSize advance; - if (orientation() == Horizontal || m_isBrokenIdeographFont) { + if (platformData().orientation() == Horizontal || m_isBrokenIdeographFallback) { NSFont* font = platformData().font(); float pointSize = platformData().m_size; CGAffineTransform m = CGAffineTransformMakeScale(pointSize, pointSize); diff --git a/Source/WebCore/platform/graphics/mac/WebLayer.h b/Source/WebCore/platform/graphics/mac/WebLayer.h index 30bf55b..2e9bea0 100644 --- a/Source/WebCore/platform/graphics/mac/WebLayer.h +++ b/Source/WebCore/platform/graphics/mac/WebLayer.h @@ -32,6 +32,7 @@ namespace WebCore { class GraphicsLayer; + class PlatformCALayer; class PlatformCALayerClient; } @@ -48,7 +49,7 @@ namespace WebCore { @end // Functions allows us to share implementation across WebTiledLayer and WebLayer -void drawLayerContents(CGContextRef, CALayer *, WebCore::PlatformCALayerClient*); +void drawLayerContents(CGContextRef, CALayer *, WebCore::PlatformCALayer*); void setLayerNeedsDisplayInRect(CALayer *, WebCore::PlatformCALayerClient*, CGRect); #endif // USE(ACCELERATED_COMPOSITING) diff --git a/Source/WebCore/platform/graphics/mac/WebLayer.mm b/Source/WebCore/platform/graphics/mac/WebLayer.mm index 414a75f..c9705d0 100644 --- a/Source/WebCore/platform/graphics/mac/WebLayer.mm +++ b/Source/WebCore/platform/graphics/mac/WebLayer.mm @@ -40,8 +40,9 @@ using namespace WebCore; @implementation WebLayer -void drawLayerContents(CGContextRef context, CALayer *layer, WebCore::PlatformCALayerClient* layerContents) +void drawLayerContents(CGContextRef context, CALayer *layer, WebCore::PlatformCALayer* platformLayer) { + WebCore::PlatformCALayerClient* layerContents = platformLayer->owner(); if (!layerContents) return; @@ -62,6 +63,7 @@ void drawLayerContents(CGContextRef context, CALayer *layer, WebCore::PlatformCA GraphicsContext graphicsContext(context); graphicsContext.setIsCALayerContext(true); + graphicsContext.setIsAcceleratedContext(platformLayer->acceleratesDrawing()); if (!layerContents->platformCALayerContentsOpaque()) { // Turn off font smoothing to improve the appearance of text rendered onto a transparent background. @@ -167,7 +169,7 @@ void setLayerNeedsDisplayInRect(CALayer *layer, WebCore::PlatformCALayerClient* { PlatformCALayer* layer = PlatformCALayer::platformCALayer(self); if (layer) - drawLayerContents(context, self, layer->owner()); + drawLayerContents(context, self, layer); } @end // implementation WebLayer diff --git a/Source/WebCore/platform/graphics/mac/WebTiledLayer.mm b/Source/WebCore/platform/graphics/mac/WebTiledLayer.mm index e9fa5b7..9bcdd54 100644 --- a/Source/WebCore/platform/graphics/mac/WebTiledLayer.mm +++ b/Source/WebCore/platform/graphics/mac/WebTiledLayer.mm @@ -83,7 +83,7 @@ using namespace WebCore; { PlatformCALayer* layer = PlatformCALayer::platformCALayer(self); if (layer) - drawLayerContents(context, self, layer->owner()); + drawLayerContents(context, self, layer); } @end // implementation WebTiledLayer |