Title: [269211] trunk/Source/WebCore
Revision
269211
Author
mmaxfi...@apple.com
Date
2020-10-30 17:01:02 -0700 (Fri, 30 Oct 2020)

Log Message

[Cocoa] [GPU Process] Perform image decoding of color fonts in the Web Process
https://bugs.webkit.org/show_bug.cgi?id=217506

Reviewed by Simon Fraser.

Source/WebCore:

Core Text itself doesn't know how to draw things; it has to rely on Core Graphics to do that.
However, Core Graphics only understands the simplest of text drawing concepts; it doesn't understand
things like color fonts or emoji. Core Text sits between the application and Core Graphics, and is
responsible for splitting up an arbitrary draw command into individual simple pieces which Core
Graphics can understand. For example, when you ask Core Text to draw a string which is of the form
"outlines emoji outlines", Core Text will end up telling Core Graphics to draw the first outlines, then
draw the emoji image (using Core Graphics's normal image drawing routines), then draw the remaining
outlines.

This is exactly the same kind of filtering we want to do for the GPU Process. We want to be able to
separate out the glyphs which are rendered using outlines from the emoji glyphs which are rendered
using images. We want to handle the image glyphs ourself in WebKit using our own image drawing display
list facilities, which will cause images to be decoded in the Web Process, thereby increasing the
security of the GPU Process.

So, this patch implements a custom CGContext, backed by a function table that is populated in WebKit.
We pass this custom CGContext into Core Text, which does its normal splitting up of outlines / images,
and calls glyph / image drawing functions on our CGContext. Because these functions are implemented by
WebKit, this effectively makes WebKit able to intercept the drawing calls, and implement them ourself
by appending items to the current display list. So, when Core Text tells our CGContext to draw an emoji,
our callback runs and we "just" append a DrawImage display list item.

I use scare-quotes around "just" because it is a bit more complicated than that. Core Text internally
can change the fill/stroke color (for COLR glyphs), the text matrix (it should be updated between
adjacent runs), the CTM, and the shadow state (because Core Text sometimes will implement shadows itself
by just drawing the text two times). So, in our CGContext callback, we have to look at the state of
the CGContext, figure out if anything changed (because we're not notified when changes happen), and
if things did change, append additional display list items to make a parallel change happen at draw
time.

Tests added in https://trac.webkit.org/r269177

* Headers.cmake:
* PlatformAppleWin.cmake:
* PlatformWinCairo.cmake:
* SourcesCocoa.txt:
* WebCore.xcodeproj/project.pbxproj:
* platform/FreeType.cmake:
* platform/graphics/cg/ImageBufferCGBackend.cpp:
(WebCore::ImageBufferCGBackend::setupContext):
* platform/graphics/coretext/FontCascadeCoreText.cpp:
(WebCore::fillVectorWithHorizontalGlyphPositions):
* platform/graphics/displaylists/DisplayListDrawGlyphsRecorder.h: Added.
* platform/graphics/displaylists/DisplayListDrawGlyphsRecorderCoreText.cpp: Added.
(WebCore::DisplayList::beginLayer): VTable callback for creating a transparency layer.
(WebCore::DisplayList::endLayer): Ditto for ending a transparency layer.
(WebCore::DisplayList::drawGlyphs): VTable callback for drawing outline glyphs.
(WebCore::DisplayList::drawImage): VTable callback for drawing an image.
(WebCore::DisplayList::DrawGlyphsRecorder::createInternalContext): Set up the custom CGContext
infrastructure. Hook up the VTable callbacks.
(WebCore::DisplayList::DrawGlyphsRecorder::DrawGlyphsRecorder):
(WebCore::DisplayList::DrawGlyphsRecorder::populateInternalState): We need to save the GraphicsContext
state at the beginning of the entry point, so we can restore anything that changed when we're done.
(WebCore::DisplayList::DrawGlyphsRecorder::populateInternalContext): Because Core Text internally
interrogates the CGContext to see if it needs to do things like draw shadows itself, we need to make
sure that the recorder's state is mirrored in our custom CGContext. This applies all the relevant
state to our CGContext so it's ready when Core Text asks for it.
(WebCore::DisplayList::DrawGlyphsRecorder::prepareInternalContext): Call the above two functions.
(WebCore::DisplayList::DrawGlyphsRecorder::concludeInternalContext): Called once when we're done.
This function cleans up, by possibly appending additional display list items to restore the state
back to what it was when we started.
(WebCore::DisplayList::DrawGlyphsRecorder::updateFillColor): Detect a changed fill color, and if it has
changed, append a display list item to make a parallel change at drawing time.
(WebCore::DisplayList::DrawGlyphsRecorder::updateStrokeColor): Ditto for the stroke color.
(WebCore::DisplayList::DrawGlyphsRecorder::updateCTM): Ditto for the CTM.
(WebCore::DisplayList::shadowIsCleared):
(WebCore::DisplayList::DrawGlyphsRecorder::updateShadow): Ditto for the shadow state.
(WebCore::DisplayList::DrawGlyphsRecorder::recordBeginLayer): Hook this up to beginTransparencyLayer().
(WebCore::DisplayList::DrawGlyphsRecorder::recordEndLayer): Hook this up to endTransparencyLayer().
(WebCore::DisplayList::computeAdvancesFromPositions): CGContext gives us positions, but our display list
infrastructure requires advances. Simply subtract to convert between them.
(WebCore::DisplayList::DrawGlyphsRecorder::recordDrawGlyphs): The callback that appends a DrawGlyphs
display list item. Note it has to call the various update() functions to detect changes in the CGContext
state.
(WebCore::DisplayList::DrawGlyphsRecorder::recordDrawImage): Ditto for a DrawImage display list item.
(WebCore::DisplayList::DrawGlyphsRecorder::drawGlyphs): The main entry point. Simply set up, do the work,
then clean up.
* platform/graphics/displaylists/DisplayListDrawGlyphsRecorderHarfBuzz.cpp: Added. Dummy implementation
to make the other ports continue to compile.
(WebCore::DisplayList::DrawGlyphsRecorder::DrawGlyphsRecorder):
(WebCore::DisplayList::DrawGlyphsRecorder::drawGlyphs):
* platform/graphics/displaylists/DisplayListRecorder.cpp:
(WebCore::DisplayList::Recorder::Recorder):
(WebCore::DisplayList::Recorder::drawGlyphs): Call m_drawGlyphsRecorder.drawGlyphs() instead of just
appending a DrawGlyphs command.
(WebCore::DisplayList::Recorder::concatCTM): Tiny optimization.
(WebCore::DisplayList::Recorder::clipToDrawingCommands): The current clipToDrawingCommands's context
CTM didn't match the parallel one used during playback. In order to make the CTMs match are recording
and playback time, we have to make sure they start off the same.
* platform/graphics/displaylists/DisplayListRecorder.h: DisplayList::Recorder owns a DrawGlyphsRecorder,
whose lifetime equals that of the DisplayList::Recorder. Rather than destroying / recreating the
DrawGlyphsRecorder, the DrawGlyphsRecorder class is smart enough to clean up after itself so it can be
reused multiple times.

Source/WebCore/PAL:

Add some new entry points, and do some various cleanup.

* pal/spi/cg/CoreGraphicsSPI.h:

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (269210 => 269211)


--- trunk/Source/WebCore/ChangeLog	2020-10-30 23:56:26 UTC (rev 269210)
+++ trunk/Source/WebCore/ChangeLog	2020-10-31 00:01:02 UTC (rev 269211)
@@ -1,3 +1,104 @@
+2020-10-29  Myles C. Maxfield  <mmaxfi...@apple.com>
+
+        [Cocoa] [GPU Process] Perform image decoding of color fonts in the Web Process
+        https://bugs.webkit.org/show_bug.cgi?id=217506
+
+        Reviewed by Simon Fraser.
+
+        Core Text itself doesn't know how to draw things; it has to rely on Core Graphics to do that.
+        However, Core Graphics only understands the simplest of text drawing concepts; it doesn't understand
+        things like color fonts or emoji. Core Text sits between the application and Core Graphics, and is
+        responsible for splitting up an arbitrary draw command into individual simple pieces which Core
+        Graphics can understand. For example, when you ask Core Text to draw a string which is of the form
+        "outlines emoji outlines", Core Text will end up telling Core Graphics to draw the first outlines, then
+        draw the emoji image (using Core Graphics's normal image drawing routines), then draw the remaining
+        outlines.
+
+        This is exactly the same kind of filtering we want to do for the GPU Process. We want to be able to
+        separate out the glyphs which are rendered using outlines from the emoji glyphs which are rendered
+        using images. We want to handle the image glyphs ourself in WebKit using our own image drawing display
+        list facilities, which will cause images to be decoded in the Web Process, thereby increasing the
+        security of the GPU Process.
+
+        So, this patch implements a custom CGContext, backed by a function table that is populated in WebKit.
+        We pass this custom CGContext into Core Text, which does its normal splitting up of outlines / images,
+        and calls glyph / image drawing functions on our CGContext. Because these functions are implemented by
+        WebKit, this effectively makes WebKit able to intercept the drawing calls, and implement them ourself
+        by appending items to the current display list. So, when Core Text tells our CGContext to draw an emoji,
+        our callback runs and we "just" append a DrawImage display list item.
+
+        I use scare-quotes around "just" because it is a bit more complicated than that. Core Text internally
+        can change the fill/stroke color (for COLR glyphs), the text matrix (it should be updated between
+        adjacent runs), the CTM, and the shadow state (because Core Text sometimes will implement shadows itself
+        by just drawing the text two times). So, in our CGContext callback, we have to look at the state of
+        the CGContext, figure out if anything changed (because we're not notified when changes happen), and
+        if things did change, append additional display list items to make a parallel change happen at draw
+        time.
+
+        Tests added in https://trac.webkit.org/r269177
+
+        * Headers.cmake:
+        * PlatformAppleWin.cmake:
+        * PlatformWinCairo.cmake:
+        * SourcesCocoa.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        * platform/FreeType.cmake:
+        * platform/graphics/cg/ImageBufferCGBackend.cpp:
+        (WebCore::ImageBufferCGBackend::setupContext):
+        * platform/graphics/coretext/FontCascadeCoreText.cpp:
+        (WebCore::fillVectorWithHorizontalGlyphPositions):
+        * platform/graphics/displaylists/DisplayListDrawGlyphsRecorder.h: Added.
+        * platform/graphics/displaylists/DisplayListDrawGlyphsRecorderCoreText.cpp: Added.
+        (WebCore::DisplayList::beginLayer): VTable callback for creating a transparency layer.
+        (WebCore::DisplayList::endLayer): Ditto for ending a transparency layer.
+        (WebCore::DisplayList::drawGlyphs): VTable callback for drawing outline glyphs.
+        (WebCore::DisplayList::drawImage): VTable callback for drawing an image.
+        (WebCore::DisplayList::DrawGlyphsRecorder::createInternalContext): Set up the custom CGContext
+        infrastructure. Hook up the VTable callbacks.
+        (WebCore::DisplayList::DrawGlyphsRecorder::DrawGlyphsRecorder):
+        (WebCore::DisplayList::DrawGlyphsRecorder::populateInternalState): We need to save the GraphicsContext
+        state at the beginning of the entry point, so we can restore anything that changed when we're done.
+        (WebCore::DisplayList::DrawGlyphsRecorder::populateInternalContext): Because Core Text internally
+        interrogates the CGContext to see if it needs to do things like draw shadows itself, we need to make
+        sure that the recorder's state is mirrored in our custom CGContext. This applies all the relevant
+        state to our CGContext so it's ready when Core Text asks for it.
+        (WebCore::DisplayList::DrawGlyphsRecorder::prepareInternalContext): Call the above two functions.
+        (WebCore::DisplayList::DrawGlyphsRecorder::concludeInternalContext): Called once when we're done.
+        This function cleans up, by possibly appending additional display list items to restore the state
+        back to what it was when we started.
+        (WebCore::DisplayList::DrawGlyphsRecorder::updateFillColor): Detect a changed fill color, and if it has
+        changed, append a display list item to make a parallel change at drawing time.
+        (WebCore::DisplayList::DrawGlyphsRecorder::updateStrokeColor): Ditto for the stroke color.
+        (WebCore::DisplayList::DrawGlyphsRecorder::updateCTM): Ditto for the CTM.
+        (WebCore::DisplayList::shadowIsCleared):
+        (WebCore::DisplayList::DrawGlyphsRecorder::updateShadow): Ditto for the shadow state.
+        (WebCore::DisplayList::DrawGlyphsRecorder::recordBeginLayer): Hook this up to beginTransparencyLayer().
+        (WebCore::DisplayList::DrawGlyphsRecorder::recordEndLayer): Hook this up to endTransparencyLayer().
+        (WebCore::DisplayList::computeAdvancesFromPositions): CGContext gives us positions, but our display list
+        infrastructure requires advances. Simply subtract to convert between them.
+        (WebCore::DisplayList::DrawGlyphsRecorder::recordDrawGlyphs): The callback that appends a DrawGlyphs
+        display list item. Note it has to call the various update() functions to detect changes in the CGContext
+        state.
+        (WebCore::DisplayList::DrawGlyphsRecorder::recordDrawImage): Ditto for a DrawImage display list item.
+        (WebCore::DisplayList::DrawGlyphsRecorder::drawGlyphs): The main entry point. Simply set up, do the work,
+        then clean up.
+        * platform/graphics/displaylists/DisplayListDrawGlyphsRecorderHarfBuzz.cpp: Added. Dummy implementation
+        to make the other ports continue to compile.
+        (WebCore::DisplayList::DrawGlyphsRecorder::DrawGlyphsRecorder):
+        (WebCore::DisplayList::DrawGlyphsRecorder::drawGlyphs):
+        * platform/graphics/displaylists/DisplayListRecorder.cpp:
+        (WebCore::DisplayList::Recorder::Recorder):
+        (WebCore::DisplayList::Recorder::drawGlyphs): Call m_drawGlyphsRecorder.drawGlyphs() instead of just
+        appending a DrawGlyphs command.
+        (WebCore::DisplayList::Recorder::concatCTM): Tiny optimization.
+        (WebCore::DisplayList::Recorder::clipToDrawingCommands): The current clipToDrawingCommands's context
+        CTM didn't match the parallel one used during playback. In order to make the CTMs match are recording
+        and playback time, we have to make sure they start off the same.
+        * platform/graphics/displaylists/DisplayListRecorder.h: DisplayList::Recorder owns a DrawGlyphsRecorder,
+        whose lifetime equals that of the DisplayList::Recorder. Rather than destroying / recreating the
+        DrawGlyphsRecorder, the DrawGlyphsRecorder class is smart enough to clean up after itself so it can be
+        reused multiple times.
+
 2020-10-30  Brian Burg  <bb...@apple.com>
 
         Web Inspector: move InspectorFrontendAPIDispatcher to WebCore, clean up uses

Modified: trunk/Source/WebCore/Headers.cmake (269210 => 269211)


--- trunk/Source/WebCore/Headers.cmake	2020-10-30 23:56:26 UTC (rev 269210)
+++ trunk/Source/WebCore/Headers.cmake	2020-10-31 00:01:02 UTC (rev 269211)
@@ -1238,6 +1238,7 @@
     platform/graphics/angle/ExtensionsGLANGLE.h
 
     platform/graphics/displaylists/DisplayList.h
+    platform/graphics/displaylists/DisplayListDrawGlyphsRecorder.h
     platform/graphics/displaylists/DisplayListDrawingContext.h
     platform/graphics/displaylists/DisplayListImageBuffer.h
     platform/graphics/displaylists/DisplayListItems.h

Modified: trunk/Source/WebCore/PAL/ChangeLog (269210 => 269211)


--- trunk/Source/WebCore/PAL/ChangeLog	2020-10-30 23:56:26 UTC (rev 269210)
+++ trunk/Source/WebCore/PAL/ChangeLog	2020-10-31 00:01:02 UTC (rev 269211)
@@ -1,3 +1,14 @@
+2020-10-29  Myles C. Maxfield  <mmaxfi...@apple.com>
+
+        [Cocoa] [GPU Process] Perform image decoding of color fonts in the Web Process
+        https://bugs.webkit.org/show_bug.cgi?id=217506
+
+        Reviewed by Simon Fraser.
+
+        Add some new entry points, and do some various cleanup.
+
+        * pal/spi/cg/CoreGraphicsSPI.h:
+
 2020-10-30  Chris Fleizach  <cfleiz...@apple.com>
 
         AX: Incorrect list of voices being displayed on iOS

Modified: trunk/Source/WebCore/PAL/pal/spi/cg/CoreGraphicsSPI.h (269210 => 269211)


--- trunk/Source/WebCore/PAL/pal/spi/cg/CoreGraphicsSPI.h	2020-10-30 23:56:26 UTC (rev 269210)
+++ trunk/Source/WebCore/PAL/pal/spi/cg/CoreGraphicsSPI.h	2020-10-31 00:01:02 UTC (rev 269211)
@@ -38,6 +38,7 @@
 
 #if USE(APPLE_INTERNAL_SDK)
 
+#include <CoreGraphics/CGContextDelegatePrivate.h>
 #include <CoreGraphics/CGFontCache.h>
 #include <CoreGraphics/CGPathPrivate.h>
 #include <CoreGraphics/CoreGraphicsPrivate.h>
@@ -58,19 +59,12 @@
     int minRightSideBearing;
 };
 
-struct CGFontDescriptor {
-    CGRect bbox;
-    CGFloat ascent;
-    CGFloat descent;
-    CGFloat capHeight;
-    CGFloat italicAngle;
-    CGFloat stemV;
-    CGFloat stemH;
-    CGFloat avgWidth;
-    CGFloat maxWidth;
-    CGFloat missingWidth;
-    CGFloat leading;
-    CGFloat xHeight;
+typedef CF_ENUM (int32_t, CGContextDelegateCallbackName)
+{
+    deDrawImage = 7,
+    deDrawGlyphs = 8,
+    deBeginLayer = 17,
+    deEndLayer = 18,
 };
 
 typedef const struct CGColorTransform* CGColorTransformRef;
@@ -179,6 +173,22 @@
 
 #endif // PLATFORM(COCOA)
 
+struct CGShadowStyle {
+    unsigned a;
+    CGFloat b;
+    CGFloat azimuth;
+    CGFloat c;
+    CGFloat height;
+    CGFloat radius;
+    CGFloat d;
+};
+typedef struct CGShadowStyle CGShadowStyle;
+
+typedef CF_ENUM (int32_t, CGStyleType)
+{
+    kCGStyleShadow = 1,
+};
+
 #if PLATFORM(MAC)
 
 typedef CF_ENUM(uint32_t, CGSNotificationType) {
@@ -193,6 +203,12 @@
 
 #endif // PLATFORM(MAC)
 
+typedef struct CGContextDelegate *CGContextDelegateRef;
+typedef void (*CGContextDelegateCallback)(void);
+typedef struct CGRenderingState *CGRenderingStateRef;
+typedef struct CGGState *CGGStateRef;
+typedef struct CGStyle *CGStyleRef;
+
 #endif // USE(APPLE_INTERNAL_SDK)
 
 #if PLATFORM(COCOA)
@@ -203,7 +219,6 @@
 
 typedef CGSWindowID* CGSWindowIDList;
 typedef struct CF_BRIDGED_TYPE(id) CGSRegionObject* CGSRegionObj;
-typedef struct CF_BRIDGED_TYPE(id) CGStyle* CGStyleRef;
 
 typedef void* CGSNotificationArg;
 typedef void* CGSNotificationData;
@@ -233,7 +248,6 @@
 CGContextType CGContextGetType(CGContextRef);
 
 CFStringRef CGFontCopyFamilyName(CGFontRef);
-bool CGFontGetDescriptor(CGFontRef, CGFontDescriptor*);
 bool CGFontGetGlyphAdvancesForStyle(CGFontRef, const CGAffineTransform* , CGFontRenderingStyle, const CGGlyph[], size_t count, CGSize advances[]);
 void CGFontGetGlyphsForUnichars(CGFontRef, const UniChar[], CGGlyph[], size_t count);
 const CGFontHMetrics* CGFontGetHMetrics(CGFontRef);
@@ -252,6 +266,21 @@
 bool CGContextDrawsWithCorrectShadowOffsets(CGContextRef);
 CGPatternRef CGPatternCreateWithImage2(CGImageRef, CGAffineTransform, CGPatternTiling);
 
+CGContextDelegateRef CGContextDelegateCreate(void* info);
+void CGContextDelegateSetCallback(CGContextDelegateRef, CGContextDelegateCallbackName, CGContextDelegateCallback);
+CGContextRef CGContextCreateWithDelegate(CGContextDelegateRef, CGContextType, CGRenderingStateRef, CGGStateRef);
+void* CGContextDelegateGetInfo(CGContextDelegateRef);
+void CGContextDelegateRelease(CGContextDelegateRef);
+CGFloat CGGStateGetAlpha(CGGStateRef);
+CGFontRef CGGStateGetFont(CGGStateRef);
+const CGAffineTransform *CGGStateGetCTM(CGGStateRef);
+CGColorRef CGGStateGetFillColor(CGGStateRef);
+CGColorRef CGGStateGetStrokeColor(CGGStateRef);
+CGStyleRef CGGStateGetStyle(CGGStateRef);
+CGStyleType CGStyleGetType(CGStyleRef);
+const void *CGStyleGetData(CGStyleRef);
+CGColorRef CGStyleGetColor(CGStyleRef);
+
 #if HAVE(CGPATH_GET_NUMBER_OF_ELEMENTS)
 size_t CGPathGetNumberOfElements(CGPathRef);
 #endif
@@ -286,16 +315,9 @@
 CGSRegionEnumeratorObj CGSRegionEnumerator(CGRegionRef);
 CGStyleRef CGStyleCreateFocusRingWithColor(const CGFocusRingStyle*, CGColorRef);
 void CGContextSetStyle(CGContextRef, CGStyleRef);
-
 void CGContextDrawConicGradient(CGContextRef, CGGradientRef, CGPoint center, CGFloat angle);
-
-#if HAVE(CG_PATH_UNEVEN_CORNERS_ROUNDEDRECT)
 void CGPathAddUnevenCornersRoundedRect(CGMutablePathRef, const CGAffineTransform *, CGRect, const CGSize corners[4]);
-#endif
-
-#if HAVE(CG_FONT_RENDERING_GET_FONT_SMOOTHING_DISABLED)
 bool CGFontRenderingGetFontSmoothingDisabled(void);
-#endif
 
 #endif // PLATFORM(COCOA)
 
@@ -328,15 +350,10 @@
 size_t CGDisplayModeGetPixelsWide(CGDisplayModeRef);
 size_t CGDisplayModeGetPixelsHigh(CGDisplayModeRef);
 
-#if ENABLE(WEBPROCESS_WINDOWSERVER_BLOCKING)
-
 CGError CGSSetDenyWindowServerConnections(bool);
-
 typedef int32_t CGSDisplayID;
 CGSDisplayID CGSMainDisplayID(void);
 
-#endif // ENABLE(WEBPROCESS_WINDOWSERVER_BLOCKING)
-
 #endif // PLATFORM(MAC)
 
 #if ENABLE(PDFKIT_PLUGIN) && !USE(APPLE_INTERNAL_SDK)

Modified: trunk/Source/WebCore/PlatformAppleWin.cmake (269210 => 269211)


--- trunk/Source/WebCore/PlatformAppleWin.cmake	2020-10-30 23:56:26 UTC (rev 269210)
+++ trunk/Source/WebCore/PlatformAppleWin.cmake	2020-10-31 00:01:02 UTC (rev 269211)
@@ -30,6 +30,8 @@
     platform/graphics/avfoundation/cf/MediaPlayerPrivateAVFoundationCF.cpp
     platform/graphics/avfoundation/cf/WebCoreAVCFResourceLoader.cpp
 
+    platform/graphics/displaylists/DisplayListDrawGlyphsRecorderWin.cpp
+
     platform/graphics/win/FontCustomPlatformData.cpp
 
     platform/network/cf/AuthenticationCF.cpp

Modified: trunk/Source/WebCore/PlatformWinCairo.cmake (269210 => 269211)


--- trunk/Source/WebCore/PlatformWinCairo.cmake	2020-10-30 23:56:26 UTC (rev 269210)
+++ trunk/Source/WebCore/PlatformWinCairo.cmake	2020-10-31 00:01:02 UTC (rev 269211)
@@ -22,6 +22,8 @@
     platform/graphics/GLContext.cpp
     platform/graphics/PlatformDisplay.cpp
 
+    platform/graphics/displaylists/DisplayListDrawGlyphsRecorderHarfBuzz.cpp
+
     platform/graphics/win/FontCustomPlatformDataCairo.cpp
     platform/graphics/win/FontPlatformDataCairoWin.cpp
     platform/graphics/win/GlyphPageTreeNodeCairoWin.cpp

Modified: trunk/Source/WebCore/SourcesCocoa.txt (269210 => 269211)


--- trunk/Source/WebCore/SourcesCocoa.txt	2020-10-30 23:56:26 UTC (rev 269210)
+++ trunk/Source/WebCore/SourcesCocoa.txt	2020-10-31 00:01:02 UTC (rev 269211)
@@ -379,6 +379,7 @@
 platform/graphics/cv/PixelBufferConformerCV.cpp
 platform/graphics/cv/VideoTextureCopierCV.cpp
 platform/graphics/coreimage/FilterEffectRendererCoreImage.mm
+platform/graphics/displaylists/DisplayListDrawGlyphsRecorderCoreText.cpp
 platform/graphics/gpu/TilingData.cpp
 platform/graphics/gpu/cocoa/GPUBindGroupAllocatorMetal.mm
 platform/graphics/gpu/cocoa/GPUBindGroupLayoutMetal.mm

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (269210 => 269211)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2020-10-30 23:56:26 UTC (rev 269210)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2020-10-31 00:01:02 UTC (rev 269211)
@@ -620,6 +620,7 @@
 		1CAF34810A6C405200ABE06E /* WebScriptObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 1CAF347E0A6C405200ABE06E /* WebScriptObject.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		1CAF34820A6C405200ABE06E /* WebScriptObject.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1CAF347F0A6C405200ABE06E /* WebScriptObject.mm */; };
 		1CAF34830A6C405200ABE06E /* WebScriptObjectPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 1CAF34800A6C405200ABE06E /* WebScriptObjectPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		1CAF56DB25301AC80017B472 /* DisplayListDrawGlyphsRecorder.h in Headers */ = {isa = PBXBuildFile; fileRef = 1CAF56D8253014570017B472 /* DisplayListDrawGlyphsRecorder.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		1CCD81502231F83E0065FC2B /* WebCoreResourceHandleAsOperationQueueDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = E152551416FD234F003D7ADB /* WebCoreResourceHandleAsOperationQueueDelegate.mm */; };
 		1CCDF5BE1990332400BCEBAD /* SVGToOTFFontConversion.h in Headers */ = {isa = PBXBuildFile; fileRef = 1CCDF5BC1990332400BCEBAD /* SVGToOTFFontConversion.h */; };
 		1CFAE3230A6D6A3F0032593D /* libobjc.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 1CFAE3220A6D6A3F0032593D /* libobjc.dylib */; };
@@ -6736,6 +6737,8 @@
 		1CAF347E0A6C405200ABE06E /* WebScriptObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebScriptObject.h; sourceTree = "<group>"; };
 		1CAF347F0A6C405200ABE06E /* WebScriptObject.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebScriptObject.mm; sourceTree = "<group>"; };
 		1CAF34800A6C405200ABE06E /* WebScriptObjectPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebScriptObjectPrivate.h; sourceTree = "<group>"; };
+		1CAF56D8253014570017B472 /* DisplayListDrawGlyphsRecorder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DisplayListDrawGlyphsRecorder.h; sourceTree = "<group>"; };
+		1CAF56DE2530245A0017B472 /* DisplayListDrawGlyphsRecorderCoreText.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = DisplayListDrawGlyphsRecorderCoreText.cpp; sourceTree = "<group>"; };
 		1CB5FE8822DEBC8B009440E2 /* WHLSLError.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WHLSLError.h; sourceTree = "<group>"; };
 		1CB69B3221DED40B006E846A /* WHLSLResolvableType.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WHLSLResolvableType.h; sourceTree = "<group>"; };
 		1CB69B3421DED63A006E846A /* WHLSLFloatLiteralType.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WHLSLFloatLiteralType.h; sourceTree = "<group>"; };
@@ -17610,6 +17613,8 @@
 			children = (
 				0FE5FBCA1C3DD51E0007A2CA /* DisplayList.cpp */,
 				0FE5FBCB1C3DD51E0007A2CA /* DisplayList.h */,
+				1CAF56D8253014570017B472 /* DisplayListDrawGlyphsRecorder.h */,
+				1CAF56DE2530245A0017B472 /* DisplayListDrawGlyphsRecorderCoreText.cpp */,
 				55C0A29523FE2CE000F2CB93 /* DisplayListDrawingContext.cpp */,
 				72EA09F923FCCC6A008504A5 /* DisplayListDrawingContext.h */,
 				72EA09F723FCCB3D008504A5 /* DisplayListImageBuffer.h */,
@@ -31434,6 +31439,7 @@
 				7EDAAFC919A2CCDC0034DFD1 /* DiskCacheMonitorCocoa.h in Headers */,
 				0F790F422517CE6E009BA034 /* DisplayLayerController.h in Headers */,
 				0FE5FBD31C3DD51E0007A2CA /* DisplayList.h in Headers */,
+				1CAF56DB25301AC80017B472 /* DisplayListDrawGlyphsRecorder.h in Headers */,
 				55AD09402408964000DE4D2F /* DisplayListDrawingContext.h in Headers */,
 				55AD093E2408963500DE4D2F /* DisplayListImageBuffer.h in Headers */,
 				0FE5FBD51C3DD51E0007A2CA /* DisplayListItems.h in Headers */,

Modified: trunk/Source/WebCore/platform/FreeType.cmake (269210 => 269211)


--- trunk/Source/WebCore/platform/FreeType.cmake	2020-10-30 23:56:26 UTC (rev 269210)
+++ trunk/Source/WebCore/platform/FreeType.cmake	2020-10-31 00:01:02 UTC (rev 269211)
@@ -5,6 +5,8 @@
 )
 
 list(APPEND WebCore_SOURCES
+    platform/graphics/displaylists/DisplayListDrawGlyphsRecorderHarfBuzz.cpp
+
     platform/graphics/freetype/FontCacheFreeType.cpp
     platform/graphics/freetype/FontCustomPlatformDataFreeType.cpp
     platform/graphics/freetype/FontPlatformDataFreeType.cpp

Modified: trunk/Source/WebCore/platform/graphics/cg/ImageBufferCGBackend.cpp (269210 => 269211)


--- trunk/Source/WebCore/platform/graphics/cg/ImageBufferCGBackend.cpp	2020-10-30 23:56:26 UTC (rev 269210)
+++ trunk/Source/WebCore/platform/graphics/cg/ImageBufferCGBackend.cpp	2020-10-31 00:01:02 UTC (rev 269211)
@@ -61,6 +61,7 @@
 
 void ImageBufferCGBackend::setupContext()
 {
+    // The initial CTM matches DisplayList::Recorder::clipToDrawingCommands()'s initial CTM.
     context().scale(FloatSize(1, -1));
     context().translate(0, -m_backendSize.height());
     context().applyDeviceScaleFactor(m_resolutionScale);

Modified: trunk/Source/WebCore/platform/graphics/coretext/FontCascadeCoreText.cpp (269210 => 269211)


--- trunk/Source/WebCore/platform/graphics/coretext/FontCascadeCoreText.cpp	2020-10-30 23:56:26 UTC (rev 269210)
+++ trunk/Source/WebCore/platform/graphics/coretext/FontCascadeCoreText.cpp	2020-10-31 00:01:02 UTC (rev 269211)
@@ -41,6 +41,50 @@
 
 namespace WebCore {
 
+static const AffineTransform& rotateLeftTransform()
+{
+    static AffineTransform result(0, -1, 1, 0, 0, 0);
+    return result;
+}
+
+AffineTransform computeOverallTextMatrix(const Font& font)
+{
+    auto& platformData = font.platformData();
+    AffineTransform result;
+    if (!platformData.isColorBitmapFont())
+        result = CTFontGetMatrix(platformData.ctFont());
+    result.setB(-result.b());
+    result.setD(-result.d());
+    if (platformData.syntheticOblique()) {
+        float obliqueSkew = tanf(deg2rad(FontCascade::syntheticObliqueAngle()));
+        if (platformData.orientation() == FontOrientation::Vertical) {
+            if (font.isTextOrientationFallback())
+                result = AffineTransform(1, obliqueSkew, 0, 1, 0, 0) * result;
+            else
+                result = AffineTransform(1, -obliqueSkew, 0, 1, 0, 0) * result;
+        } else
+            result = AffineTransform(1, 0, -obliqueSkew, 1, 0, 0) * result;
+    }
+
+    // We're emulating the behavior of CGContextSetTextPosition() by adding constant amounts to each glyph's position
+    // (see fillVectorWithHorizontalGlyphPositions() and fillVectorWithVerticalGlyphPositions()).
+    // CGContextSetTextPosition() has the side effect of clobbering the E and F fields of the text matrix,
+    // so we do that explicitly here.
+    result.setE(0);
+    result.setF(0);
+    return result;
+}
+
+AffineTransform computeVerticalTextMatrix(const Font& font, const AffineTransform& previousTextMatrix)
+{
+    ASSERT_UNUSED(font, font.platformData().orientation() == FontOrientation::Vertical);
+    // The translation here ("e" and "f" fields) are irrelevant, because
+    // this matrix is inverted in fillVectorWithVerticalGlyphPositions to place the glyphs in the CTM's coordinate system.
+    // All we're trying to do here is rotate the text matrix so glyphs appear visually upright.
+    // We have to include the previous text matrix because it includes things like synthetic oblique.
+    return rotateLeftTransform() * previousTextMatrix;
+}
+
 #if !PLATFORM(WIN)
 
 // Confusingly, even when CGFontRenderingGetFontSmoothingDisabled() returns true, CGContextSetShouldSmoothFonts() still impacts text
@@ -61,14 +105,16 @@
 #endif
 }
 
-static const AffineTransform& rotateLeftTransform()
-{
-    static AffineTransform result(0, -1, 1, 0, 0, 0);
-    return result;
-}
-
 void fillVectorWithHorizontalGlyphPositions(Vector<CGPoint, 256>& positions, CGContextRef context, const CGSize* advances, unsigned count, const FloatPoint& point)
 {
+    // The input positions are in the context's coordinate system, without the text matrix.
+    // However, the positions that CT/CG accept are in the text matrix's coordinate system.
+    // CGContextGetTextMatrix() gives us the matrix that maps from text's coordinate system to the context's (non-text) coordinate system.
+    // We need to figure out what to deliver CT, inside the text's coordinate system, such that it ends up coincident with the input in the context's coordinate system.
+    //
+    // CTM * text matrix * positions we need to deliver to CT = CTM * input positions
+    // Solving for the positions we need to deliver to CT, we get
+    // positions we need to deliver to CT = inverse(text matrix) * input positions
     CGAffineTransform matrix = CGAffineTransformInvert(CGContextGetTextMatrix(context));
     positions[0] = CGPointApplyAffineTransform(point, matrix);
     for (unsigned i = 1; i < count; ++i) {
@@ -137,44 +183,6 @@
     CGContextSetShouldSubpixelQuantizeFonts(cgContext, doSubpixelQuantization);
 }
 
-AffineTransform computeOverallTextMatrix(const Font& font)
-{
-    auto& platformData = font.platformData();
-    AffineTransform result;
-    if (!platformData.isColorBitmapFont())
-        result = CTFontGetMatrix(platformData.font());
-    result.setB(-result.b());
-    result.setD(-result.d());
-    if (platformData.syntheticOblique()) {
-        float obliqueSkew = tanf(deg2rad(FontCascade::syntheticObliqueAngle()));
-        if (platformData.orientation() == FontOrientation::Vertical) {
-            if (font.isTextOrientationFallback())
-                result = AffineTransform(1, obliqueSkew, 0, 1, 0, 0) * result;
-            else
-                result = AffineTransform(1, -obliqueSkew, 0, 1, 0, 0) * result;
-        } else
-            result = AffineTransform(1, 0, -obliqueSkew, 1, 0, 0) * result;
-    }
-
-    // We're emulating the behavior of CGContextSetTextPosition() by adding constant amounts to each glyph's position
-    // (see fillVectorWithHorizontalGlyphPositions() and fillVectorWithVerticalGlyphPositions()).
-    // CGContextSetTextPosition() has the side effect of clobbering the E and F fields of the text matrix,
-    // so we do that explicitly here.
-    result.setE(0);
-    result.setF(0);
-    return result;
-}
-
-AffineTransform computeVerticalTextMatrix(const Font& font, const AffineTransform& previousTextMatrix)
-{
-    ASSERT_UNUSED(font, font.platformData().orientation() == FontOrientation::Vertical);
-    // The translation here ("e" and "f" fields) are irrelevant, because
-    // this matrix is inverted in fillVectorWithVerticalGlyphPositions to place the glyphs in the CTM's coordinate system.
-    // All we're trying to do here is rotate the text matrix so glyphs appear visually upright.
-    // We have to include the previous text matrix because it includes things like synthetic oblique.
-    return rotateLeftTransform() * previousTextMatrix;
-}
-
 void FontCascade::drawGlyphs(GraphicsContext& context, const Font& font, const GlyphBuffer& glyphBuffer, unsigned from, unsigned numGlyphs, const FloatPoint& anchorPoint, FontSmoothingMode smoothingMode)
 {
     const auto& platformData = font.platformData();

Added: trunk/Source/WebCore/platform/graphics/displaylists/DisplayListDrawGlyphsRecorder.h (0 => 269211)


--- trunk/Source/WebCore/platform/graphics/displaylists/DisplayListDrawGlyphsRecorder.h	                        (rev 0)
+++ trunk/Source/WebCore/platform/graphics/displaylists/DisplayListDrawGlyphsRecorder.h	2020-10-31 00:01:02 UTC (rev 269211)
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2020 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "AffineTransform.h"
+#include "Color.h"
+#include "Gradient.h"
+#include "GraphicsContext.h"
+#include "Pattern.h"
+#include "TextFlags.h"
+
+#if USE(CORE_TEXT)
+#include <CoreGraphics/CoreGraphics.h>
+#include <pal/spi/cg/CoreGraphicsSPI.h>
+#endif
+
+namespace WebCore {
+
+class FloatPoint;
+class Font;
+class GlyphBuffer;
+class GraphicsContext;
+
+namespace DisplayList {
+
+class Recorder;
+
+class DrawGlyphsRecorder {
+public:
+    explicit DrawGlyphsRecorder(Recorder&);
+
+    void drawGlyphs(const Font&, const GlyphBuffer&, unsigned from, unsigned numGlyphs, const FloatPoint& anchorPoint, FontSmoothingMode);
+
+#if USE(CORE_TEXT)
+    void recordBeginLayer(CGRenderingStateRef, CGGStateRef, CGRect);
+    void recordEndLayer(CGRenderingStateRef, CGGStateRef);
+    void recordDrawGlyphs(CGRenderingStateRef, CGGStateRef, const CGAffineTransform*, const CGGlyph[], const CGPoint positions[], size_t count);
+    void recordDrawImage(CGRenderingStateRef, CGGStateRef, CGRect, CGImageRef);
+#endif
+
+private:
+    GraphicsContext createInternalContext();
+
+    void populateInternalState(const GraphicsContextState&);
+    void populateInternalContext(const GraphicsContextState&);
+    void prepareInternalContext(const Font&, FontSmoothingMode);
+    void concludeInternalContext();
+
+    void updateFillColor(const Color&, Gradient* = nullptr, Pattern* = nullptr);
+    void updateStrokeColor(const Color&, Gradient* = nullptr, Pattern* = nullptr);
+    void updateCTM(const AffineTransform&);
+    enum class ShadowsIgnoreTransforms {
+        Unspecified,
+        Yes,
+        No
+    };
+    void updateShadow(const FloatSize& shadowOffset, float shadowBlur, const Color& shadowColor, ShadowsIgnoreTransforms);
+
+#if USE(CORE_TEXT)
+    void updateShadow(CGStyleRef);
+#endif
+
+    Recorder& m_owner;
+    GraphicsContext m_internalContext;
+    const Font* m_originalFont { nullptr };
+    FontSmoothingMode m_smoothingMode { FontSmoothingMode::AutoSmoothing };
+    AffineTransform m_originalTextMatrix;
+
+    struct State {
+        struct Style {
+            Color color;
+            RefPtr<Gradient> gradient;
+            RefPtr<Pattern> pattern;
+        };
+        Style fillStyle;
+        Style strokeStyle;
+
+        AffineTransform ctm;
+
+        struct ShadowState {
+            FloatSize offset;
+            float blur { 0 };
+            Color color;
+            bool ignoreTransforms { false };
+        };
+        ShadowState shadow;
+    };
+    State m_originalState;
+    State m_currentState;
+};
+
+}
+
+}
Property changes on: trunk/Source/WebCore/platform/graphics/displaylists/DisplayListDrawGlyphsRecorder.h
___________________________________________________________________

Added: svn:eol-style

+native \ No newline at end of property

Added: svn:keywords

+Author Date Id Rev URL \ No newline at end of property

Added: trunk/Source/WebCore/platform/graphics/displaylists/DisplayListDrawGlyphsRecorderCoreText.cpp (0 => 269211)


--- trunk/Source/WebCore/platform/graphics/displaylists/DisplayListDrawGlyphsRecorderCoreText.cpp	                        (rev 0)
+++ trunk/Source/WebCore/platform/graphics/displaylists/DisplayListDrawGlyphsRecorderCoreText.cpp	2020-10-31 00:01:02 UTC (rev 269211)
@@ -0,0 +1,371 @@
+/*
+ * Copyright (C) 2020 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "DisplayListDrawGlyphsRecorder.h"
+
+#include "BitmapImage.h"
+#include "Color.h"
+#include "DisplayListItems.h"
+#include "DisplayListRecorder.h"
+#include "FloatPoint.h"
+#include "Font.h"
+#include "FontCascade.h"
+#include "GlyphBuffer.h"
+
+#include <CoreText/CoreText.h>
+#include <wtf/Vector.h>
+
+#if PLATFORM(WIN)
+#include <pal/spi/win/CoreTextSPIWin.h>
+#endif
+
+namespace WebCore {
+
+namespace DisplayList {
+
+static CGContextDelegateRef beginLayer(CGContextDelegateRef delegate, CGRenderingStateRef rstate, CGGStateRef gstate, CGRect rect, CFDictionaryRef, CGContextDelegateRef)
+{
+    DrawGlyphsRecorder& recorder = *static_cast<DrawGlyphsRecorder*>(CGContextDelegateGetInfo(delegate));
+    recorder.recordBeginLayer(rstate, gstate, rect);
+    return delegate;
+}
+
+static CGContextDelegateRef endLayer(CGContextDelegateRef delegate, CGRenderingStateRef rstate, CGGStateRef gstate)
+{
+    DrawGlyphsRecorder& recorder = *static_cast<DrawGlyphsRecorder*>(CGContextDelegateGetInfo(delegate));
+    recorder.recordEndLayer(rstate, gstate);
+    return delegate;
+}
+
+static CGError drawGlyphs(CGContextDelegateRef delegate, CGRenderingStateRef rstate, CGGStateRef gstate, const CGAffineTransform* tm, const CGGlyph glyphs[], const CGPoint positions[], size_t count)
+{
+    if (CGGStateGetAlpha(gstate) > 0) {
+        DrawGlyphsRecorder& recorder = *static_cast<DrawGlyphsRecorder*>(CGContextDelegateGetInfo(delegate));
+        recorder.recordDrawGlyphs(rstate, gstate, tm, glyphs, positions, count);
+    }
+    return kCGErrorSuccess;
+}
+
+static CGError drawImage(CGContextDelegateRef delegate, CGRenderingStateRef rstate, CGGStateRef gstate, CGRect rect, CGImageRef image)
+{
+    DrawGlyphsRecorder& recorder = *static_cast<DrawGlyphsRecorder*>(CGContextDelegateGetInfo(delegate));
+    recorder.recordDrawImage(rstate, gstate, rect, image);
+    return kCGErrorSuccess;
+}
+
+GraphicsContext DrawGlyphsRecorder::createInternalContext()
+{
+    auto contextDelegate = adoptCF(CGContextDelegateCreate(this));
+    CGContextDelegateSetCallback(contextDelegate.get(), deBeginLayer, reinterpret_cast<CGContextDelegateCallback>(&beginLayer));
+    CGContextDelegateSetCallback(contextDelegate.get(), deEndLayer, reinterpret_cast<CGContextDelegateCallback>(&endLayer));
+    CGContextDelegateSetCallback(contextDelegate.get(), deDrawGlyphs, reinterpret_cast<CGContextDelegateCallback>(&WebCore::DisplayList::drawGlyphs));
+    CGContextDelegateSetCallback(contextDelegate.get(), deDrawImage, reinterpret_cast<CGContextDelegateCallback>(&drawImage));
+    auto context = adoptCF(CGContextCreateWithDelegate(contextDelegate.get(), kCGContextTypeUnknown, nullptr, nullptr));
+    return GraphicsContext(context.get());
+}
+
+DrawGlyphsRecorder::DrawGlyphsRecorder(Recorder& owner)
+    : m_owner(owner)
+    , m_internalContext(createInternalContext())
+{
+}
+
+void DrawGlyphsRecorder::populateInternalState(const GraphicsContextState& contextState)
+{
+    m_originalState.fillStyle.color = contextState.fillColor;
+    m_originalState.fillStyle.gradient = contextState.fillGradient;
+    m_originalState.fillStyle.pattern = contextState.fillPattern;
+
+    m_originalState.strokeStyle.color = contextState.strokeColor;
+    m_originalState.strokeStyle.gradient = contextState.strokeGradient;
+    m_originalState.strokeStyle.pattern = contextState.strokePattern;
+
+    m_originalState.ctm = m_owner.currentState().ctm; // FIXME: Deal with base CTM.
+
+    m_originalState.shadow.offset = contextState.shadowOffset;
+    m_originalState.shadow.blur = contextState.shadowBlur;
+    m_originalState.shadow.color = contextState.shadowColor;
+    m_originalState.shadow.ignoreTransforms = contextState.shadowsIgnoreTransforms;
+
+    m_currentState = m_originalState;
+}
+
+void DrawGlyphsRecorder::populateInternalContext(const GraphicsContextState& contextState)
+{
+    if (m_originalState.fillStyle.color.isValid())
+        m_internalContext.setFillColor(m_originalState.fillStyle.color);
+    else if (m_originalState.fillStyle.gradient)
+        m_internalContext.setFillGradient(*m_originalState.fillStyle.gradient);
+    else {
+        ASSERT(m_originalState.fillStyle.pattern);
+        if (m_originalState.fillStyle.pattern)
+            m_internalContext.setFillPattern(*m_originalState.fillStyle.pattern);
+    }
+
+    if (m_originalState.strokeStyle.color.isValid())
+        m_internalContext.setStrokeColor(m_originalState.strokeStyle.color);
+    else if (m_originalState.strokeStyle.gradient)
+        m_internalContext.setStrokeGradient(*m_originalState.strokeStyle.gradient);
+    else {
+        ASSERT(m_originalState.strokeStyle.pattern);
+        if (m_originalState.strokeStyle.pattern)
+            m_internalContext.setStrokePattern(*m_originalState.strokeStyle.pattern);
+    }
+
+    m_internalContext.setCTM(m_originalState.ctm);
+
+    m_internalContext.setShadowsIgnoreTransforms(m_originalState.shadow.ignoreTransforms);
+    if (contextState.shadowsUseLegacyRadius)
+        m_internalContext.setLegacyShadow(m_originalState.shadow.offset, m_originalState.shadow.blur, m_originalState.shadow.color);
+    else
+        m_internalContext.setShadow(m_originalState.shadow.offset, m_originalState.shadow.blur, m_originalState.shadow.color);
+
+    m_internalContext.setTextDrawingMode(contextState.textDrawingMode);
+}
+
+void DrawGlyphsRecorder::prepareInternalContext(const Font& font, FontSmoothingMode smoothingMode)
+{
+    ASSERT(CGAffineTransformIsIdentity(CTFontGetMatrix(font.platformData().ctFont())));
+
+    m_originalFont = &font;
+    m_smoothingMode = smoothingMode;
+
+    m_originalTextMatrix = computeOverallTextMatrix(font);
+    if (font.platformData().orientation() == FontOrientation::Vertical)
+        m_originalTextMatrix = computeVerticalTextMatrix(font, m_originalTextMatrix);
+
+    auto& contextState = m_owner.currentState().stateChange.m_state;
+    populateInternalState(contextState);
+    populateInternalContext(contextState);
+}
+
+void DrawGlyphsRecorder::concludeInternalContext()
+{
+    updateCTM(m_originalState.ctm);
+    updateFillColor(m_originalState.fillStyle.color, m_originalState.fillStyle.gradient.get(), m_originalState.fillStyle.pattern.get());
+    updateStrokeColor(m_originalState.strokeStyle.color, m_originalState.strokeStyle.gradient.get(), m_originalState.strokeStyle.pattern.get());
+    updateShadow(m_originalState.shadow.offset, m_originalState.shadow.blur, m_originalState.shadow.color, m_originalState.shadow.ignoreTransforms ? ShadowsIgnoreTransforms::Yes : ShadowsIgnoreTransforms::No);
+}
+
+void DrawGlyphsRecorder::updateFillColor(const Color& newColor, Gradient* newGradient, Pattern* newPattern)
+{
+    // This check looks wrong but it actually isn't, for our limited use.
+    // CT will only ever set this to a solid color, which this is the correct check for.
+    // In concludeInternalContext() we set it back to what it was originally, which this check works correctly for too.
+    if (newColor == m_currentState.fillStyle.color)
+        return;
+
+    GraphicsContextState newState;
+    newState.fillColor = newColor;
+    if (newGradient)
+        newState.fillGradient = newGradient;
+    if (newPattern)
+        newState.fillPattern = newPattern;
+    m_owner.updateState(newState, { GraphicsContextState::FillColorChange });
+    m_currentState.fillStyle.color = newColor;
+}
+
+void DrawGlyphsRecorder::updateStrokeColor(const Color& newColor, Gradient* newGradient, Pattern* newPattern)
+{
+    // This check looks wrong but it actually isn't, for our limited use.
+    // CT will only ever set this to a solid color, which this is the correct check for.
+    // In concludeInternalContext() we set it back to what it was originally, which this check works correctly for too.
+    if (newColor == m_currentState.strokeStyle.color)
+        return;
+
+    GraphicsContextState newState;
+    newState.strokeColor = newColor;
+    if (newGradient)
+        newState.strokeGradient = newGradient;
+    if (newPattern)
+        newState.strokePattern = newPattern;
+    m_owner.updateState(newState, { GraphicsContextState::StrokeColorChange });
+    m_currentState.strokeStyle.color = newColor;
+}
+
+void DrawGlyphsRecorder::updateCTM(const AffineTransform& ctm)
+{
+    if (ctm == m_currentState.ctm)
+        return;
+
+    m_owner.setCTM(ctm);
+    m_currentState.ctm = ctm;
+}
+
+static bool shadowIsCleared(const FloatSize& shadowOffset, float shadowBlur)
+{
+    return shadowOffset == FloatSize() && !shadowBlur;
+}
+
+void DrawGlyphsRecorder::updateShadow(const FloatSize& shadowOffset, float shadowBlur, const Color& shadowColor, ShadowsIgnoreTransforms shadowsIgnoreTransforms)
+{
+    // We don't need to consider shadowsIgnoreTransforms if nobody has any shadows.
+    if (shadowIsCleared(shadowOffset, shadowBlur) && shadowIsCleared(m_currentState.shadow.offset, m_currentState.shadow.blur))
+        return;
+
+    GraphicsContextState newState;
+    GraphicsContextState::StateChangeFlags stateChangeFlags;
+
+    if (shadowOffset != m_currentState.shadow.offset || shadowBlur != m_currentState.shadow.blur || shadowColor != m_currentState.shadow.color) {
+        newState.shadowOffset = shadowOffset;
+        newState.shadowBlur = shadowBlur;
+        newState.shadowColor = shadowColor;
+        stateChangeFlags.add(GraphicsContextState::ShadowChange);
+    }
+    if (shadowsIgnoreTransforms != ShadowsIgnoreTransforms::Unspecified && (shadowsIgnoreTransforms == ShadowsIgnoreTransforms::Yes) != m_currentState.shadow.ignoreTransforms) {
+        newState.shadowsIgnoreTransforms = (shadowsIgnoreTransforms == ShadowsIgnoreTransforms::Yes);
+        stateChangeFlags.add(GraphicsContextState::ShadowsIgnoreTransformsChange);
+    }
+    if (stateChangeFlags.isEmpty())
+        return;
+    m_owner.updateState(newState, stateChangeFlags);
+
+    m_currentState.shadow.offset = shadowOffset;
+    m_currentState.shadow.blur = shadowBlur;
+    m_currentState.shadow.color = shadowColor;
+    m_currentState.shadow.ignoreTransforms = (shadowsIgnoreTransforms == ShadowsIgnoreTransforms::Yes);
+}
+
+void DrawGlyphsRecorder::updateShadow(CGStyleRef style)
+{
+    if (CGStyleGetType(style) != kCGStyleShadow) {
+        // FIXME: Support more kinds of CGStyles.
+        updateShadow({0, 0}, 0, Color(), ShadowsIgnoreTransforms::Unspecified);
+        return;
+    }
+
+    const auto& shadowStyle = *static_cast<const CGShadowStyle*>(CGStyleGetData(style));
+    auto rad = deg2rad(shadowStyle.azimuth - 180);
+    auto shadowOffset = FloatSize(std::cos(rad), std::sin(rad)) * shadowStyle.height;
+    updateShadow(shadowOffset, shadowStyle.radius, CGStyleGetColor(style), ShadowsIgnoreTransforms::Yes);
+}
+
+void DrawGlyphsRecorder::recordBeginLayer(CGRenderingStateRef, CGGStateRef gstate, CGRect)
+{
+    updateCTM(*CGGStateGetCTM(gstate));
+    auto alpha = CGGStateGetAlpha(gstate);
+    m_owner.beginTransparencyLayer(alpha);
+}
+
+void DrawGlyphsRecorder::recordEndLayer(CGRenderingStateRef, CGGStateRef gstate)
+{
+    updateCTM(*CGGStateGetCTM(gstate));
+    m_owner.endTransparencyLayer();
+}
+
+static Vector<CGSize> computeAdvancesFromPositions(const CGPoint positions[], size_t count, const CGAffineTransform& textMatrix)
+{
+    Vector<CGSize> result;
+    for (size_t i = 0; i < count - 1; ++i) {
+        auto nextPosition = positions[i + 1];
+        auto currentPosition = positions[i];
+        auto advance = CGSizeMake(nextPosition.x - currentPosition.x, nextPosition.y - currentPosition.y);
+        result.append(CGSizeApplyAffineTransform(advance, textMatrix));
+    }
+    result.constructAndAppend(CGSizeMake(0, 0));
+    return result;
+}
+
+void DrawGlyphsRecorder::recordDrawGlyphs(CGRenderingStateRef, CGGStateRef gstate, const CGAffineTransform*, const CGGlyph glyphs[], const CGPoint positions[], size_t count)
+{
+    if (!count)
+        return;
+
+    CGFontRef usedFont = CGGStateGetFont(gstate);
+    if (usedFont != adoptCF(CTFontCopyGraphicsFont(m_originalFont->platformData().ctFont(), nullptr)).get())
+        return;
+
+#if ASSERT_ENABLED
+    auto textPosition = CGContextGetTextPosition(m_internalContext.platformContext());
+    ASSERT(!textPosition.x);
+    ASSERT(!textPosition.y);
+#endif
+
+    updateCTM(*CGGStateGetCTM(gstate));
+
+    // We want the replayer's CTM and text matrix to match the current CTM and text matrix.
+    // The current text matrix is a concatenation of whatever WebKit sets it to and whatever
+    // Core Text appends to it. So, we have
+    // CTM * m_originalTextMatrix * Core Text's text matrix.
+    // However, CGContextGetTextMatrix() just tells us what the whole text matrix is, so
+    // m_originalTextMatrix * Core Text's text matrix = currentTextMatrix.
+    // The only way we can emulate Core Text's text matrix is by modifying the CTM here.
+    // So, if we do that, the GPU process will have
+    // CTM * X * m_originalTextMatrix
+    // If you set these two equal to each other, and solve for X, you get
+    // CTM * currentTextMatrix = CTM * X * m_originalTextMatrix
+    // currentTextMatrix * inverse(m_originalTextMatrix) = X
+    AffineTransform currentTextMatrix = CGContextGetTextMatrix(m_internalContext.platformContext());
+    AffineTransform ctmFixup;
+    if (auto invertedOriginalTextMatrix = m_originalTextMatrix.inverse())
+        ctmFixup = currentTextMatrix * invertedOriginalTextMatrix.value();
+    AffineTransform inverseCTMFixup;
+    if (auto inverse = ctmFixup.inverse())
+        inverseCTMFixup = inverse.value();
+    else
+        ctmFixup = AffineTransform();
+    m_owner.concatCTM(ctmFixup);
+
+    updateFillColor(CGGStateGetFillColor(gstate));
+    updateStrokeColor(CGGStateGetStrokeColor(gstate));
+    updateShadow(CGGStateGetStyle(gstate));
+
+    m_owner.appendItemAndUpdateExtent(DrawGlyphs::create(*m_originalFont, glyphs, computeAdvancesFromPositions(positions, count, currentTextMatrix).data(), count, currentTextMatrix.mapPoint(positions[0]), m_smoothingMode));
+
+    m_owner.concatCTM(inverseCTMFixup);
+}
+
+void DrawGlyphsRecorder::recordDrawImage(CGRenderingStateRef, CGGStateRef gstate, CGRect rect, CGImageRef cgImage)
+{
+    updateCTM(*CGGStateGetCTM(gstate));
+    updateShadow(CGGStateGetStyle(gstate));
+
+    // Core Graphics assumes a "y up" coordinate system, but in WebKit, we use a "y-down" coordinate system.
+    // This means that WebKit's drawing routines (GraphicsContext::drawImage()) intentionally draw images upside-down from Core Graphics's point of view.
+    // (There's a y-flip inside the implementation of GraphicsContext::drawImage().)
+    // The rect has the right bounds, but we need to transform from CG's coordinate system to WebKit's by performing our own y-flip so images are drawn the right-side-up.
+    // We do this at the boundary between the two APIs, which is right here.
+    m_owner.translate(0, rect.size.height + 2 * rect.origin.y);
+    m_owner.scale(FloatSize(1, -1));
+
+    auto image = BitmapImage::create(cgImage);
+    m_owner.appendItemAndUpdateExtent(DrawImage::create(image, rect, {{ }, image->size()}, { ImageOrientation::OriginTopLeft }));
+
+    // Undo the above y-flip to restore the context.
+    m_owner.scale(FloatSize(1, -1));
+    m_owner.translate(0, -(rect.size.height + 2 * rect.origin.y));
+}
+
+void DrawGlyphsRecorder::drawGlyphs(const Font& font, const GlyphBuffer& glyphBuffer, unsigned from, unsigned numGlyphs, const FloatPoint& startPoint, FontSmoothingMode smoothingMode)
+{
+    prepareInternalContext(font, smoothingMode);
+    FontCascade::drawGlyphs(m_internalContext, font, glyphBuffer, from, numGlyphs, startPoint, smoothingMode);
+    concludeInternalContext();
+}
+
+} // namespace DisplayList
+
+} // namespace WebCore
Property changes on: trunk/Source/WebCore/platform/graphics/displaylists/DisplayListDrawGlyphsRecorderCoreText.cpp
___________________________________________________________________

Added: svn:eol-style

+native \ No newline at end of property

Added: trunk/Source/WebCore/platform/graphics/displaylists/DisplayListDrawGlyphsRecorderHarfBuzz.cpp (0 => 269211)


--- trunk/Source/WebCore/platform/graphics/displaylists/DisplayListDrawGlyphsRecorderHarfBuzz.cpp	                        (rev 0)
+++ trunk/Source/WebCore/platform/graphics/displaylists/DisplayListDrawGlyphsRecorderHarfBuzz.cpp	2020-10-31 00:01:02 UTC (rev 269211)
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2020 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "DisplayListDrawGlyphsRecorder.h"
+
+#include "DisplayListItems.h"
+#include "DisplayListRecorder.h"
+#include "FloatPoint.h"
+#include "Font.h"
+#include "GlyphBuffer.h"
+
+namespace WebCore {
+
+namespace DisplayList {
+
+DrawGlyphsRecorder::DrawGlyphsRecorder(Recorder& owner)
+    : m_owner(owner)
+{
+}
+
+void DrawGlyphsRecorder::drawGlyphs(const Font& font, const GlyphBuffer& glyphBuffer, unsigned from, unsigned numGlyphs, const FloatPoint& startPoint, FontSmoothingMode smoothingMode)
+{
+    m_owner.appendItemAndUpdateExtent(DrawGlyphs::create(font, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs, startPoint, smoothingMode));
+}
+
+} // namespace DisplayList
+
+} // namespace WebCore
Property changes on: trunk/Source/WebCore/platform/graphics/displaylists/DisplayListDrawGlyphsRecorderHarfBuzz.cpp
___________________________________________________________________

Added: svn:eol-style

+native \ No newline at end of property

Added: trunk/Source/WebCore/platform/graphics/displaylists/DisplayListDrawGlyphsRecorderWin.cpp (0 => 269211)


--- trunk/Source/WebCore/platform/graphics/displaylists/DisplayListDrawGlyphsRecorderWin.cpp	                        (rev 0)
+++ trunk/Source/WebCore/platform/graphics/displaylists/DisplayListDrawGlyphsRecorderWin.cpp	2020-10-31 00:01:02 UTC (rev 269211)
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2020 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "DisplayListDrawGlyphsRecorder.h"
+
+#include "DisplayListItems.h"
+#include "DisplayListRecorder.h"
+#include "FloatPoint.h"
+#include "Font.h"
+#include "GlyphBuffer.h"
+
+namespace WebCore {
+
+namespace DisplayList {
+
+DrawGlyphsRecorder::DrawGlyphsRecorder(Recorder& owner)
+    : m_owner(owner)
+{
+}
+
+void DrawGlyphsRecorder::drawGlyphs(const Font& font, const GlyphBuffer& glyphBuffer, unsigned from, unsigned numGlyphs, const FloatPoint& startPoint, FontSmoothingMode smoothingMode)
+{
+    m_owner.appendItemAndUpdateExtent(DrawGlyphs::create(font, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs, startPoint, smoothingMode));
+}
+
+} // namespace DisplayList
+
+} // namespace WebCore
Property changes on: trunk/Source/WebCore/platform/graphics/displaylists/DisplayListDrawGlyphsRecorderWin.cpp
___________________________________________________________________

Added: svn:eol-style

+native \ No newline at end of property

Modified: trunk/Source/WebCore/platform/graphics/displaylists/DisplayListRecorder.cpp (269210 => 269211)


--- trunk/Source/WebCore/platform/graphics/displaylists/DisplayListRecorder.cpp	2020-10-30 23:56:26 UTC (rev 269210)
+++ trunk/Source/WebCore/platform/graphics/displaylists/DisplayListRecorder.cpp	2020-10-31 00:01:02 UTC (rev 269211)
@@ -42,6 +42,7 @@
     : GraphicsContextImpl(context, initialClip, AffineTransform())
     , m_displayList(displayList)
     , m_delegate(delegate)
+    , m_drawGlyphsRecorder(*this)
 {
     LOG_WITH_STREAM(DisplayLists, stream << "\nRecording with clip " << initialClip);
     m_stateStack.append({ state, initialCTM, initialClip });
@@ -163,7 +164,7 @@
 
 void Recorder::drawGlyphs(const Font& font, const GlyphBuffer& glyphBuffer, unsigned from, unsigned numGlyphs, const FloatPoint& startPoint, FontSmoothingMode smoothingMode)
 {
-    appendItemAndUpdateExtent(DrawGlyphs::create(font, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs, startPoint, smoothingMode));
+    m_drawGlyphsRecorder.drawGlyphs(font, glyphBuffer, from, numGlyphs, startPoint, smoothingMode);
 }
 
 ImageDrawResult Recorder::drawImage(Image& image, const FloatRect& destination, const FloatRect& source, const ImagePaintingOptions& imagePaintingOptions)
@@ -243,6 +244,9 @@
 
 void Recorder::concatCTM(const AffineTransform& transform)
 {
+    if (transform.isIdentity())
+        return;
+
     currentState().concatCTM(transform);
     appendItem(ConcatenateCTM::create(transform));
 }
@@ -428,7 +432,17 @@
 
 void Recorder::clipToDrawingCommands(const FloatRect& destination, ColorSpace colorSpace, Function<void(GraphicsContext&)>&& drawingFunction)
 {
-    auto recordingContext = makeUnique<DrawingContext>(destination.size());
+    // The initial CTM matches ImageBuffer's initial CTM.
+    AffineTransform transform = getCTM(GraphicsContext::DefinitelyIncludeDeviceScale);
+    FloatSize scaleFactor(transform.xScale(), transform.yScale());
+    auto scaledSize = expandedIntSize(destination.size() * scaleFactor);
+
+    AffineTransform initialCTM;
+    initialCTM.scale(1, -1);
+    initialCTM.translate(0, -scaledSize.height());
+    initialCTM.scale(scaledSize / destination.size());
+
+    auto recordingContext = makeUnique<DrawingContext>(destination.size(), initialCTM);
     drawingFunction(recordingContext->context());
     appendItem(ClipToDrawingCommands::create(destination, colorSpace, recordingContext->takeDisplayList()));
 }

Modified: trunk/Source/WebCore/platform/graphics/displaylists/DisplayListRecorder.h (269210 => 269211)


--- trunk/Source/WebCore/platform/graphics/displaylists/DisplayListRecorder.h	2020-10-30 23:56:26 UTC (rev 269210)
+++ trunk/Source/WebCore/platform/graphics/displaylists/DisplayListRecorder.h	2020-10-31 00:01:02 UTC (rev 269211)
@@ -26,6 +26,7 @@
 #pragma once
 
 #include "DisplayList.h"
+#include "DisplayListDrawGlyphsRecorder.h"
 #include "GraphicsContextImpl.h"
 #include "Image.h" // For Image::TileRule.
 #include "TextFlags.h"
@@ -61,8 +62,6 @@
 
     size_t itemCount() const { return m_displayList.itemCount(); }
 
-    void appendItemAndUpdateExtent(Ref<DrawingItem>&&);
-
     class Delegate {
     public:
         virtual ~Delegate() { }
@@ -72,6 +71,7 @@
     };
 
 private:
+    friend class DrawGlyphsRecorder;
     bool hasPlatformContext() const override { return false; }
     PlatformGraphicsContext* platformContext() const override { return nullptr; }
 
@@ -151,6 +151,7 @@
     void appendItem(Ref<Item>&&);
     void willAppendItem(const Item&);
     void didAppendItem(const Item&);
+    void appendItemAndUpdateExtent(Ref<DrawingItem>&&);
 
     void appendStateChangeItem(const GraphicsContextStateChange&, GraphicsContextState::StateChangeFlags);
 
@@ -195,6 +196,8 @@
     Delegate* m_delegate;
 
     Vector<ContextState, 32> m_stateStack;
+
+    DrawGlyphsRecorder m_drawGlyphsRecorder;
 };
 
 }
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to