summaryrefslogtreecommitdiffstats
path: root/WebCore/platform
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/platform')
-rw-r--r--WebCore/platform/ContextMenu.cpp887
-rw-r--r--WebCore/platform/ContextMenu.h57
-rw-r--r--WebCore/platform/ContextMenuItem.cpp122
-rw-r--r--WebCore/platform/ContextMenuItem.h94
-rw-r--r--WebCore/platform/PlatformMenuDescription.h6
-rw-r--r--WebCore/platform/ScrollTypes.h66
-rw-r--r--WebCore/platform/ScrollView.cpp46
-rw-r--r--WebCore/platform/ScrollView.h34
-rw-r--r--WebCore/platform/ThemeTypes.h4
-rw-r--r--WebCore/platform/UUID.cpp2
-rw-r--r--WebCore/platform/Widget.h5
-rw-r--r--WebCore/platform/android/TemporaryLinkStubs.cpp3
-rw-r--r--WebCore/platform/audio/AudioResampler.cpp2
-rw-r--r--WebCore/platform/audio/AudioUtilities.cpp11
-rw-r--r--WebCore/platform/audio/Biquad.cpp9
-rw-r--r--WebCore/platform/audio/Cone.cpp11
-rw-r--r--WebCore/platform/audio/Cone.h4
-rw-r--r--WebCore/platform/audio/EqualPowerPanner.cpp4
-rw-r--r--WebCore/platform/audio/FFTFrame.cpp44
-rw-r--r--WebCore/platform/audio/FFTFrame.h21
-rw-r--r--WebCore/platform/audio/HRTFElevation.cpp4
-rw-r--r--WebCore/platform/audio/HRTFKernel.cpp1
-rw-r--r--WebCore/platform/audio/HRTFPanner.cpp2
-rw-r--r--WebCore/platform/audio/chromium/AudioBusChromium.cpp61
-rw-r--r--WebCore/platform/audio/mac/AudioBusMac.mm2
-rw-r--r--WebCore/platform/audio/mkl/FFTFrameMKL.cpp260
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T000_P000.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T000_P015.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T000_P030.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T000_P045.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T000_P060.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T000_P075.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T000_P090.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T000_P315.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T000_P330.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T000_P345.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T015_P000.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T015_P015.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T015_P030.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T015_P045.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T015_P060.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T015_P075.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T015_P090.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T015_P315.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T015_P330.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T015_P345.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T030_P000.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T030_P015.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T030_P030.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T030_P045.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T030_P060.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T030_P075.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T030_P090.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T030_P315.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T030_P330.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T030_P345.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T045_P000.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T045_P015.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T045_P030.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T045_P045.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T045_P060.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T045_P075.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T045_P090.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T045_P315.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T045_P330.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T045_P345.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T060_P000.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T060_P015.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T060_P030.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T060_P045.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T060_P060.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T060_P075.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T060_P090.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T060_P315.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T060_P330.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T060_P345.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T075_P000.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T075_P015.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T075_P030.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T075_P045.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T075_P060.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T075_P075.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T075_P090.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T075_P315.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T075_P330.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T075_P345.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T090_P000.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T090_P015.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T090_P030.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T090_P045.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T090_P060.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T090_P075.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T090_P090.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T090_P315.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T090_P330.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T090_P345.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T105_P000.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T105_P015.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T105_P030.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T105_P045.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T105_P060.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T105_P075.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T105_P090.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T105_P315.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T105_P330.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T105_P345.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T120_P000.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T120_P015.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T120_P030.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T120_P045.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T120_P060.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T120_P075.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T120_P090.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T120_P315.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T120_P330.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T120_P345.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T135_P000.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T135_P015.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T135_P030.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T135_P045.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T135_P060.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T135_P075.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T135_P090.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T135_P315.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T135_P330.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T135_P345.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T150_P000.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T150_P015.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T150_P030.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T150_P045.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T150_P060.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T150_P075.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T150_P090.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T150_P315.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T150_P330.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T150_P345.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T165_P000.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T165_P015.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T165_P030.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T165_P045.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T165_P060.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T165_P075.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T165_P090.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T165_P315.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T165_P330.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T165_P345.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T180_P000.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T180_P015.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T180_P030.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T180_P045.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T180_P060.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T180_P075.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T180_P090.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T180_P315.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T180_P330.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T180_P345.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T195_P000.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T195_P015.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T195_P030.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T195_P045.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T195_P060.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T195_P075.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T195_P090.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T195_P315.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T195_P330.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T195_P345.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T210_P000.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T210_P015.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T210_P030.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T210_P045.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T210_P060.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T210_P075.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T210_P090.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T210_P315.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T210_P330.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T210_P345.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T225_P000.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T225_P015.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T225_P030.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T225_P045.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T225_P060.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T225_P075.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T225_P090.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T225_P315.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T225_P330.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T225_P345.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T240_P000.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T240_P015.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T240_P030.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T240_P045.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T240_P060.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T240_P075.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T240_P090.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T240_P315.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T240_P330.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T240_P345.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T255_P000.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T255_P015.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T255_P030.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T255_P045.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T255_P060.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T255_P075.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T255_P090.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T255_P315.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T255_P330.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T255_P345.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T270_P000.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T270_P015.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T270_P030.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T270_P045.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T270_P060.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T270_P075.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T270_P090.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T270_P315.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T270_P330.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T270_P345.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T285_P000.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T285_P015.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T285_P030.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T285_P045.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T285_P060.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T285_P075.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T285_P090.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T285_P315.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T285_P330.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T285_P345.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T300_P000.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T300_P015.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T300_P030.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T300_P045.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T300_P060.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T300_P075.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T300_P090.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T300_P315.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T300_P330.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T300_P345.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T315_P000.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T315_P015.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T315_P030.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T315_P045.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T315_P060.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T315_P075.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T315_P090.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T315_P315.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T315_P330.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T315_P345.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T330_P000.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T330_P015.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T330_P030.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T330_P045.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T330_P060.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T330_P075.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T330_P090.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T330_P315.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T330_P330.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T330_P345.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T345_P000.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T345_P015.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T345_P030.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T345_P045.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T345_P060.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T345_P075.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T345_P090.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T345_P315.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T345_P330.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/audio/resources/IRC_Composite_C_R0195_T345_P345.wavbin0 -> 1068 bytes
-rw-r--r--WebCore/platform/brew/ContextMenuBrew.cpp6
-rw-r--r--WebCore/platform/chromium/ContextMenuChromium.cpp6
-rw-r--r--WebCore/platform/chromium/MIMETypeRegistryChromium.cpp3
-rw-r--r--WebCore/platform/efl/ContextMenuEfl.cpp48
-rw-r--r--WebCore/platform/efl/ContextMenuItemEfl.cpp87
-rw-r--r--WebCore/platform/efl/SharedTimerEfl.cpp55
-rw-r--r--WebCore/platform/graphics/ContextShadow.cpp105
-rw-r--r--WebCore/platform/graphics/ContextShadow.h29
-rw-r--r--WebCore/platform/graphics/Extensions3D.h6
-rw-r--r--WebCore/platform/graphics/FloatPoint3D.h22
-rw-r--r--WebCore/platform/graphics/Font.cpp113
-rw-r--r--WebCore/platform/graphics/Font.h22
-rw-r--r--WebCore/platform/graphics/FontFastPath.cpp225
-rw-r--r--WebCore/platform/graphics/GeneratedImage.cpp3
-rw-r--r--WebCore/platform/graphics/GraphicsContext.cpp183
-rw-r--r--WebCore/platform/graphics/GraphicsContext.h132
-rw-r--r--WebCore/platform/graphics/GraphicsContext3D.cpp417
-rw-r--r--WebCore/platform/graphics/GraphicsContext3D.h9
-rw-r--r--WebCore/platform/graphics/GraphicsContextPrivate.h101
-rw-r--r--WebCore/platform/graphics/GraphicsLayer.cpp1
-rw-r--r--WebCore/platform/graphics/GraphicsLayer.h15
-rw-r--r--WebCore/platform/graphics/Image.cpp4
-rw-r--r--WebCore/platform/graphics/ImageBuffer.h16
-rw-r--r--WebCore/platform/graphics/ImageSource.cpp21
-rw-r--r--WebCore/platform/graphics/ImageSource.h16
-rw-r--r--WebCore/platform/graphics/IntRect.h23
-rw-r--r--WebCore/platform/graphics/MediaPlayer.cpp104
-rw-r--r--WebCore/platform/graphics/MediaPlayer.h15
-rw-r--r--WebCore/platform/graphics/Path.h2
-rw-r--r--WebCore/platform/graphics/SimpleFontData.cpp44
-rw-r--r--WebCore/platform/graphics/SimpleFontData.h40
-rw-r--r--WebCore/platform/graphics/TextRun.h5
-rw-r--r--WebCore/platform/graphics/WidthIterator.cpp6
-rw-r--r--WebCore/platform/graphics/WidthIterator.h3
-rw-r--r--WebCore/platform/graphics/ca/GraphicsLayerCA.cpp2300
-rw-r--r--WebCore/platform/graphics/ca/GraphicsLayerCA.h (renamed from WebCore/platform/graphics/mac/GraphicsLayerMac.h)106
-rw-r--r--WebCore/platform/graphics/ca/PlatformCAAnimation.h158
-rw-r--r--WebCore/platform/graphics/ca/PlatformCALayer.h211
-rw-r--r--WebCore/platform/graphics/ca/TransformationMatrixCA.cpp69
-rw-r--r--WebCore/platform/graphics/ca/mac/PlatformCAAnimationMac.mm574
-rw-r--r--WebCore/platform/graphics/ca/mac/PlatformCALayerMac.mm725
-rw-r--r--WebCore/platform/graphics/cairo/CairoUtilities.cpp2
-rw-r--r--WebCore/platform/graphics/cairo/ContextShadowCairo.cpp25
-rw-r--r--WebCore/platform/graphics/cairo/FontCairo.cpp8
-rw-r--r--WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp222
-rw-r--r--WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h2
-rw-r--r--WebCore/platform/graphics/cairo/ImageBufferCairo.cpp2
-rw-r--r--WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp3
-rw-r--r--WebCore/platform/graphics/cg/GraphicsContextCG.cpp185
-rw-r--r--WebCore/platform/graphics/cg/ImageBufferCG.cpp314
-rw-r--r--WebCore/platform/graphics/cg/ImageBufferData.h2
-rw-r--r--WebCore/platform/graphics/cg/ImageSourceCG.cpp13
-rw-r--r--WebCore/platform/graphics/cg/TransformationMatrixCG.cpp10
-rw-r--r--WebCore/platform/graphics/chromium/Canvas2DLayerChromium.cpp6
-rw-r--r--WebCore/platform/graphics/chromium/Canvas2DLayerChromium.h2
-rw-r--r--WebCore/platform/graphics/chromium/ContentLayerChromium.cpp160
-rw-r--r--WebCore/platform/graphics/chromium/ContentLayerChromium.h19
-rw-r--r--WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp2
-rw-r--r--WebCore/platform/graphics/chromium/Extensions3DChromium.h1
-rw-r--r--WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp183
-rw-r--r--WebCore/platform/graphics/chromium/FontCacheLinux.cpp3
-rw-r--r--WebCore/platform/graphics/chromium/FontChromiumWin.cpp12
-rw-r--r--WebCore/platform/graphics/chromium/FontLinux.cpp71
-rw-r--r--WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp8
-rw-r--r--WebCore/platform/graphics/chromium/FontPlatformDataLinux.h7
-rw-r--r--WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp5
-rw-r--r--WebCore/platform/graphics/chromium/GraphicsLayerChromium.h3
-rw-r--r--WebCore/platform/graphics/chromium/ImageLayerChromium.cpp45
-rw-r--r--WebCore/platform/graphics/chromium/ImageLayerChromium.h2
-rw-r--r--WebCore/platform/graphics/chromium/LayerChromium.cpp4
-rw-r--r--WebCore/platform/graphics/chromium/LayerChromium.h18
-rw-r--r--WebCore/platform/graphics/chromium/LayerRendererChromium.cpp198
-rw-r--r--WebCore/platform/graphics/chromium/LayerRendererChromium.h17
-rw-r--r--WebCore/platform/graphics/chromium/LayerTexture.cpp93
-rw-r--r--WebCore/platform/graphics/chromium/LayerTexture.h69
-rw-r--r--WebCore/platform/graphics/chromium/PluginLayerChromium.cpp2
-rw-r--r--WebCore/platform/graphics/chromium/PluginLayerChromium.h2
-rw-r--r--WebCore/platform/graphics/chromium/RenderSurfaceChromium.cpp109
-rw-r--r--WebCore/platform/graphics/chromium/RenderSurfaceChromium.h35
-rw-r--r--WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp38
-rw-r--r--WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp36
-rw-r--r--WebCore/platform/graphics/chromium/TextureManager.cpp171
-rw-r--r--WebCore/platform/graphics/chromium/TextureManager.h83
-rw-r--r--WebCore/platform/graphics/chromium/VideoLayerChromium.cpp7
-rw-r--r--WebCore/platform/graphics/chromium/VideoLayerChromium.h2
-rw-r--r--WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp5
-rw-r--r--WebCore/platform/graphics/chromium/WebGLLayerChromium.h2
-rw-r--r--WebCore/platform/graphics/efl/FontEfl.cpp5
-rw-r--r--WebCore/platform/graphics/filters/FEBlend.cpp17
-rw-r--r--WebCore/platform/graphics/filters/FEColorMatrix.cpp24
-rw-r--r--WebCore/platform/graphics/filters/FEComponentTransfer.cpp11
-rw-r--r--WebCore/platform/graphics/filters/FEComposite.cpp122
-rw-r--r--WebCore/platform/graphics/filters/FEConvolveMatrix.cpp46
-rw-r--r--WebCore/platform/graphics/filters/FEDisplacementMap.cpp28
-rw-r--r--WebCore/platform/graphics/filters/FEFlood.cpp8
-rw-r--r--WebCore/platform/graphics/filters/FEGaussianBlur.cpp27
-rw-r--r--WebCore/platform/graphics/filters/FELighting.cpp14
-rw-r--r--WebCore/platform/graphics/filters/FEMerge.cpp11
-rw-r--r--WebCore/platform/graphics/filters/FEMerge.h2
-rw-r--r--WebCore/platform/graphics/filters/FEMorphology.cpp14
-rw-r--r--WebCore/platform/graphics/filters/FEOffset.cpp10
-rw-r--r--WebCore/platform/graphics/filters/FETile.cpp11
-rw-r--r--WebCore/platform/graphics/filters/FETurbulence.cpp16
-rw-r--r--WebCore/platform/graphics/filters/FilterEffect.cpp168
-rw-r--r--WebCore/platform/graphics/filters/FilterEffect.h23
-rw-r--r--WebCore/platform/graphics/filters/SourceAlpha.cpp7
-rw-r--r--WebCore/platform/graphics/filters/SourceGraphic.cpp8
-rw-r--r--WebCore/platform/graphics/filters/SourceGraphic.h2
-rw-r--r--WebCore/platform/graphics/freetype/FontCacheFreeType.cpp23
-rw-r--r--WebCore/platform/graphics/freetype/FontPlatformData.h1
-rw-r--r--WebCore/platform/graphics/freetype/FontPlatformDataFreeType.cpp12
-rw-r--r--WebCore/platform/graphics/freetype/SimpleFontDataFreeType.cpp28
-rw-r--r--WebCore/platform/graphics/gpu/DrawingBuffer.cpp107
-rw-r--r--WebCore/platform/graphics/gpu/Shader.cpp4
-rw-r--r--WebCore/platform/graphics/gpu/SharedGraphicsContext3D.cpp14
-rw-r--r--WebCore/platform/graphics/gpu/SharedGraphicsContext3D.h1
-rw-r--r--WebCore/platform/graphics/gpu/Texture.cpp31
-rw-r--r--WebCore/platform/graphics/gpu/Texture.h2
-rw-r--r--WebCore/platform/graphics/gstreamer/DataSourceGStreamer.cpp246
-rw-r--r--WebCore/platform/graphics/gstreamer/DataSourceGStreamer.h57
-rw-r--r--WebCore/platform/graphics/gstreamer/GStreamerGWorld.cpp9
-rw-r--r--WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp224
-rw-r--r--WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h31
-rw-r--r--WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp47
-rw-r--r--WebCore/platform/graphics/gtk/FontGtk.cpp12
-rw-r--r--WebCore/platform/graphics/gtk/ImageBufferGtk.cpp3
-rw-r--r--WebCore/platform/graphics/haiku/FontHaiku.cpp4
-rw-r--r--WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp26
-rw-r--r--WebCore/platform/graphics/haiku/ImageBufferHaiku.cpp4
-rw-r--r--WebCore/platform/graphics/haiku/SimpleFontDataHaiku.cpp31
-rw-r--r--WebCore/platform/graphics/mac/ComplexTextController.cpp13
-rw-r--r--WebCore/platform/graphics/mac/ComplexTextController.h3
-rw-r--r--WebCore/platform/graphics/mac/FontComplexTextMac.cpp47
-rw-r--r--WebCore/platform/graphics/mac/FontMac.mm46
-rw-r--r--WebCore/platform/graphics/mac/GlyphPageTreeNodeMac.cpp18
-rw-r--r--WebCore/platform/graphics/mac/GraphicsContextMac.mm4
-rw-r--r--WebCore/platform/graphics/mac/GraphicsLayerMac.mm2514
-rw-r--r--WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm4
-rw-r--r--WebCore/platform/graphics/mac/SimpleFontDataMac.mm95
-rw-r--r--WebCore/platform/graphics/mac/WebLayer.h9
-rw-r--r--WebCore/platform/graphics/mac/WebLayer.mm49
-rw-r--r--WebCore/platform/graphics/mac/WebTiledLayer.h1
-rw-r--r--WebCore/platform/graphics/mac/WebTiledLayer.mm44
-rw-r--r--WebCore/platform/graphics/opengl/Extensions3DOpenGL.cpp12
-rw-r--r--WebCore/platform/graphics/opengl/Extensions3DOpenGL.h1
-rw-r--r--WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp18
-rw-r--r--WebCore/platform/graphics/openvg/GraphicsContextOpenVG.cpp55
-rw-r--r--WebCore/platform/graphics/openvg/PainterOpenVG.cpp40
-rw-r--r--WebCore/platform/graphics/openvg/PainterOpenVG.h6
-rw-r--r--WebCore/platform/graphics/pango/SimpleFontDataPango.cpp33
-rw-r--r--WebCore/platform/graphics/qt/ContextShadowQt.cpp33
-rw-r--r--WebCore/platform/graphics/qt/Extensions3DQt.cpp5
-rw-r--r--WebCore/platform/graphics/qt/Extensions3DQt.h1
-rw-r--r--WebCore/platform/graphics/qt/FontPlatformData.h10
-rw-r--r--WebCore/platform/graphics/qt/FontPlatformDataQt.cpp8
-rw-r--r--WebCore/platform/graphics/qt/FontQt.cpp55
-rw-r--r--WebCore/platform/graphics/qt/GraphicsContextQt.cpp348
-rw-r--r--WebCore/platform/graphics/qt/GraphicsLayerQt.cpp9
-rw-r--r--WebCore/platform/graphics/qt/GraphicsLayerQt.h1
-rw-r--r--WebCore/platform/graphics/qt/ImageBufferQt.cpp2
-rw-r--r--WebCore/platform/graphics/qt/ImageDecoderQt.cpp8
-rw-r--r--WebCore/platform/graphics/qt/ImageDecoderQt.h2
-rw-r--r--WebCore/platform/graphics/qt/ImageQt.cpp4
-rw-r--r--WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp5
-rw-r--r--WebCore/platform/graphics/qt/SimpleFontDataQt.cpp16
-rw-r--r--WebCore/platform/graphics/qt/StillImageQt.cpp33
-rw-r--r--WebCore/platform/graphics/qt/TransparencyLayer.h2
-rw-r--r--WebCore/platform/graphics/skia/FontCustomPlatformData.cpp4
-rw-r--r--WebCore/platform/graphics/skia/GlyphPageTreeNodeSkia.cpp43
-rw-r--r--WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp3
-rw-r--r--WebCore/platform/graphics/skia/GraphicsContextSkia.cpp43
-rw-r--r--WebCore/platform/graphics/skia/ImageBufferSkia.cpp51
-rw-r--r--WebCore/platform/graphics/skia/ImageSkia.cpp59
-rw-r--r--WebCore/platform/graphics/skia/PlatformContextSkia.cpp25
-rw-r--r--WebCore/platform/graphics/skia/PlatformContextSkia.h4
-rw-r--r--WebCore/platform/graphics/skia/SkiaFontWin.cpp11
-rw-r--r--WebCore/platform/graphics/skia/SkiaUtils.cpp2
-rw-r--r--WebCore/platform/graphics/texmap/TextureMapper.h8
-rw-r--r--WebCore/platform/graphics/transforms/TransformationMatrix.h8
-rw-r--r--WebCore/platform/graphics/win/FontCGWin.cpp24
-rw-r--r--WebCore/platform/graphics/win/FontWin.cpp51
-rw-r--r--WebCore/platform/graphics/win/GraphicsContextCGWin.cpp9
-rw-r--r--WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp10
-rw-r--r--WebCore/platform/graphics/win/GraphicsLayerCACF.cpp5
-rw-r--r--WebCore/platform/graphics/win/GraphicsLayerCACF.h3
-rw-r--r--WebCore/platform/graphics/win/SimpleFontDataWin.cpp46
-rw-r--r--WebCore/platform/graphics/win/UniscribeController.cpp2
-rw-r--r--WebCore/platform/graphics/win/cairo/FontPlatformData.h8
-rw-r--r--WebCore/platform/graphics/wince/FontWinCE.cpp5
-rw-r--r--WebCore/platform/graphics/wince/GraphicsContextWinCE.cpp110
-rw-r--r--WebCore/platform/graphics/wince/ImageBufferWinCE.cpp2
-rw-r--r--WebCore/platform/graphics/wince/SimpleFontDataWinCE.cpp38
-rw-r--r--WebCore/platform/graphics/wx/FontWx.cpp20
-rw-r--r--WebCore/platform/graphics/wx/GraphicsContextWx.cpp50
-rw-r--r--WebCore/platform/graphics/wx/ImageBufferWx.cpp2
-rw-r--r--WebCore/platform/graphics/wx/SimpleFontDataWx.cpp31
-rw-r--r--WebCore/platform/gtk/ContextMenuGtk.cpp22
-rw-r--r--WebCore/platform/gtk/ContextMenuItemGtk.cpp135
-rw-r--r--WebCore/platform/gtk/GtkVersioning.h2
-rw-r--r--WebCore/platform/gtk/PasteboardHelper.cpp27
-rw-r--r--WebCore/platform/gtk/PlatformScreenGtk.cpp2
-rw-r--r--WebCore/platform/gtk/PopupMenuGtk.cpp112
-rw-r--r--WebCore/platform/gtk/PopupMenuGtk.h11
-rw-r--r--WebCore/platform/gtk/RenderThemeGtk.cpp453
-rw-r--r--WebCore/platform/gtk/RenderThemeGtk.h33
-rw-r--r--WebCore/platform/gtk/WidgetGtk.cpp4
-rw-r--r--WebCore/platform/gtk/WidgetRenderingContext.h4
-rw-r--r--WebCore/platform/gtk/WidgetRenderingContextGtk2.cpp27
-rw-r--r--WebCore/platform/gtk/WidgetRenderingContextGtk3.cpp21
-rw-r--r--WebCore/platform/gtk/gtk2drawing.c127
-rw-r--r--WebCore/platform/gtk/gtk3drawing.c126
-rw-r--r--WebCore/platform/gtk/gtkdrawing.h19
-rw-r--r--WebCore/platform/haiku/ContextMenuHaiku.cpp9
-rw-r--r--WebCore/platform/image-decoders/ImageDecoder.cpp16
-rw-r--r--WebCore/platform/image-decoders/ImageDecoder.h8
-rw-r--r--WebCore/platform/image-decoders/bmp/BMPImageDecoder.cpp5
-rw-r--r--WebCore/platform/image-decoders/bmp/BMPImageDecoder.h2
-rw-r--r--WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp5
-rw-r--r--WebCore/platform/image-decoders/gif/GIFImageDecoder.h2
-rw-r--r--WebCore/platform/image-decoders/ico/ICOImageDecoder.cpp9
-rw-r--r--WebCore/platform/image-decoders/ico/ICOImageDecoder.h2
-rw-r--r--WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp11
-rw-r--r--WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h2
-rw-r--r--WebCore/platform/image-decoders/png/PNGImageDecoder.cpp5
-rw-r--r--WebCore/platform/image-decoders/png/PNGImageDecoder.h2
-rw-r--r--WebCore/platform/image-decoders/webp/WEBPImageDecoder.cpp5
-rw-r--r--WebCore/platform/image-decoders/webp/WEBPImageDecoder.h2
-rw-r--r--WebCore/platform/image-encoders/skia/JPEGImageEncoder.cpp153
-rw-r--r--WebCore/platform/image-encoders/skia/JPEGImageEncoder.h51
-rw-r--r--WebCore/platform/image-encoders/skia/PNGImageEncoder.cpp182
-rw-r--r--WebCore/platform/image-encoders/skia/PNGImageEncoder.h25
-rw-r--r--WebCore/platform/mac/ContextMenuMac.mm76
-rw-r--r--WebCore/platform/mac/GeolocationServiceMac.h77
-rw-r--r--WebCore/platform/mac/GeolocationServiceMac.mm221
-rw-r--r--WebCore/platform/mac/ScrollAnimatorMac.cpp60
-rw-r--r--WebCore/platform/mac/ScrollAnimatorMac.h17
-rw-r--r--WebCore/platform/mac/ScrollAnimatorMac.mm185
-rw-r--r--WebCore/platform/mac/ScrollViewMac.mm7
-rw-r--r--WebCore/platform/mac/WebCoreSystemInterface.h7
-rw-r--r--WebCore/platform/mac/WebCoreSystemInterface.mm3
-rw-r--r--WebCore/platform/mock/GeolocationClientMock.cpp64
-rw-r--r--WebCore/platform/mock/GeolocationClientMock.h21
-rw-r--r--WebCore/platform/network/ResourceRequestBase.cpp10
-rw-r--r--WebCore/platform/network/ResourceRequestBase.h2
-rw-r--r--WebCore/platform/network/SocketStreamErrorBase.cpp17
-rw-r--r--WebCore/platform/network/SocketStreamErrorBase.h14
-rw-r--r--WebCore/platform/network/cf/DNSCFNet.cpp44
-rw-r--r--WebCore/platform/network/cf/ResourceHandleCFNet.cpp2
-rw-r--r--WebCore/platform/network/cf/ResourceResponseCFNet.cpp5
-rw-r--r--WebCore/platform/network/cf/SocketStreamError.h5
-rw-r--r--WebCore/platform/network/cf/SocketStreamHandle.h4
-rw-r--r--WebCore/platform/network/cf/SocketStreamHandleCFNet.cpp34
-rw-r--r--WebCore/platform/network/mac/AuthenticationChallenge.h1
-rw-r--r--WebCore/platform/network/mac/AuthenticationMac.mm14
-rw-r--r--WebCore/platform/network/mac/ResourceHandleMac.mm2
-rw-r--r--WebCore/platform/network/mac/ResourceResponseMac.mm6
-rw-r--r--WebCore/platform/network/qt/AuthenticationChallenge.h5
-rw-r--r--WebCore/platform/network/qt/QNetworkReplyHandler.cpp176
-rw-r--r--WebCore/platform/network/qt/QNetworkReplyHandler.h16
-rw-r--r--WebCore/platform/network/qt/QtNAMThreadSafeProxy.cpp190
-rw-r--r--WebCore/platform/network/qt/QtNAMThreadSafeProxy.h186
-rw-r--r--WebCore/platform/network/qt/ResourceHandleQt.cpp20
-rw-r--r--WebCore/platform/network/soup/ResourceHandleSoup.cpp44
-rw-r--r--WebCore/platform/network/soup/cache/soup-http-input-stream.c1
-rw-r--r--WebCore/platform/network/soup/cache/soup-request-http.c85
-rw-r--r--WebCore/platform/network/soup/cache/webkit/soup-cache.c52
-rw-r--r--WebCore/platform/qt/ClipboardQt.cpp17
-rw-r--r--WebCore/platform/qt/ContextMenuQt.cpp3
-rw-r--r--WebCore/platform/qt/CookieJarQt.cpp47
-rw-r--r--WebCore/platform/qt/FileSystemQt.cpp33
-rw-r--r--WebCore/platform/qt/GeolocationServiceQt.cpp8
-rw-r--r--WebCore/platform/qt/PlatformScreenQt.cpp2
-rw-r--r--WebCore/platform/qt/TemporaryLinkStubsQt.cpp1
-rw-r--r--WebCore/platform/text/BidiResolver.h31
-rw-r--r--WebCore/platform/text/CharacterNames.h18
-rw-r--r--WebCore/platform/text/TextBoundaries.cpp28
-rw-r--r--WebCore/platform/text/TextBoundaries.h3
-rw-r--r--WebCore/platform/text/TextCodecUTF16.cpp11
-rw-r--r--WebCore/platform/text/TextEncoding.cpp39
-rw-r--r--WebCore/platform/text/TextEncodingRegistry.cpp57
-rw-r--r--WebCore/platform/text/TextEncodingRegistry.h6
-rw-r--r--WebCore/platform/text/brew/StringBrew.cpp44
-rw-r--r--WebCore/platform/text/cf/HyphenationCF.cpp57
-rw-r--r--WebCore/platform/text/haiku/StringHaiku.cpp52
-rw-r--r--WebCore/platform/text/wince/TextCodecWinCE.cpp6
-rw-r--r--WebCore/platform/text/wx/StringWx.cpp92
-rw-r--r--WebCore/platform/win/ContextMenuItemWin.cpp212
-rw-r--r--WebCore/platform/win/ContextMenuWin.cpp196
-rw-r--r--WebCore/platform/win/FileSystemWin.cpp5
-rw-r--r--WebCore/platform/wince/FileSystemWinCE.cpp42
-rw-r--r--WebCore/platform/wx/ContextMenuWx.cpp4
-rw-r--r--WebCore/platform/wx/LocalizedStringsWx.cpp2
558 files changed, 11672 insertions, 8360 deletions
diff --git a/WebCore/platform/ContextMenu.cpp b/WebCore/platform/ContextMenu.cpp
index 93cdfdf..a51d818 100644
--- a/WebCore/platform/ContextMenu.cpp
+++ b/WebCore/platform/ContextMenu.cpp
@@ -1,7 +1,5 @@
/*
- * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
- * Copyright (C) 2008 Christian Dywan <christian@imendio.com>
- * Copyright (C) 2010 Igalia S.L
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -12,879 +10,52 @@
* 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 COMPUTER, 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 COMPUTER, 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.
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``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 ITS 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 "ContextMenu.h"
-#if ENABLE(CONTEXT_MENUS)
-
-#include "BackForwardController.h"
-#include "ContextMenuController.h"
-#include "ContextMenuClient.h"
-#include "CSSComputedStyleDeclaration.h"
-#include "CSSProperty.h"
-#include "CSSPropertyNames.h"
-#include "Document.h"
-#include "DocumentLoader.h"
-#include "Editor.h"
-#include "Frame.h"
-#include "FrameLoader.h"
-#include "InspectorController.h"
-#include "KURL.h"
-#include "LocalizedStrings.h"
-#include "Node.h"
-#include "Page.h"
-#include "ResourceRequest.h"
-#include "SelectionController.h"
-#include "Settings.h"
-#include "TextIterator.h"
-#include <wtf/text/CString.h>
-
-using namespace std;
-using namespace WTF;
-using namespace Unicode;
+#if USE(CROSS_PLATFORM_CONTEXT_MENUS)
namespace WebCore {
-ContextMenuController* ContextMenu::controller() const
-{
- if (Node* node = m_hitTestResult.innerNonSharedNode())
- if (Frame* frame = node->document()->frame())
- if (Page* page = frame->page())
- return page->contextMenuController();
- return 0;
-}
-
-static PassOwnPtr<ContextMenuItem> separatorItem()
-{
- return new ContextMenuItem(SeparatorType, ContextMenuItemTagNoAction, String());
-}
-
-static void createAndAppendFontSubMenu(const HitTestResult& result, ContextMenuItem& fontMenuItem)
-{
- ContextMenu fontMenu(result);
-
-#if PLATFORM(MAC)
- ContextMenuItem showFonts(ActionType, ContextMenuItemTagShowFonts, contextMenuItemTagShowFonts());
-#endif
- ContextMenuItem bold(CheckableActionType, ContextMenuItemTagBold, contextMenuItemTagBold());
- ContextMenuItem italic(CheckableActionType, ContextMenuItemTagItalic, contextMenuItemTagItalic());
- ContextMenuItem underline(CheckableActionType, ContextMenuItemTagUnderline, contextMenuItemTagUnderline());
- ContextMenuItem outline(ActionType, ContextMenuItemTagOutline, contextMenuItemTagOutline());
-#if PLATFORM(MAC)
- ContextMenuItem styles(ActionType, ContextMenuItemTagStyles, contextMenuItemTagStyles());
- ContextMenuItem showColors(ActionType, ContextMenuItemTagShowColors, contextMenuItemTagShowColors());
-#endif
-
-#if PLATFORM(MAC)
- fontMenu.appendItem(showFonts);
-#endif
- fontMenu.appendItem(bold);
- fontMenu.appendItem(italic);
- fontMenu.appendItem(underline);
- fontMenu.appendItem(outline);
-#if PLATFORM(MAC)
- fontMenu.appendItem(styles);
- fontMenu.appendItem(*separatorItem());
- fontMenu.appendItem(showColors);
-#endif
-
- fontMenuItem.setSubMenu(&fontMenu);
-}
-
-#if !defined(BUILDING_ON_TIGER)
-
-#if !PLATFORM(GTK)
-
-static void createAndAppendSpellingAndGrammarSubMenu(const HitTestResult& result, ContextMenuItem& spellingAndGrammarMenuItem)
-{
- ContextMenu spellingAndGrammarMenu(result);
-
- ContextMenuItem showSpellingPanel(ActionType, ContextMenuItemTagShowSpellingPanel,
- contextMenuItemTagShowSpellingPanel(true));
- ContextMenuItem checkSpelling(ActionType, ContextMenuItemTagCheckSpelling,
- contextMenuItemTagCheckSpelling());
- ContextMenuItem checkAsYouType(CheckableActionType, ContextMenuItemTagCheckSpellingWhileTyping,
- contextMenuItemTagCheckSpellingWhileTyping());
- ContextMenuItem grammarWithSpelling(CheckableActionType, ContextMenuItemTagCheckGrammarWithSpelling,
- contextMenuItemTagCheckGrammarWithSpelling());
-#if PLATFORM(MAC) && !defined(BUILDING_ON_LEOPARD)
- ContextMenuItem correctSpelling(CheckableActionType, ContextMenuItemTagCorrectSpellingAutomatically,
- contextMenuItemTagCorrectSpellingAutomatically());
-#endif
-
- spellingAndGrammarMenu.appendItem(showSpellingPanel);
- spellingAndGrammarMenu.appendItem(checkSpelling);
-#if PLATFORM(MAC) && !defined(BUILDING_ON_LEOPARD)
- spellingAndGrammarMenu.appendItem(*separatorItem());
-#endif
- spellingAndGrammarMenu.appendItem(checkAsYouType);
- spellingAndGrammarMenu.appendItem(grammarWithSpelling);
-#if PLATFORM(MAC) && !defined(BUILDING_ON_LEOPARD)
- spellingAndGrammarMenu.appendItem(correctSpelling);
-#endif
-
- spellingAndGrammarMenuItem.setSubMenu(&spellingAndGrammarMenu);
-}
-
-#endif // !PLATFORM(GTK)
-
-#else
-
-static void createAndAppendSpellingSubMenu(const HitTestResult& result, ContextMenuItem& spellingMenuItem)
-{
- ContextMenu spellingMenu(result);
-
- ContextMenuItem showSpellingPanel(ActionType, ContextMenuItemTagShowSpellingPanel,
- contextMenuItemTagShowSpellingPanel(true));
- ContextMenuItem checkSpelling(ActionType, ContextMenuItemTagCheckSpelling,
- contextMenuItemTagCheckSpelling());
- ContextMenuItem checkAsYouType(CheckableActionType, ContextMenuItemTagCheckSpellingWhileTyping,
- contextMenuItemTagCheckSpellingWhileTyping());
-
- spellingMenu.appendItem(showSpellingPanel);
- spellingMenu.appendItem(checkSpelling);
- spellingMenu.appendItem(checkAsYouType);
-
- spellingMenuItem.setSubMenu(&spellingMenu);
-}
-
-#endif
-
-#if PLATFORM(MAC)
-
-static void createAndAppendSpeechSubMenu(const HitTestResult& result, ContextMenuItem& speechMenuItem)
-{
- ContextMenu speechMenu(result);
-
- ContextMenuItem start(ActionType, ContextMenuItemTagStartSpeaking, contextMenuItemTagStartSpeaking());
- ContextMenuItem stop(ActionType, ContextMenuItemTagStopSpeaking, contextMenuItemTagStopSpeaking());
-
- speechMenu.appendItem(start);
- speechMenu.appendItem(stop);
-
- speechMenuItem.setSubMenu(&speechMenu);
-}
-
-#endif
-
-#if !PLATFORM(GTK)
-
-static void createAndAppendWritingDirectionSubMenu(const HitTestResult& result, ContextMenuItem& writingDirectionMenuItem)
-{
- ContextMenu writingDirectionMenu(result);
-
- ContextMenuItem defaultItem(ActionType, ContextMenuItemTagDefaultDirection,
- contextMenuItemTagDefaultDirection());
- ContextMenuItem ltr(CheckableActionType, ContextMenuItemTagLeftToRight, contextMenuItemTagLeftToRight());
- ContextMenuItem rtl(CheckableActionType, ContextMenuItemTagRightToLeft, contextMenuItemTagRightToLeft());
-
- writingDirectionMenu.appendItem(defaultItem);
- writingDirectionMenu.appendItem(ltr);
- writingDirectionMenu.appendItem(rtl);
-
- writingDirectionMenuItem.setSubMenu(&writingDirectionMenu);
-}
-
-static void createAndAppendTextDirectionSubMenu(const HitTestResult& result, ContextMenuItem& textDirectionMenuItem)
-{
- ContextMenu textDirectionMenu(result);
-
- ContextMenuItem defaultItem(ActionType, ContextMenuItemTagTextDirectionDefault, contextMenuItemTagDefaultDirection());
- ContextMenuItem ltr(CheckableActionType, ContextMenuItemTagTextDirectionLeftToRight, contextMenuItemTagLeftToRight());
- ContextMenuItem rtl(CheckableActionType, ContextMenuItemTagTextDirectionRightToLeft, contextMenuItemTagRightToLeft());
-
- textDirectionMenu.appendItem(defaultItem);
- textDirectionMenu.appendItem(ltr);
- textDirectionMenu.appendItem(rtl);
-
- textDirectionMenuItem.setSubMenu(&textDirectionMenu);
-}
-
-#endif
-
-#if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
-
-static void createAndAppendSubstitutionsSubMenu(const HitTestResult& result, ContextMenuItem& substitutionsMenuItem)
-{
- ContextMenu substitutionsMenu(result);
-
- ContextMenuItem showSubstitutions(ActionType, ContextMenuItemTagShowSubstitutions, contextMenuItemTagShowSubstitutions(true));
- ContextMenuItem smartCopyPaste(CheckableActionType, ContextMenuItemTagSmartCopyPaste, contextMenuItemTagSmartCopyPaste());
- ContextMenuItem smartQuotes(CheckableActionType, ContextMenuItemTagSmartQuotes, contextMenuItemTagSmartQuotes());
- ContextMenuItem smartDashes(CheckableActionType, ContextMenuItemTagSmartDashes, contextMenuItemTagSmartDashes());
- ContextMenuItem smartLinks(CheckableActionType, ContextMenuItemTagSmartLinks, contextMenuItemTagSmartLinks());
- ContextMenuItem textReplacement(CheckableActionType, ContextMenuItemTagTextReplacement, contextMenuItemTagTextReplacement());
-
- substitutionsMenu.appendItem(showSubstitutions);
- substitutionsMenu.appendItem(*separatorItem());
- substitutionsMenu.appendItem(smartCopyPaste);
- substitutionsMenu.appendItem(smartQuotes);
- substitutionsMenu.appendItem(smartDashes);
- substitutionsMenu.appendItem(smartLinks);
- substitutionsMenu.appendItem(textReplacement);
-
- substitutionsMenuItem.setSubMenu(&substitutionsMenu);
-}
-
-static void createAndAppendTransformationsSubMenu(const HitTestResult& result, ContextMenuItem& transformationsMenuItem)
+ContextMenu::ContextMenu()
{
- ContextMenu transformationsMenu(result);
-
- ContextMenuItem makeUpperCase(ActionType, ContextMenuItemTagMakeUpperCase, contextMenuItemTagMakeUpperCase());
- ContextMenuItem makeLowerCase(ActionType, ContextMenuItemTagMakeLowerCase, contextMenuItemTagMakeLowerCase());
- ContextMenuItem capitalize(ActionType, ContextMenuItemTagCapitalize, contextMenuItemTagCapitalize());
-
- transformationsMenu.appendItem(makeUpperCase);
- transformationsMenu.appendItem(makeLowerCase);
- transformationsMenu.appendItem(capitalize);
-
- transformationsMenuItem.setSubMenu(&transformationsMenu);
}
-#endif
-
-static bool selectionContainsPossibleWord(Frame* frame)
+static const ContextMenuItem* findItemWithAction(unsigned action, const Vector<ContextMenuItem>& items)
{
- // Current algorithm: look for a character that's not just a separator.
- for (TextIterator it(frame->selection()->toNormalizedRange().get()); !it.atEnd(); it.advance()) {
- int length = it.length();
- const UChar* characters = it.characters();
- for (int i = 0; i < length; ++i)
- if (!(category(characters[i]) & (Separator_Space | Separator_Line | Separator_Paragraph)))
- return true;
+ for (size_t i = 0; i < items.size(); ++i) {
+ const ContextMenuItem& item = items[i];
+ if (item.action() == action)
+ return &item;
+ if (item.type() != SubmenuType)
+ continue;
+ if (const ContextMenuItem* subMenuItem = findItemWithAction(action, item.subMenuItems()))
+ return subMenuItem;
}
- return false;
-}
-
-void ContextMenu::populate()
-{
- ContextMenuItem OpenLinkItem(ActionType, ContextMenuItemTagOpenLink, contextMenuItemTagOpenLink());
- ContextMenuItem OpenLinkInNewWindowItem(ActionType, ContextMenuItemTagOpenLinkInNewWindow,
- contextMenuItemTagOpenLinkInNewWindow());
- ContextMenuItem DownloadFileItem(ActionType, ContextMenuItemTagDownloadLinkToDisk,
- contextMenuItemTagDownloadLinkToDisk());
- ContextMenuItem CopyLinkItem(ActionType, ContextMenuItemTagCopyLinkToClipboard,
- contextMenuItemTagCopyLinkToClipboard());
- ContextMenuItem OpenImageInNewWindowItem(ActionType, ContextMenuItemTagOpenImageInNewWindow,
- contextMenuItemTagOpenImageInNewWindow());
- ContextMenuItem DownloadImageItem(ActionType, ContextMenuItemTagDownloadImageToDisk,
- contextMenuItemTagDownloadImageToDisk());
- ContextMenuItem CopyImageItem(ActionType, ContextMenuItemTagCopyImageToClipboard,
- contextMenuItemTagCopyImageToClipboard());
- ContextMenuItem OpenMediaInNewWindowItem(ActionType, ContextMenuItemTagOpenMediaInNewWindow, String());
- ContextMenuItem CopyMediaLinkItem(ActionType, ContextMenuItemTagCopyMediaLinkToClipboard,
- String());
- ContextMenuItem MediaPlayPause(ActionType, ContextMenuItemTagMediaPlayPause,
- contextMenuItemTagMediaPlay());
- ContextMenuItem MediaMute(ActionType, ContextMenuItemTagMediaMute,
- contextMenuItemTagMediaMute());
- ContextMenuItem ToggleMediaControls(CheckableActionType, ContextMenuItemTagToggleMediaControls,
- contextMenuItemTagToggleMediaControls());
- ContextMenuItem ToggleMediaLoop(CheckableActionType, ContextMenuItemTagToggleMediaLoop,
- contextMenuItemTagToggleMediaLoop());
- ContextMenuItem EnterVideoFullscreen(ActionType, ContextMenuItemTagEnterVideoFullscreen,
- contextMenuItemTagEnterVideoFullscreen());
-#if PLATFORM(MAC)
- ContextMenuItem SearchSpotlightItem(ActionType, ContextMenuItemTagSearchInSpotlight,
- contextMenuItemTagSearchInSpotlight());
- ContextMenuItem LookInDictionaryItem(ActionType, ContextMenuItemTagLookUpInDictionary,
- contextMenuItemTagLookUpInDictionary());
-#endif
-#if !PLATFORM(GTK)
- ContextMenuItem SearchWebItem(ActionType, ContextMenuItemTagSearchWeb, contextMenuItemTagSearchWeb());
-#endif
- ContextMenuItem CopyItem(ActionType, ContextMenuItemTagCopy, contextMenuItemTagCopy());
- ContextMenuItem BackItem(ActionType, ContextMenuItemTagGoBack, contextMenuItemTagGoBack());
- ContextMenuItem ForwardItem(ActionType, ContextMenuItemTagGoForward, contextMenuItemTagGoForward());
- ContextMenuItem StopItem(ActionType, ContextMenuItemTagStop, contextMenuItemTagStop());
- ContextMenuItem ReloadItem(ActionType, ContextMenuItemTagReload, contextMenuItemTagReload());
- ContextMenuItem OpenFrameItem(ActionType, ContextMenuItemTagOpenFrameInNewWindow,
- contextMenuItemTagOpenFrameInNewWindow());
- ContextMenuItem NoGuessesItem(ActionType, ContextMenuItemTagNoGuessesFound,
- contextMenuItemTagNoGuessesFound());
- ContextMenuItem IgnoreSpellingItem(ActionType, ContextMenuItemTagIgnoreSpelling,
- contextMenuItemTagIgnoreSpelling());
- ContextMenuItem LearnSpellingItem(ActionType, ContextMenuItemTagLearnSpelling,
- contextMenuItemTagLearnSpelling());
- ContextMenuItem IgnoreGrammarItem(ActionType, ContextMenuItemTagIgnoreGrammar,
- contextMenuItemTagIgnoreGrammar());
- ContextMenuItem CutItem(ActionType, ContextMenuItemTagCut, contextMenuItemTagCut());
- ContextMenuItem PasteItem(ActionType, ContextMenuItemTagPaste, contextMenuItemTagPaste());
-#if PLATFORM(GTK)
- ContextMenuItem DeleteItem(ActionType, ContextMenuItemTagDelete, contextMenuItemTagDelete());
- ContextMenuItem SelectAllItem(ActionType, ContextMenuItemTagSelectAll, contextMenuItemTagSelectAll());
-#endif
-
- HitTestResult result = hitTestResult();
-
- Node* node = m_hitTestResult.innerNonSharedNode();
- if (!node)
- return;
-#if PLATFORM(GTK)
- if (!result.isContentEditable() && (node->isElementNode() && static_cast<Element*>(node)->isFormControlElement()))
- return;
-#endif
- Frame* frame = node->document()->frame();
- if (!frame)
- return;
-
- if (!result.isContentEditable()) {
- FrameLoader* loader = frame->loader();
- KURL linkURL = result.absoluteLinkURL();
- if (!linkURL.isEmpty()) {
- if (loader->canHandleRequest(ResourceRequest(linkURL))) {
- appendItem(OpenLinkItem);
- appendItem(OpenLinkInNewWindowItem);
- appendItem(DownloadFileItem);
- }
- appendItem(CopyLinkItem);
- }
-
- KURL imageURL = result.absoluteImageURL();
- if (!imageURL.isEmpty()) {
- if (!linkURL.isEmpty())
- appendItem(*separatorItem());
-
- appendItem(OpenImageInNewWindowItem);
- appendItem(DownloadImageItem);
- if (imageURL.isLocalFile() || m_hitTestResult.image())
- appendItem(CopyImageItem);
- }
-
- KURL mediaURL = result.absoluteMediaURL();
- if (!mediaURL.isEmpty()) {
- if (!linkURL.isEmpty() || !imageURL.isEmpty())
- appendItem(*separatorItem());
- appendItem(MediaPlayPause);
- appendItem(MediaMute);
- appendItem(ToggleMediaControls);
- appendItem(ToggleMediaLoop);
- appendItem(EnterVideoFullscreen);
-
- appendItem(*separatorItem());
- appendItem(CopyMediaLinkItem);
- appendItem(OpenMediaInNewWindowItem);
- }
-
- if (imageURL.isEmpty() && linkURL.isEmpty() && mediaURL.isEmpty()) {
- if (result.isSelected()) {
- if (selectionContainsPossibleWord(frame)) {
-#if PLATFORM(MAC)
- appendItem(SearchSpotlightItem);
-#endif
-#if !PLATFORM(GTK)
- appendItem(SearchWebItem);
- appendItem(*separatorItem());
-#endif
-#if PLATFORM(MAC)
- appendItem(LookInDictionaryItem);
- appendItem(*separatorItem());
-#endif
- }
- appendItem(CopyItem);
-#if PLATFORM(MAC)
- appendItem(*separatorItem());
- ContextMenuItem SpeechMenuItem(SubmenuType, ContextMenuItemTagSpeechMenu, contextMenuItemTagSpeechMenu());
- createAndAppendSpeechSubMenu(m_hitTestResult, SpeechMenuItem);
- appendItem(SpeechMenuItem);
-#endif
- } else {
-#if ENABLE(INSPECTOR)
- if (!(frame->page() && frame->page()->inspectorController()->hasInspectorFrontendClient())) {
-#endif
- if (frame->page() && frame->page()->backForward()->canGoBackOrForward(-1))
- appendItem(BackItem);
-
- if (frame->page() && frame->page()->backForward()->canGoBackOrForward(1))
- appendItem(ForwardItem);
-
- // use isLoadingInAPISense rather than isLoading because Stop/Reload are
- // intended to match WebKit's API, not WebCore's internal notion of loading status
- if (loader->documentLoader()->isLoadingInAPISense())
- appendItem(StopItem);
- else
- appendItem(ReloadItem);
-#if ENABLE(INSPECTOR)
- }
-#endif
-
- if (frame->page() && frame != frame->page()->mainFrame())
- appendItem(OpenFrameItem);
- }
- }
- } else { // Make an editing context menu
- SelectionController* selection = frame->selection();
- bool inPasswordField = selection->isInPasswordField();
- bool spellCheckingEnabled = frame->editor()->isSpellCheckingEnabledFor(node);
-
- if (!inPasswordField && spellCheckingEnabled) {
- // Consider adding spelling-related or grammar-related context menu items (never both, since a single selected range
- // is never considered a misspelling and bad grammar at the same time)
- bool misspelling;
- bool badGrammar;
- Vector<String> guesses = frame->editor()->guessesForMisspelledOrUngrammaticalSelection(misspelling, badGrammar);
- if (misspelling || badGrammar) {
- size_t size = guesses.size();
- if (size == 0) {
- // If there's bad grammar but no suggestions (e.g., repeated word), just leave off the suggestions
- // list and trailing separator rather than adding a "No Guesses Found" item (matches AppKit)
- if (misspelling) {
- appendItem(NoGuessesItem);
- appendItem(*separatorItem());
- }
- } else {
- for (unsigned i = 0; i < size; i++) {
- const String &guess = guesses[i];
- if (!guess.isEmpty()) {
- ContextMenuItem item(ActionType, ContextMenuItemTagSpellingGuess, guess);
- appendItem(item);
- }
- }
- appendItem(*separatorItem());
- }
-
- if (misspelling) {
- appendItem(IgnoreSpellingItem);
- appendItem(LearnSpellingItem);
- } else
- appendItem(IgnoreGrammarItem);
- appendItem(*separatorItem());
-#if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
- } else {
- // If the string was autocorrected, generate a contextual menu item allowing it to be changed back.
- String replacedString = result.replacedString();
- if (!replacedString.isEmpty()) {
- ContextMenuItem item(ActionType, ContextMenuItemTagChangeBack, contextMenuItemTagChangeBack(replacedString));
- appendItem(item);
- appendItem(*separatorItem());
- }
-#endif
- }
- }
-
- FrameLoader* loader = frame->loader();
- KURL linkURL = result.absoluteLinkURL();
- if (!linkURL.isEmpty()) {
- if (loader->canHandleRequest(ResourceRequest(linkURL))) {
- appendItem(OpenLinkItem);
- appendItem(OpenLinkInNewWindowItem);
- appendItem(DownloadFileItem);
- }
- appendItem(CopyLinkItem);
- appendItem(*separatorItem());
- }
-
- if (result.isSelected() && !inPasswordField && selectionContainsPossibleWord(frame)) {
-#if PLATFORM(MAC)
- appendItem(SearchSpotlightItem);
-#endif
-#if !PLATFORM(GTK)
- appendItem(SearchWebItem);
- appendItem(*separatorItem());
-#endif
-
-#if PLATFORM(MAC)
- appendItem(LookInDictionaryItem);
- appendItem(*separatorItem());
-#endif
- }
-
- appendItem(CutItem);
- appendItem(CopyItem);
- appendItem(PasteItem);
-#if PLATFORM(GTK)
- appendItem(DeleteItem);
- appendItem(*separatorItem());
- appendItem(SelectAllItem);
-#endif
-
- if (!inPasswordField) {
- appendItem(*separatorItem());
-#ifndef BUILDING_ON_TIGER
-#if !PLATFORM(GTK)
- ContextMenuItem SpellingAndGrammarMenuItem(SubmenuType, ContextMenuItemTagSpellingMenu,
- contextMenuItemTagSpellingMenu());
- createAndAppendSpellingAndGrammarSubMenu(m_hitTestResult, SpellingAndGrammarMenuItem);
- appendItem(SpellingAndGrammarMenuItem);
-#endif
-#else
- ContextMenuItem SpellingMenuItem(SubmenuType, ContextMenuItemTagSpellingMenu,
- contextMenuItemTagSpellingMenu());
- createAndAppendSpellingSubMenu(m_hitTestResult, SpellingMenuItem);
- appendItem(SpellingMenuItem);
-#endif
-#if PLATFORM(MAC) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
- ContextMenuItem substitutionsMenuItem(SubmenuType, ContextMenuItemTagSubstitutionsMenu,
- contextMenuItemTagSubstitutionsMenu());
- createAndAppendSubstitutionsSubMenu(m_hitTestResult, substitutionsMenuItem);
- appendItem(substitutionsMenuItem);
- ContextMenuItem transformationsMenuItem(SubmenuType, ContextMenuItemTagTransformationsMenu,
- contextMenuItemTagTransformationsMenu());
- createAndAppendTransformationsSubMenu(m_hitTestResult, transformationsMenuItem);
- appendItem(transformationsMenuItem);
-#endif
-#if PLATFORM(GTK)
- bool shouldShowFontMenu = frame->editor()->canEditRichly();
-#else
- bool shouldShowFontMenu = true;
-#endif
- if (shouldShowFontMenu) {
- ContextMenuItem FontMenuItem(SubmenuType, ContextMenuItemTagFontMenu,
- contextMenuItemTagFontMenu());
- createAndAppendFontSubMenu(m_hitTestResult, FontMenuItem);
- appendItem(FontMenuItem);
- }
-#if PLATFORM(MAC)
- ContextMenuItem SpeechMenuItem(SubmenuType, ContextMenuItemTagSpeechMenu, contextMenuItemTagSpeechMenu());
- createAndAppendSpeechSubMenu(m_hitTestResult, SpeechMenuItem);
- appendItem(SpeechMenuItem);
-#endif
-#if !PLATFORM(GTK)
- ContextMenuItem WritingDirectionMenuItem(SubmenuType, ContextMenuItemTagWritingDirectionMenu,
- contextMenuItemTagWritingDirectionMenu());
- createAndAppendWritingDirectionSubMenu(m_hitTestResult, WritingDirectionMenuItem);
- appendItem(WritingDirectionMenuItem);
- if (Page* page = frame->page()) {
- if (Settings* settings = page->settings()) {
- bool includeTextDirectionSubmenu = settings->textDirectionSubmenuInclusionBehavior() == TextDirectionSubmenuAlwaysIncluded
- || (settings->textDirectionSubmenuInclusionBehavior() == TextDirectionSubmenuAutomaticallyIncluded && frame->editor()->hasBidiSelection());
- if (includeTextDirectionSubmenu) {
- ContextMenuItem TextDirectionMenuItem(SubmenuType, ContextMenuItemTagTextDirectionMenu,
- contextMenuItemTagTextDirectionMenu());
- createAndAppendTextDirectionSubMenu(m_hitTestResult, TextDirectionMenuItem);
- appendItem(TextDirectionMenuItem);
- }
- }
- }
-#endif
- }
- }
-}
-
-#if ENABLE(INSPECTOR)
-void ContextMenu::addInspectElementItem()
-{
- Node* node = m_hitTestResult.innerNonSharedNode();
- if (!node)
- return;
-
- Frame* frame = node->document()->frame();
- if (!frame)
- return;
-
- Page* page = frame->page();
- if (!page)
- return;
-
- if (!page->inspectorController())
- return;
-
- ContextMenuItem InspectElementItem(ActionType, ContextMenuItemTagInspectElement, contextMenuItemTagInspectElement());
- appendItem(*separatorItem());
- appendItem(InspectElementItem);
+ return 0;
}
-#endif // ENABLE(INSPECTOR)
-void ContextMenu::checkOrEnableIfNeeded(ContextMenuItem& item) const
+ContextMenuItem* ContextMenu::itemWithAction(unsigned action)
{
- if (item.type() == SeparatorType)
- return;
-
- Frame* frame = m_hitTestResult.innerNonSharedNode()->document()->frame();
- if (!frame)
- return;
-
- // Custom items already have proper checked and enabled values.
- if (ContextMenuItemBaseCustomTag <= item.action() && item.action() <= ContextMenuItemLastCustomTag)
- return;
-
- bool shouldEnable = true;
- bool shouldCheck = false;
-
- switch (item.action()) {
- case ContextMenuItemTagCheckSpelling:
- shouldEnable = frame->editor()->canEdit();
- break;
- case ContextMenuItemTagDefaultDirection:
- shouldCheck = false;
- shouldEnable = false;
- break;
- case ContextMenuItemTagLeftToRight:
- case ContextMenuItemTagRightToLeft: {
- ExceptionCode ec = 0;
- RefPtr<CSSStyleDeclaration> style = frame->document()->createCSSStyleDeclaration();
- String direction = item.action() == ContextMenuItemTagLeftToRight ? "ltr" : "rtl";
- style->setProperty(CSSPropertyDirection, direction, false, ec);
- shouldCheck = frame->editor()->selectionHasStyle(style.get()) != FalseTriState;
- shouldEnable = true;
- break;
- }
- case ContextMenuItemTagTextDirectionDefault: {
- Editor::Command command = frame->editor()->command("MakeTextWritingDirectionNatural");
- shouldCheck = command.state() == TrueTriState;
- shouldEnable = command.isEnabled();
- break;
- }
- case ContextMenuItemTagTextDirectionLeftToRight: {
- Editor::Command command = frame->editor()->command("MakeTextWritingDirectionLeftToRight");
- shouldCheck = command.state() == TrueTriState;
- shouldEnable = command.isEnabled();
- break;
- }
- case ContextMenuItemTagTextDirectionRightToLeft: {
- Editor::Command command = frame->editor()->command("MakeTextWritingDirectionRightToLeft");
- shouldCheck = command.state() == TrueTriState;
- shouldEnable = command.isEnabled();
- break;
- }
- case ContextMenuItemTagCopy:
- shouldEnable = frame->editor()->canDHTMLCopy() || frame->editor()->canCopy();
- break;
- case ContextMenuItemTagCut:
- shouldEnable = frame->editor()->canDHTMLCut() || frame->editor()->canCut();
- break;
- case ContextMenuItemTagIgnoreSpelling:
- case ContextMenuItemTagLearnSpelling:
- shouldEnable = frame->selection()->isRange();
- break;
- case ContextMenuItemTagPaste:
- shouldEnable = frame->editor()->canDHTMLPaste() || frame->editor()->canPaste();
- break;
-#if PLATFORM(GTK)
- case ContextMenuItemTagDelete:
- shouldEnable = frame->editor()->canDelete();
- break;
- case ContextMenuItemTagSelectAll:
- case ContextMenuItemTagInputMethods:
- case ContextMenuItemTagUnicode:
- shouldEnable = true;
- break;
-#endif
- case ContextMenuItemTagUnderline: {
- ExceptionCode ec = 0;
- RefPtr<CSSStyleDeclaration> style = frame->document()->createCSSStyleDeclaration();
- style->setProperty(CSSPropertyWebkitTextDecorationsInEffect, "underline", false, ec);
- shouldCheck = frame->editor()->selectionHasStyle(style.get()) != FalseTriState;
- shouldEnable = frame->editor()->canEditRichly();
- break;
- }
- case ContextMenuItemTagLookUpInDictionary:
- shouldEnable = frame->selection()->isRange();
- break;
- case ContextMenuItemTagCheckGrammarWithSpelling:
-#ifndef BUILDING_ON_TIGER
- if (frame->editor()->isGrammarCheckingEnabled())
- shouldCheck = true;
- shouldEnable = true;
-#endif
- break;
- case ContextMenuItemTagItalic: {
- ExceptionCode ec = 0;
- RefPtr<CSSStyleDeclaration> style = frame->document()->createCSSStyleDeclaration();
- style->setProperty(CSSPropertyFontStyle, "italic", false, ec);
- shouldCheck = frame->editor()->selectionHasStyle(style.get()) != FalseTriState;
- shouldEnable = frame->editor()->canEditRichly();
- break;
- }
- case ContextMenuItemTagBold: {
- ExceptionCode ec = 0;
- RefPtr<CSSStyleDeclaration> style = frame->document()->createCSSStyleDeclaration();
- style->setProperty(CSSPropertyFontWeight, "bold", false, ec);
- shouldCheck = frame->editor()->selectionHasStyle(style.get()) != FalseTriState;
- shouldEnable = frame->editor()->canEditRichly();
- break;
- }
- case ContextMenuItemTagOutline:
- shouldEnable = false;
- break;
- case ContextMenuItemTagShowSpellingPanel:
-#ifndef BUILDING_ON_TIGER
- if (frame->editor()->spellingPanelIsShowing())
- item.setTitle(contextMenuItemTagShowSpellingPanel(false));
- else
- item.setTitle(contextMenuItemTagShowSpellingPanel(true));
-#endif
- shouldEnable = frame->editor()->canEdit();
- break;
- case ContextMenuItemTagNoGuessesFound:
- shouldEnable = false;
- break;
- case ContextMenuItemTagCheckSpellingWhileTyping:
- shouldCheck = frame->editor()->isContinuousSpellCheckingEnabled();
- break;
-#if PLATFORM(MAC)
- case ContextMenuItemTagSubstitutionsMenu:
- case ContextMenuItemTagTransformationsMenu:
- break;
- case ContextMenuItemTagShowSubstitutions:
-#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
- if (frame->editor()->substitutionsPanelIsShowing())
- item.setTitle(contextMenuItemTagShowSubstitutions(false));
- else
- item.setTitle(contextMenuItemTagShowSubstitutions(true));
- shouldEnable = frame->editor()->canEdit();
-#endif
- break;
- case ContextMenuItemTagMakeUpperCase:
- case ContextMenuItemTagMakeLowerCase:
- case ContextMenuItemTagCapitalize:
- case ContextMenuItemTagChangeBack:
- shouldEnable = frame->editor()->canEdit();
- break;
- case ContextMenuItemTagCorrectSpellingAutomatically:
-#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
- shouldCheck = frame->editor()->isAutomaticSpellingCorrectionEnabled();
-#endif
- break;
- case ContextMenuItemTagSmartCopyPaste:
-#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
- shouldCheck = frame->editor()->smartInsertDeleteEnabled();
-#endif
- break;
- case ContextMenuItemTagSmartQuotes:
-#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
- shouldCheck = frame->editor()->isAutomaticQuoteSubstitutionEnabled();
-#endif
- break;
- case ContextMenuItemTagSmartDashes:
-#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
- shouldCheck = frame->editor()->isAutomaticDashSubstitutionEnabled();
-#endif
- break;
- case ContextMenuItemTagSmartLinks:
-#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
- shouldCheck = frame->editor()->isAutomaticLinkDetectionEnabled();
-#endif
- break;
- case ContextMenuItemTagTextReplacement:
-#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
- shouldCheck = frame->editor()->isAutomaticTextReplacementEnabled();
-#endif
- break;
- case ContextMenuItemTagStopSpeaking:
- shouldEnable = controller() && controller()->client() && controller()->client()->isSpeaking();
- break;
-#else // PLATFORM(MAC) ends here
- case ContextMenuItemTagStopSpeaking:
- break;
-#endif
-#if PLATFORM(GTK)
- case ContextMenuItemTagGoBack:
- shouldEnable = frame->page() && frame->page()->backForward()->canGoBackOrForward(-1);
- break;
- case ContextMenuItemTagGoForward:
- shouldEnable = frame->page() && frame->page()->backForward()->canGoBackOrForward(1);
- break;
- case ContextMenuItemTagStop:
- shouldEnable = frame->loader()->documentLoader()->isLoadingInAPISense();
- break;
- case ContextMenuItemTagReload:
- shouldEnable = !frame->loader()->documentLoader()->isLoadingInAPISense();
- break;
- case ContextMenuItemTagFontMenu:
- shouldEnable = frame->editor()->canEditRichly();
- break;
-#else
- case ContextMenuItemTagGoBack:
- case ContextMenuItemTagGoForward:
- case ContextMenuItemTagStop:
- case ContextMenuItemTagReload:
- case ContextMenuItemTagFontMenu:
-#endif
- case ContextMenuItemTagNoAction:
- case ContextMenuItemTagOpenLinkInNewWindow:
- case ContextMenuItemTagDownloadLinkToDisk:
- case ContextMenuItemTagCopyLinkToClipboard:
- case ContextMenuItemTagOpenImageInNewWindow:
- case ContextMenuItemTagDownloadImageToDisk:
- case ContextMenuItemTagCopyImageToClipboard:
- break;
- case ContextMenuItemTagOpenMediaInNewWindow:
- if (m_hitTestResult.mediaIsVideo())
- item.setTitle(contextMenuItemTagOpenVideoInNewWindow());
- else
- item.setTitle(contextMenuItemTagOpenAudioInNewWindow());
- break;
- case ContextMenuItemTagCopyMediaLinkToClipboard:
- if (m_hitTestResult.mediaIsVideo())
- item.setTitle(contextMenuItemTagCopyVideoLinkToClipboard());
- else
- item.setTitle(contextMenuItemTagCopyAudioLinkToClipboard());
- break;
- case ContextMenuItemTagToggleMediaControls:
- shouldCheck = m_hitTestResult.mediaControlsEnabled();
- break;
- case ContextMenuItemTagToggleMediaLoop:
- shouldCheck = m_hitTestResult.mediaLoopEnabled();
- break;
- case ContextMenuItemTagEnterVideoFullscreen:
- shouldEnable = m_hitTestResult.mediaSupportsFullscreen();
- break;
- case ContextMenuItemTagOpenFrameInNewWindow:
- case ContextMenuItemTagSpellingGuess:
- case ContextMenuItemTagOther:
- case ContextMenuItemTagSearchInSpotlight:
- case ContextMenuItemTagSearchWeb:
- case ContextMenuItemTagOpenWithDefaultApplication:
- case ContextMenuItemPDFActualSize:
- case ContextMenuItemPDFZoomIn:
- case ContextMenuItemPDFZoomOut:
- case ContextMenuItemPDFAutoSize:
- case ContextMenuItemPDFSinglePage:
- case ContextMenuItemPDFFacingPages:
- case ContextMenuItemPDFContinuous:
- case ContextMenuItemPDFNextPage:
- case ContextMenuItemPDFPreviousPage:
- case ContextMenuItemTagOpenLink:
- case ContextMenuItemTagIgnoreGrammar:
- case ContextMenuItemTagSpellingMenu:
- case ContextMenuItemTagShowFonts:
- case ContextMenuItemTagStyles:
- case ContextMenuItemTagShowColors:
- case ContextMenuItemTagSpeechMenu:
- case ContextMenuItemTagStartSpeaking:
- case ContextMenuItemTagWritingDirectionMenu:
- case ContextMenuItemTagTextDirectionMenu:
- case ContextMenuItemTagPDFSinglePageScrolling:
- case ContextMenuItemTagPDFFacingPagesScrolling:
-#if ENABLE(INSPECTOR)
- case ContextMenuItemTagInspectElement:
-#endif
- case ContextMenuItemBaseCustomTag:
- case ContextMenuItemCustomTagNoAction:
- case ContextMenuItemLastCustomTag:
- case ContextMenuItemBaseApplicationTag:
- break;
- case ContextMenuItemTagMediaPlayPause:
- if (m_hitTestResult.mediaPlaying())
- item.setTitle(contextMenuItemTagMediaPause());
- else
- item.setTitle(contextMenuItemTagMediaPlay());
- break;
- case ContextMenuItemTagMediaMute:
- shouldEnable = m_hitTestResult.mediaHasAudio();
- shouldCheck = shouldEnable && m_hitTestResult.mediaMuted();
- break;
- }
-
- item.setChecked(shouldCheck);
- item.setEnabled(shouldEnable);
+ // FIXME: When more platforms switch over, this fucntion should return a const ContextMenuItem*'s, and the const_cast
+ // won't be needed anymore.
+ return const_cast<ContextMenuItem*>(findItemWithAction(action, m_items));
}
} // namespace WebCore
-#endif // ENABLE(CONTEXT_MENUS)
+#endif // USE(CROSS_PLATFORM_CONTEXT_MENUS)
diff --git a/WebCore/platform/ContextMenu.h b/WebCore/platform/ContextMenu.h
index 5321ed6..575c86d 100644
--- a/WebCore/platform/ContextMenu.h
+++ b/WebCore/platform/ContextMenu.h
@@ -29,7 +29,6 @@
#include <wtf/Noncopyable.h>
#include "ContextMenuItem.h"
-#include "HitTestResult.h"
#include "PlatformMenuDescription.h"
#include "PlatformString.h"
#if PLATFORM(MAC)
@@ -41,41 +40,60 @@
namespace WebCore {
class ContextMenuController;
-#if PLATFORM(EFL)
- class ContextMenuClientEfl;
-#endif
class ContextMenu : public Noncopyable
{
public:
- ContextMenu(const HitTestResult&);
- ContextMenu(const HitTestResult&, const PlatformMenuDescription);
- ~ContextMenu();
+ ContextMenu();
+
+ ContextMenuItem* itemWithAction(unsigned);
+
+#if USE(CROSS_PLATFORM_CONTEXT_MENUS)
+#if PLATFORM(WIN)
+ typedef HMENU NativeMenu;
+#elif PLATFORM(EFL)
+ typedef void* NativeMenu;
+#endif
+ explicit ContextMenu(NativeMenu);
- void populate();
- void addInspectElementItem();
- void checkOrEnableIfNeeded(ContextMenuItem&) const;
+ NativeMenu nativeMenu() const;
+
+ static NativeMenu createNativeMenuFromItems(const Vector<ContextMenuItem>&);
+ static void getContextMenuItems(NativeMenu, Vector<ContextMenuItem>&);
+
+ // FIXME: When more platforms switch over, this should return const ContextMenuItem*'s.
+ ContextMenuItem* itemAtIndex(unsigned index) { return &m_items[index]; }
+
+ void setItems(const Vector<ContextMenuItem>& items) { m_items = items; }
+ const Vector<ContextMenuItem>& items() const { return m_items; }
+
+ void appendItem(const ContextMenuItem& item) { m_items.append(item); }
+#else
+ ContextMenu(const PlatformMenuDescription);
+ ~ContextMenu();
void insertItem(unsigned position, ContextMenuItem&);
void appendItem(ContextMenuItem&);
-
- ContextMenuItem* itemWithAction(unsigned);
+
ContextMenuItem* itemAtIndex(unsigned, const PlatformMenuDescription);
unsigned itemCount() const;
- HitTestResult hitTestResult() const { return m_hitTestResult; }
- ContextMenuController* controller() const;
-
PlatformMenuDescription platformDescription() const;
void setPlatformDescription(PlatformMenuDescription);
PlatformMenuDescription releasePlatformDescription();
+
#if PLATFORM(WX)
static ContextMenuItem* itemWithId(int);
#endif
+
+#endif // USE(CROSS_PLATFORM_CONTEXT_MENUS)
+
private:
- HitTestResult m_hitTestResult;
+#if USE(CROSS_PLATFORM_CONTEXT_MENUS)
+ Vector<ContextMenuItem> m_items;
+#else
#if PLATFORM(MAC)
// Keep this in sync with the PlatformMenuDescription typedef
RetainPtr<NSMutableArray> m_platformDescription;
@@ -83,19 +101,20 @@ namespace WebCore {
QList<ContextMenuItem> m_items;
#elif PLATFORM(CHROMIUM)
Vector<ContextMenuItem> m_items;
-#elif PLATFORM(EFL)
- ContextMenuClientEfl* m_contextMenuClient;
- PlatformMenuDescription m_platformDescription;
#else
PlatformMenuDescription m_platformDescription;
#if OS(WINCE)
unsigned m_itemCount;
#endif
#endif
+
+#endif // USE(CROSS_PLATFORM_CONTEXT_MENUS)
};
+#if !USE(CROSS_PLATFORM_CONTEXT_MENUS)
Vector<ContextMenuItem> contextMenuItemVector(PlatformMenuDescription);
PlatformMenuDescription platformMenuDescription(Vector<ContextMenuItem>&);
+#endif
}
diff --git a/WebCore/platform/ContextMenuItem.cpp b/WebCore/platform/ContextMenuItem.cpp
new file mode 100644
index 0000000..0c2a6ea
--- /dev/null
+++ b/WebCore/platform/ContextMenuItem.cpp
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2010 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. AND ITS CONTRIBUTORS ``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 ITS 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 "ContextMenuItem.h"
+
+#include "ContextMenu.h"
+
+#if USE(CROSS_PLATFORM_CONTEXT_MENUS)
+
+namespace WebCore {
+
+ContextMenuItem::ContextMenuItem(ContextMenuItemType type, ContextMenuAction action, const String& title, ContextMenu* subMenu)
+ : m_type(type)
+ , m_action(action)
+ , m_title(title)
+ , m_enabled(true)
+ , m_checked(false)
+{
+ if (subMenu)
+ setSubMenu(subMenu);
+}
+
+ContextMenuItem::ContextMenuItem(ContextMenuItemType type, ContextMenuAction action, const String& title, bool enabled, bool checked)
+ : m_type(type)
+ , m_action(action)
+ , m_title(title)
+ , m_enabled(enabled)
+ , m_checked(checked)
+{
+}
+
+ContextMenuItem::ContextMenuItem(ContextMenuAction action, const String& title, bool enabled, bool checked, const Vector<ContextMenuItem>& subMenuItems)
+ : m_type(SubmenuType)
+ , m_action(action)
+ , m_title(title)
+ , m_enabled(enabled)
+ , m_checked(checked)
+ , m_subMenuItems(subMenuItems)
+{
+}
+
+ContextMenuItem::~ContextMenuItem()
+{
+}
+
+void ContextMenuItem::setSubMenu(ContextMenu* subMenu)
+{
+ if (subMenu) {
+ m_type = SubmenuType;
+ m_subMenuItems = subMenu->items();
+ } else {
+ m_type = ActionType;
+ m_subMenuItems.clear();
+ }
+}
+
+void ContextMenuItem::setType(ContextMenuItemType type)
+{
+ m_type = type;
+}
+
+ContextMenuItemType ContextMenuItem::type() const
+{
+ return m_type;
+}
+
+void ContextMenuItem::setAction(ContextMenuAction action)
+{
+ m_action = action;
+}
+
+ContextMenuAction ContextMenuItem::action() const
+{
+ return m_action;
+}
+
+void ContextMenuItem::setChecked(bool checked)
+{
+ m_checked = checked;
+}
+
+bool ContextMenuItem::checked() const
+{
+ return m_checked;
+}
+
+void ContextMenuItem::setEnabled(bool enabled)
+{
+ m_enabled = enabled;
+}
+
+bool ContextMenuItem::enabled() const
+{
+ return m_enabled;
+}
+
+} // namespace WebCore
+
+#endif // USE(CROSS_PLATFORM_CONTEXT_MENUS)
diff --git a/WebCore/platform/ContextMenuItem.h b/WebCore/platform/ContextMenuItem.h
index 063788b..2d29010 100644
--- a/WebCore/platform/ContextMenuItem.h
+++ b/WebCore/platform/ContextMenuItem.h
@@ -40,8 +40,9 @@
class NSMenuItem;
#endif
#elif PLATFORM(WIN)
-typedef struct tagMENUITEMINFOW* LPMENUITEMINFO;
+typedef struct tagMENUITEMINFOW MENUITEMINFO;
#elif PLATFORM(GTK)
+#include <GRefPtr.h>
typedef struct _GtkMenuItem GtkMenuItem;
#elif PLATFORM(QT)
#include <QAction>
@@ -166,8 +167,6 @@ namespace WebCore {
#if PLATFORM(MAC)
typedef NSMenuItem* PlatformMenuItemDescription;
-#elif PLATFORM(WIN)
- typedef LPMENUITEMINFO PlatformMenuItemDescription;
#elif PLATFORM(QT)
struct PlatformMenuItemDescription {
PlatformMenuItemDescription()
@@ -185,6 +184,7 @@ namespace WebCore {
bool enabled;
};
#elif PLATFORM(GTK)
+<<<<<<< HEAD
struct PlatformMenuItemDescription {
PlatformMenuItemDescription()
: type(ActionType)
@@ -203,6 +203,9 @@ namespace WebCore {
};
#elif defined ANDROID
typedef void* PlatformMenuItemDescription;
+=======
+ typedef GtkMenuItem* PlatformMenuItemDescription;
+>>>>>>> webkit.org at r74534 (trunk)
#elif PLATFORM(WX)
struct PlatformMenuItemDescription {
PlatformMenuItemDescription()
@@ -234,53 +237,22 @@ namespace WebCore {
bool checked;
bool enabled;
};
-#elif PLATFORM(EFL)
- struct PlatformMenuItemDescription {
- PlatformMenuItemDescription()
- : type(ActionType)
- , action(ContextMenuItemTagNoAction)
- , title("")
- , subMenu(0)
- , checked(false)
- , enabled(true) { }
- ContextMenuItemType type;
- ContextMenuAction action;
- String title;
- ContextMenu* subMenu;
- bool checked;
- bool enabled;
- };
#else
typedef void* PlatformMenuItemDescription;
#endif
class ContextMenuItem : public FastAllocBase {
public:
- ContextMenuItem(PlatformMenuItemDescription);
- ContextMenuItem(ContextMenu* subMenu = 0);
- ContextMenuItem(ContextMenuItemType type, ContextMenuAction action, const String& title, ContextMenu* subMenu = 0);
-
+ ContextMenuItem(ContextMenuItemType, ContextMenuAction, const String&, ContextMenu* subMenu = 0);
ContextMenuItem(ContextMenuItemType, ContextMenuAction, const String&, bool enabled, bool checked);
- ContextMenuItem(ContextMenuAction, const String&, bool enabled, bool checked, Vector<ContextMenuItem>& submenuItems);
-#if PLATFORM(GTK)
- ContextMenuItem(GtkMenuItem*);
-#endif
- ~ContextMenuItem();
- PlatformMenuItemDescription releasePlatformDescription();
+ ~ContextMenuItem();
- ContextMenuItemType type() const;
void setType(ContextMenuItemType);
+ ContextMenuItemType type() const;
- ContextMenuAction action() const;
void setAction(ContextMenuAction);
-
- String title() const;
- void setTitle(const String&);
-
- PlatformMenuDescription platformSubMenu() const;
- void setSubMenu(ContextMenu*);
- void setSubMenu(Vector<ContextMenuItem>&);
+ ContextMenuAction action() const;
void setChecked(bool = true);
bool checked() const;
@@ -288,17 +260,57 @@ namespace WebCore {
void setEnabled(bool = true);
bool enabled() const;
- // FIXME: Do we need a keyboard accelerator here?
-#if PLATFORM(GTK)
- static GtkMenuItem* createNativeMenuItem(const PlatformMenuItemDescription&);
+ void setSubMenu(ContextMenu*);
+
+#if USE(CROSS_PLATFORM_CONTEXT_MENUS)
+#if PLATFORM(WIN)
+ typedef MENUITEMINFO NativeItem;
+#elif PLATFORM(EFL)
+ typedef void* NativeItem;
#endif
+ ContextMenuItem(ContextMenuAction, const String&, bool enabled, bool checked, const Vector<ContextMenuItem>& subMenuItems);
+ explicit ContextMenuItem(const NativeItem&);
+
+ // On Windows, the title (dwTypeData of the MENUITEMINFO) is not set in this function. Callers can set the title themselves,
+ // and handle the lifetime of the title, if they need it.
+ NativeItem nativeMenuItem() const;
+
+ void setTitle(const String& title) { m_title = title; }
+ const String& title() const { return m_title; }
+
+ const Vector<ContextMenuItem>& subMenuItems() const { return m_subMenuItems; }
+#else
+ public:
+ ContextMenuItem(PlatformMenuItemDescription);
+ ContextMenuItem(ContextMenu* subMenu = 0);
+ ContextMenuItem(ContextMenuAction, const String&, bool enabled, bool checked, Vector<ContextMenuItem>& submenuItems);
+
+ PlatformMenuItemDescription releasePlatformDescription();
+
+ String title() const;
+ void setTitle(const String&);
+ PlatformMenuDescription platformSubMenu() const;
+ void setSubMenu(Vector<ContextMenuItem>&);
+
+#endif // USE(CROSS_PLATFORM_CONTEXT_MENUS)
private:
+#if USE(CROSS_PLATFORM_CONTEXT_MENUS)
+ String m_title;
+ bool m_enabled;
+ bool m_checked;
+ ContextMenuAction m_action;
+ ContextMenuItemType m_type;
+ Vector<ContextMenuItem> m_subMenuItems;
+#else
#if PLATFORM(MAC)
RetainPtr<NSMenuItem> m_platformDescription;
+#elif PLATFORM(GTK)
+ PlatformRefPtr<GtkMenuItem> m_platformDescription;
#else
PlatformMenuItemDescription m_platformDescription;
#endif
+#endif // USE(CROSS_PLATFORM_CONTEXT_MENUS)
};
}
diff --git a/WebCore/platform/PlatformMenuDescription.h b/WebCore/platform/PlatformMenuDescription.h
index c986207..5e3541a 100644
--- a/WebCore/platform/PlatformMenuDescription.h
+++ b/WebCore/platform/PlatformMenuDescription.h
@@ -32,8 +32,6 @@
#else
class NSMutableArray;
#endif
-#elif PLATFORM(WIN)
-typedef struct HMENU__* HMENU;
#elif PLATFORM(QT)
#include <qlist.h>
#elif PLATFORM(GTK)
@@ -46,10 +44,9 @@ class BMenu;
namespace WebCore {
+#if !USE(CROSS_PLATFORM_CONTEXT_MENUS)
#if PLATFORM(MAC)
typedef NSMutableArray* PlatformMenuDescription;
-#elif PLATFORM(WIN)
- typedef HMENU PlatformMenuDescription;
#elif PLATFORM(QT)
class ContextMenuItem;
typedef const QList<ContextMenuItem>* PlatformMenuDescription;
@@ -65,6 +62,7 @@ namespace WebCore {
#else
typedef void* PlatformMenuDescription;
#endif
+#endif // !USE(CROSS_PLATFORM_CONTEXT_MENUS)
} // namespace
diff --git a/WebCore/platform/ScrollTypes.h b/WebCore/platform/ScrollTypes.h
index eba9055..f07fb1a 100644
--- a/WebCore/platform/ScrollTypes.h
+++ b/WebCore/platform/ScrollTypes.h
@@ -35,6 +35,72 @@ namespace WebCore {
ScrollRight
};
+ enum ScrollLogicalDirection {
+ ScrollBlockDirectionBackward,
+ ScrollBlockDirectionForward,
+ ScrollInlineDirectionBackward,
+ ScrollInlineDirectionForward
+ };
+
+
+ inline ScrollDirection logicalToPhysical(ScrollLogicalDirection direction, bool isVertical, bool isFlipped)
+ {
+ switch (direction) {
+ case ScrollBlockDirectionBackward: {
+ if (isVertical) {
+ if (!isFlipped)
+ return ScrollUp;
+ return ScrollDown;
+ } else {
+ if (!isFlipped)
+ return ScrollLeft;
+ return ScrollRight;
+ }
+ break;
+ }
+ case ScrollBlockDirectionForward: {
+ if (isVertical) {
+ if (!isFlipped)
+ return ScrollDown;
+ return ScrollUp;
+ } else {
+ if (!isFlipped)
+ return ScrollRight;
+ return ScrollLeft;
+ }
+ break;
+ }
+ case ScrollInlineDirectionBackward: {
+ if (isVertical) {
+ if (!isFlipped)
+ return ScrollLeft;
+ return ScrollRight;
+ } else {
+ if (!isFlipped)
+ return ScrollUp;
+ return ScrollDown;
+ }
+ break;
+ }
+ case ScrollInlineDirectionForward: {
+ if (isVertical) {
+ if (!isFlipped)
+ return ScrollRight;
+ return ScrollLeft;
+ } else {
+ if (!isFlipped)
+ return ScrollDown;
+ return ScrollUp;
+ }
+ break;
+ }
+ default:
+ ASSERT_NOT_REACHED();
+ break;
+ }
+ return ScrollUp;
+ }
+
enum ScrollGranularity {
ScrollByLine,
ScrollByPage,
diff --git a/WebCore/platform/ScrollView.cpp b/WebCore/platform/ScrollView.cpp
index 4f83794..ddce20c 100644
--- a/WebCore/platform/ScrollView.cpp
+++ b/WebCore/platform/ScrollView.cpp
@@ -54,7 +54,6 @@ ScrollView::ScrollView()
, m_useFixedLayout(false)
, m_paintsEntireContents(false)
, m_delegatesScrolling(false)
- , m_scrollOriginX(0)
{
platformInit();
}
@@ -309,14 +308,14 @@ int ScrollView::actualScrollY() const
IntPoint ScrollView::maximumScrollPosition() const
{
- IntPoint maximumOffset(contentsWidth() - visibleWidth() - m_scrollOriginX, contentsHeight() - visibleHeight());
+ IntPoint maximumOffset(contentsWidth() - visibleWidth() - m_scrollOrigin.x(), contentsHeight() - visibleHeight() - m_scrollOrigin.y());
maximumOffset.clampNegativeToZero();
return maximumOffset;
}
IntPoint ScrollView::minimumScrollPosition() const
{
- return IntPoint(-m_scrollOriginX, 0);
+ return IntPoint(-m_scrollOrigin.x(), -m_scrollOrigin.y());
}
IntPoint ScrollView::adjustScrollPositionWithinRange(const IntPoint& scrollPoint) const
@@ -346,9 +345,9 @@ void ScrollView::valueChanged(Scrollbar* scrollbar)
IntSize newOffset = m_scrollOffset;
if (scrollbar) {
if (scrollbar->orientation() == HorizontalScrollbar)
- newOffset.setWidth(scrollbar->value() - m_scrollOriginX);
+ newOffset.setWidth(scrollbar->value() - m_scrollOrigin.x());
else if (scrollbar->orientation() == VerticalScrollbar)
- newOffset.setHeight(scrollbar->value());
+ newOffset.setHeight(scrollbar->value() - m_scrollOrigin.y());
}
IntSize scrollDelta = newOffset - m_scrollOffset;
@@ -403,7 +402,7 @@ bool ScrollView::scroll(ScrollDirection direction, ScrollGranularity granularity
{
if (platformWidget())
return platformScroll(direction, granularity);
-
+
if (direction == ScrollUp || direction == ScrollDown) {
if (m_verticalScrollbar)
return m_verticalScrollbar->scroll(direction, granularity);
@@ -414,6 +413,11 @@ bool ScrollView::scroll(ScrollDirection direction, ScrollGranularity granularity
return false;
}
+bool ScrollView::logicalScroll(ScrollLogicalDirection direction, ScrollGranularity granularity)
+{
+ return scroll(logicalToPhysical(direction, isVerticalDocument(), isFlippedDocument()), granularity);
+}
+
void ScrollView::windowResizerRectChanged()
{
if (platformWidget())
@@ -482,11 +486,15 @@ void ScrollView::updateScrollbars(const IntSize& desiredOffset)
newHasHorizontalScrollbar = false;
if (hasHorizontalScrollbar != newHasHorizontalScrollbar) {
+ if (m_scrollOrigin.y() && !newHasHorizontalScrollbar)
+ m_scrollOrigin.setY(m_scrollOrigin.y() - m_horizontalScrollbar->height());
setHasHorizontalScrollbar(newHasHorizontalScrollbar);
sendContentResizedNotification = true;
}
if (hasVerticalScrollbar != newHasVerticalScrollbar) {
+ if (m_scrollOrigin.x() && !newHasVerticalScrollbar)
+ m_scrollOrigin.setX(m_scrollOrigin.x() - m_verticalScrollbar->width());
setHasVerticalScrollbar(newHasVerticalScrollbar);
sendContentResizedNotification = true;
}
@@ -533,7 +541,7 @@ void ScrollView::updateScrollbars(const IntSize& desiredOffset)
m_horizontalScrollbar->setSuppressInvalidation(true);
m_horizontalScrollbar->setSteps(Scrollbar::pixelsPerLineStep(), pageStep);
m_horizontalScrollbar->setProportion(clientWidth, contentsWidth());
- m_horizontalScrollbar->setValue(scroll.width() + m_scrollOriginX, Scrollbar::NotFromScrollAnimator);
+ m_horizontalScrollbar->setValue(scroll.width() + m_scrollOrigin.x(), Scrollbar::NotFromScrollAnimator);
if (m_scrollbarsSuppressed)
m_horizontalScrollbar->setSuppressInvalidation(false);
}
@@ -555,7 +563,7 @@ void ScrollView::updateScrollbars(const IntSize& desiredOffset)
m_verticalScrollbar->setSuppressInvalidation(true);
m_verticalScrollbar->setSteps(Scrollbar::pixelsPerLineStep(), pageStep);
m_verticalScrollbar->setProportion(clientHeight, contentsHeight());
- m_verticalScrollbar->setValue(scroll.height(), Scrollbar::NotFromScrollAnimator);
+ m_verticalScrollbar->setValue(scroll.height() + m_scrollOrigin.y(), Scrollbar::NotFromScrollAnimator);
if (m_scrollbarsSuppressed)
m_verticalScrollbar->setSuppressInvalidation(false);
}
@@ -1061,19 +1069,21 @@ void ScrollView::removePanScrollIcon()
hostWindow()->invalidateContentsAndWindow(IntRect(m_panScrollIconPoint, IntSize(panIconSizeLength, panIconSizeLength)), true /*immediate*/);
}
-void ScrollView::setScrollOriginX(int x)
+void ScrollView::setScrollOrigin(const IntPoint& origin, bool updatePosition)
{
- if (platformWidget())
- platformSetScrollOriginX(x);
+ if (m_scrollOrigin == origin)
+ return;
- m_scrollOriginX = x;
-}
+ m_scrollOrigin = origin;
-void ScrollView::updateScrollbars()
-{
- if (!platformWidget())
+ if (platformWidget()) {
+ platformSetScrollOrigin(origin, updatePosition);
+ return;
+ }
+
+ // Update if the scroll origin changes, since our position will be different if the content size did not change.
+ if (updatePosition)
updateScrollbars(scrollOffset());
- // FIXME: need corresponding functionality from platformWidget.
}
#if !PLATFORM(WX) && !PLATFORM(GTK) && !PLATFORM(EFL)
@@ -1106,7 +1116,7 @@ void ScrollView::platformSetScrollbarsSuppressed(bool)
{
}
-void ScrollView::platformSetScrollOriginX(int)
+void ScrollView::platformSetScrollOrigin(const IntPoint&, bool updatePosition)
{
}
diff --git a/WebCore/platform/ScrollView.h b/WebCore/platform/ScrollView.h
index 3627283..6f7ec8b 100644
--- a/WebCore/platform/ScrollView.h
+++ b/WebCore/platform/ScrollView.h
@@ -168,7 +168,7 @@ public:
IntSize scrollOffset() const { return visibleContentRect().location() - IntPoint(); } // Gets the scrolled position as an IntSize. Convenient for adding to other sizes.
IntPoint maximumScrollPosition() const; // The maximum position we can be scrolled to.
IntPoint minimumScrollPosition() const; // The minimum position we can be scrolled to.
- // Adjust the pass in scroll position within the minimum and maximum positions.
+ // Adjust the passed in scroll position to keep it between the minimum and maximum positions.
IntPoint adjustScrollPositionWithinRange(const IntPoint&) const;
int scrollX() const { return scrollPosition().x(); }
int scrollY() const { return scrollPosition().y(); }
@@ -179,7 +179,10 @@ public:
// This function scrolls by lines, pages or pixels.
bool scroll(ScrollDirection, ScrollGranularity);
-
+
+ // A logical scroll that just ends up calling the corresponding physical scroll() based off the document's writing mode.
+ bool logicalScroll(ScrollLogicalDirection, ScrollGranularity);
+
// Scroll the actual contents of the view (either blitting or invalidating as needed).
void scrollContents(const IntSize& scrollDelta);
@@ -289,9 +292,12 @@ protected:
// Scroll the content by invalidating everything.
virtual void scrollContentsSlowPath(const IntRect& updateRect);
- void setScrollOriginX(int);
- int scrollOriginX() { return m_scrollOriginX; }
- void updateScrollbars();
+ void setScrollOrigin(const IntPoint&, bool updatePosition);
+ IntPoint scrollOrigin() { return m_scrollOrigin; }
+
+ // Subclassed by FrameView to check the writing-mode of the document.
+ virtual bool isVerticalDocument() const { return true; }
+ virtual bool isFlippedDocument() const { return false; }
private:
RefPtr<Scrollbar> m_horizontalScrollbar;
@@ -328,10 +334,18 @@ private:
bool m_paintsEntireContents;
bool m_delegatesScrolling;
- // m_scrollOriginX is 0 for LTR page. And it is negative of left layout
- // overflow for RTL page. It is mainly used to set the horizontal scrollbar
- // position for RTL page.
- int m_scrollOriginX;
+ // There are 8 possible combinations of writing mode and direction. Scroll origin will be non-zero in the x or y axis
+ // if there is any reversed direction or writing-mode. The combinations are:
+ // writing-mode / direction scrollOrigin.x() set scrollOrigin.y() set
+ // horizontal-tb / ltr NO NO
+ // horizontal-tb / rtl YES NO
+ // horizontal-bt / ltr NO YES
+ // horizontal-bt / rtl YES YES
+ // vertical-lr / ltr NO NO
+ // vertical-lr / rtl NO YES
+ // vertical-rl / ltr YES NO
+ // vertical-rl / rtl YES YES
+ IntPoint m_scrollOrigin;
void init();
void destroy();
@@ -361,7 +375,7 @@ private:
void platformRepaintContentRectangle(const IntRect&, bool now);
bool platformIsOffscreen() const;
- void platformSetScrollOriginX(int);
+ void platformSetScrollOrigin(const IntPoint&, bool updatePosition);
#if PLATFORM(ANDROID)
int platformActualWidth() const;
diff --git a/WebCore/platform/ThemeTypes.h b/WebCore/platform/ThemeTypes.h
index 3567004..ec45cb7 100644
--- a/WebCore/platform/ThemeTypes.h
+++ b/WebCore/platform/ThemeTypes.h
@@ -56,9 +56,9 @@ enum ControlPart {
SliderHorizontalPart, SliderVerticalPart, SliderThumbHorizontalPart,
SliderThumbVerticalPart, CaretPart, SearchFieldPart, SearchFieldDecorationPart,
SearchFieldResultsDecorationPart, SearchFieldResultsButtonPart,
- SearchFieldCancelButtonPart, TextFieldPart, CapsLockIndicatorPart,
+ SearchFieldCancelButtonPart, TextFieldPart,
RelevancyLevelIndicatorPart, ContinuousCapacityLevelIndicatorPart, DiscreteCapacityLevelIndicatorPart, RatingLevelIndicatorPart,
- TextAreaPart
+ TextAreaPart, CapsLockIndicatorPart
};
enum SelectionPart {
diff --git a/WebCore/platform/UUID.cpp b/WebCore/platform/UUID.cpp
index faad008..5c2e076 100644
--- a/WebCore/platform/UUID.cpp
+++ b/WebCore/platform/UUID.cpp
@@ -55,7 +55,7 @@ static const int uuidVersionIdentifierIndex = 14;
String createCanonicalUUIDString()
{
-#if PLATFORM(QT)
+#if PLATFORM(QT) && !defined(QT_NO_QUUID_STRING)
QUuid uuid = QUuid::createUuid();
String canonicalUuidStr = uuid.toString().mid(1, 36).toLower(); // remove opening and closing bracket and make it lower.
ASSERT(canonicalUuidStr[uuidVersionIdentifierIndex] == uuidVersionRequired);
diff --git a/WebCore/platform/Widget.h b/WebCore/platform/Widget.h
index 85612ed..8d29aaa 100644
--- a/WebCore/platform/Widget.h
+++ b/WebCore/platform/Widget.h
@@ -65,7 +65,6 @@ typedef HWND PlatformWidget;
#endif
#if PLATFORM(GTK)
-typedef struct _GdkDrawable GdkDrawable;
typedef struct _GtkWidget GtkWidget;
typedef struct _GtkContainer GtkContainer;
typedef GtkWidget* PlatformWidget;
@@ -116,6 +115,8 @@ class PlatformMouseEvent;
class ScrollView;
class WidgetPrivate;
+enum WidgetNotification { WillPaintFlattened, DidPaintFlattened };
+
// The Widget class serves as a base class for three kinds of objects:
// (1) Scrollable areas (ScrollView)
// (2) Scrollbars (Scrollbar)
@@ -194,6 +195,8 @@ public:
virtual void handleEvent(Event*) { }
+ virtual void notifyWidget(WidgetNotification) { }
+
// It is important for cross-platform code to realize that Mac has flipped coordinates. Therefore any code
// that tries to convert the location of a rect using the point-based convertFromContainingWindow will end
// up with an inaccurate rect. Always make sure to use the rect-based convertFromContainingWindow method
diff --git a/WebCore/platform/android/TemporaryLinkStubs.cpp b/WebCore/platform/android/TemporaryLinkStubs.cpp
index bcb5bfc..98e8812 100644
--- a/WebCore/platform/android/TemporaryLinkStubs.cpp
+++ b/WebCore/platform/android/TemporaryLinkStubs.cpp
@@ -74,7 +74,6 @@
#include "ScrollbarTheme.h"
#include "SmartReplace.h"
#include "Widget.h"
-#include "loader.h"
#include <stdio.h>
#include <stdlib.h>
#include <wtf/text/CString.h>
@@ -166,7 +165,7 @@ Pasteboard::~Pasteboard()
}
-ContextMenu::ContextMenu(const HitTestResult& result) : m_hitTestResult(result)
+ContextMenu::ContextMenu()
{
ASSERT_NOT_REACHED();
notImplemented();
diff --git a/WebCore/platform/audio/AudioResampler.cpp b/WebCore/platform/audio/AudioResampler.cpp
index 7f8221e..ba5b58e 100644
--- a/WebCore/platform/audio/AudioResampler.cpp
+++ b/WebCore/platform/audio/AudioResampler.cpp
@@ -30,7 +30,7 @@
#include "AudioBus.h"
#include <algorithm>
-#include <math.h>
+#include <wtf/MathExtras.h>
using namespace std;
diff --git a/WebCore/platform/audio/AudioUtilities.cpp b/WebCore/platform/audio/AudioUtilities.cpp
index 32f4335..7a4b32e 100644
--- a/WebCore/platform/audio/AudioUtilities.cpp
+++ b/WebCore/platform/audio/AudioUtilities.cpp
@@ -24,9 +24,10 @@
#include "config.h"
-#include "AudioUtilities.h"
+#if ENABLE(WEB_AUDIO)
-#include <math.h>
+#include "AudioUtilities.h"
+#include <wtf/MathExtras.h>
namespace WebCore {
@@ -50,9 +51,13 @@ double linearToDecibels(double linear)
double discreteTimeConstantForSampleRate(double timeConstant, double sampleRate)
{
- return 1.0 - pow(1.0 / M_E, 1.0 / (sampleRate * timeConstant));
+ // hardcoded value is temporary build fix for Windows.
+ // FIXME: replace hardcode 2.718282 with M_E until the correct MathExtras.h solution is determined.
+ return 1.0 - pow(1.0 / 2.718282, 1.0 / (sampleRate * timeConstant));
}
} // AudioUtilites
} // WebCore
+
+#endif // ENABLE(WEB_AUDIO)
diff --git a/WebCore/platform/audio/Biquad.cpp b/WebCore/platform/audio/Biquad.cpp
index 49f010b..20143e3 100644
--- a/WebCore/platform/audio/Biquad.cpp
+++ b/WebCore/platform/audio/Biquad.cpp
@@ -33,9 +33,8 @@
#include "Biquad.h"
#include <algorithm>
-#include <float.h>
-#include <math.h>
#include <stdio.h>
+#include <wtf/MathExtras.h>
#if OS(DARWIN)
#include <Accelerate/Accelerate.h>
@@ -197,7 +196,7 @@ void Biquad::setLowpassParams(double cutoff, double resonance)
double d = sqrt((4.0 - sqrt(16.0 - 16.0 / (g * g))) / 2.0);
// Compute biquad coefficients for lopass filter
- double theta = M_PI * cutoff;
+ double theta = piDouble * cutoff;
double sn = 0.5 * d * sin(theta);
double beta = 0.5 * (1.0 - sn) / (1.0 + sn);
double gamma = (0.5 + beta) * cos(theta);
@@ -218,7 +217,7 @@ void Biquad::setHighpassParams(double cutoff, double resonance)
double d = sqrt((4.0 - sqrt(16.0 - 16.0 / (g * g))) / 2.0);
// Compute biquad coefficients for highpass filter
- double theta = M_PI * cutoff;
+ double theta = piDouble * cutoff;
double sn = 0.5 * d * sin(theta);
double beta = 0.5 * (1.0 - sn) / (1.0 + sn);
double gamma = (0.5 + beta) * cos(theta);
@@ -233,7 +232,7 @@ void Biquad::setHighpassParams(double cutoff, double resonance)
void Biquad::setLowShelfParams(double cutoff, double dbGain)
{
- double theta = M_PI * cutoff;
+ double theta = piDouble * cutoff;
double A = pow(10.0, dbGain / 40.0);
double S = 1.0; // filter slope (1.0 is max value)
diff --git a/WebCore/platform/audio/Cone.cpp b/WebCore/platform/audio/Cone.cpp
index 91813ab..f514cde 100644
--- a/WebCore/platform/audio/Cone.cpp
+++ b/WebCore/platform/audio/Cone.cpp
@@ -31,6 +31,7 @@
#if ENABLE(WEB_AUDIO)
#include "Cone.h"
+#include <wtf/MathExtras.h>
namespace WebCore {
@@ -41,21 +42,21 @@ ConeEffect::ConeEffect()
{
}
-double ConeEffect::gain(Vector3 sourcePosition, Vector3 sourceOrientation, Vector3 listenerPosition)
+double ConeEffect::gain(FloatPoint3D sourcePosition, FloatPoint3D sourceOrientation, FloatPoint3D listenerPosition)
{
if (sourceOrientation.isZero() || ((m_innerAngle == 360.0) && (m_outerAngle == 360.0)))
return 1.0; // no cone specified - unity gain
// Normalized source-listener vector
- Vector3 sourceToListener = listenerPosition - sourcePosition;
+ FloatPoint3D sourceToListener = listenerPosition - sourcePosition;
sourceToListener.normalize();
- Vector3 normalizedSourceOrientation = sourceOrientation;
+ FloatPoint3D normalizedSourceOrientation = sourceOrientation;
normalizedSourceOrientation.normalize();
// Angle between the source orientation vector and the source-listener vector
- double dotProduct = dot(sourceToListener, normalizedSourceOrientation);
- double angle = 180.0 * acos(dotProduct) / M_PI;
+ double dotProduct = sourceToListener.dot(normalizedSourceOrientation);
+ double angle = 180.0 * acos(dotProduct) / piDouble;
double absAngle = fabs(angle);
// Divide by 2.0 here since API is entire angle (not half-angle)
diff --git a/WebCore/platform/audio/Cone.h b/WebCore/platform/audio/Cone.h
index 9936f28..f566018 100644
--- a/WebCore/platform/audio/Cone.h
+++ b/WebCore/platform/audio/Cone.h
@@ -29,7 +29,7 @@
#ifndef Cone_h
#define Cone_h
-#include <wtf/Vector3.h>
+#include "FloatPoint3D.h"
namespace WebCore {
@@ -40,7 +40,7 @@ public:
ConeEffect();
// Returns scalar gain for the given source/listener positions/orientations
- double gain(Vector3 sourcePosition, Vector3 sourceOrientation, Vector3 listenerPosition);
+ double gain(FloatPoint3D sourcePosition, FloatPoint3D sourceOrientation, FloatPoint3D listenerPosition);
// Angles in degrees
void setInnerAngle(double innerAngle) { m_innerAngle = innerAngle; }
diff --git a/WebCore/platform/audio/EqualPowerPanner.cpp b/WebCore/platform/audio/EqualPowerPanner.cpp
index 2e4e10f..002b7c6 100644
--- a/WebCore/platform/audio/EqualPowerPanner.cpp
+++ b/WebCore/platform/audio/EqualPowerPanner.cpp
@@ -30,7 +30,7 @@
#include "AudioBus.h"
#include "AudioUtilities.h"
-#include <math.h>
+#include <wtf/MathExtras.h>
// Use a 50ms smoothing / de-zippering time-constant.
const double SmoothingTimeConstant = 0.050;
@@ -76,7 +76,7 @@ void EqualPowerPanner::pan(double azimuth, double /*elevation*/, AudioBus* input
else
desiredPanPosition = (azimuth + 30.0) / 60.0;
- double desiredGainL = 0.5 * cos(M_PI * desiredPanPosition) + 0.5;
+ double desiredGainL = 0.5 * cos(piDouble * desiredPanPosition) + 0.5;
double desiredGainR = sqrt(1.0 - desiredGainL*desiredGainL);
// Don't de-zipper on first render call.
diff --git a/WebCore/platform/audio/FFTFrame.cpp b/WebCore/platform/audio/FFTFrame.cpp
index 17292b6..d9979d9 100644
--- a/WebCore/platform/audio/FFTFrame.cpp
+++ b/WebCore/platform/audio/FFTFrame.cpp
@@ -134,32 +134,32 @@ void FFTFrame::interpolateFrequencyComponents(const FFTFrame& frame1, const FFTF
lastPhase2 = phase2;
// Unwrap phase deltas
- if (deltaPhase1 > M_PI)
- deltaPhase1 -= 2.0 * M_PI;
- if (deltaPhase1 < -M_PI)
- deltaPhase1 += 2.0 * M_PI;
- if (deltaPhase2 > M_PI)
- deltaPhase2 -= 2.0 * M_PI;
- if (deltaPhase2 < -M_PI)
- deltaPhase2 += 2.0 * M_PI;
+ if (deltaPhase1 > piDouble)
+ deltaPhase1 -= 2.0 * piDouble;
+ if (deltaPhase1 < -piDouble)
+ deltaPhase1 += 2.0 * piDouble;
+ if (deltaPhase2 > piDouble)
+ deltaPhase2 -= 2.0 * piDouble;
+ if (deltaPhase2 < -piDouble)
+ deltaPhase2 += 2.0 * piDouble;
// Blend group-delays
double deltaPhaseBlend;
- if (deltaPhase1 - deltaPhase2 > M_PI)
- deltaPhaseBlend = s1 * deltaPhase1 + s2 * (2.0 * M_PI + deltaPhase2);
- else if (deltaPhase2 - deltaPhase1 > M_PI)
- deltaPhaseBlend = s1 * (2.0 * M_PI + deltaPhase1) + s2 * deltaPhase2;
+ if (deltaPhase1 - deltaPhase2 > piDouble)
+ deltaPhaseBlend = s1 * deltaPhase1 + s2 * (2.0 * piDouble + deltaPhase2);
+ else if (deltaPhase2 - deltaPhase1 > piDouble)
+ deltaPhaseBlend = s1 * (2.0 * piDouble + deltaPhase1) + s2 * deltaPhase2;
else
deltaPhaseBlend = s1 * deltaPhase1 + s2 * deltaPhase2;
phaseAccum += deltaPhaseBlend;
// Unwrap
- if (phaseAccum > M_PI)
- phaseAccum -= 2.0 * M_PI;
- if (phaseAccum < -M_PI)
- phaseAccum += 2.0 * M_PI;
+ if (phaseAccum > piDouble)
+ phaseAccum -= 2.0 * piDouble;
+ if (phaseAccum < -piDouble)
+ phaseAccum += 2.0 * piDouble;
Complex c = complexFromMagnitudePhase(mag, phaseAccum);
@@ -179,7 +179,7 @@ double FFTFrame::extractAverageGroupDelay()
int halfSize = fftSize() / 2;
- const double kSamplePhaseDelay = (2.0 * M_PI) / double(fftSize());
+ const double kSamplePhaseDelay = (2.0 * piDouble) / double(fftSize());
// Calculate weighted average group delay
for (int i = 0; i < halfSize; i++) {
@@ -191,10 +191,10 @@ double FFTFrame::extractAverageGroupDelay()
lastPhase = phase;
// Unwrap
- if (deltaPhase < -M_PI)
- deltaPhase += 2.0 * M_PI;
- if (deltaPhase > M_PI)
- deltaPhase -= 2.0 * M_PI;
+ if (deltaPhase < -piDouble)
+ deltaPhase += 2.0 * piDouble;
+ if (deltaPhase > piDouble)
+ deltaPhase -= 2.0 * piDouble;
aveSum += mag * deltaPhase;
weightSum += mag;
@@ -224,7 +224,7 @@ void FFTFrame::addConstantGroupDelay(double sampleFrameDelay)
float* realP = realData();
float* imagP = imagData();
- const double kSamplePhaseDelay = (2.0 * M_PI) / double(fftSize());
+ const double kSamplePhaseDelay = (2.0 * piDouble) / double(fftSize());
double phaseAdj = -sampleFrameDelay * kSamplePhaseDelay;
diff --git a/WebCore/platform/audio/FFTFrame.h b/WebCore/platform/audio/FFTFrame.h
index 6147fc1..1a82ef0 100644
--- a/WebCore/platform/audio/FFTFrame.h
+++ b/WebCore/platform/audio/FFTFrame.h
@@ -35,6 +35,10 @@
#include <Accelerate/Accelerate.h>
#endif
+#if !OS(DARWIN) && USE(WEBAUDIO_MKL)
+#include "mkl_dfti.h"
+#endif
+
#include <wtf/PassOwnPtr.h>
#include <wtf/Platform.h>
@@ -95,6 +99,23 @@ private:
AudioFloatArray m_realData;
AudioFloatArray m_imagData;
#endif // OS(DARWIN)
+#if !OS(DARWIN) && USE(WEBAUDIO_MKL)
+ // Interleaves the planar real and imaginary data and returns a
+ // pointer to the resulting storage which can be used for in-place
+ // or out-of-place operations. FIXME: ideally all of the MKL
+ // routines would operate on planar data and this method would be
+ // removed.
+ float* getUpToDateComplexData();
+
+ static DFTI_DESCRIPTOR_HANDLE descriptorHandleForSize(unsigned fftSize);
+
+ static DFTI_DESCRIPTOR_HANDLE* descriptorHandles;
+
+ DFTI_DESCRIPTOR_HANDLE m_handle;
+ AudioFloatArray m_complexData;
+ AudioFloatArray m_realData;
+ AudioFloatArray m_imagData;
+#endif // !OS(DARWIN) && USE(WEBAUDIO_MKL)
};
} // namespace WebCore
diff --git a/WebCore/platform/audio/HRTFElevation.cpp b/WebCore/platform/audio/HRTFElevation.cpp
index ab722cd..06d03ea 100644
--- a/WebCore/platform/audio/HRTFElevation.cpp
+++ b/WebCore/platform/audio/HRTFElevation.cpp
@@ -34,7 +34,6 @@
#include "AudioBus.h"
#include "AudioFileReader.h"
-#include "AudioResources.h"
#include "Biquad.h"
#include "FFTFrame.h"
#include "HRTFPanner.h"
@@ -108,9 +107,10 @@ bool HRTFElevation::calculateKernelsForAzimuthElevation(int azimuth, int elevati
return false;
size_t responseLength = impulseResponse->length();
+ size_t expectedLength = static_cast<size_t>(256 * (sampleRate / 44100.0));
// Check number of channels and length. For now these are fixed and known.
- bool isBusGood = responseLength == 512 && impulseResponse->numberOfChannels() == 2;
+ bool isBusGood = responseLength == expectedLength && impulseResponse->numberOfChannels() == 2;
ASSERT(isBusGood);
if (!isBusGood)
return false;
diff --git a/WebCore/platform/audio/HRTFKernel.cpp b/WebCore/platform/audio/HRTFKernel.cpp
index 852cdbf..22d4b12 100644
--- a/WebCore/platform/audio/HRTFKernel.cpp
+++ b/WebCore/platform/audio/HRTFKernel.cpp
@@ -35,6 +35,7 @@
#include "AudioChannel.h"
#include "Biquad.h"
#include "FFTFrame.h"
+#include <wtf/MathExtras.h>
using namespace std;
diff --git a/WebCore/platform/audio/HRTFPanner.cpp b/WebCore/platform/audio/HRTFPanner.cpp
index 56f06f1..68bc505 100644
--- a/WebCore/platform/audio/HRTFPanner.cpp
+++ b/WebCore/platform/audio/HRTFPanner.cpp
@@ -33,7 +33,7 @@
#include "HRTFDatabase.h"
#include "HRTFDatabaseLoader.h"
#include <algorithm>
-#include <math.h>
+#include <wtf/MathExtras.h>
#include <wtf/RefPtr.h>
using namespace std;
diff --git a/WebCore/platform/audio/chromium/AudioBusChromium.cpp b/WebCore/platform/audio/chromium/AudioBusChromium.cpp
new file mode 100644
index 0000000..a93703d
--- /dev/null
+++ b/WebCore/platform/audio/chromium/AudioBusChromium.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2010, Google 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. AND ITS CONTRIBUTORS ``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 ITS 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"
+
+#if ENABLE(WEB_AUDIO)
+
+#include "AudioBus.h"
+
+#include "AudioFileReader.h"
+#include "ChromiumBridge.h"
+#include <wtf/PassOwnPtr.h>
+
+namespace WebCore {
+
+// We will use this version of loadPlatformResource() once the resources are checked into Chromium.
+
+// PassOwnPtr<AudioBus> AudioBus::loadPlatformResource(const char* name, double sampleRate)
+// {
+// return ChromiumBridge::loadPlatformAudioResource(name, sampleRate);
+// }
+
+PassOwnPtr<AudioBus> createBusFromInMemoryAudioFile(const void* data, size_t dataSize, bool mixToMono, double sampleRate)
+{
+ OwnPtr<AudioBus> audioBus = ChromiumBridge::decodeAudioFileData(static_cast<const char*>(data), dataSize, sampleRate);
+ if (audioBus->numberOfChannels() == 2 && mixToMono) {
+ OwnPtr<AudioBus> monoAudioBus = adoptPtr(new AudioBus(1, audioBus->length()));
+
+ // FIXME: AudioBus::copyFrom() should be able to do a downmix to mono.
+ // for now simply copy the left channel.
+ monoAudioBus->channel(0)->copyFrom(audioBus->channel(0));
+ return monoAudioBus.release();
+ }
+
+ return audioBus.release();
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(WEB_AUDIO)
diff --git a/WebCore/platform/audio/mac/AudioBusMac.mm b/WebCore/platform/audio/mac/AudioBusMac.mm
index 3f3185a..3d454a9 100644
--- a/WebCore/platform/audio/mac/AudioBusMac.mm
+++ b/WebCore/platform/audio/mac/AudioBusMac.mm
@@ -47,7 +47,7 @@ PassOwnPtr<AudioBus> AudioBus::loadPlatformResource(const char* name, double sam
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NSBundle *bundle = [NSBundle bundleForClass:[WebCoreAudioBundleClass class]];
- NSString *audioFilePath = [bundle pathForResource:[NSString stringWithUTF8String:name] ofType:@"aif" inDirectory:@"audio"];
+ NSString *audioFilePath = [bundle pathForResource:[NSString stringWithUTF8String:name] ofType:@"wav" inDirectory:@"audio"];
NSData *audioData = [NSData dataWithContentsOfFile:audioFilePath];
if (audioData) {
diff --git a/WebCore/platform/audio/mkl/FFTFrameMKL.cpp b/WebCore/platform/audio/mkl/FFTFrameMKL.cpp
new file mode 100644
index 0000000..f66a485
--- /dev/null
+++ b/WebCore/platform/audio/mkl/FFTFrameMKL.cpp
@@ -0,0 +1,260 @@
+/*
+ * Copyright (C) 2010 Google 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 AND ITS CONTRIBUTORS "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 OR ITS 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.
+ */
+
+// FFTFrame implementation using Intel's Math Kernel Library (MKL),
+// suitable for use on Windows and Linux.
+
+#include "config.h"
+
+#if ENABLE(WEB_AUDIO)
+
+#include "FFTFrame.h"
+
+#include "mkl_vml.h"
+#include <wtf/MathExtras.h>
+
+namespace {
+
+DFTI_DESCRIPTOR_HANDLE createDescriptorHandle(int fftSize)
+{
+ DFTI_DESCRIPTOR_HANDLE handle = 0;
+
+ // Create DFTI descriptor for 1D single precision transform.
+ MKL_LONG status = DftiCreateDescriptor(&handle, DFTI_SINGLE, DFTI_REAL, 1, fftSize);
+ ASSERT(DftiErrorClass(status, DFTI_NO_ERROR));
+
+ // Set placement of result to DFTI_NOT_INPLACE.
+ status = DftiSetValue(handle, DFTI_PLACEMENT, DFTI_NOT_INPLACE);
+ ASSERT(DftiErrorClass(status, DFTI_NO_ERROR));
+
+ // Set packing format to PERM; this produces the layout which
+ // matches Accelerate.framework's on the Mac, though interleaved.
+ status = DftiSetValue(handle, DFTI_PACKED_FORMAT, DFTI_PERM_FORMAT);
+ ASSERT(DftiErrorClass(status, DFTI_NO_ERROR));
+
+ // Set the forward scale factor to 2 to match Accelerate.framework's.
+ // FIXME: FFTFrameMac's scaling factor could be fixed to be 1.0,
+ // in which case this code would need to be changed as well.
+ status = DftiSetValue(handle, DFTI_FORWARD_SCALE, 2.0);
+ ASSERT(DftiErrorClass(status, DFTI_NO_ERROR));
+
+ // Set the backward scale factor to 1 / 2n to match Accelerate.framework's.
+ // FIXME: if the above scaling factor is fixed then this needs to be as well.
+ double scale = 1.0 / (2.0 * fftSize);
+ status = DftiSetValue(handle, DFTI_BACKWARD_SCALE, scale);
+ ASSERT(DftiErrorClass(status, DFTI_NO_ERROR));
+
+ // Use the default DFTI_CONJUGATE_EVEN_STORAGE = DFTI_COMPLEX_REAL.
+
+ // Commit DFTI descriptor.
+ status = DftiCommitDescriptor(handle);
+ ASSERT(DftiErrorClass(status, DFTI_NO_ERROR));
+
+ return handle;
+}
+
+} // anonymous namespace
+
+namespace WebCore {
+
+const int kMaxFFTPow2Size = 24;
+
+DFTI_DESCRIPTOR_HANDLE* FFTFrame::descriptorHandles = 0;
+
+// Normal constructor: allocates for a given fftSize.
+FFTFrame::FFTFrame(unsigned fftSize)
+ : m_FFTSize(fftSize)
+ , m_log2FFTSize(static_cast<unsigned>(log2(fftSize)))
+ , m_handle(0)
+ , m_complexData(fftSize)
+ , m_realData(fftSize / 2)
+ , m_imagData(fftSize / 2)
+{
+ // We only allow power of two.
+ ASSERT(1UL << m_log2FFTSize == m_FFTSize);
+
+ m_handle = descriptorHandleForSize(fftSize);
+}
+
+// Creates a blank/empty frame (interpolate() must later be called).
+FFTFrame::FFTFrame()
+ : m_FFTSize(0)
+ , m_log2FFTSize(0)
+ , m_handle(0)
+{
+}
+
+// Copy constructor.
+FFTFrame::FFTFrame(const FFTFrame& frame)
+ : m_FFTSize(frame.m_FFTSize)
+ , m_log2FFTSize(frame.m_log2FFTSize)
+ , m_handle(0)
+ , m_complexData(frame.m_FFTSize)
+ , m_realData(frame.m_FFTSize / 2)
+ , m_imagData(frame.m_FFTSize / 2)
+{
+ m_handle = descriptorHandleForSize(m_FFTSize);
+
+ // Copy/setup frame data.
+ unsigned nbytes = sizeof(float) * (m_FFTSize / 2);
+ memcpy(realData(), frame.realData(), nbytes);
+ memcpy(imagData(), frame.imagData(), nbytes);
+}
+
+FFTFrame::~FFTFrame()
+{
+}
+
+void FFTFrame::multiply(const FFTFrame& frame)
+{
+ FFTFrame& frame1 = *this;
+ FFTFrame& frame2 = const_cast<FFTFrame&>(frame);
+
+ float* realP1 = frame1.realData();
+ float* imagP1 = frame1.imagData();
+ const float* realP2 = frame2.realData();
+ const float* imagP2 = frame2.imagData();
+
+ // Scale accounts for vecLib's peculiar scaling.
+ // This ensures the right scaling all the way back to inverse FFT.
+ // FIXME: this scaling factor will be 1.0f if the above 2.0 -> 1.0
+ // scaling factor is fixed.
+ float scale = 0.5f;
+
+ // Multiply packed DC/nyquist component.
+ realP1[0] *= scale * realP2[0];
+ imagP1[0] *= scale * imagP2[0];
+
+ // Multiply the rest, skipping packed DC/Nyquist components.
+ float* interleavedData1 = frame1.getUpToDateComplexData();
+ float* interleavedData2 = frame2.getUpToDateComplexData();
+
+ unsigned halfSize = m_FFTSize / 2;
+
+ // Complex multiply.
+ vcMul(halfSize - 1,
+ reinterpret_cast<MKL_Complex8*>(interleavedData1) + 1,
+ reinterpret_cast<MKL_Complex8*>(interleavedData2) + 1,
+ reinterpret_cast<MKL_Complex8*>(interleavedData1) + 1);
+
+ // De-interleave and scale the rest of the data.
+ // FIXME: find an MKL routine to do at least the scaling more efficiently.
+ for (unsigned i = 1; i < halfSize; ++i) {
+ int baseComplexIndex = 2 * i;
+ realP1[i] = scale * interleavedData1[baseComplexIndex];
+ imagP1[i] = scale * interleavedData1[baseComplexIndex + 1];
+ }
+}
+
+void FFTFrame::doFFT(float* data)
+{
+ // Compute Forward transform.
+ MKL_LONG status = DftiComputeForward(m_handle, data, m_complexData.data());
+ ASSERT(DftiErrorClass(status, DFTI_NO_ERROR));
+
+ // De-interleave to separate real and complex arrays. FIXME:
+ // figure out if it's possible to get MKL to use split-complex
+ // form for 1D real-to-complex out-of-place FFTs.
+ int len = m_FFTSize / 2;
+ for (int i = 0; i < len; ++i) {
+ int baseComplexIndex = 2 * i;
+ // m_realData[0] is the DC component and m_imagData[0] the
+ // Nyquist component since the interleaved complex data is
+ // packed.
+ m_realData[i] = m_complexData[baseComplexIndex];
+ m_imagData[i] = m_complexData[baseComplexIndex + 1];
+ }
+}
+
+void FFTFrame::doInverseFFT(float* data)
+{
+ // Prepare interleaved data. FIXME: figure out if it's possible to
+ // get MKL to use split-complex form for 1D backward
+ // (complex-to-real) out-of-place FFTs.
+ float* interleavedData = getUpToDateComplexData();
+
+ // Compute backward transform.
+ MKL_LONG status = DftiComputeBackward(m_handle, interleavedData, data);
+ ASSERT(DftiErrorClass(status, DFTI_NO_ERROR));
+}
+
+void FFTFrame::cleanup()
+{
+ if (!descriptorHandles)
+ return;
+
+ for (int i = 0; i < kMaxFFTPow2Size; ++i) {
+ if (descriptorHandles[i]) {
+ MKL_LONG status = DftiFreeDescriptor(&descriptorHandles[i]);
+ ASSERT(DftiErrorClass(status, DFTI_NO_ERROR));
+ }
+ }
+
+ delete[] descriptorHandles;
+ descriptorHandles = 0;
+}
+
+float* FFTFrame::realData() const
+{
+ return const_cast<float*>(m_realData.data());
+}
+
+float* FFTFrame::imagData() const
+{
+ return const_cast<float*>(m_imagData.data());
+}
+
+float* FFTFrame::getUpToDateComplexData()
+{
+ // FIXME: if we can't completely get rid of this method, SSE
+ // optimization could be considered if it shows up hot on profiles.
+ int len = m_FFTSize / 2;
+ for (int i = 0; i < len; ++i) {
+ int baseComplexIndex = 2 * i;
+ m_complexData[baseComplexIndex] = m_realData[i];
+ m_complexData[baseComplexIndex + 1] = m_imagData[i];
+ }
+ return const_cast<float*>(m_complexData.data());
+}
+
+DFTI_DESCRIPTOR_HANDLE FFTFrame::descriptorHandleForSize(unsigned fftSize)
+{
+ if (!descriptorHandles) {
+ descriptorHandles = new DFTI_DESCRIPTOR_HANDLE[kMaxFFTPow2Size];
+ for (int i = 0; i < kMaxFFTPow2Size; ++i)
+ descriptorHandles[i] = 0;
+ }
+
+ ASSERT(fftSize);
+ int pow2size = static_cast<int>(log2(fftSize));
+ ASSERT(pow2size < kMaxFFTPow2Size);
+ if (!descriptorHandles[pow2size])
+ descriptorHandles[pow2size] = createDescriptorHandle(fftSize);
+ return descriptorHandles[pow2size];
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(WEB_AUDIO)
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T000_P000.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T000_P000.wav
new file mode 100644
index 0000000..57f2ef3
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T000_P000.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T000_P015.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T000_P015.wav
new file mode 100644
index 0000000..3ecea33
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T000_P015.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T000_P030.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T000_P030.wav
new file mode 100644
index 0000000..7320802
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T000_P030.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T000_P045.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T000_P045.wav
new file mode 100644
index 0000000..1a10d9a
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T000_P045.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T000_P060.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T000_P060.wav
new file mode 100644
index 0000000..9b12c22
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T000_P060.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T000_P075.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T000_P075.wav
new file mode 100644
index 0000000..3153bb8
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T000_P075.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T000_P090.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T000_P090.wav
new file mode 100644
index 0000000..3282da9
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T000_P090.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T000_P315.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T000_P315.wav
new file mode 100644
index 0000000..b999852
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T000_P315.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T000_P330.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T000_P330.wav
new file mode 100644
index 0000000..53a03b6
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T000_P330.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T000_P345.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T000_P345.wav
new file mode 100644
index 0000000..16d5766
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T000_P345.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T015_P000.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T015_P000.wav
new file mode 100644
index 0000000..3788e16
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T015_P000.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T015_P015.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T015_P015.wav
new file mode 100644
index 0000000..ad2efb6
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T015_P015.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T015_P030.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T015_P030.wav
new file mode 100644
index 0000000..ee86702
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T015_P030.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T015_P045.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T015_P045.wav
new file mode 100644
index 0000000..98ff82e
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T015_P045.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T015_P060.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T015_P060.wav
new file mode 100644
index 0000000..98ff82e
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T015_P060.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T015_P075.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T015_P075.wav
new file mode 100644
index 0000000..98ff82e
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T015_P075.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T015_P090.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T015_P090.wav
new file mode 100644
index 0000000..98ff82e
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T015_P090.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T015_P315.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T015_P315.wav
new file mode 100644
index 0000000..10bdf78
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T015_P315.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T015_P330.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T015_P330.wav
new file mode 100644
index 0000000..c8398a4
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T015_P330.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T015_P345.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T015_P345.wav
new file mode 100644
index 0000000..82b92a8
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T015_P345.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T030_P000.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T030_P000.wav
new file mode 100644
index 0000000..8b8714c
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T030_P000.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T030_P015.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T030_P015.wav
new file mode 100644
index 0000000..882efd4
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T030_P015.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T030_P030.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T030_P030.wav
new file mode 100644
index 0000000..abd99e6
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T030_P030.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T030_P045.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T030_P045.wav
new file mode 100644
index 0000000..28765be
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T030_P045.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T030_P060.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T030_P060.wav
new file mode 100644
index 0000000..42c1445
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T030_P060.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T030_P075.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T030_P075.wav
new file mode 100644
index 0000000..42c1445
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T030_P075.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T030_P090.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T030_P090.wav
new file mode 100644
index 0000000..42c1445
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T030_P090.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T030_P315.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T030_P315.wav
new file mode 100644
index 0000000..99b00f7
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T030_P315.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T030_P330.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T030_P330.wav
new file mode 100644
index 0000000..f81bee2
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T030_P330.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T030_P345.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T030_P345.wav
new file mode 100644
index 0000000..139d0cb
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T030_P345.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T045_P000.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T045_P000.wav
new file mode 100644
index 0000000..68b7b4f
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T045_P000.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T045_P015.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T045_P015.wav
new file mode 100644
index 0000000..d6773ae
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T045_P015.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T045_P030.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T045_P030.wav
new file mode 100644
index 0000000..9e786bb
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T045_P030.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T045_P045.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T045_P045.wav
new file mode 100644
index 0000000..fbef2f3
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T045_P045.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T045_P060.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T045_P060.wav
new file mode 100644
index 0000000..fbef2f3
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T045_P060.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T045_P075.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T045_P075.wav
new file mode 100644
index 0000000..fbef2f3
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T045_P075.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T045_P090.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T045_P090.wav
new file mode 100644
index 0000000..fbef2f3
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T045_P090.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T045_P315.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T045_P315.wav
new file mode 100644
index 0000000..3c53b76
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T045_P315.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T045_P330.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T045_P330.wav
new file mode 100644
index 0000000..e4524c0
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T045_P330.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T045_P345.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T045_P345.wav
new file mode 100644
index 0000000..ff12535
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T045_P345.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T060_P000.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T060_P000.wav
new file mode 100644
index 0000000..5bb1b17
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T060_P000.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T060_P015.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T060_P015.wav
new file mode 100644
index 0000000..47e0209
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T060_P015.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T060_P030.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T060_P030.wav
new file mode 100644
index 0000000..536b4ac
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T060_P030.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T060_P045.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T060_P045.wav
new file mode 100644
index 0000000..05152ad
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T060_P045.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T060_P060.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T060_P060.wav
new file mode 100644
index 0000000..221637b
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T060_P060.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T060_P075.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T060_P075.wav
new file mode 100644
index 0000000..7d6d07f
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T060_P075.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T060_P090.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T060_P090.wav
new file mode 100644
index 0000000..7d6d07f
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T060_P090.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T060_P315.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T060_P315.wav
new file mode 100644
index 0000000..a4eca78
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T060_P315.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T060_P330.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T060_P330.wav
new file mode 100644
index 0000000..37393c2
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T060_P330.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T060_P345.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T060_P345.wav
new file mode 100644
index 0000000..3d56e26
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T060_P345.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T075_P000.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T075_P000.wav
new file mode 100644
index 0000000..2159f3d
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T075_P000.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T075_P015.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T075_P015.wav
new file mode 100644
index 0000000..8b689f6
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T075_P015.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T075_P030.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T075_P030.wav
new file mode 100644
index 0000000..9ee8ac5
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T075_P030.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T075_P045.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T075_P045.wav
new file mode 100644
index 0000000..88124e9
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T075_P045.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T075_P060.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T075_P060.wav
new file mode 100644
index 0000000..88124e9
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T075_P060.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T075_P075.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T075_P075.wav
new file mode 100644
index 0000000..88124e9
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T075_P075.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T075_P090.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T075_P090.wav
new file mode 100644
index 0000000..88124e9
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T075_P090.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T075_P315.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T075_P315.wav
new file mode 100644
index 0000000..59441a6
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T075_P315.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T075_P330.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T075_P330.wav
new file mode 100644
index 0000000..7cac0f5
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T075_P330.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T075_P345.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T075_P345.wav
new file mode 100644
index 0000000..dc28d64
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T075_P345.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T090_P000.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T090_P000.wav
new file mode 100644
index 0000000..ae7e583
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T090_P000.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T090_P015.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T090_P015.wav
new file mode 100644
index 0000000..509449e
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T090_P015.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T090_P030.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T090_P030.wav
new file mode 100644
index 0000000..e23b20c
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T090_P030.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T090_P045.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T090_P045.wav
new file mode 100644
index 0000000..cf247b9
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T090_P045.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T090_P060.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T090_P060.wav
new file mode 100644
index 0000000..f49d520
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T090_P060.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T090_P075.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T090_P075.wav
new file mode 100644
index 0000000..f49d520
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T090_P075.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T090_P090.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T090_P090.wav
new file mode 100644
index 0000000..f49d520
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T090_P090.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T090_P315.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T090_P315.wav
new file mode 100644
index 0000000..e5472f1
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T090_P315.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T090_P330.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T090_P330.wav
new file mode 100644
index 0000000..8e1af83
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T090_P330.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T090_P345.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T090_P345.wav
new file mode 100644
index 0000000..c477193
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T090_P345.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T105_P000.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T105_P000.wav
new file mode 100644
index 0000000..4236e08
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T105_P000.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T105_P015.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T105_P015.wav
new file mode 100644
index 0000000..2461fb0
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T105_P015.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T105_P030.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T105_P030.wav
new file mode 100644
index 0000000..11d549b
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T105_P030.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T105_P045.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T105_P045.wav
new file mode 100644
index 0000000..0aa100e
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T105_P045.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T105_P060.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T105_P060.wav
new file mode 100644
index 0000000..0aa100e
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T105_P060.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T105_P075.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T105_P075.wav
new file mode 100644
index 0000000..0aa100e
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T105_P075.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T105_P090.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T105_P090.wav
new file mode 100644
index 0000000..0aa100e
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T105_P090.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T105_P315.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T105_P315.wav
new file mode 100644
index 0000000..572e602
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T105_P315.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T105_P330.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T105_P330.wav
new file mode 100644
index 0000000..7f41da3
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T105_P330.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T105_P345.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T105_P345.wav
new file mode 100644
index 0000000..d0101b8
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T105_P345.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T120_P000.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T120_P000.wav
new file mode 100644
index 0000000..800fbd7
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T120_P000.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T120_P015.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T120_P015.wav
new file mode 100644
index 0000000..9b35e72
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T120_P015.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T120_P030.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T120_P030.wav
new file mode 100644
index 0000000..bb58c4e
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T120_P030.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T120_P045.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T120_P045.wav
new file mode 100644
index 0000000..8963e3e
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T120_P045.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T120_P060.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T120_P060.wav
new file mode 100644
index 0000000..22241ee
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T120_P060.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T120_P075.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T120_P075.wav
new file mode 100644
index 0000000..9e4fee0
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T120_P075.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T120_P090.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T120_P090.wav
new file mode 100644
index 0000000..9e4fee0
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T120_P090.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T120_P315.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T120_P315.wav
new file mode 100644
index 0000000..95976c6
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T120_P315.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T120_P330.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T120_P330.wav
new file mode 100644
index 0000000..8fc55f1
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T120_P330.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T120_P345.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T120_P345.wav
new file mode 100644
index 0000000..eeeb702
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T120_P345.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T135_P000.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T135_P000.wav
new file mode 100644
index 0000000..1847d8d
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T135_P000.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T135_P015.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T135_P015.wav
new file mode 100644
index 0000000..52e812c
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T135_P015.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T135_P030.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T135_P030.wav
new file mode 100644
index 0000000..32ca344
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T135_P030.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T135_P045.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T135_P045.wav
new file mode 100644
index 0000000..3de60c8
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T135_P045.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T135_P060.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T135_P060.wav
new file mode 100644
index 0000000..3de60c8
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T135_P060.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T135_P075.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T135_P075.wav
new file mode 100644
index 0000000..3de60c8
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T135_P075.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T135_P090.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T135_P090.wav
new file mode 100644
index 0000000..3de60c8
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T135_P090.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T135_P315.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T135_P315.wav
new file mode 100644
index 0000000..2668e41
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T135_P315.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T135_P330.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T135_P330.wav
new file mode 100644
index 0000000..e69670b
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T135_P330.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T135_P345.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T135_P345.wav
new file mode 100644
index 0000000..1cc48ee
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T135_P345.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T150_P000.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T150_P000.wav
new file mode 100644
index 0000000..252968b
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T150_P000.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T150_P015.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T150_P015.wav
new file mode 100644
index 0000000..50aff3c
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T150_P015.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T150_P030.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T150_P030.wav
new file mode 100644
index 0000000..3abd6e8
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T150_P030.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T150_P045.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T150_P045.wav
new file mode 100644
index 0000000..3f0d5ef
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T150_P045.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T150_P060.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T150_P060.wav
new file mode 100644
index 0000000..616f760
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T150_P060.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T150_P075.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T150_P075.wav
new file mode 100644
index 0000000..616f760
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T150_P075.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T150_P090.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T150_P090.wav
new file mode 100644
index 0000000..616f760
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T150_P090.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T150_P315.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T150_P315.wav
new file mode 100644
index 0000000..bfb6032
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T150_P315.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T150_P330.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T150_P330.wav
new file mode 100644
index 0000000..1983cdb
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T150_P330.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T150_P345.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T150_P345.wav
new file mode 100644
index 0000000..27c0762
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T150_P345.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T165_P000.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T165_P000.wav
new file mode 100644
index 0000000..b04391b
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T165_P000.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T165_P015.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T165_P015.wav
new file mode 100644
index 0000000..5955612
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T165_P015.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T165_P030.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T165_P030.wav
new file mode 100644
index 0000000..af5d83a
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T165_P030.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T165_P045.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T165_P045.wav
new file mode 100644
index 0000000..a592f71
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T165_P045.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T165_P060.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T165_P060.wav
new file mode 100644
index 0000000..a592f71
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T165_P060.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T165_P075.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T165_P075.wav
new file mode 100644
index 0000000..a592f71
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T165_P075.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T165_P090.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T165_P090.wav
new file mode 100644
index 0000000..a592f71
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T165_P090.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T165_P315.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T165_P315.wav
new file mode 100644
index 0000000..a985aa1
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T165_P315.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T165_P330.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T165_P330.wav
new file mode 100644
index 0000000..a8b83d1
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T165_P330.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T165_P345.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T165_P345.wav
new file mode 100644
index 0000000..7e649a3
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T165_P345.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T180_P000.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T180_P000.wav
new file mode 100644
index 0000000..b74985c
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T180_P000.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T180_P015.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T180_P015.wav
new file mode 100644
index 0000000..e112ee0
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T180_P015.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T180_P030.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T180_P030.wav
new file mode 100644
index 0000000..ac842cc
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T180_P030.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T180_P045.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T180_P045.wav
new file mode 100644
index 0000000..95c3a6d
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T180_P045.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T180_P060.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T180_P060.wav
new file mode 100644
index 0000000..610eedb
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T180_P060.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T180_P075.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T180_P075.wav
new file mode 100644
index 0000000..d4a57bf
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T180_P075.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T180_P090.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T180_P090.wav
new file mode 100644
index 0000000..d4a57bf
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T180_P090.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T180_P315.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T180_P315.wav
new file mode 100644
index 0000000..bd6e4f8
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T180_P315.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T180_P330.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T180_P330.wav
new file mode 100644
index 0000000..7d4be6f
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T180_P330.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T180_P345.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T180_P345.wav
new file mode 100644
index 0000000..b7ef81a
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T180_P345.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T195_P000.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T195_P000.wav
new file mode 100644
index 0000000..0c4af2a
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T195_P000.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T195_P015.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T195_P015.wav
new file mode 100644
index 0000000..dd7a505
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T195_P015.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T195_P030.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T195_P030.wav
new file mode 100644
index 0000000..e169049
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T195_P030.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T195_P045.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T195_P045.wav
new file mode 100644
index 0000000..49008a0
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T195_P045.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T195_P060.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T195_P060.wav
new file mode 100644
index 0000000..49008a0
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T195_P060.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T195_P075.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T195_P075.wav
new file mode 100644
index 0000000..49008a0
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T195_P075.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T195_P090.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T195_P090.wav
new file mode 100644
index 0000000..49008a0
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T195_P090.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T195_P315.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T195_P315.wav
new file mode 100644
index 0000000..1e7d478
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T195_P315.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T195_P330.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T195_P330.wav
new file mode 100644
index 0000000..2a77d74
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T195_P330.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T195_P345.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T195_P345.wav
new file mode 100644
index 0000000..843b928
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T195_P345.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T210_P000.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T210_P000.wav
new file mode 100644
index 0000000..770af17
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T210_P000.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T210_P015.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T210_P015.wav
new file mode 100644
index 0000000..437a1c6
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T210_P015.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T210_P030.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T210_P030.wav
new file mode 100644
index 0000000..f0d9d8e
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T210_P030.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T210_P045.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T210_P045.wav
new file mode 100644
index 0000000..cd4ae55
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T210_P045.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T210_P060.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T210_P060.wav
new file mode 100644
index 0000000..7dd5a1a
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T210_P060.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T210_P075.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T210_P075.wav
new file mode 100644
index 0000000..7dd5a1a
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T210_P075.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T210_P090.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T210_P090.wav
new file mode 100644
index 0000000..7dd5a1a
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T210_P090.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T210_P315.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T210_P315.wav
new file mode 100644
index 0000000..bfac19d
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T210_P315.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T210_P330.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T210_P330.wav
new file mode 100644
index 0000000..8b3e086
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T210_P330.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T210_P345.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T210_P345.wav
new file mode 100644
index 0000000..8b4da46
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T210_P345.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T225_P000.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T225_P000.wav
new file mode 100644
index 0000000..b6d4703
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T225_P000.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T225_P015.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T225_P015.wav
new file mode 100644
index 0000000..0ff35e9
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T225_P015.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T225_P030.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T225_P030.wav
new file mode 100644
index 0000000..e934c78
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T225_P030.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T225_P045.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T225_P045.wav
new file mode 100644
index 0000000..c931e3c
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T225_P045.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T225_P060.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T225_P060.wav
new file mode 100644
index 0000000..c931e3c
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T225_P060.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T225_P075.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T225_P075.wav
new file mode 100644
index 0000000..c931e3c
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T225_P075.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T225_P090.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T225_P090.wav
new file mode 100644
index 0000000..c931e3c
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T225_P090.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T225_P315.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T225_P315.wav
new file mode 100644
index 0000000..f999966
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T225_P315.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T225_P330.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T225_P330.wav
new file mode 100644
index 0000000..d958590
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T225_P330.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T225_P345.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T225_P345.wav
new file mode 100644
index 0000000..ac06260
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T225_P345.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T240_P000.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T240_P000.wav
new file mode 100644
index 0000000..b720ed1
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T240_P000.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T240_P015.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T240_P015.wav
new file mode 100644
index 0000000..b48852a
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T240_P015.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T240_P030.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T240_P030.wav
new file mode 100644
index 0000000..92c7ef0
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T240_P030.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T240_P045.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T240_P045.wav
new file mode 100644
index 0000000..2d5ff65
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T240_P045.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T240_P060.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T240_P060.wav
new file mode 100644
index 0000000..07dcfde
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T240_P060.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T240_P075.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T240_P075.wav
new file mode 100644
index 0000000..283e250
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T240_P075.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T240_P090.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T240_P090.wav
new file mode 100644
index 0000000..283e250
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T240_P090.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T240_P315.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T240_P315.wav
new file mode 100644
index 0000000..b99ad7d
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T240_P315.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T240_P330.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T240_P330.wav
new file mode 100644
index 0000000..4886915
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T240_P330.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T240_P345.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T240_P345.wav
new file mode 100644
index 0000000..c932833
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T240_P345.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T255_P000.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T255_P000.wav
new file mode 100644
index 0000000..b204def
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T255_P000.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T255_P015.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T255_P015.wav
new file mode 100644
index 0000000..fa48113
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T255_P015.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T255_P030.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T255_P030.wav
new file mode 100644
index 0000000..2e2de70
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T255_P030.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T255_P045.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T255_P045.wav
new file mode 100644
index 0000000..685f102
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T255_P045.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T255_P060.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T255_P060.wav
new file mode 100644
index 0000000..685f102
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T255_P060.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T255_P075.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T255_P075.wav
new file mode 100644
index 0000000..685f102
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T255_P075.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T255_P090.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T255_P090.wav
new file mode 100644
index 0000000..685f102
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T255_P090.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T255_P315.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T255_P315.wav
new file mode 100644
index 0000000..c7cce6e
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T255_P315.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T255_P330.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T255_P330.wav
new file mode 100644
index 0000000..93a6b8a
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T255_P330.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T255_P345.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T255_P345.wav
new file mode 100644
index 0000000..efc72bc
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T255_P345.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T270_P000.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T270_P000.wav
new file mode 100644
index 0000000..8f49078
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T270_P000.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T270_P015.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T270_P015.wav
new file mode 100644
index 0000000..96510f7
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T270_P015.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T270_P030.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T270_P030.wav
new file mode 100644
index 0000000..60b84f4
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T270_P030.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T270_P045.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T270_P045.wav
new file mode 100644
index 0000000..ec995e6
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T270_P045.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T270_P060.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T270_P060.wav
new file mode 100644
index 0000000..e287d0e
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T270_P060.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T270_P075.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T270_P075.wav
new file mode 100644
index 0000000..e287d0e
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T270_P075.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T270_P090.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T270_P090.wav
new file mode 100644
index 0000000..e287d0e
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T270_P090.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T270_P315.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T270_P315.wav
new file mode 100644
index 0000000..01f0921
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T270_P315.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T270_P330.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T270_P330.wav
new file mode 100644
index 0000000..380e707
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T270_P330.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T270_P345.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T270_P345.wav
new file mode 100644
index 0000000..124a534
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T270_P345.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T285_P000.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T285_P000.wav
new file mode 100644
index 0000000..1a577f3
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T285_P000.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T285_P015.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T285_P015.wav
new file mode 100644
index 0000000..ce698bb
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T285_P015.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T285_P030.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T285_P030.wav
new file mode 100644
index 0000000..8d5134f
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T285_P030.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T285_P045.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T285_P045.wav
new file mode 100644
index 0000000..583c6ed
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T285_P045.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T285_P060.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T285_P060.wav
new file mode 100644
index 0000000..583c6ed
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T285_P060.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T285_P075.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T285_P075.wav
new file mode 100644
index 0000000..583c6ed
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T285_P075.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T285_P090.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T285_P090.wav
new file mode 100644
index 0000000..583c6ed
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T285_P090.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T285_P315.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T285_P315.wav
new file mode 100644
index 0000000..7b1b43b
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T285_P315.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T285_P330.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T285_P330.wav
new file mode 100644
index 0000000..e9ed7ed
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T285_P330.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T285_P345.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T285_P345.wav
new file mode 100644
index 0000000..6ce83ed
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T285_P345.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T300_P000.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T300_P000.wav
new file mode 100644
index 0000000..b4ea6bf
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T300_P000.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T300_P015.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T300_P015.wav
new file mode 100644
index 0000000..76d5b71
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T300_P015.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T300_P030.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T300_P030.wav
new file mode 100644
index 0000000..04ee003
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T300_P030.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T300_P045.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T300_P045.wav
new file mode 100644
index 0000000..22d7413
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T300_P045.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T300_P060.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T300_P060.wav
new file mode 100644
index 0000000..1b35018
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T300_P060.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T300_P075.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T300_P075.wav
new file mode 100644
index 0000000..2f55df8
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T300_P075.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T300_P090.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T300_P090.wav
new file mode 100644
index 0000000..2f55df8
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T300_P090.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T300_P315.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T300_P315.wav
new file mode 100644
index 0000000..7bcc8a4
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T300_P315.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T300_P330.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T300_P330.wav
new file mode 100644
index 0000000..a3bacf3
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T300_P330.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T300_P345.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T300_P345.wav
new file mode 100644
index 0000000..bdfba2d
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T300_P345.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T315_P000.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T315_P000.wav
new file mode 100644
index 0000000..719320c
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T315_P000.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T315_P015.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T315_P015.wav
new file mode 100644
index 0000000..5d366fc
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T315_P015.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T315_P030.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T315_P030.wav
new file mode 100644
index 0000000..e10e88b
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T315_P030.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T315_P045.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T315_P045.wav
new file mode 100644
index 0000000..ecb4b50
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T315_P045.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T315_P060.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T315_P060.wav
new file mode 100644
index 0000000..ecb4b50
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T315_P060.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T315_P075.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T315_P075.wav
new file mode 100644
index 0000000..ecb4b50
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T315_P075.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T315_P090.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T315_P090.wav
new file mode 100644
index 0000000..ecb4b50
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T315_P090.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T315_P315.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T315_P315.wav
new file mode 100644
index 0000000..35c44d4
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T315_P315.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T315_P330.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T315_P330.wav
new file mode 100644
index 0000000..8fe859b
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T315_P330.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T315_P345.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T315_P345.wav
new file mode 100644
index 0000000..3e44b83
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T315_P345.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T330_P000.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T330_P000.wav
new file mode 100644
index 0000000..e878220
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T330_P000.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T330_P015.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T330_P015.wav
new file mode 100644
index 0000000..7628cbc
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T330_P015.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T330_P030.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T330_P030.wav
new file mode 100644
index 0000000..7c4430c
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T330_P030.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T330_P045.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T330_P045.wav
new file mode 100644
index 0000000..55e3c5e
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T330_P045.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T330_P060.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T330_P060.wav
new file mode 100644
index 0000000..563313e
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T330_P060.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T330_P075.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T330_P075.wav
new file mode 100644
index 0000000..563313e
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T330_P075.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T330_P090.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T330_P090.wav
new file mode 100644
index 0000000..563313e
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T330_P090.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T330_P315.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T330_P315.wav
new file mode 100644
index 0000000..3eccc16
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T330_P315.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T330_P330.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T330_P330.wav
new file mode 100644
index 0000000..fd3f5e1
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T330_P330.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T330_P345.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T330_P345.wav
new file mode 100644
index 0000000..5937c59
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T330_P345.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T345_P000.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T345_P000.wav
new file mode 100644
index 0000000..99dc851
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T345_P000.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T345_P015.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T345_P015.wav
new file mode 100644
index 0000000..28994d5
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T345_P015.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T345_P030.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T345_P030.wav
new file mode 100644
index 0000000..beb24a2
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T345_P030.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T345_P045.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T345_P045.wav
new file mode 100644
index 0000000..f840c59
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T345_P045.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T345_P060.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T345_P060.wav
new file mode 100644
index 0000000..f840c59
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T345_P060.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T345_P075.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T345_P075.wav
new file mode 100644
index 0000000..f840c59
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T345_P075.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T345_P090.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T345_P090.wav
new file mode 100644
index 0000000..f840c59
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T345_P090.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T345_P315.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T345_P315.wav
new file mode 100644
index 0000000..68baa8e
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T345_P315.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T345_P330.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T345_P330.wav
new file mode 100644
index 0000000..6cb01b8
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T345_P330.wav
Binary files differ
diff --git a/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T345_P345.wav b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T345_P345.wav
new file mode 100644
index 0000000..b2ae88c
--- /dev/null
+++ b/WebCore/platform/audio/resources/IRC_Composite_C_R0195_T345_P345.wav
Binary files differ
diff --git a/WebCore/platform/brew/ContextMenuBrew.cpp b/WebCore/platform/brew/ContextMenuBrew.cpp
index 924e9dd..56ac351 100644
--- a/WebCore/platform/brew/ContextMenuBrew.cpp
+++ b/WebCore/platform/brew/ContextMenuBrew.cpp
@@ -32,15 +32,13 @@
namespace WebCore {
-ContextMenu::ContextMenu(const HitTestResult& result)
- : m_hitTestResult(result)
+ContextMenu::ContextMenu()
{
ASSERT_NOT_REACHED();
notImplemented();
}
-ContextMenu::ContextMenu(const HitTestResult& result, const PlatformMenuDescription menu)
- : m_hitTestResult(result)
+ContextMenu::ContextMenu(const PlatformMenuDescription menu)
{
ASSERT_NOT_REACHED();
notImplemented();
diff --git a/WebCore/platform/chromium/ContextMenuChromium.cpp b/WebCore/platform/chromium/ContextMenuChromium.cpp
index 93c0ec4..9bddd28 100644
--- a/WebCore/platform/chromium/ContextMenuChromium.cpp
+++ b/WebCore/platform/chromium/ContextMenuChromium.cpp
@@ -36,13 +36,11 @@ namespace WebCore {
// This is a stub implementation of WebKit's ContextMenu class that does
// nothing.
-ContextMenu::ContextMenu(const HitTestResult& result)
- : m_hitTestResult(result)
+ContextMenu::ContextMenu()
{
}
-ContextMenu::ContextMenu(const HitTestResult& result, const PlatformMenuDescription menu)
- : m_hitTestResult(result)
+ContextMenu::ContextMenu(const PlatformMenuDescription menu)
{
}
diff --git a/WebCore/platform/chromium/MIMETypeRegistryChromium.cpp b/WebCore/platform/chromium/MIMETypeRegistryChromium.cpp
index 23f7926..9df8847 100644
--- a/WebCore/platform/chromium/MIMETypeRegistryChromium.cpp
+++ b/WebCore/platform/chromium/MIMETypeRegistryChromium.cpp
@@ -91,8 +91,7 @@ bool MIMETypeRegistry::isSupportedImageResourceMIMEType(const String& mimeType)
bool MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(const String& mimeType)
{
- // FIXME: Fill this out. See: http://trac.webkit.org/changeset/30888
- return isSupportedImageMIMEType(mimeType);
+ return mimeType == "image/jpeg" || mimeType == "image/png";
}
bool MIMETypeRegistry::isSupportedJavaScriptMIMEType(const String& mimeType)
diff --git a/WebCore/platform/efl/ContextMenuEfl.cpp b/WebCore/platform/efl/ContextMenuEfl.cpp
index 8d85608..a5c6524 100644
--- a/WebCore/platform/efl/ContextMenuEfl.cpp
+++ b/WebCore/platform/efl/ContextMenuEfl.cpp
@@ -22,60 +22,34 @@
#include "config.h"
#include "ContextMenu.h"
-#include "ContextMenuClient.h"
-#include "ContextMenuClientEfl.h"
-#include "ContextMenuController.h"
#include "NotImplemented.h"
namespace WebCore {
-ContextMenu::ContextMenu(const HitTestResult& result)
- : m_hitTestResult(result)
+ContextMenu::ContextMenu(void* menu)
{
- m_contextMenuClient = static_cast<ContextMenuClientEfl*>(controller()->client());
- m_platformDescription = m_contextMenuClient->createPlatformDescription(this);
+ getContextMenuItems(menu, m_items);
}
-ContextMenu::ContextMenu(const HitTestResult& result, const PlatformMenuDescription menu)
- : m_hitTestResult(result)
- , m_platformDescription(menu)
+ContextMenu::ContextMenu()
{
- m_contextMenuClient = static_cast<ContextMenuClientEfl*>(controller()->client());
+ notImplemented();
}
-ContextMenu::~ContextMenu()
+void ContextMenu::getContextMenuItems(void* menu, Vector<ContextMenuItem>& items)
{
- if (m_platformDescription)
- m_contextMenuClient->freePlatformDescription(m_platformDescription);
+ notImplemented();
}
-void ContextMenu::appendItem(ContextMenuItem& item)
+void* ContextMenu::createNativeMenuFromItems(const Vector<ContextMenuItem>& items)
{
- checkOrEnableIfNeeded(item);
- m_contextMenuClient->appendItem(m_platformDescription, item);
+ notImplemented();
+ return 0;
}
-void ContextMenu::setPlatformDescription(PlatformMenuDescription menu)
+void* ContextMenu::nativeMenu() const
{
- ASSERT(!m_platformDescription);
-
- m_platformDescription = menu;
- m_contextMenuClient->show(m_platformDescription);
-}
-
-PlatformMenuDescription ContextMenu::platformDescription() const
-{
- return m_platformDescription;
-}
-
-PlatformMenuDescription ContextMenu::releasePlatformDescription()
-{
- // Ref count remains the same, just pass it and remove our ref, so it
- // will not be decremented when this object goes away.
- PlatformMenuDescription description = m_platformDescription;
- m_platformDescription = 0;
-
- return description;
+ return createNativeMenuFromItems(m_items);
}
}
diff --git a/WebCore/platform/efl/ContextMenuItemEfl.cpp b/WebCore/platform/efl/ContextMenuItemEfl.cpp
index efa743f..5ce8fab 100644
--- a/WebCore/platform/efl/ContextMenuItemEfl.cpp
+++ b/WebCore/platform/efl/ContextMenuItemEfl.cpp
@@ -30,114 +30,73 @@
#include "config.h"
#include "ContextMenuItem.h"
-#include "ContextMenu.h"
#include "NotImplemented.h"
namespace WebCore {
-ContextMenuItem::ContextMenuItem(PlatformMenuItemDescription)
+ContextMenuItem::ContextMenuItem(void* const&)
{
- // It's inside WebKit that this initialization is done, as WebCore doesn't
- // know how PlatformMenuItemDescription is implemented.
notImplemented();
}
-ContextMenuItem::ContextMenuItem(ContextMenu* submenu)
+ContextMenuItem::ContextMenuItem(ContextMenuItemType, ContextMenuAction, const String&, ContextMenu*)
{
- m_platformDescription.type = SubmenuType;
- setSubMenu(submenu);
-}
-
-ContextMenuItem::ContextMenuItem(ContextMenuItemType type, ContextMenuAction action, const String& title, ContextMenu* subMenu)
-{
- m_platformDescription.type = type;
- m_platformDescription.action = action;
- m_platformDescription.title = String(title);
-
- setSubMenu(subMenu);
+ notImplemented();
}
ContextMenuItem::~ContextMenuItem()
{
- if (m_platformDescription.subMenu)
- delete m_platformDescription.subMenu;
+ notImplemented();
}
-PlatformMenuItemDescription ContextMenuItem::releasePlatformDescription()
+void* ContextMenuItem::nativeMenuItem() const
{
- return m_platformDescription;
+ notImplemented();
+ return 0;
}
ContextMenuItemType ContextMenuItem::type() const
{
- return m_platformDescription.type;
+ notImplemented();
+ return ActionType;
}
-void ContextMenuItem::setType(ContextMenuItemType type)
+void ContextMenuItem::setAction(ContextMenuAction)
{
- m_platformDescription.type = type;
+ notImplemented();
}
ContextMenuAction ContextMenuItem::action() const
{
- return m_platformDescription.action;
-}
-
-void ContextMenuItem::setAction(ContextMenuAction action)
-{
- m_platformDescription.action = action;
-}
-
-String ContextMenuItem::title() const
-{
- return m_platformDescription.title;
-}
-
-void ContextMenuItem::setTitle(const String& title)
-{
- m_platformDescription.title = String(title);
-}
-
-PlatformMenuDescription ContextMenuItem::platformSubMenu() const
-{
- if (!m_platformDescription.subMenu)
- return 0;
-
- return m_platformDescription.subMenu->platformDescription();
-
+ notImplemented();
+ return ContextMenuItemTagNoAction;
}
-void ContextMenuItem::setSubMenu(ContextMenu* subMenu)
+void ContextMenuItem::setChecked(bool)
{
- delete m_platformDescription.subMenu;
- m_platformDescription.subMenu = 0;
-
- if (!subMenu)
- return;
-
- m_platformDescription.type = SubmenuType;
- m_platformDescription.subMenu = new ContextMenu(subMenu->hitTestResult(),
- subMenu->releasePlatformDescription());
+ notImplemented();
}
bool ContextMenuItem::checked() const
{
- return m_platformDescription.checked;
+ notImplemented();
+ return 0;
}
-void ContextMenuItem::setChecked(bool shouldCheck)
+void ContextMenuItem::setEnabled(bool)
{
- m_platformDescription.checked = shouldCheck;
+ notImplemented();
}
bool ContextMenuItem::enabled() const
{
- return m_platformDescription.enabled;
+ notImplemented();
+ return false;
}
-void ContextMenuItem::setEnabled(bool shouldEnable)
+void ContextMenuItem::setSubMenu(ContextMenu*)
{
- m_platformDescription.enabled = shouldEnable;
+ notImplemented();
}
}
diff --git a/WebCore/platform/efl/SharedTimerEfl.cpp b/WebCore/platform/efl/SharedTimerEfl.cpp
index 990d0c8..2534c60 100644
--- a/WebCore/platform/efl/SharedTimerEfl.cpp
+++ b/WebCore/platform/efl/SharedTimerEfl.cpp
@@ -30,25 +30,16 @@
#include "SharedTimer.h"
#include <Ecore.h>
-#include <pthread.h>
-#include <stdio.h>
#include <wtf/Assertions.h>
#include <wtf/CurrentTime.h>
#include <wtf/MainThread.h>
namespace WebCore {
-static pthread_mutex_t timerMutex = PTHREAD_MUTEX_INITIALIZER;
static Ecore_Timer *_sharedTimer = 0;
-static Ecore_Pipe *_pipe = 0;
static void (*_timerFunction)();
-struct timerOp {
- double time;
- unsigned char op; // 0 - add a timer; 1 - del a timer;
-};
-
void setSharedTimerFiredFunction(void (*func)())
{
_timerFunction = func;
@@ -64,58 +55,20 @@ static Eina_Bool timerEvent(void*)
return ECORE_CALLBACK_CANCEL;
}
-void processTimers(struct timerOp *tOp)
+void stopSharedTimer()
{
if (_sharedTimer) {
ecore_timer_del(_sharedTimer);
_sharedTimer = 0;
}
-
- if (tOp->op == 1)
- return;
-
- double interval = tOp->time - currentTime();
-
- if (interval <= ecore_animator_frametime_get()) {
- if (_timerFunction)
- _timerFunction();
- return;
- }
-
- _sharedTimer = ecore_timer_add(interval, timerEvent, 0);
-}
-
-void pipeHandlerCb(void *data, void *buffer, unsigned int nbyte)
-{
- ASSERT(nbyte == sizeof(struct timerOp));
-
- struct timerOp *tOp = (struct timerOp *)buffer;
- processTimers(tOp);
-}
-
-void stopSharedTimer()
-{
- struct timerOp tOp;
- pthread_mutex_lock(&timerMutex);
- if (!_pipe)
- _pipe = ecore_pipe_add(pipeHandlerCb, 0);
- pthread_mutex_unlock(&timerMutex);
-
- tOp.op = 1;
- ecore_pipe_write(_pipe, &tOp, sizeof(tOp));
}
void addNewTimer(double fireTime)
{
- struct timerOp tOp;
- pthread_mutex_lock(&timerMutex);
- if (!_pipe)
- _pipe = ecore_pipe_add(pipeHandlerCb, 0);
- pthread_mutex_unlock(&timerMutex);
+ double interval = fireTime - currentTime();
+ stopSharedTimer();
- tOp.time = fireTime;
- tOp.op = 0;
- ecore_pipe_write(_pipe, &tOp, sizeof(tOp));
+ _sharedTimer = ecore_timer_loop_add(interval, timerEvent, 0);
}
void setSharedTimerFireTime(double fireTime)
diff --git a/WebCore/platform/graphics/ContextShadow.cpp b/WebCore/platform/graphics/ContextShadow.cpp
index 87a1c5c..b34e546 100644
--- a/WebCore/platform/graphics/ContextShadow.cpp
+++ b/WebCore/platform/graphics/ContextShadow.cpp
@@ -29,6 +29,8 @@
#include "config.h"
#include "ContextShadow.h"
+#include "FloatQuad.h"
+#include <cmath>
#include <wtf/MathExtras.h>
#include <wtf/Noncopyable.h>
@@ -41,6 +43,7 @@ ContextShadow::ContextShadow()
: m_type(NoShadow)
, m_blurDistance(0)
, m_layerContext(0)
+ , m_shadowsIgnoreTransforms(false)
{
}
@@ -49,6 +52,7 @@ ContextShadow::ContextShadow(const Color& color, float radius, const FloatSize&
, m_blurDistance(round(radius))
, m_offset(offset)
, m_layerContext(0)
+ , m_shadowsIgnoreTransforms(false)
{
// See comments in http://webkit.org/b/40793, it seems sensible
// to follow Skia's limit of 128 pixels of blur radius
@@ -77,6 +81,23 @@ void ContextShadow::clear()
m_offset = FloatSize();
}
+bool ContextShadow::mustUseContextShadow(PlatformContext context)
+{
+ // We can't avoid ContextShadow, since the shadow has blur.
+ if (m_type == ContextShadow::BlurShadow)
+ return true;
+ // We can avoid ContextShadow and optimize, since we're not drawing on a
+ // canvas and box shadows are affected by the transformation matrix.
+ if (!shadowsIgnoreTransforms())
+ return false;
+ // We can avoid ContextShadow, since there are no transformations to apply to the canvas.
+ const TransformationMatrix transform(getTransformationMatrixFromContext(context));
+ if (transform.isIdentity())
+ return false;
+ // Otherwise, no chance avoiding ContextShadow.
+ return true;
+}
+
// Instead of integer division, we use 17.15 for fixed-point division.
static const int BlurSumShift = 15;
@@ -149,29 +170,89 @@ void ContextShadow::blurLayerImage(unsigned char* imageData, const IntSize& size
}
}
-void ContextShadow::calculateLayerBoundingRect(const FloatRect& layerArea, const IntRect& clipRect)
+void ContextShadow::adjustBlurDistance(const PlatformContext context)
+{
+ // Adjust blur if we're scaling, since the radius must not be affected by transformations.
+ const TransformationMatrix transform(getTransformationMatrixFromContext(context));
+
+ if (transform.isIdentity())
+ return;
+
+ // Calculale transformed unit vectors.
+ const FloatQuad unitQuad(FloatPoint(0, 0), FloatPoint(1, 0),
+ FloatPoint(0, 1), FloatPoint(1, 1));
+ const FloatQuad transformedUnitQuad = transform.mapQuad(unitQuad);
+
+ // Calculate X axis scale factor.
+ const FloatSize xUnitChange = transformedUnitQuad.p2() - transformedUnitQuad.p1();
+ const float xAxisScale = sqrtf(xUnitChange.width() * xUnitChange.width()
+ + xUnitChange.height() * xUnitChange.height());
+
+ // Calculate Y axis scale factor.
+ const FloatSize yUnitChange = transformedUnitQuad.p3() - transformedUnitQuad.p1();
+ const float yAxisScale = sqrtf(yUnitChange.width() * yUnitChange.width()
+ + yUnitChange.height() * yUnitChange.height());
+
+ // blurLayerImage() does not support per-axis blurring, so calculate a balanced scaling.
+ const float scale = sqrtf(xAxisScale * yAxisScale);
+ m_blurDistance = roundf(static_cast<float>(m_blurDistance) / scale);
+}
+
+IntRect ContextShadow::calculateLayerBoundingRect(const PlatformContext context, const FloatRect& layerArea, const IntRect& clipRect)
{
- // Calculate the destination of the blurred layer.
- FloatRect destinationRect(layerArea);
- destinationRect.move(m_offset);
- m_layerRect = enclosingIntRect(destinationRect);
+ // Calculate the destination of the blurred and/or transformed layer.
+ FloatRect layerFloatRect;
+ float inflation = 0;
+
+ const TransformationMatrix transform(getTransformationMatrixFromContext(context));
+ if (m_shadowsIgnoreTransforms && !transform.isIdentity()) {
+ FloatQuad transformedPolygon = transform.mapQuad(FloatQuad(layerArea));
+ transformedPolygon.move(m_offset);
+ layerFloatRect = transform.inverse().mapQuad(transformedPolygon).boundingBox();
+ } else {
+ layerFloatRect = layerArea;
+ layerFloatRect.move(m_offset);
+ }
// We expand the area by the blur radius to give extra space for the blur transition.
- m_layerRect.inflate(m_type == BlurShadow ? m_blurDistance : 0);
+ if (m_type == BlurShadow) {
+ layerFloatRect.inflate(m_blurDistance);
+ inflation += m_blurDistance;
+ }
+
+ FloatRect unclippedLayerRect = layerFloatRect;
- if (!clipRect.contains(m_layerRect)) {
+ if (!clipRect.contains(enclosingIntRect(layerFloatRect))) {
// No need to have the buffer larger than the clip.
- m_layerRect.intersect(clipRect);
+ layerFloatRect.intersect(clipRect);
// If we are totally outside the clip region, we aren't painting at all.
- if (m_layerRect.isEmpty())
- return;
+ if (layerFloatRect.isEmpty())
+ return IntRect(0, 0, 0, 0);
// We adjust again because the pixels at the borders are still
// potentially affected by the pixels outside the buffer.
- if (m_type == BlurShadow)
- m_layerRect.inflate(m_type == BlurShadow ? m_blurDistance : 0);
+ if (m_type == BlurShadow) {
+ layerFloatRect.inflate(m_blurDistance);
+ unclippedLayerRect.inflate(m_blurDistance);
+ inflation += m_blurDistance;
+ }
}
+
+ const int frameSize = inflation * 2;
+ m_sourceRect = IntRect(0, 0, layerArea.width() + frameSize, layerArea.height() + frameSize);
+ m_layerOrigin = FloatPoint(layerFloatRect.x(), layerFloatRect.y());
+
+ const FloatPoint m_unclippedLayerOrigin = FloatPoint(unclippedLayerRect.x(), unclippedLayerRect.y());
+ const FloatSize clippedOut = m_unclippedLayerOrigin - m_layerOrigin;
+
+ // Set the origin as the top left corner of the scratch image, or, in case there's a clipped
+ // out region, set the origin accordingly to the full bounding rect's top-left corner.
+ const float translationX = -layerArea.x() + inflation - fabsf(clippedOut.width());
+ const float translationY = -layerArea.y() + inflation - fabsf(clippedOut.height());
+ m_layerContextTranslation = FloatPoint(translationX, translationY);
+
+ return enclosingIntRect(layerFloatRect);
}
} // namespace WebCore
diff --git a/WebCore/platform/graphics/ContextShadow.h b/WebCore/platform/graphics/ContextShadow.h
index 26f0a36..8f14229 100644
--- a/WebCore/platform/graphics/ContextShadow.h
+++ b/WebCore/platform/graphics/ContextShadow.h
@@ -79,6 +79,7 @@ public:
ContextShadow();
ContextShadow(const Color&, float radius, const FloatSize& offset);
+ bool mustUseContextShadow(PlatformContext);
void clear();
// The pair beginShadowLayer and endShadowLayer creates a temporary image
@@ -106,27 +107,29 @@ public:
PlatformContext beginShadowLayer(PlatformContext, const FloatRect& layerArea);
void endShadowLayer(PlatformContext);
static void purgeScratchBuffer();
+ static TransformationMatrix getTransformationMatrixFromContext(PlatformContext);
+
+ void setShadowsIgnoreTransforms(bool enable) { m_shadowsIgnoreTransforms = enable; }
+ bool shadowsIgnoreTransforms() const { return m_shadowsIgnoreTransforms; }
#if PLATFORM(CAIRO)
void drawRectShadow(GraphicsContext* context, const IntRect& rect, const IntSize& topLeftRadius = IntSize(), const IntSize& topRightRadius = IntSize(), const IntSize& bottomLeftRadius = IntSize(), const IntSize& bottomRightRadius = IntSize());
#endif
-
#if PLATFORM(QT)
- QPointF offset() { return QPointF(m_offset.width(), m_offset.height()); }
+ QPointF offset() const { return QPointF(m_offset.width(), m_offset.height()); }
#endif
-
private:
- IntRect m_layerRect;
- PlatformImage m_layerImage;
- PlatformContext m_layerContext;
-
-#if PLATFORM(QT)
- // Used for reference when canvas scale(x,y) was called.
- FloatRect m_unscaledLayerRect;
-#endif
-
+ PlatformImage m_layerImage; // Buffer to where the temporary shadow will be drawn to.
+ PlatformContext m_layerContext; // Context used to paint the shadow to the layer image.
+ FloatRect m_sourceRect; // Sub-rect of m_layerImage that contains the shadow pixels.
+ FloatPoint m_layerOrigin; // Top-left corner of the (possibly clipped) bounding rect to draw the shadow to.
+ FloatPoint m_layerContextTranslation; // Translation to apply to m_layerContext for the shadow to be correctly clipped.
+ bool m_shadowsIgnoreTransforms;
+
+ void adjustBlurDistance(const PlatformContext);
void blurLayerImage(unsigned char*, const IntSize& imageSize, int stride);
- void calculateLayerBoundingRect(const FloatRect& layerArea, const IntRect& clipRect);
+ IntRect calculateLayerBoundingRect(const PlatformContext, const FloatRect& layerArea, const IntRect& clipRect);
+
#if PLATFORM(CAIRO)
void drawRectShadowWithoutTiling(PlatformContext context, const IntRect& shadowRect, const IntSize& topLeftRadius, const IntSize& topRightRadius, const IntSize& bottomLeftRadius, const IntSize& bottomRightRadius, float alpha);
#endif
diff --git a/WebCore/platform/graphics/Extensions3D.h b/WebCore/platform/graphics/Extensions3D.h
index 74210a5..0363a48 100644
--- a/WebCore/platform/graphics/Extensions3D.h
+++ b/WebCore/platform/graphics/Extensions3D.h
@@ -50,11 +50,17 @@ public:
// GL_ARB_texture_non_power_of_two / GL_OES_texture_npot
// GL_EXT_packed_depth_stencil / GL_OES_packed_depth_stencil
// GL_ANGLE_framebuffer_blit / GL_ANGLE_framebuffer_multisample
+ // GL_OES_texture_float
// Takes full name of extension; for example,
// "GL_EXT_texture_format_BGRA8888".
virtual bool supports(const String&) = 0;
+ // Certain OpenGL and WebGL implementations may support enabling
+ // extensions lazily. This method may only be called with
+ // extension names for which supports returns true.
+ virtual void ensureEnabled(const String&) = 0;
+
enum ExtensionsEnumType {
// GL_EXT_texture_format_BGRA8888 enums
BGRA_EXT = 0x80E1,
diff --git a/WebCore/platform/graphics/FloatPoint3D.h b/WebCore/platform/graphics/FloatPoint3D.h
index b6cbaa8..ba0ee9d 100644
--- a/WebCore/platform/graphics/FloatPoint3D.h
+++ b/WebCore/platform/graphics/FloatPoint3D.h
@@ -84,6 +84,11 @@ public:
m_z *= sz;
}
+ bool isZero() const
+ {
+ return !m_x && !m_y && !m_z;
+ }
+
void normalize();
float dot(const FloatPoint3D& a) const
@@ -115,6 +120,8 @@ public:
float lengthSquared() const { return this->dot(*this); }
float length() const { return sqrtf(lengthSquared()); }
+
+ float distanceTo(const FloatPoint3D& a) const;
private:
float m_x;
@@ -160,6 +167,21 @@ inline float operator*(const FloatPoint3D& a, const FloatPoint3D& b)
return a.dot(b);
}
+inline FloatPoint3D operator*(float k, const FloatPoint3D& v)
+{
+ return FloatPoint3D(k * v.x(), k * v.y(), k * v.z());
+}
+
+inline FloatPoint3D operator*(const FloatPoint3D& v, float k)
+{
+ return FloatPoint3D(k * v.x(), k * v.y(), k * v.z());
+}
+
+inline float FloatPoint3D::distanceTo(const FloatPoint3D& a) const
+{
+ return (*this - a).length();
+}
+
} // namespace WebCore
#endif // FloatPoint3D_h
diff --git a/WebCore/platform/graphics/Font.cpp b/WebCore/platform/graphics/Font.cpp
index 6bbf3d7..8828a31 100644
--- a/WebCore/platform/graphics/Font.cpp
+++ b/WebCore/platform/graphics/Font.cpp
@@ -156,6 +156,26 @@ void Font::drawText(GraphicsContext* context, const TextRun& run, const FloatPoi
return drawComplexText(context, run, point, from, to);
}
+void Font::drawEmphasisMarks(GraphicsContext* context, const TextRun& run, const AtomicString& mark, const FloatPoint& point, int from, int to) const
+{
+ if (m_fontList && m_fontList->loadingCustomFonts())
+ return;
+
+ if (to < 0)
+ to = run.length();
+
+#if ENABLE(SVG_FONTS)
+ // FIXME: Implement for SVG fonts.
+ if (primaryFont()->isSVGFont())
+ return;
+#endif
+
+ if (codePath(run) != Complex)
+ drawEmphasisMarksForSimpleText(context, run, mark, point, from, to);
+ else
+ drawEmphasisMarksForComplexText(context, run, mark, point, from, to);
+}
+
float Font::floatWidth(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
{
#if ENABLE(SVG_FONTS)
@@ -354,6 +374,42 @@ bool Font::isCJKIdeograph(UChar32 c)
if (c >= 0x2F00 && c <= 0x2FDF)
return true;
+ // CJK Strokes.
+ if (c >= 0x31C0 && c <= 0x31EF)
+ return true;
+
+ // CJK Compatibility Ideographs.
+ if (c >= 0xF900 && c <= 0xFAFF)
+ return true;
+
+ // CJK Unified Ideographs Extension B.
+ if (c >= 0x20000 && c <= 0x2A6DF)
+ return true;
+
+ // CJK Unified Ideographs Extension C.
+ if (c >= 0x2A700 && c <= 0x2B73F)
+ return true;
+
+ // CJK Unified Ideographs Extension D.
+ if (c >= 0x2B740 && c <= 0x2B81F)
+ return true;
+
+ // CJK Compatibility Ideographs Supplement.
+ if (c >= 0x2F800 && c <= 0x2FA1F)
+ return true;
+
+ return false;
+}
+
+bool Font::isCJKIdeographOrSymbol(UChar32 c)
+{
+ // 0x2C7 Caron, Mandarin Chinese 3rd Tone
+ // 0x2CA Modifier Letter Acute Accent, Mandarin Chinese 2nd Tone
+ // 0x2CB Modifier Letter Grave Access, Mandarin Chinese 4th Tone
+ // 0x2D9 Dot Above, Mandarin Chinese 5th Tone
+ if ((c == 0x2C7) || (c == 0x2CA) || (c == 0x2CB) || (c == 0x2D9))
+ return true;
+
// Ideographic Description Characters.
if (c >= 0x2FF0 && c <= 0x2FFF)
return true;
@@ -361,11 +417,23 @@ bool Font::isCJKIdeograph(UChar32 c)
// CJK Symbols and Punctuation.
if (c >= 0x3000 && c <= 0x303F)
return true;
-
- // CJK Strokes.
- if (c >= 0x31C0 && c <= 0x31EF)
+
+ // Hiragana
+ if (c >= 0x3040 && c <= 0x309F)
+ return true;
+
+ // Katakana
+ if (c >= 0x30A0 && c <= 0x30FF)
+ return true;
+
+ // Bopomofo
+ if (c >= 0x3100 && c <= 0x312F)
return true;
+ // Bopomofo Extended
+ if (c >= 0x31A0 && c <= 0x31BF)
+ return true;
+
// Enclosed CJK Letters and Months.
if (c >= 0x3200 && c <= 0x32FF)
return true;
@@ -374,35 +442,34 @@ bool Font::isCJKIdeograph(UChar32 c)
if (c >= 0x3300 && c <= 0x33FF)
return true;
- // CJK Compatibility Ideographs.
- if (c >= 0xF900 && c <= 0xFAFF)
- return true;
-
// CJK Compatibility Forms.
if (c >= 0xFE30 && c <= 0xFE4F)
return true;
+ // Halfwidth and Fullwidth Forms
+ // Usually only used in CJK
+ if (c >= 0xFF00 && c <= 0xFFEF)
+ return true;
+
// Emoji.
if (c >= 0x1F200 && c <= 0x1F6F)
return true;
- // CJK Unified Ideographs Extension B.
- if (c >= 0x20000 && c <= 0x2A6DF)
- return true;
-
- // CJK Unified Ideographs Extension C.
- if (c >= 0x2A700 && c <= 0x2B73F)
- return true;
-
- // CJK Unified Ideographs Extension D.
- if (c >= 0x2B740 && c <= 0x2B81F)
- return true;
-
- // CJK Compatibility Ideographs Supplement.
- if (c >= 0x2F800 && c <= 0x2FA1F)
- return true;
+ return isCJKIdeograph(c);
+}
- return false;
+bool Font::canReceiveTextEmphasis(UChar32 c)
+{
+ CharCategory category = Unicode::category(c);
+ if (category & (Separator_Space | Separator_Line | Separator_Paragraph | Other_NotAssigned | Other_Control | Other_Format))
+ return false;
+
+ // Additional word-separator characters listed in CSS Text Level 3 Editor's Draft 3 November 2010.
+ if (c == ethiopicWordspace || c == aegeanWordSeparatorLine || c == aegeanWordSeparatorDot
+ || c == ugariticWordDivider || c == tibetanMarkIntersyllabicTsheg || c == tibetanMarkDelimiterTshegBstar)
+ return false;
+
+ return true;
}
}
diff --git a/WebCore/platform/graphics/Font.h b/WebCore/platform/graphics/Font.h
index cb83ad2..4097f1e 100644
--- a/WebCore/platform/graphics/Font.h
+++ b/WebCore/platform/graphics/Font.h
@@ -93,6 +93,7 @@ public:
void update(PassRefPtr<FontSelector>) const;
void drawText(GraphicsContext*, const TextRun&, const FloatPoint&, int from = 0, int to = -1) const;
+ void drawEmphasisMarks(GraphicsContext*, const TextRun&, const AtomicString& mark, const FloatPoint&, int from = 0, int to = -1) const;
int width(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts = 0, GlyphOverflow* glyphOverflow = 0) const { return lroundf(floatWidth(run, fallbackFonts, glyphOverflow)); }
float floatWidth(const TextRun&, HashSet<const SimpleFontData*>* fallbackFonts = 0, GlyphOverflow* glyphOverflow = 0) const;
@@ -136,14 +137,18 @@ public:
unsigned unitsPerEm() const { return primaryFont()->unitsPerEm(); }
int spaceWidth() const { return (int)ceilf(primaryFont()->adjustedSpaceWidth() + m_letterSpacing); }
float tabWidth(const SimpleFontData& fontData) const { return 8 * ceilf(fontData.adjustedSpaceWidth() + letterSpacing()); }
+ int emphasisMarkAscent(const AtomicString&) const;
+ int emphasisMarkDescent(const AtomicString&) const;
+ int emphasisMarkHeight(const AtomicString&) const;
const SimpleFontData* primaryFont() const;
const FontData* fontDataAt(unsigned) const;
- GlyphData glyphDataForCharacter(UChar32, bool mirror, bool forceSmallCaps = false) const;
+ GlyphData glyphDataForCharacter(UChar32, bool mirror, FontDataVariant = AutoVariant) const;
// Used for complex text, and does not utilize the glyph map cache.
const FontData* fontDataForCharacters(const UChar*, int length) const;
static bool isCJKIdeograph(UChar32);
+ static bool isCJKIdeographOrSymbol(UChar32);
#if PLATFORM(QT)
QFont font() const;
@@ -163,17 +168,29 @@ private:
int offsetForPositionForTextUsingSVGFont(const TextRun&, float position, bool includePartialGlyphs) const;
#endif
+ enum ForTextEmphasisOrNot { NotForTextEmphasis, ForTextEmphasis };
+
+ // Returns the initial in-stream advance.
+ float getGlyphsAndAdvancesForSimpleText(const TextRun&, int from, int to, GlyphBuffer&, ForTextEmphasisOrNot = NotForTextEmphasis) const;
void drawSimpleText(GraphicsContext*, const TextRun&, const FloatPoint&, int from, int to) const;
+ void drawEmphasisMarksForSimpleText(GraphicsContext*, const TextRun&, const AtomicString& mark, const FloatPoint&, int from, int to) const;
void drawGlyphs(GraphicsContext*, const SimpleFontData*, const GlyphBuffer&, int from, int to, const FloatPoint&) const;
- void drawGlyphBuffer(GraphicsContext*, const GlyphBuffer&, const TextRun&, const FloatPoint&) const;
+ void drawGlyphBuffer(GraphicsContext*, const GlyphBuffer&, const FloatPoint&) const;
+ void drawEmphasisMarks(GraphicsContext* context, const GlyphBuffer&, const AtomicString&, const FloatPoint&) const;
float floatWidthForSimpleText(const TextRun&, GlyphBuffer*, HashSet<const SimpleFontData*>* fallbackFonts = 0, GlyphOverflow* = 0) const;
int offsetForPositionForSimpleText(const TextRun&, float position, bool includePartialGlyphs) const;
FloatRect selectionRectForSimpleText(const TextRun&, const FloatPoint&, int h, int from, int to) const;
+ bool getEmphasisMarkGlyphData(const AtomicString&, GlyphData&) const;
+
static bool canReturnFallbackFontsForComplexText();
CodePath codePath(const TextRun&) const;
+
+ // Returns the initial in-stream advance.
+ float getGlyphsAndAdvancesForComplexText(const TextRun&, int from, int to, GlyphBuffer&, ForTextEmphasisOrNot = NotForTextEmphasis) const;
void drawComplexText(GraphicsContext*, const TextRun&, const FloatPoint&, int from, int to) const;
+ void drawEmphasisMarksForComplexText(GraphicsContext*, const TextRun&, const AtomicString& mark, const FloatPoint&, int from, int to) const;
float floatWidthForComplexText(const TextRun&, HashSet<const SimpleFontData*>* fallbackFonts = 0, GlyphOverflow* = 0) const;
int offsetForPositionForComplexText(const TextRun&, float position, bool includePartialGlyphs) const;
FloatRect selectionRectForComplexText(const TextRun&, const FloatPoint&, int h, int from, int to) const;
@@ -195,6 +212,7 @@ public:
FontSelector* fontSelector() const;
static bool treatAsSpace(UChar c) { return c == ' ' || c == '\t' || c == '\n' || c == noBreakSpace; }
static bool treatAsZeroWidthSpace(UChar c) { return c < 0x20 || (c >= 0x7F && c < 0xA0) || c == softHyphen || (c >= 0x200c && c <= 0x200f) || (c >= 0x202a && c <= 0x202e) || c == objectReplacementCharacter; }
+ static bool canReceiveTextEmphasis(UChar32 c);
static inline UChar normalizeSpaces(UChar character)
{
diff --git a/WebCore/platform/graphics/FontFastPath.cpp b/WebCore/platform/graphics/FontFastPath.cpp
index f0dd33e..73904e0 100644
--- a/WebCore/platform/graphics/FontFastPath.cpp
+++ b/WebCore/platform/graphics/FontFastPath.cpp
@@ -1,5 +1,5 @@
/**
- * Copyright (C) 2003, 2006 Apple Computer, Inc.
+ * Copyright (C) 2003, 2006, 2010 Apple Inc. All rights reserved.
* Copyright (C) 2008 Holger Hans Peter Freyther
* Copyright (C) 2009 Torch Mobile, Inc.
*
@@ -40,17 +40,20 @@ using namespace Unicode;
namespace WebCore {
-GlyphData Font::glyphDataForCharacter(UChar32 c, bool mirror, bool forceSmallCaps) const
+GlyphData Font::glyphDataForCharacter(UChar32 c, bool mirror, FontDataVariant variant) const
{
ASSERT(isMainThread());
- bool useSmallCapsFont = forceSmallCaps;
- if (m_fontDescription.smallCaps()) {
- UChar32 upperC = toUpper(c);
- if (upperC != c) {
- c = upperC;
- useSmallCapsFont = true;
- }
+ if (variant == AutoVariant) {
+ if (m_fontDescription.smallCaps()) {
+ UChar32 upperC = toUpper(c);
+ if (upperC != c) {
+ c = upperC;
+ variant = SmallCapsVariant;
+ } else
+ variant = NormalVariant;
+ } else
+ variant = NormalVariant;
}
if (mirror)
@@ -68,14 +71,14 @@ GlyphData Font::glyphDataForCharacter(UChar32 c, bool mirror, bool forceSmallCap
}
GlyphPage* page;
- if (!useSmallCapsFont) {
- // Fastest loop, for the common case (not small caps).
+ if (variant == NormalVariant) {
+ // Fastest loop, for the common case (normal variant).
while (true) {
page = node->page();
if (page) {
GlyphData data = page->glyphDataForCharacter(c);
if (data.fontData) {
- if (data.fontData->platformData().orientation() == Vertical && data.fontData->orientation() == Horizontal && Font::isCJKIdeograph(c)) {
+ if (data.fontData->platformData().orientation() == Vertical && data.fontData->orientation() == Horizontal && Font::isCJKIdeographOrSymbol(c)) {
const SimpleFontData* ideographFontData = data.fontData->brokenIdeographFontData();
GlyphPageTreeNode* ideographNode = GlyphPageTreeNode::getRootChild(ideographFontData, pageNumber);
const GlyphPage* ideographPage = ideographNode->page();
@@ -108,23 +111,23 @@ GlyphData Font::glyphDataForCharacter(UChar32 c, bool mirror, bool forceSmallCap
if (page) {
GlyphData data = page->glyphDataForCharacter(c);
if (data.fontData) {
- // The smallCapsFontData function should not normally return 0.
+ // The variantFontData function should not normally return 0.
// But if it does, we will just render the capital letter big.
- const SimpleFontData* smallCapsFontData = data.fontData->smallCapsFontData(m_fontDescription);
- if (!smallCapsFontData)
+ const SimpleFontData* variantFontData = data.fontData->variantFontData(m_fontDescription, variant);
+ if (!variantFontData)
return data;
- GlyphPageTreeNode* smallCapsNode = GlyphPageTreeNode::getRootChild(smallCapsFontData, pageNumber);
- const GlyphPage* smallCapsPage = smallCapsNode->page();
- if (smallCapsPage) {
- GlyphData data = smallCapsPage->glyphDataForCharacter(c);
+ GlyphPageTreeNode* variantNode = GlyphPageTreeNode::getRootChild(variantFontData, pageNumber);
+ const GlyphPage* variantPage = variantNode->page();
+ if (variantPage) {
+ GlyphData data = variantPage->glyphDataForCharacter(c);
if (data.fontData)
return data;
}
- // Do not attempt system fallback off the smallCapsFontData. This is the very unlikely case that
+ // Do not attempt system fallback off the variantFontData. This is the very unlikely case that
// a font has the lowercase character but the small caps font does not have its uppercase version.
- return smallCapsFontData->missingGlyphData();
+ return variantFontData->missingGlyphData();
}
if (node->isSystemFallback())
@@ -157,14 +160,14 @@ GlyphData Font::glyphDataForCharacter(UChar32 c, bool mirror, bool forceSmallCap
codeUnitsLength = 2;
}
const SimpleFontData* characterFontData = fontCache()->getFontDataForCharacters(*this, codeUnits, codeUnitsLength);
- if (useSmallCapsFont && characterFontData)
- characterFontData = characterFontData->smallCapsFontData(m_fontDescription);
+ if (variant != NormalVariant && characterFontData)
+ characterFontData = characterFontData->variantFontData(m_fontDescription, variant);
if (characterFontData) {
// Got the fallback glyph and font.
GlyphPage* fallbackPage = GlyphPageTreeNode::getRootChild(characterFontData, pageNumber)->page();
GlyphData data = fallbackPage && fallbackPage->fontDataForCharacter(c) ? fallbackPage->glyphDataForCharacter(c) : characterFontData->missingGlyphData();
// Cache it so we don't have to do system fallback again next time.
- if (!useSmallCapsFont) {
+ if (variant == NormalVariant) {
#if OS(WINCE)
// missingGlyphData returns a null character, which is not suitable for GDI to display.
// Also, sometimes we cannot map a font for the character on WINCE, but GDI can still
@@ -182,7 +185,7 @@ GlyphData Font::glyphDataForCharacter(UChar32 c, bool mirror, bool forceSmallCap
// Even system fallback can fail; use the missing glyph in that case.
// FIXME: It would be nicer to use the missing glyph from the last resort font instead.
GlyphData data = primaryFont()->missingGlyphData();
- if (!useSmallCapsFont) {
+ if (variant == NormalVariant) {
#if OS(WINCE)
// See comment about WINCE GDI handling near setGlyphDataForCharacter above.
page->setGlyphDataForCharacter(c, c, data.fontData);
@@ -194,42 +197,136 @@ GlyphData Font::glyphDataForCharacter(UChar32 c, bool mirror, bool forceSmallCap
return data;
}
-void Font::drawSimpleText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const
+// FIXME: This function may not work if the emphasis mark uses a complex script, but none of the
+// standard emphasis marks do so.
+bool Font::getEmphasisMarkGlyphData(const AtomicString& mark, GlyphData& glyphData) const
{
- // This glyph buffer holds our glyphs+advances+font data for each glyph.
- GlyphBuffer glyphBuffer;
+ if (mark.isEmpty())
+ return false;
- float startX = point.x();
- WidthIterator it(this, run);
+#if ENABLE(SVG_FONTS)
+ // FIXME: Implement for SVG fonts.
+ if (primaryFont()->isSVGFont())
+ return false;
+#endif
+
+ UChar32 character = mark[0];
+
+ if (U16_IS_SURROGATE(character)) {
+ if (!U16_IS_SURROGATE_LEAD(character))
+ return false;
+
+ if (mark.length() < 2)
+ return false;
+
+ UChar low = mark[1];
+ if (!U16_IS_TRAIL(low))
+ return false;
+
+ character = U16_GET_SUPPLEMENTARY(character, low);
+ }
+
+ glyphData = glyphDataForCharacter(character, false, EmphasisMarkVariant);
+ return true;
+}
+
+int Font::emphasisMarkAscent(const AtomicString& mark) const
+{
+ GlyphData markGlyphData;
+ if (!getEmphasisMarkGlyphData(mark, markGlyphData))
+ return 0;
+
+ const SimpleFontData* markFontData = markGlyphData.fontData;
+ ASSERT(markFontData);
+ if (!markFontData)
+ return 0;
+
+ return markFontData->ascent();
+}
+
+int Font::emphasisMarkDescent(const AtomicString& mark) const
+{
+ GlyphData markGlyphData;
+ if (!getEmphasisMarkGlyphData(mark, markGlyphData))
+ return 0;
+
+ const SimpleFontData* markFontData = markGlyphData.fontData;
+ ASSERT(markFontData);
+ if (!markFontData)
+ return 0;
+
+ return markFontData->descent();
+}
+
+int Font::emphasisMarkHeight(const AtomicString& mark) const
+{
+ GlyphData markGlyphData;
+ if (!getEmphasisMarkGlyphData(mark, markGlyphData))
+ return 0;
+
+ const SimpleFontData* markFontData = markGlyphData.fontData;
+ ASSERT(markFontData);
+ if (!markFontData)
+ return 0;
+
+ return markFontData->height();
+}
+
+float Font::getGlyphsAndAdvancesForSimpleText(const TextRun& run, int from, int to, GlyphBuffer& glyphBuffer, ForTextEmphasisOrNot forTextEmphasis) const
+{
+ float initialAdvance;
+
+ WidthIterator it(this, run, 0, false, forTextEmphasis);
it.advance(from);
float beforeWidth = it.m_runWidthSoFar;
it.advance(to, &glyphBuffer);
-
- // We couldn't generate any glyphs for the run. Give up.
+
if (glyphBuffer.isEmpty())
- return;
-
+ return 0;
+
float afterWidth = it.m_runWidthSoFar;
if (run.rtl()) {
float finalRoundingWidth = it.m_finalRoundingWidth;
it.advance(run.length());
- startX += finalRoundingWidth + it.m_runWidthSoFar - afterWidth;
+ initialAdvance = finalRoundingWidth + it.m_runWidthSoFar - afterWidth;
} else
- startX += beforeWidth;
+ initialAdvance = beforeWidth;
- // Swap the order of the glyphs if right-to-left.
- if (run.rtl())
+ if (run.rtl()) {
for (int i = 0, end = glyphBuffer.size() - 1; i < glyphBuffer.size() / 2; ++i, --end)
glyphBuffer.swap(i, end);
+ }
+
+ return initialAdvance;
+}
+
+void Font::drawSimpleText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const
+{
+ // This glyph buffer holds our glyphs+advances+font data for each glyph.
+ GlyphBuffer glyphBuffer;
+
+ float startX = point.x() + getGlyphsAndAdvancesForSimpleText(run, from, to, glyphBuffer);
+
+ if (glyphBuffer.isEmpty())
+ return;
- // Calculate the starting point of the glyphs to be displayed by adding
- // all the advances up to the first glyph.
FloatPoint startPoint(startX, point.y());
- drawGlyphBuffer(context, glyphBuffer, run, startPoint);
+ drawGlyphBuffer(context, glyphBuffer, startPoint);
+}
+
+void Font::drawEmphasisMarksForSimpleText(GraphicsContext* context, const TextRun& run, const AtomicString& mark, const FloatPoint& point, int from, int to) const
+{
+ GlyphBuffer glyphBuffer;
+ float initialAdvance = getGlyphsAndAdvancesForSimpleText(run, from, to, glyphBuffer, ForTextEmphasis);
+
+ if (glyphBuffer.isEmpty())
+ return;
+
+ drawEmphasisMarks(context, glyphBuffer, mark, FloatPoint(point.x() + initialAdvance, point.y()));
}
-void Font::drawGlyphBuffer(GraphicsContext* context, const GlyphBuffer& glyphBuffer, const TextRun&, const FloatPoint& point) const
+void Font::drawGlyphBuffer(GraphicsContext* context, const GlyphBuffer& glyphBuffer, const FloatPoint& point) const
{
// Draw each contiguous run of glyphs that use the same font data.
const SimpleFontData* fontData = glyphBuffer.fontDataAt(0);
@@ -256,6 +353,50 @@ void Font::drawGlyphBuffer(GraphicsContext* context, const GlyphBuffer& glyphBuf
drawGlyphs(context, fontData, glyphBuffer, lastFrom, nextGlyph - lastFrom, startPoint);
}
+inline static float offsetToMiddleOfGlyph(const SimpleFontData* fontData, Glyph glyph)
+{
+ if (fontData->orientation() == Horizontal) {
+ FloatRect bounds = fontData->boundsForGlyph(glyph);
+ return bounds.x() + bounds.width() / 2;
+ }
+ // FIXME: Use glyph bounds once they make sense for vertical fonts.
+ return fontData->widthForGlyph(glyph) / 2;
+}
+
+inline static float offsetToMiddleOfGlyphAtIndex(const GlyphBuffer& glyphBuffer, size_t i)
+{
+ return offsetToMiddleOfGlyph(glyphBuffer.fontDataAt(i), glyphBuffer.glyphAt(i));
+}
+
+void Font::drawEmphasisMarks(GraphicsContext* context, const GlyphBuffer& glyphBuffer, const AtomicString& mark, const FloatPoint& point) const
+{
+ GlyphData markGlyphData;
+ if (!getEmphasisMarkGlyphData(mark, markGlyphData))
+ return;
+
+ const SimpleFontData* markFontData = markGlyphData.fontData;
+ ASSERT(markFontData);
+ if (!markFontData)
+ return;
+
+ Glyph markGlyph = markGlyphData.glyph;
+ Glyph spaceGlyph = markFontData->spaceGlyph();
+
+ float middleOfLastGlyph = offsetToMiddleOfGlyphAtIndex(glyphBuffer, 0);
+ FloatPoint startPoint(point.x() + middleOfLastGlyph - offsetToMiddleOfGlyph(markFontData, markGlyph), point.y());
+
+ GlyphBuffer markBuffer;
+ for (int i = 0; i + 1 < glyphBuffer.size(); ++i) {
+ float middleOfNextGlyph = offsetToMiddleOfGlyphAtIndex(glyphBuffer, i + 1);
+ float advance = glyphBuffer.advanceAt(i) - middleOfLastGlyph + middleOfNextGlyph;
+ markBuffer.add(glyphBuffer.glyphAt(i) ? markGlyph : spaceGlyph, markFontData, advance);
+ middleOfLastGlyph = middleOfNextGlyph;
+ }
+ markBuffer.add(glyphBuffer.glyphAt(glyphBuffer.size() - 1) ? markGlyph : spaceGlyph, markFontData, 0);
+
+ drawGlyphBuffer(context, markBuffer, startPoint);
+}
+
float Font::floatWidthForSimpleText(const TextRun& run, GlyphBuffer* glyphBuffer, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
{
WidthIterator it(this, run, fallbackFonts, glyphOverflow);
diff --git a/WebCore/platform/graphics/GeneratedImage.cpp b/WebCore/platform/graphics/GeneratedImage.cpp
index 5df2608..f2c175b 100644
--- a/WebCore/platform/graphics/GeneratedImage.cpp
+++ b/WebCore/platform/graphics/GeneratedImage.cpp
@@ -57,7 +57,8 @@ void GeneratedImage::drawPattern(GraphicsContext* context, const FloatRect& srcR
// Create a BitmapImage and call drawPattern on it.
OwnPtr<ImageBuffer> imageBuffer = ImageBuffer::create(adjustedSize);
- ASSERT(imageBuffer.get());
+ if (!imageBuffer)
+ return;
// Fill with the gradient.
GraphicsContext* graphicsContext = imageBuffer->context();
diff --git a/WebCore/platform/graphics/GraphicsContext.cpp b/WebCore/platform/graphics/GraphicsContext.cpp
index d80b365..49a7a9c 100644
--- a/WebCore/platform/graphics/GraphicsContext.cpp
+++ b/WebCore/platform/graphics/GraphicsContext.cpp
@@ -29,7 +29,6 @@
#include "BidiResolver.h"
#include "Font.h"
#include "Generator.h"
-#include "GraphicsContextPrivate.h"
#include "ImageBuffer.h"
using namespace std;
@@ -74,14 +73,15 @@ private:
int m_offset;
};
-GraphicsContextPrivate* GraphicsContext::createGraphicsContextPrivate()
+GraphicsContext::GraphicsContext(PlatformGraphicsContext* platformGraphicsContext)
+ : m_updatingControlTints(false)
{
- return new GraphicsContextPrivate;
+ platformInit(platformGraphicsContext);
}
-void GraphicsContext::destroyGraphicsContextPrivate(GraphicsContextPrivate* deleteMe)
+GraphicsContext::~GraphicsContext()
{
- delete deleteMe;
+ platformDestroy();
}
void GraphicsContext::save()
@@ -89,7 +89,7 @@ void GraphicsContext::save()
if (paintingDisabled())
return;
- m_common->stack.append(m_common->state);
+ m_stack.append(m_state);
savePlatformState();
}
@@ -99,120 +99,139 @@ void GraphicsContext::restore()
if (paintingDisabled())
return;
- if (m_common->stack.isEmpty()) {
+ if (m_stack.isEmpty()) {
LOG_ERROR("ERROR void GraphicsContext::restore() stack is empty");
return;
}
- m_common->state = m_common->stack.last();
- m_common->stack.removeLast();
+ m_state = m_stack.last();
+ m_stack.removeLast();
restorePlatformState();
}
void GraphicsContext::setStrokeThickness(float thickness)
{
- m_common->state.strokeThickness = thickness;
+ m_state.strokeThickness = thickness;
setPlatformStrokeThickness(thickness);
}
void GraphicsContext::setStrokeStyle(const StrokeStyle& style)
{
- m_common->state.strokeStyle = style;
+ m_state.strokeStyle = style;
setPlatformStrokeStyle(style);
}
void GraphicsContext::setStrokeColor(const Color& color, ColorSpace colorSpace)
{
- m_common->state.strokeColor = color;
- m_common->state.strokeColorSpace = colorSpace;
- m_common->state.strokeGradient.clear();
- m_common->state.strokePattern.clear();
+ m_state.strokeColor = color;
+ m_state.strokeColorSpace = colorSpace;
+ m_state.strokeGradient.clear();
+ m_state.strokePattern.clear();
setPlatformStrokeColor(color, colorSpace);
}
void GraphicsContext::setShadow(const FloatSize& offset, float blur, const Color& color, ColorSpace colorSpace)
{
- m_common->state.shadowOffset = offset;
- m_common->state.shadowBlur = blur;
- m_common->state.shadowColor = color;
+ m_state.shadowOffset = offset;
+ m_state.shadowBlur = blur;
+ m_state.shadowColor = color;
+ m_state.shadowColorSpace = colorSpace;
setPlatformShadow(offset, blur, color, colorSpace);
}
void GraphicsContext::clearShadow()
{
- m_common->state.shadowOffset = FloatSize();
- m_common->state.shadowBlur = 0;
- m_common->state.shadowColor = Color();
+ m_state.shadowOffset = FloatSize();
+ m_state.shadowBlur = 0;
+ m_state.shadowColor = Color();
+ m_state.shadowColorSpace = ColorSpaceDeviceRGB;
clearPlatformShadow();
}
-bool GraphicsContext::getShadow(FloatSize& offset, float& blur, Color& color) const
+bool GraphicsContext::getShadow(FloatSize& offset, float& blur, Color& color, ColorSpace& colorSpace) const
{
- offset = m_common->state.shadowOffset;
- blur = m_common->state.shadowBlur;
- color = m_common->state.shadowColor;
+ offset = m_state.shadowOffset;
+ blur = m_state.shadowBlur;
+ color = m_state.shadowColor;
+ colorSpace = m_state.shadowColorSpace;
return color.isValid() && color.alpha() && (blur || offset.width() || offset.height());
}
float GraphicsContext::strokeThickness() const
{
- return m_common->state.strokeThickness;
+ return m_state.strokeThickness;
}
StrokeStyle GraphicsContext::strokeStyle() const
{
- return m_common->state.strokeStyle;
+ return m_state.strokeStyle;
}
Color GraphicsContext::strokeColor() const
{
- return m_common->state.strokeColor;
+ return m_state.strokeColor;
}
ColorSpace GraphicsContext::strokeColorSpace() const
{
- return m_common->state.strokeColorSpace;
+ return m_state.strokeColorSpace;
}
WindRule GraphicsContext::fillRule() const
{
- return m_common->state.fillRule;
+ return m_state.fillRule;
}
void GraphicsContext::setFillRule(WindRule fillRule)
{
- m_common->state.fillRule = fillRule;
+ m_state.fillRule = fillRule;
}
void GraphicsContext::setFillColor(const Color& color, ColorSpace colorSpace)
{
- m_common->state.fillColor = color;
- m_common->state.fillColorSpace = colorSpace;
- m_common->state.fillGradient.clear();
- m_common->state.fillPattern.clear();
+ m_state.fillColor = color;
+ m_state.fillColorSpace = colorSpace;
+ m_state.fillGradient.clear();
+ m_state.fillPattern.clear();
setPlatformFillColor(color, colorSpace);
}
Color GraphicsContext::fillColor() const
{
- return m_common->state.fillColor;
+ return m_state.fillColor;
}
ColorSpace GraphicsContext::fillColorSpace() const
{
- return m_common->state.fillColorSpace;
+ return m_state.fillColorSpace;
}
void GraphicsContext::setShouldAntialias(bool b)
{
- m_common->state.shouldAntialias = b;
+ m_state.shouldAntialias = b;
setPlatformShouldAntialias(b);
}
bool GraphicsContext::shouldAntialias() const
{
- return m_common->state.shouldAntialias;
+ return m_state.shouldAntialias;
+}
+
+void GraphicsContext::setShouldSmoothFonts(bool b)
+{
+ m_state.shouldSmoothFonts = b;
+ setPlatformShouldSmoothFonts(b);
+}
+
+bool GraphicsContext::shouldSmoothFonts() const
+{
+ return m_state.shouldSmoothFonts;
+}
+
+const GraphicsContextState& GraphicsContext::state() const
+{
+ return m_state;
}
void GraphicsContext::setStrokePattern(PassRefPtr<Pattern> pattern)
@@ -222,9 +241,9 @@ void GraphicsContext::setStrokePattern(PassRefPtr<Pattern> pattern)
setStrokeColor(Color::black, ColorSpaceDeviceRGB);
return;
}
- m_common->state.strokeGradient.clear();
- m_common->state.strokePattern = pattern;
- setPlatformStrokePattern(m_common->state.strokePattern.get());
+ m_state.strokeGradient.clear();
+ m_state.strokePattern = pattern;
+ setPlatformStrokePattern(m_state.strokePattern.get());
}
void GraphicsContext::setFillPattern(PassRefPtr<Pattern> pattern)
@@ -234,9 +253,9 @@ void GraphicsContext::setFillPattern(PassRefPtr<Pattern> pattern)
setFillColor(Color::black, ColorSpaceDeviceRGB);
return;
}
- m_common->state.fillGradient.clear();
- m_common->state.fillPattern = pattern;
- setPlatformFillPattern(m_common->state.fillPattern.get());
+ m_state.fillGradient.clear();
+ m_state.fillPattern = pattern;
+ setPlatformFillPattern(m_state.fillPattern.get());
}
void GraphicsContext::setStrokeGradient(PassRefPtr<Gradient> gradient)
@@ -246,9 +265,9 @@ void GraphicsContext::setStrokeGradient(PassRefPtr<Gradient> gradient)
setStrokeColor(Color::black, ColorSpaceDeviceRGB);
return;
}
- m_common->state.strokeGradient = gradient;
- m_common->state.strokePattern.clear();
- setPlatformStrokeGradient(m_common->state.strokeGradient.get());
+ m_state.strokeGradient = gradient;
+ m_state.strokePattern.clear();
+ setPlatformStrokeGradient(m_state.strokeGradient.get());
}
void GraphicsContext::setFillGradient(PassRefPtr<Gradient> gradient)
@@ -258,34 +277,39 @@ void GraphicsContext::setFillGradient(PassRefPtr<Gradient> gradient)
setFillColor(Color::black, ColorSpaceDeviceRGB);
return;
}
- m_common->state.fillGradient = gradient;
- m_common->state.fillPattern.clear();
- setPlatformFillGradient(m_common->state.fillGradient.get());
+ m_state.fillGradient = gradient;
+ m_state.fillPattern.clear();
+ setPlatformFillGradient(m_state.fillGradient.get());
}
Gradient* GraphicsContext::fillGradient() const
{
- return m_common->state.fillGradient.get();
+ return m_state.fillGradient.get();
}
Gradient* GraphicsContext::strokeGradient() const
{
- return m_common->state.strokeGradient.get();
+ return m_state.strokeGradient.get();
}
Pattern* GraphicsContext::fillPattern() const
{
- return m_common->state.fillPattern.get();
+ return m_state.fillPattern.get();
}
Pattern* GraphicsContext::strokePattern() const
{
- return m_common->state.strokePattern.get();
+ return m_state.strokePattern.get();
}
void GraphicsContext::setShadowsIgnoreTransforms(bool ignoreTransforms)
{
- m_common->state.shadowsIgnoreTransforms = ignoreTransforms;
+ m_state.shadowsIgnoreTransforms = ignoreTransforms;
+}
+
+bool GraphicsContext::shadowsIgnoreTransforms() const
+{
+ return m_state.shadowsIgnoreTransforms;
}
bool GraphicsContext::shadowsIgnoreTransforms() const
@@ -295,23 +319,23 @@ bool GraphicsContext::shadowsIgnoreTransforms() const
bool GraphicsContext::updatingControlTints() const
{
- return m_common->m_updatingControlTints;
+ return m_updatingControlTints;
}
void GraphicsContext::setUpdatingControlTints(bool b)
{
setPaintingDisabled(b);
- m_common->m_updatingControlTints = b;
+ m_updatingControlTints = b;
}
void GraphicsContext::setPaintingDisabled(bool f)
{
- m_common->state.paintingDisabled = f;
+ m_state.paintingDisabled = f;
}
bool GraphicsContext::paintingDisabled() const
{
- return m_common->state.paintingDisabled;
+ return m_state.paintingDisabled;
}
void GraphicsContext::drawImage(Image* image, ColorSpace styleColorSpace, const IntPoint& p, CompositeOperator op)
@@ -344,6 +368,14 @@ void GraphicsContext::drawText(const Font& font, const TextRun& run, const IntPo
}
#endif
+void GraphicsContext::drawEmphasisMarks(const Font& font, const TextRun& run, const AtomicString& mark, const IntPoint& point, int from, int to)
+{
+ if (paintingDisabled())
+ return;
+
+ font.drawEmphasisMarks(this, run, mark, point, from, to);
+}
+
void GraphicsContext::drawBidiText(const Font& font, const TextRun& run, const FloatPoint& point)
{
if (paintingDisabled())
@@ -531,14 +563,14 @@ void GraphicsContext::clipToImageBuffer(ImageBuffer* buffer, const FloatRect& re
buffer->clip(this, rect);
}
-int GraphicsContext::textDrawingMode()
+TextDrawingModeFlags GraphicsContext::textDrawingMode() const
{
- return m_common->state.textDrawingMode;
+ return m_state.textDrawingMode;
}
-void GraphicsContext::setTextDrawingMode(int mode)
+void GraphicsContext::setTextDrawingMode(TextDrawingModeFlags mode)
{
- m_common->state.textDrawingMode = mode;
+ m_state.textDrawingMode = mode;
if (paintingDisabled())
return;
setPlatformTextDrawingMode(mode);
@@ -551,7 +583,22 @@ void GraphicsContext::fillRect(const FloatRect& rect, Generator& generator)
generator.fill(this, rect);
}
+<<<<<<< HEAD
#if !(PLATFORM(SKIA) && !PLATFORM(ANDROID))
+=======
+void GraphicsContext::setCompositeOperation(CompositeOperator compositeOperation)
+{
+ m_state.compositeOperator = compositeOperation;
+ setPlatformCompositeOperation(compositeOperation);
+}
+
+CompositeOperator GraphicsContext::compositeOperation() const
+{
+ return m_state.compositeOperator;
+}
+
+#if !PLATFORM(SKIA)
+>>>>>>> webkit.org at r74534 (trunk)
void GraphicsContext::setPlatformFillGradient(Gradient*)
{
}
@@ -572,7 +619,7 @@ void GraphicsContext::setPlatformStrokePattern(Pattern*)
#if !PLATFORM(CG) && !(PLATFORM(SKIA) && !PLATFORM(ANDROID))
// Implement this if you want to go ahead and push the drawing mode into your native context
// immediately.
-void GraphicsContext::setPlatformTextDrawingMode(int mode)
+void GraphicsContext::setPlatformTextDrawingMode(TextDrawingModeFlags mode)
{
}
#endif
@@ -583,6 +630,12 @@ void GraphicsContext::setPlatformStrokeStyle(const StrokeStyle&)
}
#endif
+#if !PLATFORM(CG)
+void GraphicsContext::setPlatformShouldSmoothFonts(bool)
+{
+}
+#endif
+
#if !PLATFORM(SKIA)
void GraphicsContext::setSharedGraphicsContext3D(SharedGraphicsContext3D*, DrawingBuffer*, const IntSize&)
{
diff --git a/WebCore/platform/graphics/GraphicsContext.h b/WebCore/platform/graphics/GraphicsContext.h
index 0ea717b..22215a0 100644
--- a/WebCore/platform/graphics/GraphicsContext.h
+++ b/WebCore/platform/graphics/GraphicsContext.h
@@ -30,9 +30,11 @@
#include "ColorSpace.h"
#include "DashArray.h"
#include "FloatRect.h"
+#include "Gradient.h"
#include "Image.h"
#include "IntRect.h"
#include "Path.h"
+#include "Pattern.h"
#include "TextDirection.h"
#include <wtf/Noncopyable.h>
#include <wtf/PassOwnPtr.h>
@@ -97,11 +99,6 @@ typedef struct HDC__ PlatformGraphicsContext;
typedef void PlatformGraphicsContext;
#endif
-#if PLATFORM(GTK)
-typedef struct _GdkDrawable GdkDrawable;
-typedef struct _GdkEventExpose GdkEventExpose;
-#endif
-
#if PLATFORM(WIN)
typedef struct HDC__* HDC;
#if !PLATFORM(CG)
@@ -130,21 +127,19 @@ namespace WebCore {
class DrawingBuffer;
class Font;
class Generator;
- class Gradient;
class GraphicsContextPlatformPrivate;
- class GraphicsContextPrivate;
class ImageBuffer;
class KURL;
- class Path;
- class Pattern;
class SharedGraphicsContext3D;
class TextRun;
- // These bits can be ORed together for a total of 8 possible text drawing modes.
- const int cTextInvisible = 0;
- const int cTextFill = 1;
- const int cTextStroke = 2;
- const int cTextClip = 4;
+ enum TextDrawingMode {
+ TextModeInvisible = 0,
+ TextModeFill = 1 << 0,
+ TextModeStroke = 1 << 1,
+ TextModeClip = 1 << 2
+ };
+ typedef unsigned TextDrawingModeFlags;
enum StrokeStyle {
NoStroke,
@@ -161,6 +156,64 @@ namespace WebCore {
InterpolationHigh
};
+ struct GraphicsContextState {
+ GraphicsContextState()
+ : strokeThickness(0)
+ , shadowBlur(0)
+#if PLATFORM(CAIRO)
+ , globalAlpha(1)
+#endif
+ , textDrawingMode(TextModeFill)
+ , strokeColor(Color::black)
+ , fillColor(Color::black)
+ , strokeStyle(SolidStroke)
+ , fillRule(RULE_NONZERO)
+ , strokeColorSpace(ColorSpaceDeviceRGB)
+ , fillColorSpace(ColorSpaceDeviceRGB)
+ , shadowColorSpace(ColorSpaceDeviceRGB)
+ , compositeOperator(CompositeSourceOver)
+ , shouldAntialias(true)
+ , shouldSmoothFonts(true)
+ , paintingDisabled(false)
+ , shadowsIgnoreTransforms(false)
+ {
+ }
+
+ RefPtr<Gradient> strokeGradient;
+ RefPtr<Pattern> strokePattern;
+
+ RefPtr<Gradient> fillGradient;
+ RefPtr<Pattern> fillPattern;
+
+ FloatSize shadowOffset;
+
+ float strokeThickness;
+ float shadowBlur;
+
+#if PLATFORM(CAIRO)
+ float globalAlpha;
+#endif
+ TextDrawingModeFlags textDrawingMode;
+
+ Color strokeColor;
+ Color fillColor;
+ Color shadowColor;
+
+ StrokeStyle strokeStyle;
+ WindRule fillRule;
+
+ ColorSpace strokeColorSpace;
+ ColorSpace fillColorSpace;
+ ColorSpace shadowColorSpace;
+
+ CompositeOperator compositeOperator;
+
+ bool shouldAntialias : 1;
+ bool shouldSmoothFonts : 1;
+ bool paintingDisabled : 1;
+ bool shadowsIgnoreTransforms : 1;
+ };
+
class GraphicsContext : public Noncopyable {
public:
GraphicsContext(PlatformGraphicsContext*);
@@ -202,9 +255,18 @@ namespace WebCore {
void setShouldAntialias(bool);
bool shouldAntialias() const;
+ void setShouldSmoothFonts(bool);
+ bool shouldSmoothFonts() const;
+
+ const GraphicsContextState& state() const;
+
#if PLATFORM(CG)
void applyStrokePattern();
void applyFillPattern();
+ void drawPath(const Path&);
+
+ // Allow font smoothing (LCD antialiasing). Not part of the graphics state.
+ void setAllowsFontSmoothing(bool);
#endif
#if PLATFORM(ANDROID)
@@ -246,9 +308,8 @@ namespace WebCore {
void drawEllipse(const IntRect&);
void drawConvexPolygon(size_t numPoints, const FloatPoint*, bool shouldAntialias = false);
- void drawPath();
- void fillPath();
- void strokePath();
+ void fillPath(const Path&);
+ void strokePath(const Path&);
// Arc drawing (used by border-radius in CSS) just supports stroking at the moment.
void strokeArc(const IntRect&, int startAngle, int angleSpan);
@@ -289,14 +350,15 @@ namespace WebCore {
void addInnerRoundedRectClip(const IntRect&, int thickness);
void clipOut(const IntRect&);
void clipOutRoundedRect(const IntRect&, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight);
- void clipPath(WindRule);
+ void clipPath(const Path&, WindRule);
void clipConvexPolygon(size_t numPoints, const FloatPoint*, bool antialias = true);
void clipToImageBuffer(ImageBuffer*, const FloatRect&);
- int textDrawingMode();
- void setTextDrawingMode(int);
+ TextDrawingModeFlags textDrawingMode() const;
+ void setTextDrawingMode(TextDrawingModeFlags);
void drawText(const Font&, const TextRun&, const IntPoint&, int from = 0, int to = -1);
+ void drawEmphasisMarks(const Font&, const TextRun& , const AtomicString& mark, const IntPoint&, int from = 0, int to = -1);
void drawBidiText(const Font&, const TextRun&, const FloatPoint&);
void drawHighlightForText(const Font&, const TextRun&, const IntPoint&, int h, const Color& backgroundColor, ColorSpace, int from = 0, int to = -1);
@@ -320,7 +382,7 @@ namespace WebCore {
void endTransparencyLayer();
void setShadow(const FloatSize&, float blur, const Color&, ColorSpace);
- bool getShadow(FloatSize&, float&, Color&) const;
+ bool getShadow(FloatSize&, float&, Color&, ColorSpace&) const;
void clearShadow();
void drawFocusRing(const Vector<IntRect>&, int width, int offset, const Color&);
@@ -337,9 +399,12 @@ namespace WebCore {
#endif
void setCompositeOperation(CompositeOperator);
+ CompositeOperator compositeOperation() const;
+#if PLATFORM(SKIA)
void beginPath();
void addPath(const Path&);
+#endif
void clip(const Path&);
@@ -429,7 +494,6 @@ namespace WebCore {
#if PLATFORM(QT)
bool inTransparencyLayer() const;
- PlatformPath* currentPath();
void pushTransparencyLayerInternal(const QRect &rect, qreal opacity, QPixmap& alphaMask);
void takeOwnershipOfPlatformContext();
static QPainter::CompositionMode toQtCompositionMode(CompositeOperator op);
@@ -441,7 +505,7 @@ namespace WebCore {
#if PLATFORM(GTK)
void setGdkExposeEvent(GdkEventExpose*);
- GdkDrawable* gdkDrawable() const;
+ GdkWindow* gdkWindow() const;
GdkEventExpose* gdkExposeEvent() const;
#endif
@@ -454,10 +518,17 @@ namespace WebCore {
void markDirtyRect(const IntRect&); // Hints that a portion of the backing store is dirty.
private:
+ void platformInit(PlatformGraphicsContext*);
+ void platformDestroy();
+
+#if PLATFORM(WIN) && !OS(WINCE)
+ void platformInit(HDC, bool hasAlpha = false);
+#endif
+
void savePlatformState();
void restorePlatformState();
- void setPlatformTextDrawingMode(int);
+ void setPlatformTextDrawingMode(TextDrawingModeFlags);
void setPlatformFont(const Font& font);
void setPlatformStrokeColor(const Color&, ColorSpace);
@@ -470,18 +541,21 @@ namespace WebCore {
void setPlatformFillGradient(Gradient*);
void setPlatformFillPattern(Pattern*);
- void setPlatformShouldAntialias(bool b);
+ void setPlatformShouldAntialias(bool);
+ void setPlatformShouldSmoothFonts(bool);
void setPlatformShadow(const FloatSize&, float blur, const Color&, ColorSpace);
void clearPlatformShadow();
+ void setPlatformCompositeOperation(CompositeOperator);
+
static void adjustLineToPixelBoundaries(FloatPoint& p1, FloatPoint& p2, float strokeWidth, const StrokeStyle&);
- static GraphicsContextPrivate* createGraphicsContextPrivate();
- static void destroyGraphicsContextPrivate(GraphicsContextPrivate*);
+ GraphicsContextPlatformPrivate* m_data;
- GraphicsContextPrivate* m_common;
- GraphicsContextPlatformPrivate* m_data; // Deprecated; m_commmon can just be downcasted. To be removed.
+ GraphicsContextState m_state;
+ Vector<GraphicsContextState> m_stack;
+ bool m_updatingControlTints;
};
} // namespace WebCore
diff --git a/WebCore/platform/graphics/GraphicsContext3D.cpp b/WebCore/platform/graphics/GraphicsContext3D.cpp
index d0ee639..7fae4a1 100644
--- a/WebCore/platform/graphics/GraphicsContext3D.cpp
+++ b/WebCore/platform/graphics/GraphicsContext3D.cpp
@@ -31,27 +31,108 @@
#include "GraphicsContext3D.h"
#include "ArrayBufferView.h"
+#include "CheckedInt.h"
#include "DrawingBuffer.h"
#include "Image.h"
#include "ImageData.h"
+#include <wtf/OwnArrayPtr.h>
+#include <wtf/PassOwnArrayPtr.h>
+
namespace WebCore {
-static uint8_t convertColor16LittleTo8(uint16_t value)
-{
- return value >> 8;
-}
+namespace {
+
+ unsigned bytesPerComponent(unsigned type)
+ {
+ switch (type) {
+ case GraphicsContext3D::UNSIGNED_BYTE:
+ return 1;
+ case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
+ case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
+ case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
+ return 2;
+ case GraphicsContext3D::FLOAT:
+ return 4;
+ default:
+ return 1;
+ }
+ }
+
+ unsigned componentsPerPixel(unsigned format, unsigned type)
+ {
+ switch (type) {
+ case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
+ case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
+ case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
+ case GraphicsContext3D::FLOAT:
+ return 1;
+ default:
+ break;
+ }
+ switch (format) {
+ case GraphicsContext3D::ALPHA:
+ case GraphicsContext3D::LUMINANCE:
+ return 1;
+ case GraphicsContext3D::LUMINANCE_ALPHA:
+ return 2;
+ case GraphicsContext3D::RGB:
+ return 3;
+ case GraphicsContext3D::RGBA:
+ return 4;
+ default:
+ return 4;
+ }
+ }
+
+ // This function should only be called if width and height is non-zero and
+ // format/type are valid. Return 0 if overflow happens.
+ size_t imageSizeInBytes(unsigned width, unsigned height, unsigned format, unsigned type)
+ {
+ ASSERT(width && height);
+ CheckedInt<uint32_t> checkedWidth(width);
+ CheckedInt<uint32_t> checkedHeight(height);
+ CheckedInt<uint32_t> checkedBytesPerPixel(bytesPerComponent(type) * componentsPerPixel(format, type));
+ CheckedInt<uint32_t> checkedSize = checkedWidth * checkedHeight * checkedBytesPerPixel;
+ if (checkedSize.valid())
+ return checkedSize.value();
+ return 0;
+ }
+
+ uint8_t convertColor16LittleTo8(uint16_t value)
+ {
+ return value >> 8;
+ }
+
+ uint8_t convertColor16BigTo8(uint16_t value)
+ {
+ return static_cast<uint8_t>(value & 0x00FF);
+ }
+
+} // anonymous namespace
-static uint8_t convertColor16BigTo8(uint16_t value)
-{
- return static_cast<uint8_t>(value & 0x00FF);
-}
PassRefPtr<DrawingBuffer> GraphicsContext3D::createDrawingBuffer(const IntSize& size)
{
return DrawingBuffer::create(this, size);
}
+bool GraphicsContext3D::texImage2DResourceSafe(unsigned target, unsigned level, unsigned internalformat, unsigned width, unsigned height, unsigned border, unsigned format, unsigned type)
+{
+ OwnArrayPtr<unsigned char> zero;
+ if (width && height) {
+ size_t size = imageSizeInBytes(width, height, format, type);
+ if (!size) {
+ synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
+ return false;
+ }
+ zero = adoptArrayPtr(new unsigned char[size]);
+ memset(zero.get(), 0, size);
+ }
+ texImage2D(target, level, internalformat, width, height, border, format, type, zero.get());
+ return true;
+}
+
bool GraphicsContext3D::computeFormatAndTypeParameters(unsigned int format,
unsigned int type,
unsigned long* componentsPerPixel,
@@ -86,6 +167,9 @@ bool GraphicsContext3D::computeFormatAndTypeParameters(unsigned int format,
*componentsPerPixel = 1;
*bytesPerComponent = sizeof(unsigned short);
break;
+ case GraphicsContext3D::FLOAT: // OES_texture_float
+ *bytesPerComponent = sizeof(float);
+ break;
default:
return false;
}
@@ -188,6 +272,27 @@ bool GraphicsContext3D::extractTextureData(unsigned int width, unsigned int heig
ASSERT_NOT_REACHED();
}
break;
+ case FLOAT: // OES_texture_float
+ switch (format) {
+ case RGBA:
+ sourceDataFormat = SourceFormatRGBA32F;
+ break;
+ case RGB:
+ sourceDataFormat = SourceFormatRGB32F;
+ break;
+ case ALPHA:
+ sourceDataFormat = SourceFormatA32F;
+ break;
+ case LUMINANCE:
+ sourceDataFormat = SourceFormatR32F;
+ break;
+ case LUMINANCE_ALPHA:
+ sourceDataFormat = SourceFormatRA32F;
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ }
+ break;
case UNSIGNED_SHORT_5_5_5_1:
sourceDataFormat = SourceFormatRGBA5551;
break;
@@ -501,6 +606,38 @@ void unpackA16BigToRGBA8(const uint16_t* source, uint8_t* destination)
destination[3] = convertColor16BigTo8(source[0]);
}
+void unpackRGB32FToRGBA32F(const float* source, float* destination)
+{
+ destination[0] = source[0];
+ destination[1] = source[1];
+ destination[2] = source[2];
+ destination[3] = 1;
+}
+
+void unpackR32FToRGBA32F(const float* source, float* destination)
+{
+ destination[0] = source[0];
+ destination[1] = source[0];
+ destination[2] = source[0];
+ destination[3] = 1;
+}
+
+void unpackRA32FToRGBA32F(const float* source, float* destination)
+{
+ destination[0] = source[0];
+ destination[1] = source[0];
+ destination[2] = source[0];
+ destination[3] = source[1];
+}
+
+void unpackA32FToRGBA32F(const float* source, float* destination)
+{
+ destination[0] = 0;
+ destination[1] = 0;
+ destination[2] = 0;
+ destination[3] = source[0];
+}
+
//----------------------------------------------------------------------
// Pixel packing routines.
//
@@ -713,14 +850,68 @@ void packRGBA8ToUnsignedShort565Unmultiply(const uint8_t* source, uint16_t* dest
| ((sourceB & 0xF8) >> 3));
}
+void packRGBA32FToRGB32F(const float* source, float* destination)
+{
+ destination[0] = source[0];
+ destination[1] = source[1];
+ destination[2] = source[2];
+}
+
+void packRGBA32FToRGB32FPremultiply(const float* source, float* destination)
+{
+ float scaleFactor = source[3];
+ destination[0] = source[0] * scaleFactor;
+ destination[1] = source[1] * scaleFactor;
+ destination[2] = source[2] * scaleFactor;
+}
+
+void packRGBA32FToRGBA32FPremultiply(const float* source, float* destination)
+{
+ float scaleFactor = source[3];
+ destination[0] = source[0] * scaleFactor;
+ destination[1] = source[1] * scaleFactor;
+ destination[2] = source[2] * scaleFactor;
+ destination[3] = source[3];
+}
+
+void packRGBA32FToA32F(const float* source, float* destination)
+{
+ destination[0] = source[3];
+}
+
+void packRGBA32FToR32F(const float* source, float* destination)
+{
+ destination[0] = source[0];
+}
+
+void packRGBA32FToR32FPremultiply(const float* source, float* destination)
+{
+ float scaleFactor = source[3];
+ destination[0] = source[0] * scaleFactor;
+}
+
+
+void packRGBA32FToRA32F(const float* source, float* destination)
+{
+ destination[0] = source[0];
+ destination[1] = source[3];
+}
+
+void packRGBA32FToRA32FPremultiply(const float* source, float* destination)
+{
+ float scaleFactor = source[3];
+ destination[0] = source[0] * scaleFactor;
+ destination[1] = scaleFactor;
+}
+
} // anonymous namespace
// This is used whenever unpacking is necessary; i.e., the source data
-// is not in RGBA8 format, or the unpack alignment specifies that rows
-// are not tightly packed.
-template<typename SourceType, typename DestType,
- void unpackingFunc(const SourceType*, uint8_t*),
- void packingFunc(const uint8_t*, DestType*)>
+// is not in RGBA8/RGBA32F format, or the unpack alignment specifies
+// that rows are not tightly packed.
+template<typename SourceType, typename IntermediateType, typename DestType,
+ void unpackingFunc(const SourceType*, IntermediateType*),
+ void packingFunc(const IntermediateType*, DestType*)>
static void doUnpackingAndPacking(const SourceType* sourceData,
unsigned int width,
unsigned int height,
@@ -732,7 +923,7 @@ static void doUnpackingAndPacking(const SourceType* sourceData,
if (!sourceElementsPerRow) {
unsigned int numElements = width * height * sourceElementsPerPixel;
const SourceType* endPointer = sourceData + numElements;
- uint8_t temporaryRGBAData[4];
+ IntermediateType temporaryRGBAData[4];
while (sourceData < endPointer) {
unpackingFunc(sourceData, temporaryRGBAData);
packingFunc(temporaryRGBAData, destinationData);
@@ -740,7 +931,7 @@ static void doUnpackingAndPacking(const SourceType* sourceData,
destinationData += destinationElementsPerPixel;
}
} else {
- uint8_t temporaryRGBAData[4];
+ IntermediateType temporaryRGBAData[4];
for (unsigned int y = 0; y < height; ++y) {
const SourceType* currentSource = sourceData;
for (unsigned int x = 0; x < width; ++x) {
@@ -802,176 +993,176 @@ static void doPacking(const void* sourceData,
destinationData += destinationElementsPerPixel;
}
} else {
- doUnpackingAndPacking<uint8_t, DestType, unpackRGBA8ToRGBA8, packingFunc>(static_cast<const uint8_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
+ doUnpackingAndPacking<uint8_t, uint8_t, DestType, unpackRGBA8ToRGBA8, packingFunc>(static_cast<const uint8_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
}
break;
}
case GraphicsContext3D::SourceFormatRGBA16Little: {
unsigned int sourceElementsPerPixel, sourceElementsPerRow;
computeIncrementParameters<uint16_t>(width, 8, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
- doUnpackingAndPacking<uint16_t, DestType, unpackRGBA16LittleToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
+ doUnpackingAndPacking<uint16_t, uint8_t, DestType, unpackRGBA16LittleToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
break;
}
case GraphicsContext3D::SourceFormatRGBA16Big: {
unsigned int sourceElementsPerPixel, sourceElementsPerRow;
computeIncrementParameters<uint16_t>(width, 8, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
- doUnpackingAndPacking<uint16_t, DestType, unpackRGBA16BigToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
+ doUnpackingAndPacking<uint16_t, uint8_t, DestType, unpackRGBA16BigToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
break;
}
case GraphicsContext3D::SourceFormatRGB8: {
unsigned int sourceElementsPerPixel, sourceElementsPerRow;
computeIncrementParameters<uint8_t>(width, 3, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
- doUnpackingAndPacking<uint8_t, DestType, unpackRGB8ToRGBA8, packingFunc>(static_cast<const uint8_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
+ doUnpackingAndPacking<uint8_t, uint8_t, DestType, unpackRGB8ToRGBA8, packingFunc>(static_cast<const uint8_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
break;
}
case GraphicsContext3D::SourceFormatRGB16Little: {
unsigned int sourceElementsPerPixel, sourceElementsPerRow;
computeIncrementParameters<uint16_t>(width, 6, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
- doUnpackingAndPacking<uint16_t, DestType, unpackRGB16LittleToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
+ doUnpackingAndPacking<uint16_t, uint8_t, DestType, unpackRGB16LittleToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
break;
}
case GraphicsContext3D::SourceFormatRGB16Big: {
unsigned int sourceElementsPerPixel, sourceElementsPerRow;
computeIncrementParameters<uint16_t>(width, 6, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
- doUnpackingAndPacking<uint16_t, DestType, unpackRGB16BigToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
+ doUnpackingAndPacking<uint16_t, uint8_t, DestType, unpackRGB16BigToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
break;
}
case GraphicsContext3D::SourceFormatBGR8: {
unsigned int sourceElementsPerPixel, sourceElementsPerRow;
computeIncrementParameters<uint8_t>(width, 3, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
- doUnpackingAndPacking<uint8_t, DestType, unpackBGR8ToRGBA8, packingFunc>(static_cast<const uint8_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
+ doUnpackingAndPacking<uint8_t, uint8_t, DestType, unpackBGR8ToRGBA8, packingFunc>(static_cast<const uint8_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
break;
}
case GraphicsContext3D::SourceFormatARGB8: {
unsigned int sourceElementsPerPixel, sourceElementsPerRow;
computeIncrementParameters<uint8_t>(width, 4, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
- doUnpackingAndPacking<uint8_t, DestType, unpackARGB8ToRGBA8, packingFunc>(static_cast<const uint8_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
+ doUnpackingAndPacking<uint8_t, uint8_t, DestType, unpackARGB8ToRGBA8, packingFunc>(static_cast<const uint8_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
break;
}
case GraphicsContext3D::SourceFormatARGB16Little: {
unsigned int sourceElementsPerPixel, sourceElementsPerRow;
computeIncrementParameters<uint16_t>(width, 8, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
- doUnpackingAndPacking<uint16_t, DestType, unpackARGB16LittleToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
+ doUnpackingAndPacking<uint16_t, uint8_t, DestType, unpackARGB16LittleToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
break;
}
case GraphicsContext3D::SourceFormatARGB16Big: {
unsigned int sourceElementsPerPixel, sourceElementsPerRow;
computeIncrementParameters<uint16_t>(width, 8, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
- doUnpackingAndPacking<uint16_t, DestType, unpackARGB16BigToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
+ doUnpackingAndPacking<uint16_t, uint8_t, DestType, unpackARGB16BigToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
break;
}
case GraphicsContext3D::SourceFormatABGR8: {
unsigned int sourceElementsPerPixel, sourceElementsPerRow;
computeIncrementParameters<uint8_t>(width, 4, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
- doUnpackingAndPacking<uint8_t, DestType, unpackABGR8ToRGBA8, packingFunc>(static_cast<const uint8_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
+ doUnpackingAndPacking<uint8_t, uint8_t, DestType, unpackABGR8ToRGBA8, packingFunc>(static_cast<const uint8_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
break;
}
case GraphicsContext3D::SourceFormatBGRA8: {
unsigned int sourceElementsPerPixel, sourceElementsPerRow;
computeIncrementParameters<uint8_t>(width, 4, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
- doUnpackingAndPacking<uint8_t, DestType, unpackBGRA8ToRGBA8, packingFunc>(static_cast<const uint8_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
+ doUnpackingAndPacking<uint8_t, uint8_t, DestType, unpackBGRA8ToRGBA8, packingFunc>(static_cast<const uint8_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
break;
}
case GraphicsContext3D::SourceFormatBGRA16Little: {
unsigned int sourceElementsPerPixel, sourceElementsPerRow;
computeIncrementParameters<uint16_t>(width, 8, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
- doUnpackingAndPacking<uint16_t, DestType, unpackBGRA16LittleToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
+ doUnpackingAndPacking<uint16_t, uint8_t, DestType, unpackBGRA16LittleToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
break;
}
case GraphicsContext3D::SourceFormatBGRA16Big: {
unsigned int sourceElementsPerPixel, sourceElementsPerRow;
computeIncrementParameters<uint16_t>(width, 8, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
- doUnpackingAndPacking<uint16_t, DestType, unpackBGRA16BigToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
+ doUnpackingAndPacking<uint16_t, uint8_t, DestType, unpackBGRA16BigToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
break;
}
case GraphicsContext3D::SourceFormatRGBA5551: {
unsigned int sourceElementsPerPixel, sourceElementsPerRow;
computeIncrementParameters<uint16_t>(width, 2, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
- doUnpackingAndPacking<uint16_t, DestType, unpackRGBA5551ToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
+ doUnpackingAndPacking<uint16_t, uint8_t, DestType, unpackRGBA5551ToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
break;
}
case GraphicsContext3D::SourceFormatRGBA4444: {
unsigned int sourceElementsPerPixel, sourceElementsPerRow;
computeIncrementParameters<uint16_t>(width, 2, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
- doUnpackingAndPacking<uint16_t, DestType, unpackRGBA4444ToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
+ doUnpackingAndPacking<uint16_t, uint8_t, DestType, unpackRGBA4444ToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
break;
}
case GraphicsContext3D::SourceFormatRGB565: {
unsigned int sourceElementsPerPixel, sourceElementsPerRow;
computeIncrementParameters<uint16_t>(width, 2, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
- doUnpackingAndPacking<uint16_t, DestType, unpackRGB565ToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
+ doUnpackingAndPacking<uint16_t, uint8_t, DestType, unpackRGB565ToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
break;
}
case GraphicsContext3D::SourceFormatR8: {
unsigned int sourceElementsPerPixel, sourceElementsPerRow;
computeIncrementParameters<uint8_t>(width, 1, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
- doUnpackingAndPacking<uint8_t, DestType, unpackR8ToRGBA8, packingFunc>(static_cast<const uint8_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
+ doUnpackingAndPacking<uint8_t, uint8_t, DestType, unpackR8ToRGBA8, packingFunc>(static_cast<const uint8_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
break;
}
case GraphicsContext3D::SourceFormatR16Little: {
unsigned int sourceElementsPerPixel, sourceElementsPerRow;
computeIncrementParameters<uint16_t>(width, 2, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
- doUnpackingAndPacking<uint16_t, DestType, unpackR16LittleToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
+ doUnpackingAndPacking<uint16_t, uint8_t, DestType, unpackR16LittleToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
break;
}
case GraphicsContext3D::SourceFormatR16Big: {
unsigned int sourceElementsPerPixel, sourceElementsPerRow;
computeIncrementParameters<uint16_t>(width, 2, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
- doUnpackingAndPacking<uint16_t, DestType, unpackR16BigToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
+ doUnpackingAndPacking<uint16_t, uint8_t, DestType, unpackR16BigToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
break;
}
case GraphicsContext3D::SourceFormatRA8: {
unsigned int sourceElementsPerPixel, sourceElementsPerRow;
computeIncrementParameters<uint8_t>(width, 2, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
- doUnpackingAndPacking<uint8_t, DestType, unpackRA8ToRGBA8, packingFunc>(static_cast<const uint8_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
+ doUnpackingAndPacking<uint8_t, uint8_t, DestType, unpackRA8ToRGBA8, packingFunc>(static_cast<const uint8_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
break;
}
case GraphicsContext3D::SourceFormatRA16Little: {
unsigned int sourceElementsPerPixel, sourceElementsPerRow;
computeIncrementParameters<uint16_t>(width, 4, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
- doUnpackingAndPacking<uint16_t, DestType, unpackRA16LittleToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
+ doUnpackingAndPacking<uint16_t, uint8_t, DestType, unpackRA16LittleToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
break;
}
case GraphicsContext3D::SourceFormatRA16Big: {
unsigned int sourceElementsPerPixel, sourceElementsPerRow;
computeIncrementParameters<uint16_t>(width, 4, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
- doUnpackingAndPacking<uint16_t, DestType, unpackRA16BigToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
+ doUnpackingAndPacking<uint16_t, uint8_t, DestType, unpackRA16BigToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
break;
}
case GraphicsContext3D::SourceFormatAR8: {
unsigned int sourceElementsPerPixel, sourceElementsPerRow;
computeIncrementParameters<uint8_t>(width, 2, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
- doUnpackingAndPacking<uint8_t, DestType, unpackAR8ToRGBA8, packingFunc>(static_cast<const uint8_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
+ doUnpackingAndPacking<uint8_t, uint8_t, DestType, unpackAR8ToRGBA8, packingFunc>(static_cast<const uint8_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
break;
}
case GraphicsContext3D::SourceFormatAR16Little: {
unsigned int sourceElementsPerPixel, sourceElementsPerRow;
computeIncrementParameters<uint16_t>(width, 4, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
- doUnpackingAndPacking<uint16_t, DestType, unpackAR16LittleToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
+ doUnpackingAndPacking<uint16_t, uint8_t, DestType, unpackAR16LittleToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
break;
}
case GraphicsContext3D::SourceFormatAR16Big: {
unsigned int sourceElementsPerPixel, sourceElementsPerRow;
computeIncrementParameters<uint16_t>(width, 4, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
- doUnpackingAndPacking<uint16_t, DestType, unpackAR16BigToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
+ doUnpackingAndPacking<uint16_t, uint8_t, DestType, unpackAR16BigToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
break;
}
case GraphicsContext3D::SourceFormatA8: {
unsigned int sourceElementsPerPixel, sourceElementsPerRow;
computeIncrementParameters<uint8_t>(width, 1, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
- doUnpackingAndPacking<uint8_t, DestType, unpackA8ToRGBA8, packingFunc>(static_cast<const uint8_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
+ doUnpackingAndPacking<uint8_t, uint8_t, DestType, unpackA8ToRGBA8, packingFunc>(static_cast<const uint8_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
break;
}
case GraphicsContext3D::SourceFormatA16Little: {
unsigned int sourceElementsPerPixel, sourceElementsPerRow;
computeIncrementParameters<uint16_t>(width, 2, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
- doUnpackingAndPacking<uint16_t, DestType, unpackA16LittleToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
+ doUnpackingAndPacking<uint16_t, uint8_t, DestType, unpackA16LittleToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
break;
}
case GraphicsContext3D::SourceFormatA16Big: {
unsigned int sourceElementsPerPixel, sourceElementsPerRow;
computeIncrementParameters<uint16_t>(width, 2, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
- doUnpackingAndPacking<uint16_t, DestType, unpackA16BigToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
+ doUnpackingAndPacking<uint16_t, uint8_t, DestType, unpackA16BigToRGBA8, packingFunc>(static_cast<const uint16_t*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
break;
}
default:
@@ -979,6 +1170,63 @@ static void doPacking(const void* sourceData,
}
}
+// This specialized routine is used only for floating-point texture uploads. It
+// does not need to be as general as doPacking, above; because there are
+// currently no native floating-point image formats in WebKit, there are only a
+// few upload paths.
+template<void packingFunc(const float*, float*)>
+static void doFloatingPointPacking(const void* sourceData,
+ GraphicsContext3D::SourceDataFormat sourceDataFormat,
+ unsigned int width,
+ unsigned int height,
+ unsigned int sourceUnpackAlignment,
+ float* destinationData,
+ unsigned int destinationElementsPerPixel)
+{
+ switch (sourceDataFormat) {
+ case GraphicsContext3D::SourceFormatRGBA8: {
+ unsigned int sourceElementsPerPixel, sourceElementsPerRow;
+ computeIncrementParameters<float>(width, 4, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
+ ASSERT(!sourceElementsPerRow); // Guaranteed because each color channel is sizeof(float) bytes.
+ const float* source = static_cast<const float*>(sourceData);
+ unsigned int numElements = width * height * 4;
+ const float* endPointer = source + numElements;
+ while (source < endPointer) {
+ packingFunc(source, destinationData);
+ source += sourceElementsPerPixel;
+ destinationData += destinationElementsPerPixel;
+ }
+ break;
+ }
+ case GraphicsContext3D::SourceFormatRGB32F: {
+ unsigned int sourceElementsPerPixel, sourceElementsPerRow;
+ computeIncrementParameters<float>(width, 3, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
+ doUnpackingAndPacking<float, float, float, unpackRGB32FToRGBA32F, packingFunc>(static_cast<const float*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
+ break;
+ }
+ case GraphicsContext3D::SourceFormatR32F: {
+ unsigned int sourceElementsPerPixel, sourceElementsPerRow;
+ computeIncrementParameters<float>(width, 1, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
+ doUnpackingAndPacking<float, float, float, unpackR32FToRGBA32F, packingFunc>(static_cast<const float*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
+ break;
+ }
+ case GraphicsContext3D::SourceFormatRA32F: {
+ unsigned int sourceElementsPerPixel, sourceElementsPerRow;
+ computeIncrementParameters<float>(width, 2, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
+ doUnpackingAndPacking<float, float, float, unpackRA32FToRGBA32F, packingFunc>(static_cast<const float*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
+ break;
+ }
+ case GraphicsContext3D::SourceFormatA32F: {
+ unsigned int sourceElementsPerPixel, sourceElementsPerRow;
+ computeIncrementParameters<float>(width, 1, sourceUnpackAlignment, &sourceElementsPerPixel, &sourceElementsPerRow);
+ doUnpackingAndPacking<float, float, float, unpackA32FToRGBA32F, packingFunc>(static_cast<const float*>(sourceData), width, height, sourceElementsPerPixel, sourceElementsPerRow, destinationData, destinationElementsPerPixel);
+ break;
+ }
+ default:
+ ASSERT_NOT_REACHED();
+ }
+}
+
bool GraphicsContext3D::packPixels(const uint8_t* sourceData,
GraphicsContext3D::SourceDataFormat sourceDataFormat,
unsigned int width,
@@ -1113,6 +1361,87 @@ bool GraphicsContext3D::packPixels(const uint8_t* sourceData,
}
break;
}
+ case FLOAT: {
+ // OpenGL ES, and therefore WebGL, require that the format and
+ // internalformat be identical, which implies that the source and
+ // destination formats will both be floating-point in this branch -- at
+ // least, until WebKit supports floating-point image formats natively.
+ ASSERT(sourceDataFormat == SourceFormatRGBA32F || sourceDataFormat == SourceFormatRGB32F
+ || sourceDataFormat == SourceFormatRA32F || sourceDataFormat == SourceFormatR32F
+ || sourceDataFormat == SourceFormatA32F);
+ // Because WebKit doesn't use floating-point color channels for anything
+ // internally, there's no chance we have to do a (lossy) unmultiply
+ // operation.
+ ASSERT(alphaOp == AlphaDoNothing || alphaOp == AlphaDoPremultiply);
+ // For the source formats with an even number of channels (RGBA32F,
+ // RA32F) it is guaranteed that the pixel data is tightly packed because
+ // unpack alignment <= sizeof(float) * number of channels.
+ float* destination = static_cast<float*>(destinationData);
+ if (alphaOp == AlphaDoNothing
+ && ((sourceDataFormat == SourceFormatRGBA32F && destinationFormat == RGBA)
+ || (sourceDataFormat == SourceFormatRA32F && destinationFormat == LUMINANCE_ALPHA))) {
+ // No conversion necessary.
+ int numChannels = (sourceDataFormat == SourceFormatRGBA32F ? 4 : 2);
+ memcpy(destinationData, sourceData, width * height * numChannels * sizeof(float));
+ break;
+ }
+ switch (destinationFormat) {
+ case RGB:
+ switch (alphaOp) {
+ case AlphaDoNothing:
+ doFloatingPointPacking<packRGBA32FToRGB32F>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 3);
+ break;
+ case AlphaDoPremultiply:
+ doFloatingPointPacking<packRGBA32FToRGB32FPremultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 3);
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ }
+ break;
+ case RGBA:
+ // AlphaDoNothing is handled above with fast path.
+ ASSERT(alphaOp == AlphaDoPremultiply);
+ doFloatingPointPacking<packRGBA32FToRGBA32FPremultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 4);
+ break;
+ case ALPHA:
+ // From the desktop OpenGL conversion rules (OpenGL 2.1
+ // specification, Table 3.15), the alpha channel is chosen
+ // from the RGBA data.
+ doFloatingPointPacking<packRGBA32FToA32F>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 1);
+ break;
+ case LUMINANCE:
+ // From the desktop OpenGL conversion rules (OpenGL 2.1
+ // specification, Table 3.15), the red channel is chosen
+ // from the RGBA data.
+ switch (alphaOp) {
+ case AlphaDoNothing:
+ doFloatingPointPacking<packRGBA32FToR32F>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 1);
+ break;
+ case AlphaDoPremultiply:
+ doFloatingPointPacking<packRGBA32FToR32FPremultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 1);
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ }
+ break;
+ case LUMINANCE_ALPHA:
+ // From the desktop OpenGL conversion rules (OpenGL 2.1
+ // specification, Table 3.15), the red and alpha channels
+ // are chosen from the RGBA data.
+ switch (alphaOp) {
+ case AlphaDoNothing:
+ doFloatingPointPacking<packRGBA32FToRA32F>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 2);
+ break;
+ case AlphaDoPremultiply:
+ doFloatingPointPacking<packRGBA32FToRA32FPremultiply>(sourceData, sourceDataFormat, width, height, sourceUnpackAlignment, destination, 2);
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ }
+ break;
+ }
+ break;
+ }
}
return true;
}
diff --git a/WebCore/platform/graphics/GraphicsContext3D.h b/WebCore/platform/graphics/GraphicsContext3D.h
index c2d5c24..f9540be 100644
--- a/WebCore/platform/graphics/GraphicsContext3D.h
+++ b/WebCore/platform/graphics/GraphicsContext3D.h
@@ -472,6 +472,10 @@ public:
// like GL_FLOAT, GL_INT, etc.
int sizeInBytes(int type);
+ // Helper to texImage2D with pixel==0 case: pixels are initialized to 0.
+ // Return true if no GL error is synthesized.
+ bool texImage2DResourceSafe(unsigned target, unsigned level, unsigned internalformat, unsigned width, unsigned height, unsigned border, unsigned format, unsigned type);
+
bool isGLES2Compliant() const;
//----------------------------------------------------------------------
@@ -536,9 +540,11 @@ public:
SourceFormatRGBA8 = 0,
SourceFormatRGBA16Little,
SourceFormatRGBA16Big,
+ SourceFormatRGBA32F,
SourceFormatRGB8,
SourceFormatRGB16Little,
SourceFormatRGB16Big,
+ SourceFormatRGB32F,
SourceFormatBGR8,
SourceFormatBGRA8,
SourceFormatBGRA16Little,
@@ -553,15 +559,18 @@ public:
SourceFormatR8,
SourceFormatR16Little,
SourceFormatR16Big,
+ SourceFormatR32F,
SourceFormatRA8,
SourceFormatRA16Little,
SourceFormatRA16Big,
+ SourceFormatRA32F,
SourceFormatAR8,
SourceFormatAR16Little,
SourceFormatAR16Big,
SourceFormatA8,
SourceFormatA16Little,
SourceFormatA16Big,
+ SourceFormatA32F,
SourceFormatNumFormats
};
diff --git a/WebCore/platform/graphics/GraphicsContextPrivate.h b/WebCore/platform/graphics/GraphicsContextPrivate.h
deleted file mode 100644
index 985cad9..0000000
--- a/WebCore/platform/graphics/GraphicsContextPrivate.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 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 COMPUTER, 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 COMPUTER, 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.
- */
-
-#ifndef GraphicsContextPrivate_h
-#define GraphicsContextPrivate_h
-
-#include "Gradient.h"
-#include "GraphicsContext.h"
-#include "Pattern.h"
-#include "TransformationMatrix.h"
-
-namespace WebCore {
-
- struct GraphicsContextState {
- GraphicsContextState()
- : textDrawingMode(cTextFill)
- , strokeStyle(SolidStroke)
- , strokeThickness(0)
- , strokeColor(Color::black)
- , strokeColorSpace(ColorSpaceDeviceRGB)
- , fillRule(RULE_NONZERO)
- , fillColor(Color::black)
- , fillColorSpace(ColorSpaceDeviceRGB)
- , shouldAntialias(true)
- , paintingDisabled(false)
- , shadowBlur(0)
- , shadowsIgnoreTransforms(false)
-#if PLATFORM(CAIRO)
- , globalAlpha(1)
-#endif
- {
- }
-
- int textDrawingMode;
-
- StrokeStyle strokeStyle;
- float strokeThickness;
- Color strokeColor;
- ColorSpace strokeColorSpace;
- RefPtr<Gradient> strokeGradient;
- RefPtr<Pattern> strokePattern;
-
- WindRule fillRule;
- Color fillColor;
- ColorSpace fillColorSpace;
- RefPtr<Gradient> fillGradient;
- RefPtr<Pattern> fillPattern;
-
- bool shouldAntialias;
-
- bool paintingDisabled;
-
- FloatSize shadowOffset;
- float shadowBlur;
- Color shadowColor;
-
- bool shadowsIgnoreTransforms;
-#if PLATFORM(CAIRO)
- float globalAlpha;
-#elif PLATFORM(QT)
- TransformationMatrix pathTransform;
-#endif
- };
-
- class GraphicsContextPrivate : public Noncopyable {
- public:
- GraphicsContextPrivate()
- : m_updatingControlTints(false)
- {
- }
-
- GraphicsContextState state;
- Vector<GraphicsContextState> stack;
- bool m_updatingControlTints;
- };
-
-} // namespace WebCore
-
-#endif // GraphicsContextPrivate_h
diff --git a/WebCore/platform/graphics/GraphicsLayer.cpp b/WebCore/platform/graphics/GraphicsLayer.cpp
index 08b79ab..84905a9 100644
--- a/WebCore/platform/graphics/GraphicsLayer.cpp
+++ b/WebCore/platform/graphics/GraphicsLayer.cpp
@@ -73,6 +73,7 @@ GraphicsLayer::GraphicsLayer(GraphicsLayerClient* client)
, m_usingTiledLayer(false)
, m_masksToBounds(false)
, m_drawsContent(false)
+ , m_acceleratesDrawing(false)
, m_paintingPhase(GraphicsLayerPaintAll)
, m_contentsOrientation(CompositingCoordinatesTopDown)
, m_parent(0)
diff --git a/WebCore/platform/graphics/GraphicsLayer.h b/WebCore/platform/graphics/GraphicsLayer.h
index 81aa6d0..f31c8f9 100644
--- a/WebCore/platform/graphics/GraphicsLayer.h
+++ b/WebCore/platform/graphics/GraphicsLayer.h
@@ -49,23 +49,19 @@
@class WebLayer;
@class CALayer;
typedef CALayer PlatformLayer;
-typedef CALayer* NativeLayer;
#else
typedef void* PlatformLayer;
-typedef void* NativeLayer;
#endif
#elif PLATFORM(WIN)
namespace WebCore {
class WKCACFLayer;
typedef WKCACFLayer PlatformLayer;
-typedef void* NativeLayer;
}
#elif PLATFORM(QT)
#if USE(TEXTURE_MAPPER)
namespace WebCore {
class TextureMapperPlatformLayer;
typedef TextureMapperPlatformLayer PlatformLayer;
-typedef TextureMapperPlatformLayer* NativeLayer;
};
#else
QT_BEGIN_NAMESPACE
@@ -73,14 +69,12 @@ class QGraphicsObject;
QT_END_NAMESPACE
namespace WebCore {
typedef QGraphicsObject PlatformLayer;
-typedef QGraphicsObject* NativeLayer;
}
#endif
#elif PLATFORM(CHROMIUM)
namespace WebCore {
class LayerChromium;
typedef LayerChromium PlatformLayer;
-typedef void* NativeLayer;
}
#elif PLATFORM(ANDROID)
namespace WebCore {
@@ -90,7 +84,6 @@ typedef void* NativeLayer;
}
#else
typedef void* PlatformLayer;
-typedef void* NativeLayer;
#endif
enum LayerTreeAsTextBehaviorFlags {
@@ -206,9 +199,6 @@ public:
const String& name() const { return m_name; }
virtual void setName(const String& name) { m_name = name; }
- // For hosting this GraphicsLayer in a native layer hierarchy.
- virtual NativeLayer nativeLayer() const { return 0; }
-
GraphicsLayer* parent() const { return m_parent; };
void setParent(GraphicsLayer* layer) { m_parent = layer; } // Internal use only.
@@ -274,6 +264,9 @@ public:
bool drawsContent() const { return m_drawsContent; }
virtual void setDrawsContent(bool b) { m_drawsContent = b; }
+ bool acceleratesDrawing() const { return m_acceleratesDrawing; }
+ virtual void setAcceleratesDrawing(bool b) { m_acceleratesDrawing = b; }
+
// The color used to paint the layer backgrounds
const Color& backgroundColor() const { return m_backgroundColor; }
virtual void setBackgroundColor(const Color&);
@@ -329,6 +322,7 @@ public:
// Callback from the underlying graphics system when the layer has been displayed
virtual void didDisplay(PlatformLayer*) { }
+ // For hosting this GraphicsLayer in a native layer hierarchy.
virtual PlatformLayer* platformLayer() const { return 0; }
void dumpLayer(TextStream&, int indent = 0, LayerTreeAsTextBehavior = LayerTreeAsTextBehaviorNormal) const;
@@ -409,6 +403,7 @@ protected:
bool m_usingTiledLayer : 1;
bool m_masksToBounds : 1;
bool m_drawsContent : 1;
+ bool m_acceleratesDrawing : 1;
GraphicsLayerPaintingPhase m_paintingPhase;
CompositingCoordinatesOrientation m_contentsOrientation; // affects orientation of layer contents
diff --git a/WebCore/platform/graphics/Image.cpp b/WebCore/platform/graphics/Image.cpp
index 6f2311c..3096680 100644
--- a/WebCore/platform/graphics/Image.cpp
+++ b/WebCore/platform/graphics/Image.cpp
@@ -81,10 +81,10 @@ void Image::fillWithSolidColor(GraphicsContext* ctxt, const FloatRect& dstRect,
if (color.alpha() <= 0)
return;
- ctxt->save();
+ CompositeOperator previousOperator = ctxt->compositeOperation();
ctxt->setCompositeOperation(!color.hasAlpha() && op == CompositeSourceOver ? CompositeCopy : op);
ctxt->fillRect(dstRect, color, styleColorSpace);
- ctxt->restore();
+ ctxt->setCompositeOperation(previousOperator);
}
static inline FloatSize calculatePatternScale(const FloatRect& dstRect, const FloatRect& srcRect, Image::TileRule hRule, Image::TileRule vRule)
diff --git a/WebCore/platform/graphics/ImageBuffer.h b/WebCore/platform/graphics/ImageBuffer.h
index 822a0ff..8f9abf3 100644
--- a/WebCore/platform/graphics/ImageBuffer.h
+++ b/WebCore/platform/graphics/ImageBuffer.h
@@ -39,6 +39,10 @@
#include <wtf/PassOwnPtr.h>
#include <wtf/PassRefPtr.h>
+#if (PLATFORM(MAC) && PLATFORM(CA) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD))
+#define USE_IOSURFACE 1
+#endif
+
namespace WebCore {
class GraphicsContext;
@@ -51,13 +55,18 @@ namespace WebCore {
Unmultiplied
};
+ enum RenderingMode {
+ Unaccelerated,
+ Accelerated
+ };
+
class ImageBuffer : public Noncopyable {
public:
// Will return a null pointer on allocation failure.
- static PassOwnPtr<ImageBuffer> create(const IntSize& size, ColorSpace colorSpace = ColorSpaceDeviceRGB)
+ static PassOwnPtr<ImageBuffer> create(const IntSize& size, ColorSpace colorSpace = ColorSpaceDeviceRGB, RenderingMode renderingMode = Unaccelerated)
{
bool success = false;
- OwnPtr<ImageBuffer> buf(new ImageBuffer(size, colorSpace, success));
+ OwnPtr<ImageBuffer> buf(new ImageBuffer(size, colorSpace, renderingMode, success));
if (success)
return buf.release();
return 0;
@@ -104,6 +113,7 @@ namespace WebCore {
ImageBufferData m_data;
IntSize m_size;
+ bool m_accelerateRendering;
OwnPtr<GraphicsContext> m_context;
#if !PLATFORM(CG)
@@ -113,7 +123,7 @@ namespace WebCore {
// This constructor will place its success into the given out-variable
// so that create() knows when it should return failure.
- ImageBuffer(const IntSize&, ColorSpace colorSpace, bool& success);
+ ImageBuffer(const IntSize&, ColorSpace colorSpace, RenderingMode renderingMode, bool& success);
};
} // namespace WebCore
diff --git a/WebCore/platform/graphics/ImageSource.cpp b/WebCore/platform/graphics/ImageSource.cpp
index d1a944a..92553c5 100644
--- a/WebCore/platform/graphics/ImageSource.cpp
+++ b/WebCore/platform/graphics/ImageSource.cpp
@@ -41,10 +41,10 @@ namespace WebCore {
unsigned ImageSource::s_maxPixelsPerDecodedImage = 1024 * 1024;
#endif
-ImageSource::ImageSource(bool premultiplyAlpha, bool ignoreGammaAndColorProfile)
+ImageSource::ImageSource(ImageSource::AlphaOption alphaOption, ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption)
: m_decoder(0)
- , m_premultiplyAlpha(premultiplyAlpha)
- , m_ignoreGammaAndColorProfile(ignoreGammaAndColorProfile)
+ , m_alphaOption(alphaOption)
+ , m_gammaAndColorProfileOption(gammaAndColorProfileOption)
{
}
@@ -79,7 +79,7 @@ void ImageSource::setData(SharedBuffer* data, bool allDataReceived)
// If insufficient bytes are available to determine the image type, no decoder plugin will be
// made.
if (!m_decoder) {
- m_decoder = static_cast<NativeImageSourcePtr>(ImageDecoder::create(*data, m_premultiplyAlpha, m_ignoreGammaAndColorProfile));
+ m_decoder = static_cast<NativeImageSourcePtr>(ImageDecoder::create(*data, m_alphaOption, m_gammaAndColorProfileOption));
#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
if (m_decoder && s_maxPixelsPerDecodedImage)
m_decoder->setMaxNumPixels(s_maxPixelsPerDecodedImage);
@@ -153,13 +153,14 @@ float ImageSource::frameDurationAtIndex(size_t index)
if (!buffer || buffer->status() == RGBA32Buffer::FrameEmpty)
return 0;
- // Many annoying ads specify a 0 duration to make an image flash as quickly
- // as possible. We follow WinIE's behavior and use a duration of 100 ms
- // for any frames that specify a duration of <= 50 ms. See
- // <http://bugs.webkit.org/show_bug.cgi?id=14413> or Radar 4051389 for
- // more.
+ // Many annoying ads specify a 0 duration to make an image flash as quickly as possible.
+ // We follow Firefox's behavior and use a duration of 100 ms for any frames that specify
+ // a duration of <= 10 ms. See <rdar://problem/7689300> and <http://webkit.org/b/36082>
+ // for more information.
const float duration = buffer->duration() / 1000.0f;
- return (duration < 0.051f) ? 0.100f : duration;
+ if (duration < 0.011f)
+ return 0.100f;
+ return duration;
}
bool ImageSource::frameHasAlphaAtIndex(size_t index)
diff --git a/WebCore/platform/graphics/ImageSource.h b/WebCore/platform/graphics/ImageSource.h
index 3d96698..29c1be3 100644
--- a/WebCore/platform/graphics/ImageSource.h
+++ b/WebCore/platform/graphics/ImageSource.h
@@ -138,7 +138,17 @@ const int cAnimationNone = -2;
class ImageSource : public Noncopyable {
public:
- ImageSource(bool premultiplyAlpha = true, bool ignoreGammaAndColorProfile = false);
+ enum AlphaOption {
+ AlphaPremultiplied,
+ AlphaNotPremultiplied
+ };
+
+ enum GammaAndColorProfileOption {
+ GammaAndColorProfileApplied,
+ GammaAndColorProfileIgnored
+ };
+
+ ImageSource(AlphaOption alphaOption = AlphaPremultiplied, GammaAndColorProfileOption gammaAndColorProfileOption = GammaAndColorProfileApplied);
~ImageSource();
// Tells the ImageSource that the Image no longer cares about decoded frame
@@ -206,8 +216,8 @@ private:
protected:
#endif
NativeImageSourcePtr m_decoder;
- bool m_premultiplyAlpha;
- bool m_ignoreGammaAndColorProfile;
+ AlphaOption m_alphaOption;
+ GammaAndColorProfileOption m_gammaAndColorProfileOption;
#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
static unsigned s_maxPixelsPerDecodedImage;
#endif
diff --git a/WebCore/platform/graphics/IntRect.h b/WebCore/platform/graphics/IntRect.h
index e43e290..638db75 100644
--- a/WebCore/platform/graphics/IntRect.h
+++ b/WebCore/platform/graphics/IntRect.h
@@ -117,6 +117,29 @@ public:
void move(const IntSize& s) { m_location += s; }
void move(int dx, int dy) { m_location.move(dx, dy); }
+
+ void shiftLeftEdgeTo(int edge)
+ {
+ int delta = edge - x();
+ setX(edge);
+ setWidth(std::max(0, width() - delta));
+ }
+ void shiftRightEdgeTo(int edge)
+ {
+ int delta = edge - right();
+ setWidth(std::max(0, width() + delta));
+ }
+ void shiftTopEdgeTo(int edge)
+ {
+ int delta = edge - y();
+ setY(edge);
+ setHeight(std::max(0, height() - delta));
+ }
+ void shiftBottomEdgeTo(int edge)
+ {
+ int delta = edge - bottom();
+ setHeight(std::max(0, height() + delta));
+ }
bool intersects(const IntRect&) const;
bool contains(const IntRect&) const;
diff --git a/WebCore/platform/graphics/MediaPlayer.cpp b/WebCore/platform/graphics/MediaPlayer.cpp
index dc743bf..4a39e9e 100644
--- a/WebCore/platform/graphics/MediaPlayer.cpp
+++ b/WebCore/platform/graphics/MediaPlayer.cpp
@@ -164,7 +164,8 @@ struct MediaPlayerFactory : Noncopyable {
};
static void addMediaEngine(CreateMediaEnginePlayer, MediaEngineSupportedTypes, MediaEngineSupportsType);
-static MediaPlayerFactory* chooseBestEngineForTypeAndCodecs(const String& type, const String& codecs);
+static MediaPlayerFactory* bestMediaEngineForTypeAndCodecs(const String& type, const String& codecs, MediaPlayerFactory* current = 0);
+static MediaPlayerFactory* nextMediaEngine(MediaPlayerFactory* current);
static Vector<MediaPlayerFactory*>& installedMediaEngines()
{
@@ -212,10 +213,12 @@ static const AtomicString& codecs()
return codecs;
}
-static MediaPlayerFactory* chooseBestEngineForTypeAndCodecs(const String& type, const String& codecs)
+static MediaPlayerFactory* bestMediaEngineForTypeAndCodecs(const String& type, const String& codecs, MediaPlayerFactory* current)
{
- Vector<MediaPlayerFactory*>& engines = installedMediaEngines();
+ if (type.isEmpty())
+ return 0;
+ Vector<MediaPlayerFactory*>& engines = installedMediaEngines();
if (engines.isEmpty())
return 0;
@@ -229,9 +232,13 @@ static MediaPlayerFactory* chooseBestEngineForTypeAndCodecs(const String& type,
MediaPlayerFactory* engine = 0;
MediaPlayer::SupportsType supported = MediaPlayer::IsNotSupported;
-
unsigned count = engines.size();
for (unsigned ndx = 0; ndx < count; ndx++) {
+ if (current) {
+ if (current == engines[ndx])
+ current = 0;
+ continue;
+ }
MediaPlayer::SupportsType engineSupport = engines[ndx]->supportsTypeAndCodecs(type, codecs);
if (engineSupport > supported) {
supported = engineSupport;
@@ -242,10 +249,27 @@ static MediaPlayerFactory* chooseBestEngineForTypeAndCodecs(const String& type,
return engine;
}
+static MediaPlayerFactory* nextMediaEngine(MediaPlayerFactory* current)
+{
+ Vector<MediaPlayerFactory*>& engines = installedMediaEngines();
+ if (engines.isEmpty())
+ return 0;
+
+ if (!current)
+ return engines.first();
+
+ size_t currentIndex = engines.find(current);
+ if (currentIndex == WTF::notFound || currentIndex == engines.size())
+ return 0;
+
+ return engines[currentIndex + 1];
+}
+
// media player
MediaPlayer::MediaPlayer(MediaPlayerClient* client)
: m_mediaPlayerClient(client)
+ , m_reloadTimer(this, &MediaPlayer::reloadTimerFired)
, m_private(createNullMediaPlayer(this))
, m_currentMediaEngine(0)
, m_frameView(0)
@@ -268,12 +292,15 @@ MediaPlayer::MediaPlayer(MediaPlayerClient* client)
m_currentMediaEngine = engines[0];
m_private.clear();
m_private.set(engines[0]->constructor(this));
+ if (m_mediaPlayerClient)
+ m_mediaPlayerClient->mediaPlayerEngineUpdated(this);
}
#endif
}
MediaPlayer::~MediaPlayer()
{
+ m_mediaPlayerClient = 0;
}
void MediaPlayer::load(const String& url, const ContentType& contentType)
@@ -281,26 +308,38 @@ void MediaPlayer::load(const String& url, const ContentType& contentType)
String type = contentType.type().lower();
String typeCodecs = contentType.parameter(codecs());
- // If the MIME type is unhelpful, see if the type registry has a match for the file extension.
+ // If the MIME type is missing or is not meaningful, try to figure it out from the URL.
if (type.isEmpty() || type == applicationOctetStream() || type == textPlain()) {
- size_t pos = url.reverseFind('.');
- if (pos != notFound) {
- String extension = url.substring(pos + 1);
- String mediaType = MIMETypeRegistry::getMediaMIMETypeForExtension(extension);
- if (!mediaType.isEmpty())
- type = mediaType;
+ if (protocolIs(url, "data"))
+ type = mimeTypeFromDataURL(url);
+ else {
+ size_t pos = url.reverseFind('.');
+ if (pos != notFound) {
+ String extension = url.substring(pos + 1);
+ String mediaType = MIMETypeRegistry::getMediaMIMETypeForExtension(extension);
+ if (!mediaType.isEmpty())
+ type = mediaType;
+ }
}
}
- MediaPlayerFactory* engine = 0;
- if (!type.isEmpty())
- engine = chooseBestEngineForTypeAndCodecs(type, typeCodecs);
+ m_url = url;
+ m_contentMIMEType = type;
+ m_contentTypeCodecs = typeCodecs;
+ loadWithNextMediaEngine(0);
+}
- // If we didn't find an engine and no MIME type is specified, just use the first engine.
- if (!engine && type.isEmpty() && !installedMediaEngines().isEmpty())
- engine = installedMediaEngines()[0];
+void MediaPlayer::loadWithNextMediaEngine(MediaPlayerFactory* current)
+{
+ MediaPlayerFactory* engine;
+
+ // If no MIME type is specified, just use the next engine.
+ if (m_contentMIMEType.isEmpty())
+ engine = nextMediaEngine(current);
+ else
+ engine = bestMediaEngineForTypeAndCodecs(m_contentMIMEType, m_contentTypeCodecs, current);
- // Don't delete and recreate the player unless it comes from a different engine
+ // Don't delete and recreate the player unless it comes from a different engine.
if (!engine) {
m_currentMediaEngine = engine;
m_private.clear();
@@ -308,6 +347,8 @@ void MediaPlayer::load(const String& url, const ContentType& contentType)
m_currentMediaEngine = engine;
m_private.clear();
m_private.set(engine->constructor(this));
+ if (m_mediaPlayerClient)
+ m_mediaPlayerClient->mediaPlayerEngineUpdated(this);
#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
m_private->setMediaPlayerProxy(m_playerProxy);
#endif
@@ -316,9 +357,12 @@ void MediaPlayer::load(const String& url, const ContentType& contentType)
}
if (m_private)
- m_private->load(url);
- else
+ m_private->load(m_url);
+ else {
m_private.set(createNullMediaPlayer(this));
+ if (m_mediaPlayerClient)
+ m_mediaPlayerClient->mediaPlayerEngineUpdated(this);
+ }
}
bool MediaPlayer::hasAvailableVideoFrame() const
@@ -559,7 +603,7 @@ void MediaPlayer::paintCurrentFrameInContext(GraphicsContext* p, const IntRect&
m_private->paintCurrentFrameInContext(p, r);
}
-MediaPlayer::SupportsType MediaPlayer::supportsType(ContentType contentType)
+MediaPlayer::SupportsType MediaPlayer::supportsType(const ContentType& contentType)
{
String type = contentType.type().lower();
String typeCodecs = contentType.parameter(codecs());
@@ -569,7 +613,7 @@ MediaPlayer::SupportsType MediaPlayer::supportsType(ContentType contentType)
if (type == applicationOctetStream())
return IsNotSupported;
- MediaPlayerFactory* engine = chooseBestEngineForTypeAndCodecs(type, typeCodecs);
+ MediaPlayerFactory* engine = bestMediaEngineForTypeAndCodecs(type, typeCodecs);
if (!engine)
return IsNotSupported;
@@ -652,9 +696,25 @@ double MediaPlayer::maximumDurationToCacheMediaTime() const
return m_private->maximumDurationToCacheMediaTime();
}
+void MediaPlayer::reloadTimerFired(Timer<MediaPlayer>*)
+{
+ m_private->cancelLoad();
+ loadWithNextMediaEngine(m_currentMediaEngine);
+}
+
+
// Client callbacks.
void MediaPlayer::networkStateChanged()
{
+ // If more than one media engine is installed and this one failed before finding metadata,
+ // let the next engine try.
+ if (m_private->networkState() >= FormatError
+ && m_private->readyState() < HaveMetadata
+ && installedMediaEngines().size() > 1
+ && bestMediaEngineForTypeAndCodecs(m_contentMIMEType, m_contentTypeCodecs, m_currentMediaEngine)) {
+ m_reloadTimer.startOneShot(0);
+ return;
+ }
if (m_mediaPlayerClient)
m_mediaPlayerClient->mediaPlayerNetworkStateChanged(this);
}
diff --git a/WebCore/platform/graphics/MediaPlayer.h b/WebCore/platform/graphics/MediaPlayer.h
index a9499a5..6525ca6 100644
--- a/WebCore/platform/graphics/MediaPlayer.h
+++ b/WebCore/platform/graphics/MediaPlayer.h
@@ -91,6 +91,7 @@ class GraphicsContext;
class IntRect;
class IntSize;
class MediaPlayer;
+struct MediaPlayerFactory;
class TimeRanges;
class MediaPlayerClient {
@@ -136,6 +137,8 @@ public:
// the movie size has changed
virtual void mediaPlayerSizeChanged(MediaPlayer*) { }
+ virtual void mediaPlayerEngineUpdated(MediaPlayer*) { }
+
#if USE(ACCELERATED_COMPOSITING)
// whether the rendering system can accelerate the display of this MediaPlayer.
virtual bool mediaPlayerRenderingCanBeAccelerated(MediaPlayer*) { return false; }
@@ -157,7 +160,7 @@ public:
// media engine support
enum SupportsType { IsNotSupported, IsSupported, MayBeSupported };
- static MediaPlayer::SupportsType supportsType(ContentType contentType);
+ static MediaPlayer::SupportsType supportsType(const ContentType&);
static void getSupportedTypes(HashSet<String>&);
static bool isAvailable();
@@ -184,7 +187,7 @@ public:
IntSize size() const { return m_size; }
void setSize(const IntSize& size);
- void load(const String& url, const ContentType& contentType);
+ void load(const String& url, const ContentType&);
void cancelLoad();
bool visible() const;
@@ -285,12 +288,18 @@ public:
private:
MediaPlayer(MediaPlayerClient*);
+ void loadWithNextMediaEngine(MediaPlayerFactory*);
+ void reloadTimerFired(Timer<MediaPlayer>*);
static void initializeMediaEngines();
MediaPlayerClient* m_mediaPlayerClient;
+ Timer<MediaPlayer> m_reloadTimer;
OwnPtr<MediaPlayerPrivateInterface*> m_private;
- void* m_currentMediaEngine;
+ MediaPlayerFactory* m_currentMediaEngine;
+ String m_url;
+ String m_contentMIMEType;
+ String m_contentTypeCodecs;
FrameView* m_frameView;
IntSize m_size;
Preload m_preload;
diff --git a/WebCore/platform/graphics/Path.h b/WebCore/platform/graphics/Path.h
index ba25dc2..423a792 100644
--- a/WebCore/platform/graphics/Path.h
+++ b/WebCore/platform/graphics/Path.h
@@ -46,7 +46,7 @@ class wxGraphicsPath;
typedef wxGraphicsPath PlatformPath;
#elif PLATFORM(CAIRO)
namespace WebCore {
- struct CairoPath;
+class CairoPath;
}
typedef WebCore::CairoPath PlatformPath;
#elif PLATFORM(SKIA)
diff --git a/WebCore/platform/graphics/SimpleFontData.cpp b/WebCore/platform/graphics/SimpleFontData.cpp
index 391873a..e773880 100644
--- a/WebCore/platform/graphics/SimpleFontData.cpp
+++ b/WebCore/platform/graphics/SimpleFontData.cpp
@@ -57,8 +57,6 @@ SimpleFontData::SimpleFontData(const FontPlatformData& platformData, bool isCust
, m_isCustomFont(isCustomFont)
, m_isLoading(isLoading)
, m_isBrokenIdeographFont(false)
- , m_smallCapsFontData(0)
- , m_brokenIdeographFontData(0)
{
platformInit();
platformGlyphInit();
@@ -74,8 +72,6 @@ SimpleFontData::SimpleFontData(PassOwnPtr<SVGFontData> svgFontData, int size, bo
, m_isCustomFont(true)
, m_isLoading(false)
, m_isBrokenIdeographFont(false)
- , m_smallCapsFontData(0)
- , m_brokenIdeographFontData(0)
{
SVGFontFaceElement* svgFontFaceElement = m_svgFontData->svgFontFaceElement();
m_unitsPerEm = svgFontFaceElement->unitsPerEm();
@@ -186,16 +182,6 @@ SimpleFontData::~SimpleFontData()
if (!isCustomFont())
GlyphPageTreeNode::pruneTreeFontData(this);
- else {
- if (m_smallCapsFontData)
- GlyphPageTreeNode::pruneTreeCustomFontData(m_smallCapsFontData);
-
- if (m_brokenIdeographFontData)
- GlyphPageTreeNode::pruneTreeCustomFontData(m_brokenIdeographFontData);
- }
-
- delete m_smallCapsFontData;
- delete m_brokenIdeographFontData;
}
const SimpleFontData* SimpleFontData::fontDataForCharacter(UChar32) const
@@ -210,12 +196,14 @@ bool SimpleFontData::isSegmented() const
SimpleFontData* SimpleFontData::brokenIdeographFontData() const
{
- if (!m_brokenIdeographFontData) {
- m_brokenIdeographFontData = new SimpleFontData(m_platformData, isCustomFont(), false);
- m_brokenIdeographFontData->m_orientation = Vertical;
- m_brokenIdeographFontData->m_isBrokenIdeographFont = true;
+ if (!m_derivedFontData)
+ m_derivedFontData = DerivedFontData::create(isCustomFont());
+ if (!m_derivedFontData->brokenIdeograph) {
+ m_derivedFontData->brokenIdeograph = new SimpleFontData(m_platformData, isCustomFont(), false);
+ m_derivedFontData->brokenIdeograph->m_orientation = Vertical;
+ m_derivedFontData->brokenIdeograph->m_isBrokenIdeographFont = true;
}
- return m_brokenIdeographFontData;
+ return m_derivedFontData->brokenIdeograph.get();
}
#ifndef NDEBUG
@@ -230,4 +218,22 @@ String SimpleFontData::description() const
}
#endif
+PassOwnPtr<SimpleFontData::DerivedFontData> SimpleFontData::DerivedFontData::create(bool forCustomFont)
+{
+ return adoptPtr(new DerivedFontData(forCustomFont));
+}
+
+SimpleFontData::DerivedFontData::~DerivedFontData()
+{
+ if (!forCustomFont)
+ return;
+
+ if (smallCaps)
+ GlyphPageTreeNode::pruneTreeCustomFontData(smallCaps.get());
+ if (emphasisMark)
+ GlyphPageTreeNode::pruneTreeCustomFontData(emphasisMark.get());
+ if (brokenIdeograph)
+ GlyphPageTreeNode::pruneTreeCustomFontData(brokenIdeograph.get());
+}
+
} // namespace WebCore
diff --git a/WebCore/platform/graphics/SimpleFontData.h b/WebCore/platform/graphics/SimpleFontData.h
index ea053cd..90713af 100644
--- a/WebCore/platform/graphics/SimpleFontData.h
+++ b/WebCore/platform/graphics/SimpleFontData.h
@@ -65,6 +65,7 @@ class FontDescription;
class SharedBuffer;
class SVGFontData;
+enum FontDataVariant { AutoVariant, NormalVariant, SmallCapsVariant, EmphasisMarkVariant };
enum Pitch { UnknownPitch, FixedPitch, VariablePitch };
class SimpleFontData : public FontData {
@@ -76,7 +77,24 @@ public:
virtual ~SimpleFontData();
const FontPlatformData& platformData() const { return m_platformData; }
- SimpleFontData* smallCapsFontData(const FontDescription& fontDescription) const;
+
+ SimpleFontData* smallCapsFontData(const FontDescription&) const;
+ SimpleFontData* emphasisMarkFontData(const FontDescription&) const;
+
+ SimpleFontData* variantFontData(const FontDescription& description, FontDataVariant variant) const
+ {
+ switch (variant) {
+ case SmallCapsVariant:
+ return smallCapsFontData(description);
+ case EmphasisMarkVariant:
+ return emphasisMarkFontData(description);
+ case AutoVariant:
+ case NormalVariant:
+ break;
+ }
+ ASSERT_NOT_REACHED();
+ return const_cast<SimpleFontData*>(this);
+ }
SimpleFontData* brokenIdeographFontData() const;
@@ -183,6 +201,8 @@ private:
void commonInit();
+ SimpleFontData* scaledFontData(const FontDescription&, float scaleFactor) const;
+
#if (PLATFORM(WIN) && !OS(WINCE)) \
|| (OS(WINDOWS) && PLATFORM(WX))
void initGDIFont();
@@ -226,9 +246,23 @@ private:
GlyphData m_missingGlyphData;
- mutable SimpleFontData* m_smallCapsFontData;
+ struct DerivedFontData {
+ static PassOwnPtr<DerivedFontData> create(bool forCustomFont);
+ ~DerivedFontData();
+
+ bool forCustomFont;
+ OwnPtr<SimpleFontData> smallCaps;
+ OwnPtr<SimpleFontData> emphasisMark;
+ OwnPtr<SimpleFontData> brokenIdeograph;
+
+ private:
+ DerivedFontData(bool custom)
+ : forCustomFont(custom)
+ {
+ }
+ };
- mutable SimpleFontData* m_brokenIdeographFontData;
+ mutable OwnPtr<DerivedFontData> m_derivedFontData;
#if PLATFORM(CG) || PLATFORM(CAIRO) || PLATFORM(WX)
float m_syntheticBoldOffset;
diff --git a/WebCore/platform/graphics/TextRun.h b/WebCore/platform/graphics/TextRun.h
index 79b6cb3..dce5535 100644
--- a/WebCore/platform/graphics/TextRun.h
+++ b/WebCore/platform/graphics/TextRun.h
@@ -117,7 +117,10 @@ private:
const UChar* m_characters;
int m_len;
- int m_xpos;
+ // m_xpos is the x position relative to the left start of the text line, not relative to the left
+ // start of the containing block. In the case of right alignment or center alignment, left start of
+ // the text line is not the same as left start of the containing block.
+ int m_xpos;
int m_padding;
#if ENABLE(SVG)
float m_horizontalGlyphStretch;
diff --git a/WebCore/platform/graphics/WidthIterator.cpp b/WebCore/platform/graphics/WidthIterator.cpp
index ae58918..2a951e8 100644
--- a/WebCore/platform/graphics/WidthIterator.cpp
+++ b/WebCore/platform/graphics/WidthIterator.cpp
@@ -40,7 +40,7 @@ namespace WebCore {
// According to http://www.unicode.org/Public/UNIDATA/UCD.html#Canonical_Combining_Class_Values
static const uint8_t hiraganaKatakanaVoicingMarksCombiningClass = 8;
-WidthIterator::WidthIterator(const Font* font, const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, bool accountForGlyphBounds)
+WidthIterator::WidthIterator(const Font* font, const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, bool accountForGlyphBounds, bool forTextEmphasis)
: m_font(font)
, m_run(run)
, m_end(run.length())
@@ -53,6 +53,7 @@ WidthIterator::WidthIterator(const Font* font, const TextRun& run, HashSet<const
, m_minGlyphBoundingBoxY(numeric_limits<float>::max())
, m_firstGlyphOverflow(0)
, m_lastGlyphOverflow(0)
+ , m_forTextEmphasis(forTextEmphasis)
{
// If the padding is non-zero, count the number of spaces in the run
// and divide that by the padding for per space addition.
@@ -199,6 +200,9 @@ void WidthIterator::advance(int offset, GlyphBuffer* glyphBuffer)
m_firstGlyphOverflow = max<float>(0, -bounds.x());
}
+ if (m_forTextEmphasis && !Font::canReceiveTextEmphasis(c))
+ glyph = 0;
+
// Advance past the character we just dealt with.
cp += clusterLength;
currentCharacter += clusterLength;
diff --git a/WebCore/platform/graphics/WidthIterator.h b/WebCore/platform/graphics/WidthIterator.h
index d42a0c5..8b3c067 100644
--- a/WebCore/platform/graphics/WidthIterator.h
+++ b/WebCore/platform/graphics/WidthIterator.h
@@ -33,7 +33,7 @@ class SimpleFontData;
class TextRun;
struct WidthIterator {
- WidthIterator(const Font*, const TextRun&, HashSet<const SimpleFontData*>* fallbackFonts = 0, bool accountForGlyphBounds = false);
+ WidthIterator(const Font*, const TextRun&, HashSet<const SimpleFontData*>* fallbackFonts = 0, bool accountForGlyphBounds = false, bool forTextEmphasis = false);
void advance(int to, GlyphBuffer* = 0);
bool advanceOneCharacter(float& width, GlyphBuffer* = 0);
@@ -63,6 +63,7 @@ private:
float m_minGlyphBoundingBoxY;
float m_firstGlyphOverflow;
float m_lastGlyphOverflow;
+ bool m_forTextEmphasis;
};
}
diff --git a/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp b/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp
new file mode 100644
index 0000000..8bde9fd
--- /dev/null
+++ b/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp
@@ -0,0 +1,2300 @@
+/*
+ * Copyright (C) 2010 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 COMPUTER, 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"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "GraphicsLayerCA.h"
+
+#include "Animation.h"
+#include "FloatConversion.h"
+#include "FloatRect.h"
+#include "PlatformCALayer.h"
+#include "PlatformString.h"
+#include "RotateTransformOperation.h"
+#include "ScaleTransformOperation.h"
+#include "SystemTime.h"
+#include "TranslateTransformOperation.h"
+#include <QuartzCore/QuartzCore.h>
+#include <limits.h>
+#include <wtf/CurrentTime.h>
+#include <wtf/text/StringConcatenate.h>
+
+using namespace std;
+
+#define HAVE_MODERN_QUARTZCORE (!defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD))
+
+namespace WebCore {
+
+// The threshold width or height above which a tiled layer will be used. This should be
+// large enough to avoid tiled layers for most GraphicsLayers, but less than the OpenGL
+// texture size limit on all supported hardware.
+static const int cMaxPixelDimension = 2000;
+
+// If we send a duration of 0 to CA, then it will use the default duration
+// of 250ms. So send a very small value instead.
+static const float cAnimationAlmostZeroDuration = 1e-3f;
+
+// CACurrentMediaTime() is a time since boot. These methods convert between that and
+// WebCore time, which is system time (UTC).
+static CFTimeInterval currentTimeToMediaTime(double t)
+{
+ return CACurrentMediaTime() + t - WTF::currentTime();
+}
+
+static bool isTransformTypeTransformationMatrix(TransformOperation::OperationType transformType)
+{
+ switch (transformType) {
+ case TransformOperation::SKEW_X:
+ case TransformOperation::SKEW_Y:
+ case TransformOperation::SKEW:
+ case TransformOperation::MATRIX:
+ case TransformOperation::ROTATE_3D:
+ case TransformOperation::MATRIX_3D:
+ case TransformOperation::PERSPECTIVE:
+ case TransformOperation::IDENTITY:
+ case TransformOperation::NONE:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool isTransformTypeFloatPoint3D(TransformOperation::OperationType transformType)
+{
+ switch (transformType) {
+ case TransformOperation::SCALE:
+ case TransformOperation::SCALE_3D:
+ case TransformOperation::TRANSLATE:
+ case TransformOperation::TRANSLATE_3D:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool isTransformTypeNumber(TransformOperation::OperationType transformType)
+{
+ return !isTransformTypeTransformationMatrix(transformType) && !isTransformTypeFloatPoint3D(transformType);
+}
+
+static void getTransformFunctionValue(const TransformOperation* transformOp, TransformOperation::OperationType transformType, const IntSize& size, float& value)
+{
+ switch (transformType) {
+ case TransformOperation::ROTATE:
+ case TransformOperation::ROTATE_X:
+ case TransformOperation::ROTATE_Y:
+ value = transformOp ? narrowPrecisionToFloat(deg2rad(static_cast<const RotateTransformOperation*>(transformOp)->angle())) : 0;
+ break;
+ case TransformOperation::SCALE_X:
+ value = transformOp ? narrowPrecisionToFloat(static_cast<const ScaleTransformOperation*>(transformOp)->x()) : 1;
+ break;
+ case TransformOperation::SCALE_Y:
+ value = transformOp ? narrowPrecisionToFloat(static_cast<const ScaleTransformOperation*>(transformOp)->y()) : 1;
+ break;
+ case TransformOperation::SCALE_Z:
+ value = transformOp ? narrowPrecisionToFloat(static_cast<const ScaleTransformOperation*>(transformOp)->z()) : 1;
+ break;
+ case TransformOperation::TRANSLATE_X:
+ value = transformOp ? narrowPrecisionToFloat(static_cast<const TranslateTransformOperation*>(transformOp)->x(size)) : 0;
+ break;
+ case TransformOperation::TRANSLATE_Y:
+ value = transformOp ? narrowPrecisionToFloat(static_cast<const TranslateTransformOperation*>(transformOp)->y(size)) : 0;
+ break;
+ case TransformOperation::TRANSLATE_Z:
+ value = transformOp ? narrowPrecisionToFloat(static_cast<const TranslateTransformOperation*>(transformOp)->z(size)) : 0;
+ break;
+ default:
+ break;
+ }
+}
+
+static void getTransformFunctionValue(const TransformOperation* transformOp, TransformOperation::OperationType transformType, const IntSize& size, FloatPoint3D& value)
+{
+ switch (transformType) {
+ case TransformOperation::SCALE:
+ case TransformOperation::SCALE_3D:
+ value.setX(transformOp ? narrowPrecisionToFloat(static_cast<const ScaleTransformOperation*>(transformOp)->x()) : 1);
+ value.setY(transformOp ? narrowPrecisionToFloat(static_cast<const ScaleTransformOperation*>(transformOp)->y()) : 1);
+ value.setZ(transformOp ? narrowPrecisionToFloat(static_cast<const ScaleTransformOperation*>(transformOp)->z()) : 1);
+ break;
+ case TransformOperation::TRANSLATE:
+ case TransformOperation::TRANSLATE_3D:
+ value.setX(transformOp ? narrowPrecisionToFloat(static_cast<const TranslateTransformOperation*>(transformOp)->x(size)) : 0);
+ value.setY(transformOp ? narrowPrecisionToFloat(static_cast<const TranslateTransformOperation*>(transformOp)->y(size)) : 0);
+ value.setZ(transformOp ? narrowPrecisionToFloat(static_cast<const TranslateTransformOperation*>(transformOp)->z(size)) : 0);
+ break;
+ default:
+ break;
+ }
+}
+
+static void getTransformFunctionValue(const TransformOperation* transformOp, TransformOperation::OperationType transformType, const IntSize& size, TransformationMatrix& value)
+{
+ switch (transformType) {
+ case TransformOperation::SKEW_X:
+ case TransformOperation::SKEW_Y:
+ case TransformOperation::SKEW:
+ case TransformOperation::MATRIX:
+ case TransformOperation::ROTATE_3D:
+ case TransformOperation::MATRIX_3D:
+ case TransformOperation::PERSPECTIVE:
+ case TransformOperation::IDENTITY:
+ case TransformOperation::NONE:
+ if (transformOp)
+ transformOp->apply(value, size);
+ else
+ value.makeIdentity();
+ break;
+ default:
+ break;
+ }
+}
+
+#if HAVE_MODERN_QUARTZCORE
+static PlatformCAAnimation::ValueFunctionType getValueFunctionNameForTransformOperation(TransformOperation::OperationType transformType)
+{
+ // Use literal strings to avoid link-time dependency on those symbols.
+ switch (transformType) {
+ case TransformOperation::ROTATE_X:
+ return PlatformCAAnimation::RotateX;
+ case TransformOperation::ROTATE_Y:
+ return PlatformCAAnimation::RotateY;
+ case TransformOperation::ROTATE:
+ return PlatformCAAnimation::RotateZ;
+ case TransformOperation::SCALE_X:
+ return PlatformCAAnimation::ScaleX;
+ case TransformOperation::SCALE_Y:
+ return PlatformCAAnimation::ScaleY;
+ case TransformOperation::SCALE_Z:
+ return PlatformCAAnimation::ScaleZ;
+ case TransformOperation::TRANSLATE_X:
+ return PlatformCAAnimation::TranslateX;
+ case TransformOperation::TRANSLATE_Y:
+ return PlatformCAAnimation::TranslateY;
+ case TransformOperation::TRANSLATE_Z:
+ return PlatformCAAnimation::TranslateZ;
+ case TransformOperation::SCALE:
+ case TransformOperation::SCALE_3D:
+ return PlatformCAAnimation::Scale;
+ case TransformOperation::TRANSLATE:
+ case TransformOperation::TRANSLATE_3D:
+ return PlatformCAAnimation::Translate;
+ default:
+ return PlatformCAAnimation::NoValueFunction;
+ }
+}
+#endif
+
+static String propertyIdToString(AnimatedPropertyID property)
+{
+ switch (property) {
+ case AnimatedPropertyWebkitTransform:
+ return "transform";
+ case AnimatedPropertyOpacity:
+ return "opacity";
+ case AnimatedPropertyBackgroundColor:
+ return "backgroundColor";
+ case AnimatedPropertyInvalid:
+ ASSERT_NOT_REACHED();
+ }
+ ASSERT_NOT_REACHED();
+ return "";
+}
+
+static String animationIdentifier(const String& animationName, AnimatedPropertyID property, int index)
+{
+ return makeString(animationName, '_', String::number(property), '_', String::number(index));
+}
+
+static bool animationHasStepsTimingFunction(const KeyframeValueList& valueList, const Animation* anim)
+{
+ if (anim->timingFunction()->isStepsTimingFunction())
+ return true;
+
+ for (unsigned i = 0; i < valueList.size(); ++i) {
+ const TimingFunction* timingFunction = valueList.at(i)->timingFunction();
+ if (timingFunction && timingFunction->isStepsTimingFunction())
+ return true;
+ }
+
+ return false;
+}
+
+PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client)
+{
+ return new GraphicsLayerCA(client);
+}
+
+GraphicsLayerCA::GraphicsLayerCA(GraphicsLayerClient* client)
+ : GraphicsLayer(client)
+ , m_contentsLayerPurpose(NoContentsLayer)
+ , m_contentsLayerHasBackgroundColor(false)
+ , m_uncommittedChanges(NoChange)
+{
+ m_layer = PlatformCALayer::create(PlatformCALayer::LayerTypeWebLayer, this);
+
+#if !HAVE_MODERN_QUARTZCORE
+ setContentsOrientation(defaultContentsOrientation());
+#endif
+
+ updateDebugIndicators();
+}
+
+GraphicsLayerCA::~GraphicsLayerCA()
+{
+ // We release our references to the PlatformCALayers here, but do not actively unparent them,
+ // since that will cause a commit and break our batched commit model. The layers will
+ // get released when the rootmost modified GraphicsLayerCA rebuilds its child layers.
+
+ // Clean up the layer.
+ if (m_layer)
+ m_layer->setOwner(0);
+
+ if (m_contentsLayer)
+ m_contentsLayer->setOwner(0);
+
+ if (m_structuralLayer)
+ m_structuralLayer->setOwner(0);
+
+ removeCloneLayers();
+}
+
+void GraphicsLayerCA::setName(const String& name)
+{
+ String longName = String::format("CALayer(%p) GraphicsLayer(%p) ", m_layer.get(), this) + name;
+ GraphicsLayer::setName(longName);
+ noteLayerPropertyChanged(NameChanged);
+}
+
+PlatformLayer* GraphicsLayerCA::platformLayer() const
+{
+ return primaryLayer()->platformLayer();
+}
+
+bool GraphicsLayerCA::setChildren(const Vector<GraphicsLayer*>& children)
+{
+ bool childrenChanged = GraphicsLayer::setChildren(children);
+ if (childrenChanged)
+ noteSublayersChanged();
+
+ return childrenChanged;
+}
+
+void GraphicsLayerCA::addChild(GraphicsLayer* childLayer)
+{
+ GraphicsLayer::addChild(childLayer);
+ noteSublayersChanged();
+}
+
+void GraphicsLayerCA::addChildAtIndex(GraphicsLayer* childLayer, int index)
+{
+ GraphicsLayer::addChildAtIndex(childLayer, index);
+ noteSublayersChanged();
+}
+
+void GraphicsLayerCA::addChildBelow(GraphicsLayer* childLayer, GraphicsLayer* sibling)
+{
+ GraphicsLayer::addChildBelow(childLayer, sibling);
+ noteSublayersChanged();
+}
+
+void GraphicsLayerCA::addChildAbove(GraphicsLayer* childLayer, GraphicsLayer* sibling)
+{
+ GraphicsLayer::addChildAbove(childLayer, sibling);
+ noteSublayersChanged();
+}
+
+bool GraphicsLayerCA::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild)
+{
+ if (GraphicsLayer::replaceChild(oldChild, newChild)) {
+ noteSublayersChanged();
+ return true;
+ }
+ return false;
+}
+
+void GraphicsLayerCA::removeFromParent()
+{
+ if (m_parent)
+ static_cast<GraphicsLayerCA*>(m_parent)->noteSublayersChanged();
+ GraphicsLayer::removeFromParent();
+}
+
+void GraphicsLayerCA::setMaskLayer(GraphicsLayer* layer)
+{
+ if (layer == m_maskLayer)
+ return;
+
+ GraphicsLayer::setMaskLayer(layer);
+ noteLayerPropertyChanged(MaskLayerChanged);
+
+ propagateLayerChangeToReplicas();
+
+ if (m_replicatedLayer)
+ static_cast<GraphicsLayerCA*>(m_replicatedLayer)->propagateLayerChangeToReplicas();
+}
+
+void GraphicsLayerCA::setReplicatedLayer(GraphicsLayer* layer)
+{
+ if (layer == m_replicatedLayer)
+ return;
+
+ GraphicsLayer::setReplicatedLayer(layer);
+ noteLayerPropertyChanged(ReplicatedLayerChanged);
+}
+
+void GraphicsLayerCA::setReplicatedByLayer(GraphicsLayer* layer)
+{
+ if (layer == m_replicaLayer)
+ return;
+
+ GraphicsLayer::setReplicatedByLayer(layer);
+ noteSublayersChanged();
+ noteLayerPropertyChanged(ReplicatedLayerChanged);
+}
+
+void GraphicsLayerCA::setPosition(const FloatPoint& point)
+{
+ if (point == m_position)
+ return;
+
+ GraphicsLayer::setPosition(point);
+ noteLayerPropertyChanged(PositionChanged);
+}
+
+void GraphicsLayerCA::setAnchorPoint(const FloatPoint3D& point)
+{
+ if (point == m_anchorPoint)
+ return;
+
+ GraphicsLayer::setAnchorPoint(point);
+ noteLayerPropertyChanged(AnchorPointChanged);
+}
+
+void GraphicsLayerCA::setSize(const FloatSize& size)
+{
+ if (size == m_size)
+ return;
+
+ GraphicsLayer::setSize(size);
+ noteLayerPropertyChanged(SizeChanged);
+}
+
+void GraphicsLayerCA::setTransform(const TransformationMatrix& t)
+{
+ if (t == m_transform)
+ return;
+
+ GraphicsLayer::setTransform(t);
+ noteLayerPropertyChanged(TransformChanged);
+}
+
+void GraphicsLayerCA::setChildrenTransform(const TransformationMatrix& t)
+{
+ if (t == m_childrenTransform)
+ return;
+
+ GraphicsLayer::setChildrenTransform(t);
+ noteLayerPropertyChanged(ChildrenTransformChanged);
+}
+
+void GraphicsLayerCA::moveOrCopyLayerAnimation(MoveOrCopy operation, const String& animationIdentifier, PlatformCALayer *fromLayer, PlatformCALayer *toLayer)
+{
+ RefPtr<PlatformCAAnimation> anim = fromLayer->animationForKey(animationIdentifier);
+ if (!anim)
+ return;
+
+ switch (operation) {
+ case Move:
+ fromLayer->removeAnimationForKey(animationIdentifier);
+ toLayer->addAnimationForKey(animationIdentifier, anim.get());
+ break;
+
+ case Copy:
+ toLayer->addAnimationForKey(animationIdentifier, anim.get());
+ break;
+ }
+}
+
+void GraphicsLayerCA::moveOrCopyAnimationsForProperty(MoveOrCopy operation, AnimatedPropertyID property, PlatformCALayer *fromLayer, PlatformCALayer *toLayer)
+{
+ // Look for running animations affecting this property.
+ AnimationsMap::const_iterator end = m_runningAnimations.end();
+ for (AnimationsMap::const_iterator it = m_runningAnimations.begin(); it != end; ++it) {
+ const Vector<LayerPropertyAnimation>& propertyAnimations = it->second;
+ size_t numAnimations = propertyAnimations.size();
+ for (size_t i = 0; i < numAnimations; ++i) {
+ const LayerPropertyAnimation& currAnimation = propertyAnimations[i];
+ if (currAnimation.m_property == property)
+ moveOrCopyLayerAnimation(operation, animationIdentifier(currAnimation.m_name, currAnimation.m_property, currAnimation.m_index), fromLayer, toLayer);
+ }
+ }
+}
+
+void GraphicsLayerCA::setPreserves3D(bool preserves3D)
+{
+ if (preserves3D == m_preserves3D)
+ return;
+
+ GraphicsLayer::setPreserves3D(preserves3D);
+ noteLayerPropertyChanged(Preserves3DChanged);
+}
+
+void GraphicsLayerCA::setMasksToBounds(bool masksToBounds)
+{
+ if (masksToBounds == m_masksToBounds)
+ return;
+
+ GraphicsLayer::setMasksToBounds(masksToBounds);
+ noteLayerPropertyChanged(MasksToBoundsChanged);
+}
+
+void GraphicsLayerCA::setDrawsContent(bool drawsContent)
+{
+ if (drawsContent == m_drawsContent)
+ return;
+
+ GraphicsLayer::setDrawsContent(drawsContent);
+ noteLayerPropertyChanged(DrawsContentChanged);
+}
+
+void GraphicsLayerCA::setAcceleratesDrawing(bool acceleratesDrawing)
+{
+ if (acceleratesDrawing == m_acceleratesDrawing)
+ return;
+
+ GraphicsLayer::setAcceleratesDrawing(acceleratesDrawing);
+ noteLayerPropertyChanged(DrawsContentChanged);
+}
+
+void GraphicsLayerCA::setBackgroundColor(const Color& color)
+{
+ if (m_backgroundColorSet && m_backgroundColor == color)
+ return;
+
+ GraphicsLayer::setBackgroundColor(color);
+
+ m_contentsLayerHasBackgroundColor = true;
+ noteLayerPropertyChanged(BackgroundColorChanged);
+}
+
+void GraphicsLayerCA::clearBackgroundColor()
+{
+ if (!m_backgroundColorSet)
+ return;
+
+ GraphicsLayer::clearBackgroundColor();
+ m_contentsLayerHasBackgroundColor = false;
+ noteLayerPropertyChanged(BackgroundColorChanged);
+}
+
+void GraphicsLayerCA::setContentsOpaque(bool opaque)
+{
+ if (m_contentsOpaque == opaque)
+ return;
+
+ GraphicsLayer::setContentsOpaque(opaque);
+ noteLayerPropertyChanged(ContentsOpaqueChanged);
+}
+
+void GraphicsLayerCA::setBackfaceVisibility(bool visible)
+{
+ if (m_backfaceVisibility == visible)
+ return;
+
+ GraphicsLayer::setBackfaceVisibility(visible);
+ noteLayerPropertyChanged(BackfaceVisibilityChanged);
+}
+
+void GraphicsLayerCA::setOpacity(float opacity)
+{
+ float clampedOpacity = max(0.0f, min(opacity, 1.0f));
+
+ if (clampedOpacity == m_opacity)
+ return;
+
+ GraphicsLayer::setOpacity(clampedOpacity);
+ noteLayerPropertyChanged(OpacityChanged);
+}
+
+void GraphicsLayerCA::setNeedsDisplay()
+{
+ FloatRect hugeRect(-numeric_limits<float>::max() / 2, -numeric_limits<float>::max() / 2,
+ numeric_limits<float>::max(), numeric_limits<float>::max());
+
+ setNeedsDisplayInRect(hugeRect);
+}
+
+void GraphicsLayerCA::setNeedsDisplayInRect(const FloatRect& rect)
+{
+ if (!drawsContent())
+ return;
+
+ const size_t maxDirtyRects = 32;
+
+ for (size_t i = 0; i < m_dirtyRects.size(); ++i) {
+ if (m_dirtyRects[i].contains(rect))
+ return;
+ }
+
+ if (m_dirtyRects.size() < maxDirtyRects)
+ m_dirtyRects.append(rect);
+ else
+ m_dirtyRects[0].unite(rect);
+
+ noteLayerPropertyChanged(DirtyRectsChanged);
+}
+
+void GraphicsLayerCA::setContentsNeedsDisplay()
+{
+ noteLayerPropertyChanged(ContentsNeedsDisplay);
+}
+
+void GraphicsLayerCA::setContentsRect(const IntRect& rect)
+{
+ if (rect == m_contentsRect)
+ return;
+
+ GraphicsLayer::setContentsRect(rect);
+ noteLayerPropertyChanged(ContentsRectChanged);
+}
+
+bool GraphicsLayerCA::addAnimation(const KeyframeValueList& valueList, const IntSize& boxSize, const Animation* anim, const String& animationName, double timeOffset)
+{
+ ASSERT(!animationName.isEmpty());
+
+ if (!anim || anim->isEmptyOrZeroDuration() || valueList.size() < 2)
+ return false;
+
+#if !HAVE_MODERN_QUARTZCORE
+ // Older versions of QuartzCore do not handle opacity in transform layers properly, so we will
+ // always do software animation in that case.
+ if (valueList.property() == AnimatedPropertyOpacity)
+ return false;
+#endif
+
+ // CoreAnimation does not handle the steps() timing function. Fall back
+ // to software animation in that case.
+ if (animationHasStepsTimingFunction(valueList, anim))
+ return false;
+
+ bool createdAnimations = false;
+ if (valueList.property() == AnimatedPropertyWebkitTransform)
+ createdAnimations = createTransformAnimationsFromKeyframes(valueList, anim, animationName, timeOffset, boxSize);
+ else
+ createdAnimations = createAnimationFromKeyframes(valueList, anim, animationName, timeOffset);
+
+ if (createdAnimations)
+ noteLayerPropertyChanged(AnimationChanged);
+
+ return createdAnimations;
+}
+
+void GraphicsLayerCA::pauseAnimation(const String& animationName, double timeOffset)
+{
+ if (!animationIsRunning(animationName))
+ return;
+
+ AnimationsToProcessMap::iterator it = m_animationsToProcess.find(animationName);
+ if (it != m_animationsToProcess.end()) {
+ AnimationProcessingAction& processingInfo = it->second;
+ // If an animation is scheduled to be removed, don't change the remove to a pause.
+ if (processingInfo.action != Remove)
+ processingInfo.action = Pause;
+ } else
+ m_animationsToProcess.add(animationName, AnimationProcessingAction(Pause, timeOffset));
+
+ noteLayerPropertyChanged(AnimationChanged);
+}
+
+void GraphicsLayerCA::removeAnimation(const String& animationName)
+{
+ if (!animationIsRunning(animationName))
+ return;
+
+ m_animationsToProcess.add(animationName, AnimationProcessingAction(Remove));
+ noteLayerPropertyChanged(AnimationChanged);
+}
+
+void GraphicsLayerCA::animationStarted(CFTimeInterval startTime)
+{
+ if (m_client)
+ m_client->notifyAnimationStarted(this, startTime);
+}
+
+void GraphicsLayerCA::setContentsToImage(Image* image)
+{
+ if (image) {
+ CGImageRef newImage = image->nativeImageForCurrentFrame();
+ if (!newImage)
+ return;
+
+ // Check to see if the image changed; we have to do this because the call to
+ // CGImageCreateCopyWithColorSpace() below can create a new image every time.
+ if (m_uncorrectedContentsImage && m_uncorrectedContentsImage.get() == newImage)
+ return;
+
+ m_uncorrectedContentsImage = newImage;
+ m_pendingContentsImage = newImage;
+ CGColorSpaceRef colorSpace = CGImageGetColorSpace(m_pendingContentsImage.get());
+
+ static CGColorSpaceRef deviceRGB = CGColorSpaceCreateDeviceRGB();
+ if (colorSpace && CFEqual(colorSpace, deviceRGB)) {
+ // CoreGraphics renders images tagged with DeviceRGB using the color space of the main display. When we hand such
+ // images to CA we need to tag them similarly so CA rendering matches CG rendering.
+ static CGColorSpaceRef genericRGB = CGDisplayCopyColorSpace(kCGDirectMainDisplay);
+ m_pendingContentsImage.adoptCF(CGImageCreateCopyWithColorSpace(m_pendingContentsImage.get(), genericRGB));
+ }
+ m_contentsLayerPurpose = ContentsLayerForImage;
+ if (!m_contentsLayer)
+ noteSublayersChanged();
+ } else {
+ m_uncorrectedContentsImage = 0;
+ m_pendingContentsImage = 0;
+ m_contentsLayerPurpose = NoContentsLayer;
+ if (m_contentsLayer)
+ noteSublayersChanged();
+ }
+
+ noteLayerPropertyChanged(ContentsImageChanged);
+}
+
+void GraphicsLayerCA::setContentsToMedia(PlatformLayer* mediaLayer)
+{
+ if (m_contentsLayer && mediaLayer == m_contentsLayer->platformLayer())
+ return;
+
+ // Create the PlatformCALayer to wrap the incoming layer
+ m_contentsLayer = mediaLayer ? PlatformCALayer::create(mediaLayer, this) : 0;
+
+ m_contentsLayerPurpose = mediaLayer ? ContentsLayerForMedia : NoContentsLayer;
+
+ noteSublayersChanged();
+ noteLayerPropertyChanged(ContentsMediaLayerChanged);
+}
+
+void GraphicsLayerCA::setContentsToCanvas(PlatformLayer* canvasLayer)
+{
+ if (m_contentsLayer && canvasLayer == m_contentsLayer->platformLayer())
+ return;
+
+ // Create the PlatformCALayer to wrap the incoming layer
+ m_contentsLayer = canvasLayer ? PlatformCALayer::create(canvasLayer, this) : 0;
+
+ m_contentsLayerPurpose = canvasLayer ? ContentsLayerForCanvas : NoContentsLayer;
+
+ noteSublayersChanged();
+ noteLayerPropertyChanged(ContentsCanvasLayerChanged);
+}
+
+void GraphicsLayerCA::didDisplay(PlatformLayer* layer)
+{
+ PlatformCALayer* currentLayer = PlatformCALayer::platformCALayer(layer);
+ PlatformCALayer* sourceLayer;
+ LayerMap* layerCloneMap;
+
+ if (currentLayer == m_layer) {
+ sourceLayer = m_layer.get();
+ layerCloneMap = m_layerClones.get();
+ } else if (currentLayer == m_contentsLayer) {
+ sourceLayer = m_contentsLayer.get();
+ layerCloneMap = m_contentsLayerClones.get();
+ } else
+ return;
+
+ if (layerCloneMap) {
+ LayerMap::const_iterator end = layerCloneMap->end();
+ for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
+ PlatformCALayer* currClone = it->second.get();
+ if (!currClone)
+ continue;
+
+ if (currClone->contents() != sourceLayer->contents())
+ currClone->setContents(sourceLayer->contents());
+ else
+ currClone->setContentsChanged();
+ }
+ }
+}
+
+void GraphicsLayerCA::syncCompositingState()
+{
+ recursiveCommitChanges();
+}
+
+void GraphicsLayerCA::syncCompositingStateForThisLayerOnly()
+{
+ commitLayerChangesBeforeSublayers();
+ commitLayerChangesAfterSublayers();
+}
+
+void GraphicsLayerCA::recursiveCommitChanges()
+{
+ commitLayerChangesBeforeSublayers();
+
+ if (m_maskLayer)
+ static_cast<GraphicsLayerCA*>(m_maskLayer)->commitLayerChangesBeforeSublayers();
+
+ const Vector<GraphicsLayer*>& childLayers = children();
+ size_t numChildren = childLayers.size();
+ for (size_t i = 0; i < numChildren; ++i) {
+ GraphicsLayerCA* curChild = static_cast<GraphicsLayerCA*>(childLayers[i]);
+ curChild->recursiveCommitChanges();
+ }
+
+ if (m_replicaLayer)
+ static_cast<GraphicsLayerCA*>(m_replicaLayer)->recursiveCommitChanges();
+
+ if (m_maskLayer)
+ static_cast<GraphicsLayerCA*>(m_maskLayer)->commitLayerChangesAfterSublayers();
+
+ commitLayerChangesAfterSublayers();
+}
+
+void GraphicsLayerCA::commitLayerChangesBeforeSublayers()
+{
+ if (!m_uncommittedChanges)
+ return;
+
+ // Need to handle Preserves3DChanged first, because it affects which layers subsequent properties are applied to
+ if (m_uncommittedChanges & (Preserves3DChanged | ReplicatedLayerChanged))
+ updateStructuralLayer();
+
+ if (m_uncommittedChanges & NameChanged)
+ updateLayerNames();
+
+ if (m_uncommittedChanges & ContentsImageChanged) // Needs to happen before ChildrenChanged
+ updateContentsImage();
+
+ if (m_uncommittedChanges & ContentsMediaLayerChanged) // Needs to happen before ChildrenChanged
+ updateContentsMediaLayer();
+
+ if (m_uncommittedChanges & ContentsCanvasLayerChanged) // Needs to happen before ChildrenChanged
+ updateContentsCanvasLayer();
+
+ if (m_uncommittedChanges & BackgroundColorChanged) // Needs to happen before ChildrenChanged, and after updating image or video
+ updateLayerBackgroundColor();
+
+ if (m_uncommittedChanges & ChildrenChanged)
+ updateSublayerList();
+
+ if (m_uncommittedChanges & PositionChanged)
+ updateLayerPosition();
+
+ if (m_uncommittedChanges & AnchorPointChanged)
+ updateAnchorPoint();
+
+ if (m_uncommittedChanges & SizeChanged)
+ updateLayerSize();
+
+ if (m_uncommittedChanges & TransformChanged)
+ updateTransform();
+
+ if (m_uncommittedChanges & ChildrenTransformChanged)
+ updateChildrenTransform();
+
+ if (m_uncommittedChanges & MasksToBoundsChanged)
+ updateMasksToBounds();
+
+ if (m_uncommittedChanges & DrawsContentChanged)
+ updateLayerDrawsContent();
+
+ if (m_uncommittedChanges & ContentsOpaqueChanged)
+ updateContentsOpaque();
+
+ if (m_uncommittedChanges & BackfaceVisibilityChanged)
+ updateBackfaceVisibility();
+
+ if (m_uncommittedChanges & OpacityChanged)
+ updateOpacityOnLayer();
+
+ if (m_uncommittedChanges & AnimationChanged)
+ updateLayerAnimations();
+
+ if (m_uncommittedChanges & DirtyRectsChanged)
+ repaintLayerDirtyRects();
+
+ if (m_uncommittedChanges & ContentsRectChanged)
+ updateContentsRect();
+
+ if (m_uncommittedChanges & MaskLayerChanged)
+ updateMaskLayer();
+
+ if (m_uncommittedChanges & ContentsNeedsDisplay)
+ updateContentsNeedsDisplay();
+
+ if (m_uncommittedChanges & AcceleratesDrawingChanged)
+ updateAcceleratesDrawing();
+}
+
+void GraphicsLayerCA::commitLayerChangesAfterSublayers()
+{
+ if (!m_uncommittedChanges)
+ return;
+
+ if (m_uncommittedChanges & ReplicatedLayerChanged)
+ updateReplicatedLayers();
+
+ m_uncommittedChanges = NoChange;
+}
+
+void GraphicsLayerCA::updateLayerNames()
+{
+ switch (structuralLayerPurpose()) {
+ case StructuralLayerForPreserves3D:
+ m_structuralLayer->setName("Transform layer " + name());
+ break;
+ case StructuralLayerForReplicaFlattening:
+ m_structuralLayer->setName("Replica flattening layer " + name());
+ break;
+ case NoStructuralLayer:
+ break;
+ }
+ m_layer->setName(name());
+}
+
+void GraphicsLayerCA::updateSublayerList()
+{
+ PlatformCALayerList newSublayers;
+ const Vector<GraphicsLayer*>& childLayers = children();
+
+ if (m_structuralLayer || m_contentsLayer || childLayers.size() > 0) {
+ if (m_structuralLayer) {
+ // Add the replica layer first.
+ if (m_replicaLayer)
+ newSublayers.append(static_cast<GraphicsLayerCA*>(m_replicaLayer)->primaryLayer());
+ // Add the primary layer. Even if we have negative z-order children, the primary layer always comes behind.
+ newSublayers.append(m_layer);
+ } else if (m_contentsLayer) {
+ // FIXME: add the contents layer in the correct order with negative z-order children.
+ // This does not cause visible rendering issues because currently contents layers are only used
+ // for replaced elements that don't have children.
+ newSublayers.append(m_contentsLayer);
+ }
+
+ size_t numChildren = childLayers.size();
+ for (size_t i = 0; i < numChildren; ++i) {
+ GraphicsLayerCA* curChild = static_cast<GraphicsLayerCA*>(childLayers[i]);
+ PlatformCALayer* childLayer = curChild->layerForSuperlayer();
+ newSublayers.append(childLayer);
+ }
+
+ for (size_t i = 0; i < newSublayers.size(); ++i)
+ newSublayers[i]->removeFromSuperlayer();
+ }
+
+ if (m_structuralLayer) {
+ m_structuralLayer->setSublayers(newSublayers);
+
+ if (m_contentsLayer) {
+ // If we have a transform layer, then the contents layer is parented in the
+ // primary layer (which is itself a child of the transform layer).
+ m_layer->removeAllSublayers();
+ m_layer->appendSublayer(m_contentsLayer.get());
+ }
+ } else
+ m_layer->setSublayers(newSublayers);
+}
+
+void GraphicsLayerCA::updateLayerPosition()
+{
+ FloatSize usedSize = m_usingTiledLayer ? constrainedSize() : m_size;
+
+ // Position is offset on the layer by the layer anchor point.
+ FloatPoint posPoint(m_position.x() + m_anchorPoint.x() * usedSize.width(),
+ m_position.y() + m_anchorPoint.y() * usedSize.height());
+
+ primaryLayer()->setPosition(posPoint);
+
+ if (LayerMap* layerCloneMap = primaryLayerClones()) {
+ LayerMap::const_iterator end = layerCloneMap->end();
+ for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
+ FloatPoint clonePosition = posPoint;
+ if (m_replicaLayer && isReplicatedRootClone(it->first)) {
+ // Maintain the special-case position for the root of a clone subtree,
+ // which we set up in replicatedLayerRoot().
+ clonePosition = positionForCloneRootLayer();
+ }
+ it->second->setPosition(clonePosition);
+ }
+ }
+}
+
+void GraphicsLayerCA::updateLayerSize()
+{
+ FloatRect rect(0, 0, m_size.width(), m_size.height());
+ if (m_structuralLayer) {
+ m_structuralLayer->setBounds(rect);
+
+ if (LayerMap* layerCloneMap = m_structuralLayerClones.get()) {
+ LayerMap::const_iterator end = layerCloneMap->end();
+ for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it)
+ it->second->setBounds(rect);
+ }
+
+ // The anchor of the contents layer is always at 0.5, 0.5, so the position is center-relative.
+ CGPoint centerPoint = CGPointMake(m_size.width() / 2.0f, m_size.height() / 2.0f);
+ m_layer->setPosition(centerPoint);
+
+ if (LayerMap* layerCloneMap = m_layerClones.get()) {
+ LayerMap::const_iterator end = layerCloneMap->end();
+ for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it)
+ it->second->setPosition(centerPoint);
+ }
+ }
+
+ bool needTiledLayer = requiresTiledLayer(m_size);
+ if (needTiledLayer != m_usingTiledLayer)
+ swapFromOrToTiledLayer(needTiledLayer);
+
+ if (m_usingTiledLayer) {
+ FloatSize sizeToUse = constrainedSize();
+ rect = CGRectMake(0, 0, sizeToUse.width(), sizeToUse.height());
+ }
+
+ m_layer->setBounds(rect);
+ if (LayerMap* layerCloneMap = m_layerClones.get()) {
+ LayerMap::const_iterator end = layerCloneMap->end();
+ for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it)
+ it->second->setBounds(rect);
+ }
+
+ // Contents transform may depend on height.
+ updateContentsTransform();
+
+ // Note that we don't resize m_contentsLayer. It's up the caller to do that.
+
+ // if we've changed the bounds, we need to recalculate the position
+ // of the layer, taking anchor point into account.
+ updateLayerPosition();
+}
+
+void GraphicsLayerCA::updateAnchorPoint()
+{
+ primaryLayer()->setAnchorPoint(m_anchorPoint);
+
+ if (LayerMap* layerCloneMap = primaryLayerClones()) {
+ LayerMap::const_iterator end = layerCloneMap->end();
+ for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
+ PlatformCALayer* currLayer = it->second.get();
+ currLayer->setAnchorPoint(m_anchorPoint);
+ }
+ }
+
+ updateLayerPosition();
+}
+
+void GraphicsLayerCA::updateTransform()
+{
+ primaryLayer()->setTransform(m_transform);
+
+ if (LayerMap* layerCloneMap = primaryLayerClones()) {
+ LayerMap::const_iterator end = layerCloneMap->end();
+ for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
+ PlatformCALayer* currLayer = it->second.get();
+ if (m_replicaLayer && isReplicatedRootClone(it->first)) {
+ // Maintain the special-case transform for the root of a clone subtree,
+ // which we set up in replicatedLayerRoot().
+ currLayer->setTransform(TransformationMatrix());
+ } else
+ currLayer->setTransform(m_transform);
+ }
+ }
+}
+
+void GraphicsLayerCA::updateChildrenTransform()
+{
+ primaryLayer()->setSublayerTransform(m_childrenTransform);
+
+ if (LayerMap* layerCloneMap = primaryLayerClones()) {
+ LayerMap::const_iterator end = layerCloneMap->end();
+ for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it)
+ it->second->setSublayerTransform(m_childrenTransform);
+ }
+}
+
+void GraphicsLayerCA::updateMasksToBounds()
+{
+ m_layer->setMasksToBounds(m_masksToBounds);
+
+ if (LayerMap* layerCloneMap = m_layerClones.get()) {
+ LayerMap::const_iterator end = layerCloneMap->end();
+ for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it)
+ it->second->setMasksToBounds(m_masksToBounds);
+ }
+
+ updateDebugIndicators();
+}
+
+void GraphicsLayerCA::updateContentsOpaque()
+{
+ m_layer.get()->setOpaque(m_contentsOpaque);
+
+ if (LayerMap* layerCloneMap = m_layerClones.get()) {
+ LayerMap::const_iterator end = layerCloneMap->end();
+ for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it)
+ it->second->setOpaque(m_contentsOpaque);
+ }
+}
+
+void GraphicsLayerCA::updateBackfaceVisibility()
+{
+ if (m_structuralLayer && structuralLayerPurpose() == StructuralLayerForReplicaFlattening) {
+ m_structuralLayer->setDoubleSided(m_backfaceVisibility);
+
+ if (LayerMap* layerCloneMap = m_structuralLayerClones.get()) {
+ LayerMap::const_iterator end = layerCloneMap->end();
+ for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it)
+ it->second->setDoubleSided(m_backfaceVisibility);
+ }
+ }
+
+ m_layer->setDoubleSided(m_backfaceVisibility);
+
+ if (LayerMap* layerCloneMap = m_layerClones.get()) {
+ LayerMap::const_iterator end = layerCloneMap->end();
+ for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it)
+ it->second->setDoubleSided(m_backfaceVisibility);
+ }
+}
+
+void GraphicsLayerCA::updateStructuralLayer()
+{
+ ensureStructuralLayer(structuralLayerPurpose());
+}
+
+void GraphicsLayerCA::ensureStructuralLayer(StructuralLayerPurpose purpose)
+{
+ if (purpose == NoStructuralLayer) {
+ if (m_structuralLayer) {
+ // Replace the transformLayer in the parent with this layer.
+ m_layer->removeFromSuperlayer();
+ m_structuralLayer->superlayer()->replaceSublayer(m_structuralLayer.get(), m_layer.get());
+
+ moveOrCopyAnimationsForProperty(Move, AnimatedPropertyWebkitTransform, m_structuralLayer.get(), m_layer.get());
+ moveOrCopyAnimationsForProperty(Move, AnimatedPropertyOpacity, m_structuralLayer.get(), m_layer.get());
+
+ // Release the structural layer.
+ m_structuralLayer = 0;
+
+ // Update the properties of m_layer now that we no longer have a structural layer.
+ updateLayerPosition();
+ updateLayerSize();
+ updateAnchorPoint();
+ updateTransform();
+ updateChildrenTransform();
+
+ updateSublayerList();
+ updateOpacityOnLayer();
+ }
+ return;
+ }
+
+ bool structuralLayerChanged = false;
+
+ if (purpose == StructuralLayerForPreserves3D) {
+ if (m_structuralLayer && m_structuralLayer->layerType() != PlatformCALayer::LayerTypeTransformLayer)
+ m_structuralLayer = 0;
+
+ if (!m_structuralLayer) {
+ m_structuralLayer = PlatformCALayer::create(PlatformCALayer::LayerTypeTransformLayer, this);
+ structuralLayerChanged = true;
+ }
+ } else {
+ if (m_structuralLayer && m_structuralLayer->layerType() != PlatformCALayer::LayerTypeLayer)
+ m_structuralLayer = 0;
+
+ if (!m_structuralLayer) {
+ m_structuralLayer = PlatformCALayer::create(PlatformCALayer::LayerTypeLayer, this);
+ structuralLayerChanged = true;
+ }
+ }
+
+ if (!structuralLayerChanged)
+ return;
+
+ updateLayerNames();
+
+ // Update the properties of the structural layer.
+ updateLayerPosition();
+ updateLayerSize();
+ updateAnchorPoint();
+ updateTransform();
+ updateChildrenTransform();
+ updateBackfaceVisibility();
+
+ // Set properties of m_layer to their default values, since these are expressed on on the structural layer.
+ FloatPoint point(m_size.width() / 2.0f, m_size.height() / 2.0f);
+ FloatPoint3D anchorPoint(0.5f, 0.5f, 0);
+ m_layer->setPosition(point);
+ m_layer->setAnchorPoint(anchorPoint);
+ m_layer->setTransform(TransformationMatrix());
+ m_layer->setOpacity(1);
+ if (m_layerClones) {
+ LayerMap::const_iterator end = m_layerClones->end();
+ for (LayerMap::const_iterator it = m_layerClones->begin(); it != end; ++it) {
+ PlatformCALayer* currLayer = it->second.get();
+ currLayer->setPosition(point);
+ currLayer->setAnchorPoint(anchorPoint);
+ currLayer->setTransform(TransformationMatrix());
+ currLayer->setOpacity(1);
+ }
+ }
+
+ // Move this layer to be a child of the transform layer.
+ m_layer->superlayer()->replaceSublayer(m_layer.get(), m_structuralLayer.get());
+ m_structuralLayer->appendSublayer(m_layer.get());
+
+ moveOrCopyAnimationsForProperty(Move, AnimatedPropertyWebkitTransform, m_layer.get(), m_structuralLayer.get());
+ moveOrCopyAnimationsForProperty(Move, AnimatedPropertyOpacity, m_layer.get(), m_structuralLayer.get());
+
+ updateSublayerList();
+ updateOpacityOnLayer();
+}
+
+GraphicsLayerCA::StructuralLayerPurpose GraphicsLayerCA::structuralLayerPurpose() const
+{
+ if (preserves3D())
+ return StructuralLayerForPreserves3D;
+
+ if (isReplicated())
+ return StructuralLayerForReplicaFlattening;
+
+ return NoStructuralLayer;
+}
+
+void GraphicsLayerCA::updateLayerDrawsContent()
+{
+ bool needTiledLayer = requiresTiledLayer(m_size);
+ if (needTiledLayer != m_usingTiledLayer)
+ swapFromOrToTiledLayer(needTiledLayer);
+
+ if (m_drawsContent)
+ m_layer->setNeedsDisplay();
+ else
+ m_layer->setContents(0);
+
+ updateDebugIndicators();
+}
+
+void GraphicsLayerCA::updateAcceleratesDrawing()
+{
+ m_layer->setAcceleratesDrawing(m_acceleratesDrawing);
+}
+
+void GraphicsLayerCA::updateLayerBackgroundColor()
+{
+ if (!m_contentsLayer)
+ return;
+
+ // We never create the contents layer just for background color yet.
+ if (m_backgroundColorSet)
+ m_contentsLayer->setBackgroundColor(m_backgroundColor);
+ else
+ m_contentsLayer->setBackgroundColor(Color::transparent);
+}
+
+void GraphicsLayerCA::updateContentsImage()
+{
+ if (m_pendingContentsImage) {
+ if (!m_contentsLayer.get()) {
+ m_contentsLayer = PlatformCALayer::create(PlatformCALayer::LayerTypeLayer, this);
+#ifndef NDEBUG
+ m_contentsLayer->setName("Image Layer");
+#endif
+ setupContentsLayer(m_contentsLayer.get());
+ // m_contentsLayer will be parented by updateSublayerList
+ }
+
+ // FIXME: maybe only do trilinear if the image is being scaled down,
+ // but then what if the layer size changes?
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+ m_contentsLayer->setMinificationFilter(PlatformCALayer::Trilinear);
+#endif
+ m_contentsLayer->setContents(m_pendingContentsImage.get());
+ m_pendingContentsImage = 0;
+
+ if (m_contentsLayerClones) {
+ LayerMap::const_iterator end = m_contentsLayerClones->end();
+ for (LayerMap::const_iterator it = m_contentsLayerClones->begin(); it != end; ++it)
+ it->second->setContents(m_contentsLayer->contents());
+ }
+
+ updateContentsRect();
+ } else {
+ // No image.
+ // m_contentsLayer will be removed via updateSublayerList.
+ m_contentsLayer = 0;
+ }
+}
+
+void GraphicsLayerCA::updateContentsMediaLayer()
+{
+ // Video layer was set as m_contentsLayer, and will get parented in updateSublayerList().
+ if (m_contentsLayer) {
+ setupContentsLayer(m_contentsLayer.get());
+ updateContentsRect();
+ }
+}
+
+void GraphicsLayerCA::updateContentsCanvasLayer()
+{
+ // CanvasLayer was set as m_contentsLayer, and will get parented in updateSublayerList().
+ if (m_contentsLayer) {
+ setupContentsLayer(m_contentsLayer.get());
+ m_contentsLayer->setNeedsDisplay();
+ updateContentsRect();
+ }
+}
+
+void GraphicsLayerCA::updateContentsRect()
+{
+ if (!m_contentsLayer)
+ return;
+
+ FloatPoint point(m_contentsRect.x(), m_contentsRect.y());
+ FloatRect rect(0, 0, m_contentsRect.width(), m_contentsRect.height());
+
+ m_contentsLayer->setPosition(point);
+ m_contentsLayer->setBounds(rect);
+
+ if (m_contentsLayerClones) {
+ LayerMap::const_iterator end = m_contentsLayerClones->end();
+ for (LayerMap::const_iterator it = m_contentsLayerClones->begin(); it != end; ++it) {
+ it->second->setPosition(point);
+ it->second->setBounds(rect);
+ }
+ }
+}
+
+void GraphicsLayerCA::updateMaskLayer()
+{
+ PlatformCALayer* maskCALayer = m_maskLayer ? static_cast<GraphicsLayerCA*>(m_maskLayer)->primaryLayer() : 0;
+ m_layer->setMask(maskCALayer);
+
+ LayerMap* maskLayerCloneMap = m_maskLayer ? static_cast<GraphicsLayerCA*>(m_maskLayer)->primaryLayerClones() : 0;
+
+ if (LayerMap* layerCloneMap = m_layerClones.get()) {
+ LayerMap::const_iterator end = layerCloneMap->end();
+ for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
+ PlatformCALayer* maskClone = maskLayerCloneMap ? maskLayerCloneMap->get(it->first).get() : 0;
+ it->second->setMask(maskClone);
+ }
+ }
+}
+
+void GraphicsLayerCA::updateReplicatedLayers()
+{
+ // Clone the descendants of the replicated layer, and parent under us.
+ ReplicaState replicaState(ReplicaState::ReplicaBranch);
+
+ RefPtr<PlatformCALayer>replicaRoot = replicatedLayerRoot(replicaState);
+ if (!replicaRoot)
+ return;
+
+ if (m_structuralLayer)
+ m_structuralLayer->insertSublayer(replicaRoot.get(), 0);
+ else
+ m_layer->insertSublayer(replicaRoot.get(), 0);
+}
+
+// For now, this assumes that layers only ever have one replica, so replicaIndices contains only 0 and 1.
+GraphicsLayerCA::CloneID GraphicsLayerCA::ReplicaState::cloneID() const
+{
+ size_t depth = m_replicaBranches.size();
+
+ const size_t bitsPerUChar = sizeof(UChar) * 8;
+ size_t vectorSize = (depth + bitsPerUChar - 1) / bitsPerUChar;
+
+ Vector<UChar> result(vectorSize);
+ result.fill(0);
+
+ // Create a string from the bit sequence which we can use to identify the clone.
+ // Note that the string may contain embedded nulls, but that's OK.
+ for (size_t i = 0; i < depth; ++i) {
+ UChar& currChar = result[i / bitsPerUChar];
+ currChar = (currChar << 1) | m_replicaBranches[i];
+ }
+
+ return String::adopt(result);
+}
+
+PassRefPtr<PlatformCALayer> GraphicsLayerCA::replicatedLayerRoot(ReplicaState& replicaState)
+{
+ // Limit replica nesting, to avoid 2^N explosion of replica layers.
+ if (!m_replicatedLayer || replicaState.replicaDepth() == ReplicaState::maxReplicaDepth)
+ return 0;
+
+ GraphicsLayerCA* replicatedLayer = static_cast<GraphicsLayerCA*>(m_replicatedLayer);
+
+ RefPtr<PlatformCALayer> clonedLayerRoot = replicatedLayer->fetchCloneLayers(this, replicaState, RootCloneLevel);
+ FloatPoint cloneRootPosition = replicatedLayer->positionForCloneRootLayer();
+
+ // Replica root has no offset or transform
+ clonedLayerRoot->setPosition(cloneRootPosition);
+ clonedLayerRoot->setTransform(TransformationMatrix());
+
+ return clonedLayerRoot;
+}
+
+void GraphicsLayerCA::updateLayerAnimations()
+{
+ if (m_animationsToProcess.size()) {
+ AnimationsToProcessMap::const_iterator end = m_animationsToProcess.end();
+ for (AnimationsToProcessMap::const_iterator it = m_animationsToProcess.begin(); it != end; ++it) {
+ const String& currAnimationName = it->first;
+ AnimationsMap::iterator animationIt = m_runningAnimations.find(currAnimationName);
+ if (animationIt == m_runningAnimations.end())
+ continue;
+
+ const AnimationProcessingAction& processingInfo = it->second;
+ const Vector<LayerPropertyAnimation>& animations = animationIt->second;
+ for (size_t i = 0; i < animations.size(); ++i) {
+ const LayerPropertyAnimation& currAnimation = animations[i];
+ switch (processingInfo.action) {
+ case Remove:
+ removeCAAnimationFromLayer(currAnimation.m_property, currAnimationName, currAnimation.m_index);
+ break;
+ case Pause:
+ pauseCAAnimationOnLayer(currAnimation.m_property, currAnimationName, currAnimation.m_index, processingInfo.timeOffset);
+ break;
+ }
+ }
+
+ if (processingInfo.action == Remove)
+ m_runningAnimations.remove(currAnimationName);
+ }
+
+ m_animationsToProcess.clear();
+ }
+
+ size_t numAnimations;
+ if ((numAnimations = m_uncomittedAnimations.size())) {
+ for (size_t i = 0; i < numAnimations; ++i) {
+ const LayerPropertyAnimation& pendingAnimation = m_uncomittedAnimations[i];
+ setAnimationOnLayer(pendingAnimation.m_animation.get(), pendingAnimation.m_property, pendingAnimation.m_name, pendingAnimation.m_index, pendingAnimation.m_timeOffset);
+
+ AnimationsMap::iterator it = m_runningAnimations.find(pendingAnimation.m_name);
+ if (it == m_runningAnimations.end()) {
+ Vector<LayerPropertyAnimation> animations;
+ animations.append(pendingAnimation);
+ m_runningAnimations.add(pendingAnimation.m_name, animations);
+ } else {
+ Vector<LayerPropertyAnimation>& animations = it->second;
+ animations.append(pendingAnimation);
+ }
+ }
+
+ m_uncomittedAnimations.clear();
+ }
+}
+
+void GraphicsLayerCA::setAnimationOnLayer(PlatformCAAnimation* caAnim, AnimatedPropertyID property, const String& animationName, int index, double timeOffset)
+{
+ PlatformCALayer* layer = animatedLayer(property);
+
+ if (timeOffset)
+ caAnim->setBeginTime(CACurrentMediaTime() - timeOffset);
+
+ String animationID = animationIdentifier(animationName, property, index);
+
+ layer->removeAnimationForKey(animationID);
+ layer->addAnimationForKey(animationID, caAnim);
+
+ if (LayerMap* layerCloneMap = animatedLayerClones(property)) {
+ LayerMap::const_iterator end = layerCloneMap->end();
+ for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
+ // Skip immediate replicas, since they move with the original.
+ if (m_replicaLayer && isReplicatedRootClone(it->first))
+ continue;
+
+ it->second->removeAnimationForKey(animationID);
+ it->second->addAnimationForKey(animationID, caAnim);
+ }
+ }
+}
+
+// Workaround for <rdar://problem/7311367>
+static void bug7311367Workaround(PlatformCALayer* transformLayer, const TransformationMatrix& transform)
+{
+ if (!transformLayer)
+ return;
+
+ TransformationMatrix caTransform = transform;
+ caTransform.setM41(caTransform.m41() + 1);
+ transformLayer->setTransform(caTransform);
+
+ caTransform.setM41(caTransform.m41() - 1);
+ transformLayer->setTransform(caTransform);
+}
+
+bool GraphicsLayerCA::removeCAAnimationFromLayer(AnimatedPropertyID property, const String& animationName, int index)
+{
+ PlatformCALayer* layer = animatedLayer(property);
+
+ String animationID = animationIdentifier(animationName, property, index);
+
+ if (!layer->animationForKey(animationID))
+ return false;
+
+ layer->removeAnimationForKey(animationID);
+ bug7311367Workaround(m_structuralLayer.get(), m_transform);
+
+ if (LayerMap* layerCloneMap = animatedLayerClones(property)) {
+ LayerMap::const_iterator end = layerCloneMap->end();
+ for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
+ // Skip immediate replicas, since they move with the original.
+ if (m_replicaLayer && isReplicatedRootClone(it->first))
+ continue;
+
+ it->second ->removeAnimationForKey(animationID);
+ }
+ }
+ return true;
+}
+
+void GraphicsLayerCA::pauseCAAnimationOnLayer(AnimatedPropertyID property, const String& animationName, int index, double timeOffset)
+{
+ PlatformCALayer* layer = animatedLayer(property);
+
+ String animationID = animationIdentifier(animationName, property, index);
+
+ RefPtr<PlatformCAAnimation> curAnim = layer->animationForKey(animationID);
+ if (!curAnim)
+ return;
+
+ // Animations on the layer are immutable, so we have to clone and modify.
+ RefPtr<PlatformCAAnimation> newAnim = PlatformCAAnimation::create(curAnim.get());
+
+ newAnim->setSpeed(0);
+ newAnim->setTimeOffset(timeOffset);
+
+ layer->addAnimationForKey(animationID, newAnim.get()); // This will replace the running animation.
+
+ // Pause the animations on the clones too.
+ if (LayerMap* layerCloneMap = animatedLayerClones(property)) {
+ LayerMap::const_iterator end = layerCloneMap->end();
+ for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
+ // Skip immediate replicas, since they move with the original.
+ if (m_replicaLayer && isReplicatedRootClone(it->first))
+ continue;
+ it->second->addAnimationForKey(animationID, newAnim.get());
+ }
+ }
+}
+
+void GraphicsLayerCA::repaintLayerDirtyRects()
+{
+ if (!m_dirtyRects.size())
+ return;
+
+ for (size_t i = 0; i < m_dirtyRects.size(); ++i)
+ m_layer->setNeedsDisplay(&(m_dirtyRects[i]));
+
+ m_dirtyRects.clear();
+}
+
+void GraphicsLayerCA::updateContentsNeedsDisplay()
+{
+ if (m_contentsLayer)
+ m_contentsLayer->setNeedsDisplay();
+}
+
+bool GraphicsLayerCA::createAnimationFromKeyframes(const KeyframeValueList& valueList, const Animation* animation, const String& animationName, double timeOffset)
+{
+ ASSERT(valueList.property() != AnimatedPropertyWebkitTransform);
+
+ bool isKeyframe = valueList.size() > 2;
+ bool valuesOK;
+
+ bool additive = false;
+ int animationIndex = 0;
+
+ RefPtr<PlatformCAAnimation> caAnimation;
+
+ if (isKeyframe) {
+ caAnimation = createKeyframeAnimation(animation, valueList.property(), additive);
+ valuesOK = setAnimationKeyframes(valueList, animation, caAnimation.get());
+ } else {
+ caAnimation = createBasicAnimation(animation, valueList.property(), additive);
+ valuesOK = setAnimationEndpoints(valueList, animation, caAnimation.get());
+ }
+
+ if (!valuesOK)
+ return false;
+
+ m_uncomittedAnimations.append(LayerPropertyAnimation(caAnimation, animationName, valueList.property(), animationIndex, timeOffset));
+
+ return true;
+}
+
+bool GraphicsLayerCA::createTransformAnimationsFromKeyframes(const KeyframeValueList& valueList, const Animation* animation, const String& animationName, double timeOffset, const IntSize& boxSize)
+{
+ ASSERT(valueList.property() == AnimatedPropertyWebkitTransform);
+
+ TransformOperationList functionList;
+ bool listsMatch, hasBigRotation;
+ fetchTransformOperationList(valueList, functionList, listsMatch, hasBigRotation);
+
+ // We need to fall back to software animation if we don't have setValueFunction:, and
+ // we would need to animate each incoming transform function separately. This is the
+ // case if we have a rotation >= 180 or we have more than one transform function.
+ if ((hasBigRotation || functionList.size() > 1) && !PlatformCAAnimation::supportsValueFunction())
+ return false;
+
+ bool validMatrices = true;
+
+ // If functionLists don't match we do a matrix animation, otherwise we do a component hardware animation.
+ // Also, we can't do component animation unless we have valueFunction, so we need to do matrix animation
+ // if that's not true as well.
+ bool isMatrixAnimation = !listsMatch || !PlatformCAAnimation::supportsValueFunction();
+
+ size_t numAnimations = isMatrixAnimation ? 1 : functionList.size();
+ bool isKeyframe = valueList.size() > 2;
+
+ // Iterate through the transform functions, sending an animation for each one.
+ for (size_t animationIndex = 0; animationIndex < numAnimations; ++animationIndex) {
+ TransformOperation::OperationType transformOp = isMatrixAnimation ? TransformOperation::MATRIX_3D : functionList[animationIndex];
+ RefPtr<PlatformCAAnimation> caAnimation;
+
+#if defined(BUILDING_ON_LEOPARD) || defined(BUILDING_ON_SNOW_LEOPARD)
+ // CA applies animations in reverse order (<rdar://problem/7095638>) so we need the last one we add (per property)
+ // to be non-additive.
+ bool additive = animationIndex < (numAnimations - 1);
+#else
+ bool additive = animationIndex > 0;
+#endif
+ if (isKeyframe) {
+ caAnimation = createKeyframeAnimation(animation, valueList.property(), additive);
+ validMatrices = setTransformAnimationKeyframes(valueList, animation, caAnimation.get(), animationIndex, transformOp, isMatrixAnimation, boxSize);
+ } else {
+ caAnimation = createBasicAnimation(animation, valueList.property(), additive);
+ validMatrices = setTransformAnimationEndpoints(valueList, animation, caAnimation.get(), animationIndex, transformOp, isMatrixAnimation, boxSize);
+ }
+
+ if (!validMatrices)
+ break;
+
+ m_uncomittedAnimations.append(LayerPropertyAnimation(caAnimation, animationName, valueList.property(), animationIndex, timeOffset));
+ }
+
+ return validMatrices;
+}
+
+PassRefPtr<PlatformCAAnimation> GraphicsLayerCA::createBasicAnimation(const Animation* anim, AnimatedPropertyID property, bool additive)
+{
+ RefPtr<PlatformCAAnimation> basicAnim = PlatformCAAnimation::create(PlatformCAAnimation::Basic, propertyIdToString(property));
+ setupAnimation(basicAnim.get(), anim, additive);
+ return basicAnim;
+}
+
+PassRefPtr<PlatformCAAnimation>GraphicsLayerCA::createKeyframeAnimation(const Animation* anim, AnimatedPropertyID property, bool additive)
+{
+ RefPtr<PlatformCAAnimation> keyframeAnim = PlatformCAAnimation::create(PlatformCAAnimation::Keyframe, propertyIdToString(property));
+ setupAnimation(keyframeAnim.get(), anim, additive);
+ return keyframeAnim;
+}
+
+void GraphicsLayerCA::setupAnimation(PlatformCAAnimation* propertyAnim, const Animation* anim, bool additive)
+{
+ double duration = anim->duration();
+ if (duration <= 0)
+ duration = cAnimationAlmostZeroDuration;
+
+ float repeatCount = anim->iterationCount();
+ if (repeatCount == Animation::IterationCountInfinite)
+ repeatCount = FLT_MAX;
+ else if (anim->direction() == Animation::AnimationDirectionAlternate)
+ repeatCount /= 2;
+
+ PlatformCAAnimation::FillModeType fillMode = PlatformCAAnimation::NoFillMode;
+ switch (anim->fillMode()) {
+ case AnimationFillModeNone:
+ fillMode = PlatformCAAnimation::Forwards; // Use "forwards" rather than "removed" because the style system will remove the animation when it is finished. This avoids a flash.
+ break;
+ case AnimationFillModeBackwards:
+ fillMode = PlatformCAAnimation::Both; // Use "both" rather than "backwards" because the style system will remove the animation when it is finished. This avoids a flash.
+ break;
+ case AnimationFillModeForwards:
+ fillMode = PlatformCAAnimation::Forwards;
+ break;
+ case AnimationFillModeBoth:
+ fillMode = PlatformCAAnimation::Both;
+ break;
+ }
+
+ propertyAnim->setDuration(duration);
+ propertyAnim->setRepeatCount(repeatCount);
+ propertyAnim->setAutoreverses(anim->direction());
+ propertyAnim->setRemovedOnCompletion(false);
+ propertyAnim->setAdditive(additive);
+ propertyAnim->setFillMode(fillMode);
+}
+
+const TimingFunction* GraphicsLayerCA::timingFunctionForAnimationValue(const AnimationValue* animValue, const Animation* anim)
+{
+ if (animValue->timingFunction())
+ return animValue->timingFunction();
+ if (anim->isTimingFunctionSet())
+ return anim->timingFunction().get();
+
+ return 0;
+}
+
+bool GraphicsLayerCA::setAnimationEndpoints(const KeyframeValueList& valueList, const Animation* anim, PlatformCAAnimation* basicAnim)
+{
+ switch (valueList.property()) {
+ case AnimatedPropertyOpacity: {
+ basicAnim->setFromValue(static_cast<const FloatAnimationValue*>(valueList.at(0))->value());
+ basicAnim->setToValue(static_cast<const FloatAnimationValue*>(valueList.at(1))->value());
+ break;
+ }
+ default:
+ ASSERT_NOT_REACHED(); // we don't animate color yet
+ break;
+ }
+
+ // This codepath is used for 2-keyframe animations, so we still need to look in the start
+ // for a timing function.
+ const TimingFunction* timingFunction = timingFunctionForAnimationValue(valueList.at(0), anim);
+ if (timingFunction)
+ basicAnim->setTimingFunction(timingFunction);
+
+ return true;
+}
+
+bool GraphicsLayerCA::setAnimationKeyframes(const KeyframeValueList& valueList, const Animation* anim, PlatformCAAnimation* keyframeAnim)
+{
+ Vector<float> keyTimes;
+ Vector<float> values;
+ Vector<const TimingFunction*> timingFunctions;
+
+ for (unsigned i = 0; i < valueList.size(); ++i) {
+ const AnimationValue* curValue = valueList.at(i);
+ keyTimes.append(curValue->keyTime());
+
+ switch (valueList.property()) {
+ case AnimatedPropertyOpacity: {
+ const FloatAnimationValue* floatValue = static_cast<const FloatAnimationValue*>(curValue);
+ values.append(floatValue->value());
+ break;
+ }
+ default:
+ ASSERT_NOT_REACHED(); // we don't animate color yet
+ break;
+ }
+
+ timingFunctions.append(timingFunctionForAnimationValue(curValue, anim));
+ }
+
+ // We toss the last tfArray value because it has to one shorter than the others.
+ timingFunctions.removeLast();
+
+ keyframeAnim->setKeyTimes(keyTimes);
+ keyframeAnim->setValues(values);
+ keyframeAnim->setTimingFunctions(timingFunctions);
+
+ return true;
+}
+
+bool GraphicsLayerCA::setTransformAnimationEndpoints(const KeyframeValueList& valueList, const Animation* anim, PlatformCAAnimation* basicAnim, int functionIndex, TransformOperation::OperationType transformOpType, bool isMatrixAnimation, const IntSize& boxSize)
+{
+ ASSERT(valueList.size() == 2);
+ const TransformAnimationValue* startValue = static_cast<const TransformAnimationValue*>(valueList.at(0));
+ const TransformAnimationValue* endValue = static_cast<const TransformAnimationValue*>(valueList.at(1));
+
+ if (isMatrixAnimation) {
+ TransformationMatrix fromTransform, toTransform;
+ startValue->value()->apply(boxSize, fromTransform);
+ endValue->value()->apply(boxSize, toTransform);
+
+ // If any matrix is singular, CA won't animate it correctly. So fall back to software animation
+ if (!fromTransform.isInvertible() || !toTransform.isInvertible())
+ return false;
+
+ basicAnim->setFromValue(fromTransform);
+ basicAnim->setToValue(toTransform);
+ } else {
+ if (isTransformTypeNumber(transformOpType)) {
+ float value;
+ getTransformFunctionValue(startValue->value()->at(functionIndex), transformOpType, boxSize, value);
+ basicAnim->setFromValue(value);
+ getTransformFunctionValue(endValue->value()->at(functionIndex), transformOpType, boxSize, value);
+ basicAnim->setToValue(value);
+ } else if (isTransformTypeFloatPoint3D(transformOpType)) {
+ FloatPoint3D value;
+ getTransformFunctionValue(startValue->value()->at(functionIndex), transformOpType, boxSize, value);
+ basicAnim->setFromValue(value);
+ getTransformFunctionValue(endValue->value()->at(functionIndex), transformOpType, boxSize, value);
+ basicAnim->setToValue(value);
+ } else {
+ TransformationMatrix value;
+ getTransformFunctionValue(startValue->value()->at(functionIndex), transformOpType, boxSize, value);
+ basicAnim->setFromValue(value);
+ getTransformFunctionValue(endValue->value()->at(functionIndex), transformOpType, boxSize, value);
+ basicAnim->setToValue(value);
+ }
+ }
+
+ // This codepath is used for 2-keyframe animations, so we still need to look in the start
+ // for a timing function.
+ const TimingFunction* timingFunction = timingFunctionForAnimationValue(valueList.at(0), anim);
+ basicAnim->setTimingFunction(timingFunction);
+
+#if HAVE_MODERN_QUARTZCORE
+ PlatformCAAnimation::ValueFunctionType valueFunction = getValueFunctionNameForTransformOperation(transformOpType);
+ if (valueFunction != PlatformCAAnimation::NoValueFunction)
+ basicAnim->setValueFunction(valueFunction);
+#endif
+
+ return true;
+}
+
+bool GraphicsLayerCA::setTransformAnimationKeyframes(const KeyframeValueList& valueList, const Animation* animation, PlatformCAAnimation* keyframeAnim, int functionIndex, TransformOperation::OperationType transformOpType, bool isMatrixAnimation, const IntSize& boxSize)
+{
+ Vector<float> keyTimes;
+ Vector<float> floatValues;
+ Vector<FloatPoint3D> floatPoint3DValues;
+ Vector<TransformationMatrix> transformationMatrixValues;
+ Vector<const TimingFunction*> timingFunctions;
+
+ for (unsigned i = 0; i < valueList.size(); ++i) {
+ const TransformAnimationValue* curValue = static_cast<const TransformAnimationValue*>(valueList.at(i));
+ keyTimes.append(curValue->keyTime());
+
+ if (isMatrixAnimation) {
+ TransformationMatrix transform;
+ curValue->value()->apply(boxSize, transform);
+
+ // If any matrix is singular, CA won't animate it correctly. So fall back to software animation
+ if (!transform.isInvertible())
+ return false;
+
+ transformationMatrixValues.append(transform);
+ } else {
+ const TransformOperation* transformOp = curValue->value()->at(functionIndex);
+ if (isTransformTypeNumber(transformOpType)) {
+ float value;
+ getTransformFunctionValue(transformOp, transformOpType, boxSize, value);
+ floatValues.append(value);
+ } else if (isTransformTypeFloatPoint3D(transformOpType)) {
+ FloatPoint3D value;
+ getTransformFunctionValue(transformOp, transformOpType, boxSize, value);
+ floatPoint3DValues.append(value);
+ } else {
+ TransformationMatrix value;
+ getTransformFunctionValue(transformOp, transformOpType, boxSize, value);
+ transformationMatrixValues.append(value);
+ }
+ }
+
+ const TimingFunction* timingFunction = timingFunctionForAnimationValue(curValue, animation);
+ timingFunctions.append(timingFunction);
+ }
+
+ // We toss the last tfArray value because it has to one shorter than the others.
+ timingFunctions.removeLast();
+
+ keyframeAnim->setKeyTimes(keyTimes);
+
+ if (isTransformTypeNumber(transformOpType))
+ keyframeAnim->setValues(floatValues);
+ else if (isTransformTypeFloatPoint3D(transformOpType))
+ keyframeAnim->setValues(floatPoint3DValues);
+ else
+ keyframeAnim->setValues(transformationMatrixValues);
+
+ keyframeAnim->setTimingFunctions(timingFunctions);
+
+#if HAVE_MODERN_QUARTZCORE
+ PlatformCAAnimation::ValueFunctionType valueFunction = getValueFunctionNameForTransformOperation(transformOpType);
+ if (valueFunction != PlatformCAAnimation::NoValueFunction)
+ keyframeAnim->setValueFunction(valueFunction);
+#endif
+ return true;
+}
+
+void GraphicsLayerCA::suspendAnimations(double time)
+{
+ double t = currentTimeToMediaTime(time ? time : currentTime());
+ primaryLayer()->setSpeed(0);
+ primaryLayer()->setTimeOffset(t);
+
+ // Suspend the animations on the clones too.
+ if (LayerMap* layerCloneMap = primaryLayerClones()) {
+ LayerMap::const_iterator end = layerCloneMap->end();
+ for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
+ it->second->setSpeed(0);
+ it->second->setTimeOffset(t);
+ }
+ }
+}
+
+void GraphicsLayerCA::resumeAnimations()
+{
+ primaryLayer()->setSpeed(1);
+ primaryLayer()->setTimeOffset(0);
+
+ // Resume the animations on the clones too.
+ if (LayerMap* layerCloneMap = primaryLayerClones()) {
+ LayerMap::const_iterator end = layerCloneMap->end();
+ for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
+ it->second->setSpeed(1);
+ it->second->setTimeOffset(0);
+ }
+ }
+}
+
+PlatformCALayer* GraphicsLayerCA::hostLayerForSublayers() const
+{
+ return m_structuralLayer.get() ? m_structuralLayer.get() : m_layer.get();
+}
+
+PlatformCALayer* GraphicsLayerCA::layerForSuperlayer() const
+{
+ return m_structuralLayer ? m_structuralLayer.get() : m_layer.get();
+}
+
+PlatformCALayer* GraphicsLayerCA::animatedLayer(AnimatedPropertyID property) const
+{
+ return (property == AnimatedPropertyBackgroundColor) ? m_contentsLayer.get() : primaryLayer();
+}
+
+GraphicsLayerCA::LayerMap* GraphicsLayerCA::animatedLayerClones(AnimatedPropertyID property) const
+{
+ return (property == AnimatedPropertyBackgroundColor) ? m_contentsLayerClones.get() : primaryLayerClones();
+}
+
+void GraphicsLayerCA::setDebugBackgroundColor(const Color& color)
+{
+ if (color.isValid())
+ m_layer->setBackgroundColor(color);
+ else
+ m_layer->setBackgroundColor(Color::transparent);
+}
+
+void GraphicsLayerCA::setDebugBorder(const Color& color, float borderWidth)
+{
+ if (color.isValid()) {
+ m_layer->setBorderColor(color);
+ m_layer->setBorderWidth(borderWidth);
+ } else {
+ m_layer->setBorderColor(Color::transparent);
+ m_layer->setBorderWidth(0);
+ }
+}
+
+FloatSize GraphicsLayerCA::constrainedSize() const
+{
+ float tileColumns = ceilf(m_size.width() / kTiledLayerTileSize);
+ float tileRows = ceilf(m_size.height() / kTiledLayerTileSize);
+ double numTiles = tileColumns * tileRows;
+
+ FloatSize constrainedSize = m_size;
+ const unsigned cMaxTileCount = 512;
+ while (numTiles > cMaxTileCount) {
+ // Constrain the wider dimension.
+ if (constrainedSize.width() >= constrainedSize.height()) {
+ tileColumns = max(floorf(cMaxTileCount / tileRows), 1.0f);
+ constrainedSize.setWidth(tileColumns * kTiledLayerTileSize);
+ } else {
+ tileRows = max(floorf(cMaxTileCount / tileColumns), 1.0f);
+ constrainedSize.setHeight(tileRows * kTiledLayerTileSize);
+ }
+ numTiles = tileColumns * tileRows;
+ }
+
+ return constrainedSize;
+}
+
+bool GraphicsLayerCA::requiresTiledLayer(const FloatSize& size) const
+{
+ if (!m_drawsContent)
+ return false;
+
+ // FIXME: catch zero-size height or width here (or earlier)?
+ return size.width() > cMaxPixelDimension || size.height() > cMaxPixelDimension;
+}
+
+void GraphicsLayerCA::swapFromOrToTiledLayer(bool useTiledLayer)
+{
+ if (useTiledLayer == m_usingTiledLayer)
+ return;
+
+ RefPtr<PlatformCALayer> oldLayer = m_layer;
+
+ m_layer = PlatformCALayer::create(useTiledLayer ? PlatformCALayer::LayerTypeWebTiledLayer : PlatformCALayer::LayerTypeWebLayer, this);
+
+ m_usingTiledLayer = useTiledLayer;
+
+ if (useTiledLayer) {
+#if !HAVE_MODERN_QUARTZCORE
+ // Tiled layer has issues with flipped coordinates.
+ setContentsOrientation(CompositingCoordinatesTopDown);
+#endif
+ } else {
+#if !HAVE_MODERN_QUARTZCORE
+ setContentsOrientation(GraphicsLayerCA::defaultContentsOrientation());
+#endif
+ }
+
+ m_layer->adoptSublayers(oldLayer.get());
+
+ oldLayer->superlayer()->replaceSublayer(oldLayer.get(), m_layer.get());
+
+ updateContentsTransform();
+
+ updateLayerPosition();
+ updateLayerSize();
+ updateAnchorPoint();
+ updateTransform();
+ updateChildrenTransform();
+ updateMasksToBounds();
+ updateContentsOpaque();
+ updateBackfaceVisibility();
+ updateLayerBackgroundColor();
+
+ updateOpacityOnLayer();
+
+#ifndef NDEBUG
+ String name = String::format("CALayer(%p) GraphicsLayer(%p) ", m_layer.get(), this) + m_name;
+ m_layer->setName(name);
+#endif
+
+ // move over animations
+ moveOrCopyAnimationsForProperty(Move, AnimatedPropertyWebkitTransform, oldLayer.get(), m_layer.get());
+ moveOrCopyAnimationsForProperty(Move, AnimatedPropertyOpacity, oldLayer.get(), m_layer.get());
+ moveOrCopyAnimationsForProperty(Move, AnimatedPropertyBackgroundColor, oldLayer.get(), m_layer.get());
+
+ // need to tell new layer to draw itself
+ setNeedsDisplay();
+
+ updateDebugIndicators();
+}
+
+GraphicsLayer::CompositingCoordinatesOrientation GraphicsLayerCA::defaultContentsOrientation() const
+{
+#if !HAVE_MODERN_QUARTZCORE
+ // Older QuartzCore does not support -geometryFlipped, so we manually flip the root
+ // layer geometry, and then flip the contents of each layer back so that the CTM for CG
+ // is unflipped, allowing it to do the correct font auto-hinting.
+ return CompositingCoordinatesBottomUp;
+#else
+ return CompositingCoordinatesTopDown;
+#endif
+}
+
+void GraphicsLayerCA::updateContentsTransform()
+{
+#if !HAVE_MODERN_QUARTZCORE
+ if (contentsOrientation() == CompositingCoordinatesBottomUp) {
+ CGAffineTransform contentsTransform = CGAffineTransformMakeScale(1, -1);
+ contentsTransform = CGAffineTransformTranslate(contentsTransform, 0, -m_layer->bounds().size().height());
+ m_layer->setContentsTransform(TransformationMatrix(contentsTransform));
+ }
+#endif
+}
+
+void GraphicsLayerCA::setupContentsLayer(PlatformCALayer* contentsLayer)
+{
+ // Turn off implicit animations on the inner layer.
+ contentsLayer->setMasksToBounds(true);
+
+ if (defaultContentsOrientation() == CompositingCoordinatesBottomUp) {
+ TransformationMatrix flipper(
+ 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, -1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f);
+ contentsLayer->setTransform(flipper);
+ contentsLayer->setAnchorPoint(FloatPoint3D(0, 1, 0));
+ } else
+ contentsLayer->setAnchorPoint(FloatPoint3D());
+
+ if (showDebugBorders()) {
+ contentsLayer->setBorderColor(Color(0, 0, 128, 180));
+ contentsLayer->setBorderWidth(1.0f);
+ }
+}
+
+PassRefPtr<PlatformCALayer> GraphicsLayerCA::findOrMakeClone(CloneID cloneID, PlatformCALayer *sourceLayer, LayerMap* clones, CloneLevel cloneLevel)
+{
+ if (!sourceLayer)
+ return 0;
+
+ RefPtr<PlatformCALayer> resultLayer;
+
+ // Add with a dummy value to get an iterator for the insertion position, and a boolean that tells
+ // us whether there's an item there. This technique avoids two hash lookups.
+ RefPtr<PlatformCALayer> dummy;
+ pair<LayerMap::iterator, bool> addResult = clones->add(cloneID, dummy);
+ if (!addResult.second) {
+ // Value was not added, so it exists already.
+ resultLayer = addResult.first->second.get();
+ } else {
+ resultLayer = cloneLayer(sourceLayer, cloneLevel);
+#ifndef NDEBUG
+ resultLayer->setName(String::format("Clone %d of layer %p", cloneID[0U], sourceLayer));
+#endif
+ addResult.first->second = resultLayer;
+ }
+
+ return resultLayer;
+}
+
+void GraphicsLayerCA::ensureCloneLayers(CloneID cloneID, RefPtr<PlatformCALayer>& primaryLayer, RefPtr<PlatformCALayer>& structuralLayer, RefPtr<PlatformCALayer>& contentsLayer, CloneLevel cloneLevel)
+{
+ structuralLayer = 0;
+ contentsLayer = 0;
+
+ if (!m_layerClones)
+ m_layerClones = new LayerMap;
+
+ if (!m_structuralLayerClones && m_structuralLayer)
+ m_structuralLayerClones = new LayerMap;
+
+ if (!m_contentsLayerClones && m_contentsLayer)
+ m_contentsLayerClones = new LayerMap;
+
+ primaryLayer = findOrMakeClone(cloneID, m_layer.get(), m_layerClones.get(), cloneLevel);
+ structuralLayer = findOrMakeClone(cloneID, m_structuralLayer.get(), m_structuralLayerClones.get(), cloneLevel);
+ contentsLayer = findOrMakeClone(cloneID, m_contentsLayer.get(), m_contentsLayerClones.get(), cloneLevel);
+}
+
+void GraphicsLayerCA::removeCloneLayers()
+{
+ m_layerClones = 0;
+ m_structuralLayerClones = 0;
+ m_contentsLayerClones = 0;
+}
+
+FloatPoint GraphicsLayerCA::positionForCloneRootLayer() const
+{
+ // This can get called during a sync when we've just removed the m_replicaLayer.
+ if (!m_replicaLayer)
+ return FloatPoint();
+
+ FloatPoint replicaPosition = m_replicaLayer->replicatedLayerPosition();
+ return FloatPoint(replicaPosition.x() + m_anchorPoint.x() * m_size.width(),
+ replicaPosition.y() + m_anchorPoint.y() * m_size.height());
+}
+
+void GraphicsLayerCA::propagateLayerChangeToReplicas()
+{
+ for (GraphicsLayer* currLayer = this; currLayer; currLayer = currLayer->parent()) {
+ GraphicsLayerCA* currLayerCA = static_cast<GraphicsLayerCA*>(currLayer);
+ if (!currLayerCA->hasCloneLayers())
+ break;
+
+ if (currLayerCA->replicaLayer())
+ static_cast<GraphicsLayerCA*>(currLayerCA->replicaLayer())->noteLayerPropertyChanged(ReplicatedLayerChanged);
+ }
+}
+
+PassRefPtr<PlatformCALayer> GraphicsLayerCA::fetchCloneLayers(GraphicsLayer* replicaRoot, ReplicaState& replicaState, CloneLevel cloneLevel)
+{
+ RefPtr<PlatformCALayer> primaryLayer;
+ RefPtr<PlatformCALayer> structuralLayer;
+ RefPtr<PlatformCALayer> contentsLayer;
+ ensureCloneLayers(replicaState.cloneID(), primaryLayer, structuralLayer, contentsLayer, cloneLevel);
+
+ if (m_maskLayer) {
+ RefPtr<PlatformCALayer> maskClone = static_cast<GraphicsLayerCA*>(m_maskLayer)->fetchCloneLayers(replicaRoot, replicaState, IntermediateCloneLevel);
+ primaryLayer->setMask(maskClone.get());
+ }
+
+ if (m_replicatedLayer) {
+ // We are a replica being asked for clones of our layers.
+ RefPtr<PlatformCALayer> replicaRoot = replicatedLayerRoot(replicaState);
+ if (!replicaRoot)
+ return 0;
+
+ if (structuralLayer) {
+ structuralLayer->insertSublayer(replicaRoot.get(), 0);
+ return structuralLayer;
+ }
+
+ primaryLayer->insertSublayer(replicaRoot.get(), 0);
+ return primaryLayer;
+ }
+
+ const Vector<GraphicsLayer*>& childLayers = children();
+ Vector<RefPtr<PlatformCALayer> > clonalSublayers;
+
+ RefPtr<PlatformCALayer> replicaLayer;
+
+ if (m_replicaLayer && m_replicaLayer != replicaRoot) {
+ // We have nested replicas. Ask the replica layer for a clone of its contents.
+ replicaState.setBranchType(ReplicaState::ReplicaBranch);
+ replicaLayer = static_cast<GraphicsLayerCA*>(m_replicaLayer)->fetchCloneLayers(replicaRoot, replicaState, RootCloneLevel);
+ replicaState.setBranchType(ReplicaState::ChildBranch);
+ }
+
+ if (replicaLayer || structuralLayer || contentsLayer || childLayers.size() > 0) {
+ if (structuralLayer) {
+ // Replicas render behind the actual layer content.
+ if (replicaLayer)
+ clonalSublayers.append(replicaLayer);
+
+ // Add the primary layer next. Even if we have negative z-order children, the primary layer always comes behind.
+ clonalSublayers.append(primaryLayer);
+ } else if (contentsLayer) {
+ // FIXME: add the contents layer in the correct order with negative z-order children.
+ // This does not cause visible rendering issues because currently contents layers are only used
+ // for replaced elements that don't have children.
+ clonalSublayers.append(contentsLayer);
+ }
+
+ replicaState.push(ReplicaState::ChildBranch);
+
+ size_t numChildren = childLayers.size();
+ for (size_t i = 0; i < numChildren; ++i) {
+ GraphicsLayerCA* curChild = static_cast<GraphicsLayerCA*>(childLayers[i]);
+
+ RefPtr<PlatformCALayer> childLayer = curChild->fetchCloneLayers(replicaRoot, replicaState, IntermediateCloneLevel);
+ if (childLayer)
+ clonalSublayers.append(childLayer);
+ }
+
+ replicaState.pop();
+
+ for (size_t i = 0; i < clonalSublayers.size(); ++i)
+ clonalSublayers[i]->removeFromSuperlayer();
+ }
+
+ RefPtr<PlatformCALayer> result;
+ if (structuralLayer) {
+ structuralLayer->setSublayers(clonalSublayers);
+
+ if (contentsLayer) {
+ // If we have a transform layer, then the contents layer is parented in the
+ // primary layer (which is itself a child of the transform layer).
+ primaryLayer->removeAllSublayers();
+ primaryLayer->appendSublayer(contentsLayer.get());
+ }
+
+ result = structuralLayer;
+ } else {
+ primaryLayer->setSublayers(clonalSublayers);
+ result = primaryLayer;
+ }
+
+ return result;
+}
+
+PassRefPtr<PlatformCALayer> GraphicsLayerCA::cloneLayer(PlatformCALayer *layer, CloneLevel cloneLevel)
+{
+ PlatformCALayer::LayerType layerType = (layer->layerType() == PlatformCALayer::LayerTypeTransformLayer) ?
+ PlatformCALayer::LayerTypeTransformLayer : PlatformCALayer::LayerTypeLayer;
+ RefPtr<PlatformCALayer> newLayer = PlatformCALayer::create(layerType, this);
+
+ newLayer->setPosition(layer->position());
+ newLayer->setBounds(layer->bounds());
+ newLayer->setAnchorPoint(layer->anchorPoint());
+ newLayer->setTransform(layer->transform());
+ newLayer->setSublayerTransform(layer->sublayerTransform());
+ newLayer->setContents(layer->contents());
+ newLayer->setMasksToBounds(layer->masksToBounds());
+ newLayer->setDoubleSided(layer->isDoubleSided());
+ newLayer->setOpaque(layer->isOpaque());
+ newLayer->setBackgroundColor(layer->backgroundColor());
+
+ if (cloneLevel == IntermediateCloneLevel) {
+ newLayer->setOpacity(layer->opacity());
+ moveOrCopyAnimationsForProperty(Copy, AnimatedPropertyWebkitTransform, layer, newLayer.get());
+ moveOrCopyAnimationsForProperty(Copy, AnimatedPropertyOpacity, layer, newLayer.get());
+ }
+
+ if (showDebugBorders()) {
+ newLayer->setBorderColor(Color(255, 122, 251));
+ newLayer->setBorderWidth(2);
+ }
+
+ return newLayer;
+}
+
+void GraphicsLayerCA::setOpacityInternal(float accumulatedOpacity)
+{
+ LayerMap* layerCloneMap = 0;
+
+ if (preserves3D()) {
+ m_layer->setOpacity(accumulatedOpacity);
+ layerCloneMap = m_layerClones.get();
+ } else {
+ primaryLayer()->setOpacity(accumulatedOpacity);
+ layerCloneMap = primaryLayerClones();
+ }
+
+ if (layerCloneMap) {
+ LayerMap::const_iterator end = layerCloneMap->end();
+ for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
+ if (m_replicaLayer && isReplicatedRootClone(it->first))
+ continue;
+ it->second->setOpacity(m_opacity);
+ }
+ }
+}
+
+void GraphicsLayerCA::updateOpacityOnLayer()
+{
+#if !HAVE_MODERN_QUARTZCORE
+ // Distribute opacity either to our own layer or to our children. We pass in the
+ // contribution from our parent(s).
+ distributeOpacity(parent() ? parent()->accumulatedOpacity() : 1);
+#else
+ primaryLayer()->setOpacity(m_opacity);
+
+ if (LayerMap* layerCloneMap = primaryLayerClones()) {
+ LayerMap::const_iterator end = layerCloneMap->end();
+ for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
+ if (m_replicaLayer && isReplicatedRootClone(it->first))
+ continue;
+
+ it->second->setOpacity(m_opacity);
+ }
+
+ }
+#endif
+}
+
+void GraphicsLayerCA::noteSublayersChanged()
+{
+ noteLayerPropertyChanged(ChildrenChanged);
+ propagateLayerChangeToReplicas();
+}
+
+void GraphicsLayerCA::noteLayerPropertyChanged(LayerChangeFlags flags)
+{
+ if (!m_uncommittedChanges && m_client)
+ m_client->notifySyncRequired(this);
+
+ m_uncommittedChanges |= flags;
+}
+
+} // namespace WebCore
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/WebCore/platform/graphics/mac/GraphicsLayerMac.h b/WebCore/platform/graphics/ca/GraphicsLayerCA.h
index 5d4dfe2..22921c1 100644
--- a/WebCore/platform/graphics/mac/GraphicsLayerMac.h
+++ b/WebCore/platform/graphics/ca/GraphicsLayerCA.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2010 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -23,36 +23,38 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef GraphicsLayerMac_h
-#define GraphicsLayerMac_h
+#ifndef GraphicsLayerCA_h
+#define GraphicsLayerCA_h
#if USE(ACCELERATED_COMPOSITING)
#include "GraphicsLayer.h"
-#include "WebLayer.h"
+#include "Image.h"
+#include "PlatformCAAnimation.h"
#include <wtf/HashMap.h>
#include <wtf/HashSet.h>
#include <wtf/RetainPtr.h>
#include <wtf/text/StringHash.h>
-@class CABasicAnimation;
-@class CAKeyframeAnimation;
-@class CAMediaTimingFunction;
-@class CAPropertyAnimation;
-@class WebAnimationDelegate;
-
namespace WebCore {
-class GraphicsLayerMac : public GraphicsLayer {
+class PlatformCALayer;
+
+class GraphicsLayerCA : public GraphicsLayer {
public:
+ // The width and height of a single tile in a tiled layer. Should be large enough to
+ // avoid lots of small tiles (and therefore lots of drawing callbacks), but small enough
+ // to keep the overall tile cost low.
+ static const int kTiledLayerTileSize = 512;
- GraphicsLayerMac(GraphicsLayerClient*);
- virtual ~GraphicsLayerMac();
+ GraphicsLayerCA(GraphicsLayerClient*);
+ virtual ~GraphicsLayerCA();
+
+ virtual void animationStarted(CFTimeInterval beginTime);
virtual void setName(const String&);
- // for hosting this GraphicsLayer in a native layer hierarchy
- virtual NativeLayer nativeLayer() const;
+ virtual PlatformLayer* platformLayer() const;
virtual bool setChildren(const Vector<GraphicsLayer*>&);
virtual void addChild(GraphicsLayer*);
@@ -77,6 +79,7 @@ public:
virtual void setPreserves3D(bool);
virtual void setMasksToBounds(bool);
virtual void setDrawsContent(bool);
+ virtual void setAcceleratesDrawing(bool);
virtual void setBackgroundColor(const Color&);
virtual void clearBackgroundColor();
@@ -106,8 +109,6 @@ public:
virtual bool hasContentsLayer() const { return m_contentsLayer; }
- virtual PlatformLayer* platformLayer() const;
-
virtual void setDebugBackgroundColor(const Color&);
virtual void setDebugBorder(const Color&, float borderWidth);
@@ -118,24 +119,21 @@ public:
virtual void syncCompositingState();
virtual void syncCompositingStateForThisLayerOnly();
- // Should only be called by animationDidStart: callback
- void animationDidStart(CAAnimation*);
-
protected:
virtual void setOpacityInternal(float);
private:
void updateOpacityOnLayer();
- CALayer* primaryLayer() const { return m_structuralLayer.get() ? m_structuralLayer.get() : m_layer.get(); }
- CALayer* hostLayerForSublayers() const;
- CALayer* layerForSuperlayer() const;
- CALayer* animatedLayer(AnimatedPropertyID) const;
+ PlatformCALayer* primaryLayer() const { return m_structuralLayer.get() ? m_structuralLayer.get() : m_layer.get(); }
+ PlatformCALayer* hostLayerForSublayers() const;
+ PlatformCALayer* layerForSuperlayer() const;
+ PlatformCALayer* animatedLayer(AnimatedPropertyID) const;
typedef String CloneID; // Identifier for a given clone, based on original/replica branching down the tree.
static bool isReplicatedRootClone(const CloneID& cloneID) { return cloneID[0U] & 1; }
- typedef HashMap<CloneID, RetainPtr<CALayer> > LayerMap;
+ typedef HashMap<CloneID, RefPtr<PlatformCALayer> > LayerMap;
LayerMap* primaryLayerClones() const { return m_structuralLayer.get() ? m_structuralLayerClones.get() : m_layerClones.get(); }
LayerMap* animatedLayerClones(AnimatedPropertyID) const;
@@ -143,17 +141,17 @@ private:
bool createTransformAnimationsFromKeyframes(const KeyframeValueList&, const Animation*, const String& animationName, double timeOffset, const IntSize& boxSize);
// Return autoreleased animation (use RetainPtr?)
- CABasicAnimation* createBasicAnimation(const Animation*, AnimatedPropertyID, bool additive);
- CAKeyframeAnimation* createKeyframeAnimation(const Animation*, AnimatedPropertyID, bool additive);
- void setupAnimation(CAPropertyAnimation*, const Animation*, bool additive);
+ PassRefPtr<PlatformCAAnimation> createBasicAnimation(const Animation*, AnimatedPropertyID, bool additive);
+ PassRefPtr<PlatformCAAnimation> createKeyframeAnimation(const Animation*, AnimatedPropertyID, bool additive);
+ void setupAnimation(PlatformCAAnimation*, const Animation*, bool additive);
- CAMediaTimingFunction* timingFunctionForAnimationValue(const AnimationValue*, const Animation*);
+ const TimingFunction* timingFunctionForAnimationValue(const AnimationValue*, const Animation*);
- bool setAnimationEndpoints(const KeyframeValueList&, const Animation*, CABasicAnimation*);
- bool setAnimationKeyframes(const KeyframeValueList&, const Animation*, CAKeyframeAnimation*);
+ bool setAnimationEndpoints(const KeyframeValueList&, const Animation*, PlatformCAAnimation*);
+ bool setAnimationKeyframes(const KeyframeValueList&, const Animation*, PlatformCAAnimation*);
- bool setTransformAnimationEndpoints(const KeyframeValueList&, const Animation*, CABasicAnimation*, int functionIndex, TransformOperation::OperationType, bool isMatrixAnimation, const IntSize& boxSize);
- bool setTransformAnimationKeyframes(const KeyframeValueList&, const Animation*, CAKeyframeAnimation*, int functionIndex, TransformOperation::OperationType, bool isMatrixAnimation, const IntSize& boxSize);
+ bool setTransformAnimationEndpoints(const KeyframeValueList&, const Animation*, PlatformCAAnimation*, int functionIndex, TransformOperation::OperationType, bool isMatrixAnimation, const IntSize& boxSize);
+ bool setTransformAnimationKeyframes(const KeyframeValueList&, const Animation*, PlatformCAAnimation*, int functionIndex, TransformOperation::OperationType, bool isMatrixAnimation, const IntSize& boxSize);
bool animationIsRunning(const String& animationName) const
{
@@ -171,8 +169,8 @@ private:
CompositingCoordinatesOrientation defaultContentsOrientation() const;
void updateContentsTransform();
- void setupContentsLayer(CALayer*);
- CALayer* contentsLayer() const { return m_contentsLayer.get(); }
+ void setupContentsLayer(PlatformCALayer*);
+ PlatformCALayer* contentsLayer() const { return m_contentsLayer.get(); }
virtual void setReplicatedByLayer(GraphicsLayer*);
@@ -224,15 +222,15 @@ private:
Vector<ReplicaBranchType> m_replicaBranches;
size_t m_replicaDepth;
};
- CALayer *replicatedLayerRoot(ReplicaState&);
+ PassRefPtr<PlatformCALayer>replicatedLayerRoot(ReplicaState&);
enum CloneLevel { RootCloneLevel, IntermediateCloneLevel };
- CALayer *fetchCloneLayers(GraphicsLayer* replicaRoot, ReplicaState&, CloneLevel);
+ PassRefPtr<PlatformCALayer> fetchCloneLayers(GraphicsLayer* replicaRoot, ReplicaState&, CloneLevel);
- CALayer *cloneLayer(CALayer *, CloneLevel);
- CALayer *findOrMakeClone(CloneID, CALayer *, LayerMap*, CloneLevel);
+ PassRefPtr<PlatformCALayer> cloneLayer(PlatformCALayer *, CloneLevel);
+ PassRefPtr<PlatformCALayer> findOrMakeClone(CloneID, PlatformCALayer *, LayerMap*, CloneLevel);
- void ensureCloneLayers(CloneID index, CALayer *& primaryLayer, CALayer *& structuralLayer, CALayer *& contentsLayer, CloneLevel);
+ void ensureCloneLayers(CloneID cloneID, RefPtr<PlatformCALayer>& primaryLayer, RefPtr<PlatformCALayer>& structuralLayer, RefPtr<PlatformCALayer>& contentsLayer, CloneLevel cloneLevel);
bool hasCloneLayers() const { return m_layerClones; }
void removeCloneLayers();
@@ -264,6 +262,7 @@ private:
void updateLayerAnimations();
void updateContentsNeedsDisplay();
+ void updateAcceleratesDrawing();
enum StructuralLayerPurpose {
NoStructuralLayer = 0,
@@ -273,18 +272,18 @@ private:
void ensureStructuralLayer(StructuralLayerPurpose);
StructuralLayerPurpose structuralLayerPurpose() const;
- void setCAAnimationOnLayer(CAPropertyAnimation*, AnimatedPropertyID, const String& animationName, int index, double timeOffset);
+ void setAnimationOnLayer(PlatformCAAnimation*, AnimatedPropertyID, const String& animationName, int index, double timeOffset);
bool removeCAAnimationFromLayer(AnimatedPropertyID, const String& animationName, int index);
void pauseCAAnimationOnLayer(AnimatedPropertyID, const String& animationName, int index, double timeOffset);
enum MoveOrCopy { Move, Copy };
- static void moveOrCopyLayerAnimation(MoveOrCopy, const String& animationIdentifier, CALayer *fromLayer, CALayer *toLayer);
- void moveOrCopyAnimationsForProperty(MoveOrCopy, AnimatedPropertyID, CALayer * fromLayer, CALayer * toLayer);
+ static void moveOrCopyLayerAnimation(MoveOrCopy, const String& animationIdentifier, PlatformCALayer *fromLayer, PlatformCALayer *toLayer);
+ void moveOrCopyAnimationsForProperty(MoveOrCopy, AnimatedPropertyID, PlatformCALayer * fromLayer, PlatformCALayer * toLayer);
enum LayerChange {
NoChange = 0,
NameChanged = 1 << 1,
- ChildrenChanged = 1 << 2, // also used for content layer, and preserves-3d, and size if tiling changes?
+ ChildrenChanged = 1 << 2, // also used for content layer, and preserves-3d, and size if tiling changes?
PositionChanged = 1 << 3,
AnchorPointChanged = 1 << 4,
SizeChanged = 1 << 5,
@@ -292,7 +291,7 @@ private:
ChildrenTransformChanged = 1 << 7,
Preserves3DChanged = 1 << 8,
MasksToBoundsChanged = 1 << 9,
- DrawsContentChanged = 1 << 10, // need this?
+ DrawsContentChanged = 1 << 10, // need this?
BackgroundColorChanged = 1 << 11,
ContentsOpaqueChanged = 1 << 12,
BackfaceVisibilityChanged = 1 << 13,
@@ -305,7 +304,8 @@ private:
ContentsRectChanged = 1 << 20,
MaskLayerChanged = 1 << 21,
ReplicatedLayerChanged = 1 << 22,
- ContentsNeedsDisplay = 1 << 23
+ ContentsNeedsDisplay = 1 << 23,
+ AcceleratesDrawingChanged = 1 << 24
};
typedef unsigned LayerChangeFlags;
void noteLayerPropertyChanged(LayerChangeFlags flags);
@@ -313,9 +313,9 @@ private:
void repaintLayerDirtyRects();
- RetainPtr<WebLayer> m_layer; // The main layer
- RetainPtr<CALayer> m_structuralLayer; // A layer used for structural reasons, like preserves-3d or replica-flattening. Is the parent of m_layer.
- RetainPtr<CALayer> m_contentsLayer; // A layer used for inner content, like image and video
+ RefPtr<PlatformCALayer> m_layer; // The main layer
+ RefPtr<PlatformCALayer> m_structuralLayer; // A layer used for structural reasons, like preserves-3d or replica-flattening. Is the parent of m_layer.
+ RefPtr<PlatformCALayer> m_contentsLayer; // A layer used for inner content, like image and video
// References to clones of our layers, for replicated layers.
OwnPtr<LayerMap> m_layerClones;
@@ -332,15 +332,13 @@ private:
ContentsLayerPurpose m_contentsLayerPurpose;
bool m_contentsLayerHasBackgroundColor : 1;
- RetainPtr<WebAnimationDelegate> m_animationDelegate;
-
RetainPtr<CGImageRef> m_uncorrectedContentsImage;
RetainPtr<CGImageRef> m_pendingContentsImage;
// This represents the animation of a single property. There may be multiple transform animations for
// a single transition or keyframe animation, so index is used to distinguish these.
struct LayerPropertyAnimation {
- LayerPropertyAnimation(CAPropertyAnimation* caAnimation, const String& animationName, AnimatedPropertyID property, int index, double timeOffset)
+ LayerPropertyAnimation(PassRefPtr<PlatformCAAnimation> caAnimation, const String& animationName, AnimatedPropertyID property, int index, double timeOffset)
: m_animation(caAnimation)
, m_name(animationName)
, m_property(property)
@@ -348,7 +346,7 @@ private:
, m_timeOffset(timeOffset)
{ }
- RetainPtr<CAPropertyAnimation*> m_animation;
+ RefPtr<PlatformCAAnimation> m_animation;
String m_name;
AnimatedPropertyID m_property;
int m_index;
@@ -385,4 +383,4 @@ private:
#endif // USE(ACCELERATED_COMPOSITING)
-#endif // GraphicsLayerMac_h
+#endif // GraphicsLayerCA_h
diff --git a/WebCore/platform/graphics/ca/PlatformCAAnimation.h b/WebCore/platform/graphics/ca/PlatformCAAnimation.h
new file mode 100644
index 0000000..d802700
--- /dev/null
+++ b/WebCore/platform/graphics/ca/PlatformCAAnimation.h
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2010 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 COMPUTER, 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.
+ */
+
+#ifndef PlatformCAAnimation_h
+#define PlatformCAAnimation_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "Color.h"
+#include "FloatPoint3D.h"
+#include "TransformationMatrix.h"
+#include <wtf/RefCounted.h>
+#include <wtf/RetainPtr.h>
+#include <wtf/Vector.h>
+
+#if PLATFORM(MAC)
+#ifdef __OBJC__
+@class CAPropertyAnimation;
+typedef CAPropertyAnimation* PlatformAnimationRef;
+#else
+typedef void* CAPropertyAnimation; // So the m_animation declaration works
+typedef void* PlatformAnimationRef;
+#endif
+#elif PLATFORM(WIN)
+namespace WebCore {
+class WKCACFAnimation;
+typedef WKCACFAnimation* PlatformAnimationRef;
+}
+#endif
+
+namespace WebCore {
+
+class FloatRect;
+class PlatformCAAnimation;
+class TimingFunction;
+
+class PlatformCAAnimation : public RefCounted<PlatformCAAnimation> {
+public:
+ friend class PlatformCALayer;
+
+ enum AnimationType { Basic, Keyframe };
+ enum FillModeType { NoFillMode, Forwards, Backwards, Both };
+ enum ValueFunctionType { NoValueFunction, RotateX, RotateY, RotateZ, ScaleX, ScaleY, ScaleZ, Scale, TranslateX, TranslateY, TranslateZ, Translate };
+
+ static PassRefPtr<PlatformCAAnimation> create(AnimationType, const String& keyPath);
+ static PassRefPtr<PlatformCAAnimation> create(PlatformAnimationRef animation);
+ static PassRefPtr<PlatformCAAnimation> create(const PlatformCAAnimation* animation);
+
+ ~PlatformCAAnimation();
+
+ static bool supportsValueFunction();
+
+ PlatformAnimationRef platformAnimation() const;
+
+ AnimationType animationType() const { return m_type; }
+ String keyPath() const;
+
+ CFTimeInterval beginTime() const;
+ void setBeginTime(CFTimeInterval);
+
+ CFTimeInterval duration() const;
+ void setDuration(CFTimeInterval);
+
+ float speed() const;
+ void setSpeed(float);
+
+ CFTimeInterval timeOffset() const;
+ void setTimeOffset(CFTimeInterval);
+
+ float repeatCount() const;
+ void setRepeatCount(float);
+
+ bool autoreverses() const;
+ void setAutoreverses(bool);
+
+ FillModeType fillMode() const;
+ void setFillMode(FillModeType);
+
+ void setTimingFunction(const TimingFunction*);
+ void copyTimingFunctionFrom(const PlatformCAAnimation*);
+
+ bool isRemovedOnCompletion() const;
+ void setRemovedOnCompletion(bool);
+
+ bool isAdditive() const;
+ void setAdditive(bool);
+
+ ValueFunctionType valueFunction() const;
+ void setValueFunction(ValueFunctionType);
+
+ // Basic-animation properties.
+ void setFromValue(float);
+ void setFromValue(const WebCore::TransformationMatrix&);
+ void setFromValue(const FloatPoint3D&);
+ void setFromValue(const WebCore::Color&);
+ void copyFromValueFrom(const PlatformCAAnimation*);
+
+ void setToValue(float);
+ void setToValue(const WebCore::TransformationMatrix&);
+ void setToValue(const FloatPoint3D&);
+ void setToValue(const WebCore::Color&);
+ void copyToValueFrom(const PlatformCAAnimation*);
+
+ // Keyframe-animation properties.
+ void setValues(const Vector<float>&);
+ void setValues(const Vector<WebCore::TransformationMatrix>&);
+ void setValues(const Vector<FloatPoint3D>&);
+ void setValues(const Vector<WebCore::Color>&);
+ void copyValuesFrom(const PlatformCAAnimation*);
+
+ void setKeyTimes(const Vector<float>&);
+ void copyKeyTimesFrom(const PlatformCAAnimation*);
+
+ void setTimingFunctions(const Vector<const TimingFunction*>&);
+ void copyTimingFunctionsFrom(const PlatformCAAnimation*);
+
+protected:
+ PlatformCAAnimation(AnimationType, const String& keyPath);
+ PlatformCAAnimation(PlatformAnimationRef animation);
+ PlatformCAAnimation(const PlatformCAAnimation* animation);
+
+private:
+ AnimationType m_type;
+
+#if PLATFORM(MAC)
+ RetainPtr<CAPropertyAnimation> m_animation;
+#elif PLATFORM(WIN)
+ RetainPtr<CACFAnimationRef> m_animation;
+#endif
+};
+
+}
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif // PlatformCAAnimation_h
diff --git a/WebCore/platform/graphics/ca/PlatformCALayer.h b/WebCore/platform/graphics/ca/PlatformCALayer.h
new file mode 100644
index 0000000..9cf0ccb
--- /dev/null
+++ b/WebCore/platform/graphics/ca/PlatformCALayer.h
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2010 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 COMPUTER, 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.
+ */
+
+#ifndef PlatformCALayer_h
+#define PlatformCALayer_h
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "GraphicsContext.h"
+#include "GraphicsLayerCA.h"
+#include "PlatformCAAnimation.h"
+#include "PlatformString.h"
+#include <wtf/HashMap.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RetainPtr.h>
+#include <wtf/Vector.h>
+#include <wtf/text/StringHash.h>
+
+namespace WebCore {
+
+class PlatformCALayer;
+
+typedef Vector<RefPtr<PlatformCALayer> > PlatformCALayerList;
+
+class PlatformCALayer : public RefCounted<PlatformCALayer> {
+public:
+ // TiledLayer used in GraphicsLayer has constant settings:
+ // cTiledLayerTileSize = 512
+ // setTileSize:(cTiledLayerTileSize, cTiledLayerTileSize)
+ // setLevelsOfDetail:1
+ // setLevelsOfDetailBias:0
+ // setContentsGravity:@"bottomLeft"
+ //
+ // TiledLayer also has drawing functions like WebLayer
+ //
+ // WebLayer is a CALayer with drawing functions specific to WebKit
+ //
+ // Layer and TransformLayer are used as is
+
+ enum LayerType { LayerTypeLayer, LayerTypeWebLayer, LayerTypeTransformLayer, LayerTypeWebTiledLayer, LayerTypeCustom };
+ enum FilterType { Linear, Nearest, Trilinear };
+
+ static PassRefPtr<PlatformCALayer> create(LayerType, GraphicsLayerCA*);
+
+ // This function passes the layer as a void* rather than a PlatformLayer because PlatformLayer
+ // is defined differently for Obj C and C++. This allows callers from both languages.
+ static PassRefPtr<PlatformCALayer> create(void* platformLayer, GraphicsLayerCA*);
+
+ ~PlatformCALayer();
+
+ // This function passes the layer as a void* rather than a PlatformLayer because PlatformLayer
+ // is defined differently for Obj C and C++. This allows callers from both languages.
+ static PlatformCALayer* platformCALayer(void* platformLayer);
+
+ PlatformLayer* platformLayer() const;
+
+ static bool isValueFunctionSupported();
+
+ GraphicsLayerCA* owner() const { return m_owner; }
+ void setOwner(GraphicsLayerCA* owner);
+
+ void animationStarted(CFTimeInterval beginTime)
+ {
+ if (m_owner)
+ m_owner->animationStarted(beginTime);
+ }
+
+ void setNeedsDisplay(const FloatRect* dirtyRect = 0);
+
+ void setContentsChanged();
+
+ LayerType layerType() const { return m_layerType; }
+
+ PlatformCALayer* superlayer() const;
+ void removeFromSuperlayer();
+ void setSublayers(const PlatformCALayerList&);
+ void removeAllSublayers();
+ void appendSublayer(PlatformCALayer*);
+ void insertSublayer(PlatformCALayer*, size_t index);
+ void replaceSublayer(PlatformCALayer* reference, PlatformCALayer*);
+ size_t sublayerCount() const;
+
+ // This method removes the sublayers from the source and reparents them to the current layer.
+ void adoptSublayers(PlatformCALayer* source);
+
+ void addAnimationForKey(const String& key, PlatformCAAnimation* animation);
+ void removeAnimationForKey(const String& key);
+ PassRefPtr<PlatformCAAnimation> animationForKey(const String& key);
+
+ PlatformCALayer* mask() const;
+ void setMask(PlatformCALayer*);
+
+ bool isOpaque() const;
+ void setOpaque(bool);
+
+ FloatRect bounds() const;
+ void setBounds(const FloatRect&);
+
+ FloatPoint3D position() const;
+ void setPosition(const FloatPoint3D&);
+ void setPosition(const FloatPoint& pos) { setPosition(FloatPoint3D(pos.x(), pos.y(), 0)); }
+
+ FloatPoint3D anchorPoint() const;
+ void setAnchorPoint(const FloatPoint3D&);
+
+ TransformationMatrix transform() const;
+ void setTransform(const TransformationMatrix&);
+
+ TransformationMatrix sublayerTransform() const;
+ void setSublayerTransform(const TransformationMatrix&);
+
+ TransformationMatrix contentsTransform() const;
+ void setContentsTransform(const TransformationMatrix&);
+
+ bool isHidden() const;
+ void setHidden(bool);
+
+ bool isGeometryFlipped() const;
+ void setGeometryFlipped(bool);
+
+ bool isDoubleSided() const;
+ void setDoubleSided(bool);
+
+ bool masksToBounds() const;
+ void setMasksToBounds(bool);
+
+ bool acceleratesDrawing() const;
+ void setAcceleratesDrawing(bool);
+
+ void* contents() const;
+ void setContents(void*);
+
+ FloatRect contentsRect() const;
+ void setContentsRect(const FloatRect&);
+
+ void setMinificationFilter(FilterType);
+ void setMagnificationFilter(FilterType);
+
+ Color backgroundColor() const;
+ void setBackgroundColor(const Color&);
+
+ float borderWidth() const;
+ void setBorderWidth(float);
+
+ Color borderColor() const;
+ void setBorderColor(const Color&);
+
+ float opacity() const;
+ void setOpacity(float);
+
+ String name() const;
+ void setName(const String&);
+
+ FloatRect frame() const;
+ void setFrame(const FloatRect&);
+
+ float speed() const;
+ void setSpeed(float);
+
+ CFTimeInterval timeOffset() const;
+ void setTimeOffset(CFTimeInterval);
+
+protected:
+ PlatformCALayer(LayerType, PlatformLayer*, GraphicsLayerCA*);
+
+private:
+
+ GraphicsLayerCA* m_owner;
+ LayerType m_layerType;
+
+#if PLATFORM(MAC) || PLATFORM(WIN)
+ RetainPtr<PlatformLayer> m_layer;
+#endif
+
+#if PLATFORM(MAC)
+#ifdef __OBJC__
+ RetainPtr<NSObject> m_delegate;
+#else
+ RetainPtr<void> m_delegate;
+#endif
+#endif
+};
+
+}
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
+#endif // PlatformCALayer_h
diff --git a/WebCore/platform/graphics/ca/TransformationMatrixCA.cpp b/WebCore/platform/graphics/ca/TransformationMatrixCA.cpp
new file mode 100644
index 0000000..27805e6
--- /dev/null
+++ b/WebCore/platform/graphics/ca/TransformationMatrixCA.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2010 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 COMPUTER, 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"
+
+#if PLATFORM(CA)
+
+#include "TransformationMatrix.h"
+
+#include "FloatConversion.h"
+
+namespace WebCore {
+
+TransformationMatrix::TransformationMatrix(const CATransform3D& t)
+{
+ setMatrix(
+ t.m11, t.m12, t.m13, t.m14,
+ t.m21, t.m22, t.m23, t.m24,
+ t.m31, t.m32, t.m33, t.m34,
+ t.m41, t.m42, t.m43, t.m44);
+}
+
+TransformationMatrix::operator CATransform3D() const
+{
+ CATransform3D toT3D;
+ toT3D.m11 = narrowPrecisionToFloat(m11());
+ toT3D.m12 = narrowPrecisionToFloat(m12());
+ toT3D.m13 = narrowPrecisionToFloat(m13());
+ toT3D.m14 = narrowPrecisionToFloat(m14());
+ toT3D.m21 = narrowPrecisionToFloat(m21());
+ toT3D.m22 = narrowPrecisionToFloat(m22());
+ toT3D.m23 = narrowPrecisionToFloat(m23());
+ toT3D.m24 = narrowPrecisionToFloat(m24());
+ toT3D.m31 = narrowPrecisionToFloat(m31());
+ toT3D.m32 = narrowPrecisionToFloat(m32());
+ toT3D.m33 = narrowPrecisionToFloat(m33());
+ toT3D.m34 = narrowPrecisionToFloat(m34());
+ toT3D.m41 = narrowPrecisionToFloat(m41());
+ toT3D.m42 = narrowPrecisionToFloat(m42());
+ toT3D.m43 = narrowPrecisionToFloat(m43());
+ toT3D.m44 = narrowPrecisionToFloat(m44());
+ return toT3D;
+}
+
+}
+
+#endif // PLATFORM(CA)
diff --git a/WebCore/platform/graphics/ca/mac/PlatformCAAnimationMac.mm b/WebCore/platform/graphics/ca/mac/PlatformCAAnimationMac.mm
new file mode 100644
index 0000000..2a00857
--- /dev/null
+++ b/WebCore/platform/graphics/ca/mac/PlatformCAAnimationMac.mm
@@ -0,0 +1,574 @@
+/*
+ * Copyright (C) 2010 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 COMPUTER, 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"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#import "PlatformCAAnimation.h"
+
+#import "FloatConversion.h"
+#import "PlatformString.h"
+#import "TimingFunction.h"
+#import <QuartzCore/QuartzCore.h>
+#import <wtf/UnusedParam.h>
+
+#define HAVE_MODERN_QUARTZCORE (!defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD))
+
+using namespace WebCore;
+
+// This value must be the same as in PlatformCALayerMac.mm
+static NSString * const WKNonZeroBeginTimeFlag = @"WKPlatformCAAnimationNonZeroBeginTimeFlag";
+
+static bool hasNonZeroBeginTimeFlag(const PlatformCAAnimation* animation)
+{
+ return [[animation->platformAnimation() valueForKey:WKNonZeroBeginTimeFlag] boolValue];
+}
+
+static void setNonZeroBeginTimeFlag(PlatformCAAnimation* animation, bool value)
+{
+ [animation->platformAnimation() setValue:[NSNumber numberWithBool:value] forKey:WKNonZeroBeginTimeFlag];
+}
+
+static NSString* toCAFillModeType(PlatformCAAnimation::FillModeType type)
+{
+ switch (type) {
+ case PlatformCAAnimation::NoFillMode:
+ case PlatformCAAnimation::Forwards: return kCAFillModeForwards;
+ case PlatformCAAnimation::Backwards: return kCAFillModeBackwards;
+ case PlatformCAAnimation::Both: return kCAFillModeBoth;
+ }
+ return @"";
+}
+
+static PlatformCAAnimation::FillModeType fromCAFillModeType(NSString* string)
+{
+ if ([string isEqualToString:kCAFillModeBackwards])
+ return PlatformCAAnimation::Backwards;
+
+ if ([string isEqualToString:kCAFillModeBoth])
+ return PlatformCAAnimation::Both;
+
+ return PlatformCAAnimation::Forwards;
+}
+
+#if HAVE_MODERN_QUARTZCORE
+static NSString* toCAValueFunctionType(PlatformCAAnimation::ValueFunctionType type)
+{
+ switch (type) {
+ case PlatformCAAnimation::NoValueFunction: return @"";
+ case PlatformCAAnimation::RotateX: return kCAValueFunctionRotateX;
+ case PlatformCAAnimation::RotateY: return kCAValueFunctionRotateY;
+ case PlatformCAAnimation::RotateZ: return kCAValueFunctionRotateZ;
+ case PlatformCAAnimation::ScaleX: return kCAValueFunctionScaleX;
+ case PlatformCAAnimation::ScaleY: return kCAValueFunctionScaleY;
+ case PlatformCAAnimation::ScaleZ: return kCAValueFunctionScaleZ;
+ case PlatformCAAnimation::Scale: return kCAValueFunctionScale;
+ case PlatformCAAnimation::TranslateX: return kCAValueFunctionTranslateX;
+ case PlatformCAAnimation::TranslateY: return kCAValueFunctionTranslateY;
+ case PlatformCAAnimation::TranslateZ: return kCAValueFunctionTranslateZ;
+ case PlatformCAAnimation::Translate: return kCAValueFunctionTranslate;
+ }
+ return @"";
+}
+
+static PlatformCAAnimation::ValueFunctionType fromCAValueFunctionType(NSString* string)
+{
+ if ([string isEqualToString:kCAValueFunctionRotateX])
+ return PlatformCAAnimation::RotateX;
+
+ if ([string isEqualToString:kCAValueFunctionRotateY])
+ return PlatformCAAnimation::RotateY;
+
+ if ([string isEqualToString:kCAValueFunctionRotateZ])
+ return PlatformCAAnimation::RotateZ;
+
+ if ([string isEqualToString:kCAValueFunctionScaleX])
+ return PlatformCAAnimation::ScaleX;
+
+ if ([string isEqualToString:kCAValueFunctionScaleY])
+ return PlatformCAAnimation::ScaleY;
+
+ if ([string isEqualToString:kCAValueFunctionScaleZ])
+ return PlatformCAAnimation::ScaleZ;
+
+ if ([string isEqualToString:kCAValueFunctionScale])
+ return PlatformCAAnimation::Scale;
+
+ if ([string isEqualToString:kCAValueFunctionTranslateX])
+ return PlatformCAAnimation::TranslateX;
+
+ if ([string isEqualToString:kCAValueFunctionTranslateY])
+ return PlatformCAAnimation::TranslateY;
+
+ if ([string isEqualToString:kCAValueFunctionTranslateZ])
+ return PlatformCAAnimation::TranslateZ;
+
+ if ([string isEqualToString:kCAValueFunctionTranslate])
+ return PlatformCAAnimation::Translate;
+
+ return PlatformCAAnimation::NoValueFunction;
+}
+#endif
+
+static CAMediaTimingFunction* toCAMediaTimingFunction(const TimingFunction* timingFunction)
+{
+ if (!timingFunction)
+ return [CAMediaTimingFunction functionWithControlPoints:0.25f :0.1f :0.25f :0.1f];
+
+ if (timingFunction->isCubicBezierTimingFunction()) {
+ const CubicBezierTimingFunction* ctf = static_cast<const CubicBezierTimingFunction*>(timingFunction);
+ return [CAMediaTimingFunction functionWithControlPoints:static_cast<float>(ctf->x1()) :static_cast<float>(ctf->y1())
+ :static_cast<float>(ctf->x2()) :static_cast<float>(ctf->y2())];
+ }
+
+ return [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
+
+ return 0;
+}
+
+PassRefPtr<PlatformCAAnimation> PlatformCAAnimation::create(AnimationType type, const String& keyPath)
+{
+ return adoptRef(new PlatformCAAnimation(type, keyPath));
+}
+
+PassRefPtr<PlatformCAAnimation> PlatformCAAnimation::create(PlatformAnimationRef animation)
+{
+ return adoptRef(new PlatformCAAnimation(animation));
+}
+
+PassRefPtr<PlatformCAAnimation> PlatformCAAnimation::create(const PlatformCAAnimation* animation)
+{
+ return adoptRef(new PlatformCAAnimation(animation));
+}
+
+PlatformCAAnimation::PlatformCAAnimation(AnimationType type, const String& keyPath)
+ : m_type(type)
+{
+ if (type == Basic)
+ m_animation.adoptNS([[CABasicAnimation animationWithKeyPath:keyPath] retain]);
+ else
+ m_animation.adoptNS([[CAKeyframeAnimation animationWithKeyPath:keyPath] retain]);
+}
+
+PlatformCAAnimation::PlatformCAAnimation(PlatformAnimationRef animation)
+{
+ if ([static_cast<CAAnimation*>(animation) isKindOfClass:[CABasicAnimation class]])
+ m_type = Basic;
+ else if ([static_cast<CAAnimation*>(animation) isKindOfClass:[CAKeyframeAnimation class]])
+ m_type = Keyframe;
+ else {
+ ASSERT(0);
+ return;
+ }
+
+ m_animation = static_cast<CAPropertyAnimation*>(animation);
+}
+
+PlatformCAAnimation::PlatformCAAnimation(const PlatformCAAnimation* animation)
+{
+ PlatformCAAnimation* newAnimation = new PlatformCAAnimation(animation->animationType(), animation->keyPath());
+
+ newAnimation->setBeginTime(animation->beginTime());
+ newAnimation->setDuration(animation->duration());
+ newAnimation->setSpeed(animation->speed());
+ newAnimation->setTimeOffset(animation->timeOffset());
+ newAnimation->setRepeatCount(animation->repeatCount());
+ newAnimation->setAutoreverses(animation->autoreverses());
+ newAnimation->setFillMode(animation->fillMode());
+ newAnimation->setRemovedOnCompletion(animation->isRemovedOnCompletion());
+ newAnimation->setAdditive(animation->isAdditive());
+ newAnimation->copyTimingFunctionFrom(animation);
+
+#if HAVE_MODERN_QUARTZCORE
+ newAnimation->setValueFunction(animation->valueFunction());
+#endif
+
+ setNonZeroBeginTimeFlag(newAnimation, hasNonZeroBeginTimeFlag(animation));
+
+ // Copy the specific Basic or Keyframe values
+ if (animation->animationType() == Keyframe) {
+ newAnimation->copyValuesFrom(animation);
+ newAnimation->copyKeyTimesFrom(animation);
+ newAnimation->copyTimingFunctionsFrom(animation);
+ } else {
+ newAnimation->copyFromValueFrom(animation);
+ newAnimation->copyToValueFrom(animation);
+ }
+}
+
+PlatformCAAnimation::~PlatformCAAnimation()
+{
+}
+
+bool PlatformCAAnimation::supportsValueFunction()
+{
+ static bool sHaveValueFunction = [CAPropertyAnimation instancesRespondToSelector:@selector(setValueFunction:)];
+ return sHaveValueFunction;
+}
+
+PlatformAnimationRef PlatformCAAnimation::platformAnimation() const
+{
+ return m_animation.get();
+}
+
+String PlatformCAAnimation::keyPath() const
+{
+ return [m_animation.get() keyPath];
+}
+
+CFTimeInterval PlatformCAAnimation::beginTime() const
+{
+ return [m_animation.get() beginTime];
+}
+
+void PlatformCAAnimation::setBeginTime(CFTimeInterval value)
+{
+ [m_animation.get() setBeginTime:value];
+
+ // Also set a flag to tell us if we've passed in a 0 value.
+ // The flag is needed because later beginTime will get changed
+ // to the time at which it fired and we need to know whether
+ // or not it was 0 to begin with.
+ if (value)
+ setNonZeroBeginTimeFlag(this, true);
+}
+
+CFTimeInterval PlatformCAAnimation::duration() const
+{
+ return [m_animation.get() duration];
+}
+
+void PlatformCAAnimation::setDuration(CFTimeInterval value)
+{
+ [m_animation.get() setDuration:value];
+}
+
+float PlatformCAAnimation::speed() const
+{
+ return [m_animation.get() speed];
+}
+
+void PlatformCAAnimation::setSpeed(float value)
+{
+ [m_animation.get() setSpeed:value];
+}
+
+CFTimeInterval PlatformCAAnimation::timeOffset() const
+{
+ return [m_animation.get() timeOffset];
+}
+
+void PlatformCAAnimation::setTimeOffset(CFTimeInterval value)
+{
+ [m_animation.get() setTimeOffset:value];
+}
+
+float PlatformCAAnimation::repeatCount() const
+{
+ return [m_animation.get() repeatCount];
+}
+
+void PlatformCAAnimation::setRepeatCount(float value)
+{
+ [m_animation.get() setRepeatCount:value];
+}
+
+bool PlatformCAAnimation::autoreverses() const
+{
+ return [m_animation.get() autoreverses];
+}
+
+void PlatformCAAnimation::setAutoreverses(bool value)
+{
+ [m_animation.get() setAutoreverses:value];
+}
+
+PlatformCAAnimation::FillModeType PlatformCAAnimation::fillMode() const
+{
+ return fromCAFillModeType([m_animation.get() fillMode]);
+}
+
+void PlatformCAAnimation::setFillMode(FillModeType value)
+{
+ [m_animation.get() setFillMode:toCAFillModeType(value)];
+}
+
+void PlatformCAAnimation::setTimingFunction(const TimingFunction* value)
+{
+ [m_animation.get() setTimingFunction:toCAMediaTimingFunction(value)];
+}
+
+void PlatformCAAnimation::copyTimingFunctionFrom(const PlatformCAAnimation* value)
+{
+ [m_animation.get() setTimingFunction:[value->m_animation.get() timingFunction]];
+}
+
+bool PlatformCAAnimation::isRemovedOnCompletion() const
+{
+ return [m_animation.get() isRemovedOnCompletion];
+}
+
+void PlatformCAAnimation::setRemovedOnCompletion(bool value)
+{
+ [m_animation.get() setRemovedOnCompletion:value];
+}
+
+bool PlatformCAAnimation::isAdditive() const
+{
+ return [m_animation.get() isAdditive];
+}
+
+void PlatformCAAnimation::setAdditive(bool value)
+{
+ [m_animation.get() setAdditive:value];
+}
+
+PlatformCAAnimation::ValueFunctionType PlatformCAAnimation::valueFunction() const
+{
+#if HAVE_MODERN_QUARTZCORE
+ CAValueFunction* vf = [m_animation.get() valueFunction];
+ return fromCAValueFunctionType([vf name]);
+#else
+ return NoValueFunction;
+#endif
+}
+
+void PlatformCAAnimation::setValueFunction(ValueFunctionType value)
+{
+#if HAVE_MODERN_QUARTZCORE
+ [m_animation.get() setValueFunction:[CAValueFunction functionWithName:toCAValueFunctionType(value)]];
+#else
+ UNUSED_PARAM(value);
+#endif
+}
+
+void PlatformCAAnimation::setFromValue(float value)
+{
+ if (animationType() != Basic)
+ return;
+ [static_cast<CABasicAnimation*>(m_animation.get()) setFromValue:[NSNumber numberWithDouble:value]];
+}
+
+void PlatformCAAnimation::setFromValue(const WebCore::TransformationMatrix& value)
+{
+ if (animationType() != Basic)
+ return;
+
+ [static_cast<CABasicAnimation*>(m_animation.get()) setFromValue:[NSValue valueWithCATransform3D:value]];
+}
+
+void PlatformCAAnimation::setFromValue(const FloatPoint3D& value)
+{
+ if (animationType() != Basic)
+ return;
+
+ NSArray* array = [NSArray arrayWithObjects:
+ [NSNumber numberWithDouble:value.x()],
+ [NSNumber numberWithDouble:value.y()],
+ [NSNumber numberWithDouble:value.z()],
+ nil];
+ [static_cast<CABasicAnimation*>(m_animation.get()) setFromValue:array];
+}
+
+void PlatformCAAnimation::setFromValue(const WebCore::Color& value)
+{
+ if (animationType() != Basic)
+ return;
+
+ NSArray* array = [NSArray arrayWithObjects:
+ [NSNumber numberWithDouble:value.red()],
+ [NSNumber numberWithDouble:value.green()],
+ [NSNumber numberWithDouble:value.blue()],
+ [NSNumber numberWithDouble:value.alpha()],
+ nil];
+ [static_cast<CABasicAnimation*>(m_animation.get()) setFromValue:array];
+}
+
+void PlatformCAAnimation::copyFromValueFrom(const PlatformCAAnimation* value)
+{
+ if (animationType() != Basic || value->animationType() != Basic)
+ return;
+
+ CABasicAnimation* otherAnimation = static_cast<CABasicAnimation*>(value->m_animation.get());
+ [static_cast<CABasicAnimation*>(m_animation.get()) setFromValue:[otherAnimation fromValue]];
+}
+
+void PlatformCAAnimation::setToValue(float value)
+{
+ if (animationType() != Basic)
+ return;
+ [static_cast<CABasicAnimation*>(m_animation.get()) setToValue:[NSNumber numberWithDouble:value]];
+}
+
+void PlatformCAAnimation::setToValue(const WebCore::TransformationMatrix& value)
+{
+ if (animationType() != Basic)
+ return;
+
+ [static_cast<CABasicAnimation*>(m_animation.get()) setToValue:[NSValue valueWithCATransform3D:value]];
+}
+
+void PlatformCAAnimation::setToValue(const FloatPoint3D& value)
+{
+ if (animationType() != Basic)
+ return;
+
+ NSArray* array = [NSArray arrayWithObjects:
+ [NSNumber numberWithDouble:value.x()],
+ [NSNumber numberWithDouble:value.y()],
+ [NSNumber numberWithDouble:value.z()],
+ nil];
+ [static_cast<CABasicAnimation*>(m_animation.get()) setToValue:array];
+}
+
+void PlatformCAAnimation::setToValue(const WebCore::Color& value)
+{
+ if (animationType() != Basic)
+ return;
+
+ NSArray* array = [NSArray arrayWithObjects:
+ [NSNumber numberWithDouble:value.red()],
+ [NSNumber numberWithDouble:value.green()],
+ [NSNumber numberWithDouble:value.blue()],
+ [NSNumber numberWithDouble:value.alpha()],
+ nil];
+ [static_cast<CABasicAnimation*>(m_animation.get()) setToValue:array];
+}
+
+void PlatformCAAnimation::copyToValueFrom(const PlatformCAAnimation* value)
+{
+ if (animationType() != Basic || value->animationType() != Basic)
+ return;
+
+ CABasicAnimation* otherAnimation = static_cast<CABasicAnimation*>(value->m_animation.get());
+ [static_cast<CABasicAnimation*>(m_animation.get()) setToValue:[otherAnimation toValue]];
+}
+
+
+// Keyframe-animation properties.
+void PlatformCAAnimation::setValues(const Vector<float>& value)
+{
+ if (animationType() != Keyframe)
+ return;
+
+ NSMutableArray* array = [NSMutableArray array];
+ for (size_t i = 0; i < value.size(); ++i)
+ [array addObject:[NSNumber numberWithDouble:value[i]]];
+ [static_cast<CAKeyframeAnimation*>(m_animation.get()) setValues:array];
+}
+
+void PlatformCAAnimation::setValues(const Vector<WebCore::TransformationMatrix>& value)
+{
+ if (animationType() != Keyframe)
+ return;
+
+ NSMutableArray* array = [NSMutableArray array];
+
+ for (size_t i = 0; i < value.size(); ++i)
+ [array addObject:[NSValue valueWithCATransform3D:value[i]]];
+
+ [static_cast<CAKeyframeAnimation*>(m_animation.get()) setValues:array];
+}
+
+void PlatformCAAnimation::setValues(const Vector<FloatPoint3D>& value)
+{
+ if (animationType() != Keyframe)
+ return;
+
+ NSMutableArray* array = [NSMutableArray array];
+
+ for (size_t i = 0; i < value.size(); ++i) {
+ NSArray* object = [NSArray arrayWithObjects:
+ [NSNumber numberWithDouble:value[i].x()],
+ [NSNumber numberWithDouble:value[i].y()],
+ [NSNumber numberWithDouble:value[i].z()],
+ nil];
+ [array addObject:object];
+ }
+ [static_cast<CAKeyframeAnimation*>(m_animation.get()) setValues:array];
+}
+
+void PlatformCAAnimation::setValues(const Vector<WebCore::Color>& value)
+{
+ if (animationType() != Keyframe)
+ return;
+
+ NSMutableArray* array = [NSMutableArray array];
+
+ for (size_t i = 0; i < value.size(); ++i) {
+ NSArray* object = [NSArray arrayWithObjects:
+ [NSNumber numberWithDouble:value[i].red()],
+ [NSNumber numberWithDouble:value[i].green()],
+ [NSNumber numberWithDouble:value[i].blue()],
+ [NSNumber numberWithDouble:value[i].alpha()],
+ nil];
+ [array addObject:object];
+ }
+ [static_cast<CAKeyframeAnimation*>(m_animation.get()) setValues:array];
+}
+
+void PlatformCAAnimation::copyValuesFrom(const PlatformCAAnimation* value)
+{
+ if (animationType() != Keyframe || value->animationType() != Keyframe)
+ return;
+
+ CAKeyframeAnimation* otherAnimation = static_cast<CAKeyframeAnimation*>(value->m_animation.get());
+ [static_cast<CAKeyframeAnimation*>(m_animation.get()) setValues:[otherAnimation values]];
+}
+
+void PlatformCAAnimation::setKeyTimes(const Vector<float>& value)
+{
+ NSMutableArray* array = [NSMutableArray array];
+
+ for (size_t i = 0; i < value.size(); ++i)
+ [array addObject:[NSNumber numberWithFloat:value[i]]];
+
+ [static_cast<CAKeyframeAnimation*>(m_animation.get()) setKeyTimes:array];
+}
+
+void PlatformCAAnimation::copyKeyTimesFrom(const PlatformCAAnimation* value)
+{
+ CAKeyframeAnimation* other = static_cast<CAKeyframeAnimation*>(value->m_animation.get());
+ [static_cast<CAKeyframeAnimation*>(m_animation.get()) setKeyTimes:[other keyTimes]];
+}
+
+void PlatformCAAnimation::setTimingFunctions(const Vector<const TimingFunction*>& value)
+{
+ NSMutableArray* array = [NSMutableArray array];
+
+ for (size_t i = 0; i < value.size(); ++i)
+ [array addObject:toCAMediaTimingFunction(value[i])];
+
+ [static_cast<CAKeyframeAnimation*>(m_animation.get()) setTimingFunctions:array];
+}
+
+void PlatformCAAnimation::copyTimingFunctionsFrom(const PlatformCAAnimation* value)
+{
+ CAKeyframeAnimation* other = static_cast<CAKeyframeAnimation*>(value->m_animation.get());
+ [static_cast<CAKeyframeAnimation*>(m_animation.get()) setTimingFunctions:[other timingFunctions]];
+}
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/WebCore/platform/graphics/ca/mac/PlatformCALayerMac.mm b/WebCore/platform/graphics/ca/mac/PlatformCALayerMac.mm
new file mode 100644
index 0000000..0aecf14
--- /dev/null
+++ b/WebCore/platform/graphics/ca/mac/PlatformCALayerMac.mm
@@ -0,0 +1,725 @@
+/*
+ * Copyright (C) 2010 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 COMPUTER, 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"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#import "PlatformCALayer.h"
+
+#import "BlockExceptions.h"
+#import "FloatConversion.h"
+#import "GraphicsContext.h"
+#import "GraphicsLayerCA.h"
+#import "WebLayer.h"
+#import "WebTiledLayer.h"
+#import <objc/objc-auto.h>
+#import <objc/objc-runtime.h>
+#import <QuartzCore/QuartzCore.h>
+#import <wtf/CurrentTime.h>
+#import <wtf/UnusedParam.h>
+
+#define HAVE_MODERN_QUARTZCORE (!defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD))
+
+using namespace WebCore;
+
+// This value must be the same as in PlatformCAAnimationMac.mm
+static NSString * const WKNonZeroBeginTimeFlag = @"WKPlatformCAAnimationNonZeroBeginTimeFlag";
+
+static double mediaTimeToCurrentTime(CFTimeInterval t)
+{
+ return WTF::currentTime() + t - CACurrentMediaTime();
+}
+
+// Delegate for animationDidStart callback
+@interface WebAnimationDelegate : NSObject {
+ PlatformCALayer* m_owner;
+}
+
+- (void)animationDidStart:(CAAnimation *)anim;
+- (void)setOwner:(PlatformCALayer*)owner;
+
+@end
+
+@implementation WebAnimationDelegate
+
+- (void)animationDidStart:(CAAnimation *)animation
+{
+ // hasNonZeroBeginTime is stored in a key in the animation
+ bool hasNonZeroBeginTime = [[animation valueForKey:WKNonZeroBeginTimeFlag] boolValue];
+ CFTimeInterval startTime;
+
+ if (hasNonZeroBeginTime) {
+ // We don't know what time CA used to commit the animation, so just use the current time
+ // (even though this will be slightly off).
+ startTime = mediaTimeToCurrentTime(CACurrentMediaTime());
+ } else
+ startTime = mediaTimeToCurrentTime([animation beginTime]);
+
+ if (m_owner)
+ m_owner->animationStarted(startTime);
+}
+
+- (void)setOwner:(PlatformCALayer*)owner
+{
+ m_owner = owner;
+}
+
+@end
+
+@interface CALayer(Private)
+- (void)setContentsChanged;
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
+- (void)setAcceleratesDrawing:(BOOL)flag;
+- (BOOL)acceleratesDrawing;
+#endif
+@end
+
+static NSString * const platformCALayerPointer = @"WKPlatformCALayer";
+
+bool PlatformCALayer::isValueFunctionSupported()
+{
+ static bool sHaveValueFunction = [CAPropertyAnimation instancesRespondToSelector:@selector(setValueFunction:)];
+ return sHaveValueFunction;
+}
+
+void PlatformCALayer::setOwner(GraphicsLayerCA* owner)
+{
+ m_owner = owner;
+
+ // Change the delegate's owner if needed
+ if (m_delegate)
+ [static_cast<WebAnimationDelegate*>(m_delegate.get()) setOwner:this];
+}
+
+static NSDictionary* nullActionsDictionary()
+{
+ NSNull* nullValue = [NSNull null];
+ NSDictionary* actions = [NSDictionary dictionaryWithObjectsAndKeys:
+ nullValue, @"anchorPoint",
+ nullValue, @"bounds",
+ nullValue, @"contents",
+ nullValue, @"contentsRect",
+ nullValue, @"opacity",
+ nullValue, @"position",
+ nullValue, @"shadowColor",
+ nullValue, @"sublayerTransform",
+ nullValue, @"sublayers",
+ nullValue, @"transform",
+ nullValue, @"zPosition",
+ nil];
+ return actions;
+}
+
+#if HAVE_MODERN_QUARTZCORE
+static NSString* toCAFilterType(PlatformCALayer::FilterType type)
+{
+ switch (type) {
+ case PlatformCALayer::Linear: return kCAFilterLinear;
+ case PlatformCALayer::Nearest: return kCAFilterNearest;
+ case PlatformCALayer::Trilinear: return kCAFilterTrilinear;
+ default: return 0;
+ }
+}
+#endif
+
+PassRefPtr<PlatformCALayer> PlatformCALayer::create(LayerType layerType, GraphicsLayerCA* owner)
+{
+ return adoptRef(new PlatformCALayer(layerType, 0, owner));
+}
+
+PassRefPtr<PlatformCALayer> PlatformCALayer::create(void* platformLayer, GraphicsLayerCA* owner)
+{
+ return adoptRef(new PlatformCALayer(LayerTypeCustom, static_cast<PlatformLayer*>(platformLayer), owner));
+}
+
+PlatformCALayer::PlatformCALayer(LayerType layerType, PlatformLayer* layer, GraphicsLayerCA* owner)
+ : m_owner(owner)
+{
+ BEGIN_BLOCK_OBJC_EXCEPTIONS
+ if (layer) {
+ m_layerType = LayerTypeCustom;
+ m_layer = layer;
+ } else {
+ m_layerType = layerType;
+
+ Class layerClass = Nil;
+ switch(layerType) {
+ case LayerTypeLayer:
+ layerClass = [CALayer class];
+ break;
+ case LayerTypeWebLayer:
+ layerClass = [WebLayer class];
+ break;
+ case LayerTypeTransformLayer:
+ layerClass = NSClassFromString(@"CATransformLayer");
+ break;
+ case LayerTypeWebTiledLayer:
+ layerClass = [WebTiledLayer class];
+ break;
+ case LayerTypeCustom:
+ break;
+ }
+
+ if (layerClass)
+ m_layer.adoptNS([[layerClass alloc] init]);
+ }
+
+ // Save a pointer to 'this' in the CALayer
+ [m_layer.get() setValue:[NSValue valueWithPointer:this] forKey:platformCALayerPointer];
+
+ // Clear all the implicit animations on the CALayer
+ [m_layer.get() setStyle:[NSDictionary dictionaryWithObject:nullActionsDictionary() forKey:@"actions"]];
+
+ // If this is a TiledLayer, set some initial values
+ if (m_layerType == LayerTypeWebTiledLayer) {
+ WebTiledLayer* tiledLayer = static_cast<WebTiledLayer*>(m_layer.get());
+ [tiledLayer setTileSize:CGSizeMake(GraphicsLayerCA::kTiledLayerTileSize, GraphicsLayerCA::kTiledLayerTileSize)];
+ [tiledLayer setLevelsOfDetail:1];
+ [tiledLayer setLevelsOfDetailBias:0];
+ [tiledLayer setContentsGravity:@"bottomLeft"];
+ }
+
+ END_BLOCK_OBJC_EXCEPTIONS
+}
+
+PlatformCALayer::~PlatformCALayer()
+{
+ [m_layer.get() setValue:nil forKey:platformCALayerPointer];
+
+ // Clear the owner, which also clears it in the delegate to prevent attempts
+ // to use the GraphicsLayerCA after it has been destroyed.
+ setOwner(0);
+
+ // Remove the owner pointer from the delegate in case there is a pending animationStarted event.
+ [static_cast<WebAnimationDelegate*>(m_delegate.get()) setOwner:nil];
+}
+
+PlatformCALayer* PlatformCALayer::platformCALayer(void* platformLayer)
+{
+ if (!platformLayer)
+ return 0;
+
+ // Pointer to PlatformCALayer is kept in a key of the CALayer
+ PlatformCALayer* platformCALayer = nil;
+ BEGIN_BLOCK_OBJC_EXCEPTIONS
+ platformCALayer = static_cast<PlatformCALayer*>([[static_cast<CALayer*>(platformLayer) valueForKey:platformCALayerPointer] pointerValue]);
+ END_BLOCK_OBJC_EXCEPTIONS
+ return platformCALayer;
+}
+
+PlatformLayer* PlatformCALayer::platformLayer() const
+{
+ return m_layer.get();
+}
+
+void PlatformCALayer::setNeedsDisplay(const FloatRect* dirtyRect)
+{
+ BEGIN_BLOCK_OBJC_EXCEPTIONS
+ if (dirtyRect)
+ [m_layer.get() setNeedsDisplayInRect:*dirtyRect];
+ else
+ [m_layer.get() setNeedsDisplay];
+ END_BLOCK_OBJC_EXCEPTIONS
+}
+
+void PlatformCALayer::setContentsChanged()
+{
+ BEGIN_BLOCK_OBJC_EXCEPTIONS
+ [m_layer.get() setContentsChanged];
+ END_BLOCK_OBJC_EXCEPTIONS
+}
+
+PlatformCALayer* PlatformCALayer::superlayer() const
+{
+ return platformCALayer([m_layer.get() superlayer]);
+}
+
+void PlatformCALayer::removeFromSuperlayer()
+{
+ BEGIN_BLOCK_OBJC_EXCEPTIONS
+ [m_layer.get() removeFromSuperlayer];
+ END_BLOCK_OBJC_EXCEPTIONS
+}
+
+void PlatformCALayer::setSublayers(const PlatformCALayerList& list)
+{
+ // Short circuiting here not only avoids the allocation of sublayers, but avoids <rdar://problem/7390716> (see below)
+ if (list.size() == 0) {
+ removeAllSublayers();
+ return;
+ }
+
+ BEGIN_BLOCK_OBJC_EXCEPTIONS
+ NSMutableArray* sublayers = [[NSMutableArray alloc] init];
+ for (size_t i = 0; i < list.size(); ++i)
+ [sublayers addObject:list[i]->m_layer.get()];
+
+ [m_layer.get() setSublayers:sublayers];
+ [sublayers release];
+ END_BLOCK_OBJC_EXCEPTIONS
+}
+
+void PlatformCALayer::removeAllSublayers()
+{
+ // Workaround for <rdar://problem/7390716>: -[CALayer setSublayers:] crashes if sublayers is an empty array, or nil, under GC.
+ BEGIN_BLOCK_OBJC_EXCEPTIONS
+ if (objc_collectingEnabled())
+ while ([[m_layer.get() sublayers] count])
+ [[[m_layer.get() sublayers] objectAtIndex:0] removeFromSuperlayer];
+ else
+ [m_layer.get() setSublayers:nil];
+ END_BLOCK_OBJC_EXCEPTIONS
+}
+
+void PlatformCALayer::appendSublayer(PlatformCALayer* layer)
+{
+ BEGIN_BLOCK_OBJC_EXCEPTIONS
+ [m_layer.get() addSublayer:layer->m_layer.get()];
+ END_BLOCK_OBJC_EXCEPTIONS
+}
+
+void PlatformCALayer::insertSublayer(PlatformCALayer* layer, size_t index)
+{
+ BEGIN_BLOCK_OBJC_EXCEPTIONS
+ [m_layer.get() insertSublayer:layer->m_layer.get() atIndex:index];
+ END_BLOCK_OBJC_EXCEPTIONS
+}
+
+void PlatformCALayer::replaceSublayer(PlatformCALayer* reference, PlatformCALayer* layer)
+{
+ BEGIN_BLOCK_OBJC_EXCEPTIONS
+ [m_layer.get() replaceSublayer:reference->m_layer.get() with:layer->m_layer.get()];
+ END_BLOCK_OBJC_EXCEPTIONS
+}
+
+size_t PlatformCALayer::sublayerCount() const
+{
+ return [[m_layer.get() sublayers] count];
+}
+
+void PlatformCALayer::adoptSublayers(PlatformCALayer* source)
+{
+ // Workaround for <rdar://problem/7390716>: -[CALayer setSublayers:] crashes if sublayers is an empty array, or nil, under GC.
+ NSArray* sublayers = [source->m_layer.get() sublayers];
+
+ if (objc_collectingEnabled() && ![sublayers count]) {
+ BEGIN_BLOCK_OBJC_EXCEPTIONS
+ while ([[m_layer.get() sublayers] count])
+ [[[m_layer.get() sublayers] objectAtIndex:0] removeFromSuperlayer];
+ END_BLOCK_OBJC_EXCEPTIONS
+ return;
+ }
+
+ BEGIN_BLOCK_OBJC_EXCEPTIONS
+ [m_layer.get() setSublayers:sublayers];
+ END_BLOCK_OBJC_EXCEPTIONS
+}
+
+void PlatformCALayer::addAnimationForKey(const String& key, PlatformCAAnimation* animation)
+{
+ // Add the delegate
+ if (!m_delegate) {
+ WebAnimationDelegate* webAnimationDelegate = [[WebAnimationDelegate alloc] init];
+ m_delegate.adoptNS(webAnimationDelegate);
+ [webAnimationDelegate setOwner:this];
+ }
+
+ CAPropertyAnimation* propertyAnimation = static_cast<CAPropertyAnimation*>(animation->platformAnimation());
+
+ if (![propertyAnimation delegate])
+ [propertyAnimation setDelegate:static_cast<id>(m_delegate.get())];
+
+ BEGIN_BLOCK_OBJC_EXCEPTIONS
+ [m_layer.get() addAnimation:animation->m_animation.get() forKey:key];
+ END_BLOCK_OBJC_EXCEPTIONS
+}
+
+void PlatformCALayer::removeAnimationForKey(const String& key)
+{
+ BEGIN_BLOCK_OBJC_EXCEPTIONS
+ [m_layer.get() removeAnimationForKey:key];
+ END_BLOCK_OBJC_EXCEPTIONS
+}
+
+PassRefPtr<PlatformCAAnimation> PlatformCALayer::animationForKey(const String& key)
+{
+ CAPropertyAnimation* propertyAnimation = static_cast<CAPropertyAnimation*>([m_layer.get() animationForKey:key]);
+ if (!propertyAnimation)
+ return 0;
+ return PlatformCAAnimation::create(propertyAnimation);
+}
+
+PlatformCALayer* PlatformCALayer::mask() const
+{
+ return platformCALayer([m_layer.get() mask]);
+}
+
+void PlatformCALayer::setMask(PlatformCALayer* layer)
+{
+ BEGIN_BLOCK_OBJC_EXCEPTIONS
+ [m_layer.get() setMask:layer ? layer->platformLayer() : 0];
+ END_BLOCK_OBJC_EXCEPTIONS
+}
+
+bool PlatformCALayer::isOpaque() const
+{
+ return [m_layer.get() isOpaque];
+}
+
+void PlatformCALayer::setOpaque(bool value)
+{
+ BEGIN_BLOCK_OBJC_EXCEPTIONS
+ [m_layer.get() setOpaque:value];
+ END_BLOCK_OBJC_EXCEPTIONS
+}
+
+FloatRect PlatformCALayer::bounds() const
+{
+ return [m_layer.get() bounds];
+}
+
+void PlatformCALayer::setBounds(const FloatRect& value)
+{
+ BEGIN_BLOCK_OBJC_EXCEPTIONS
+ [m_layer.get() setBounds:value];
+ END_BLOCK_OBJC_EXCEPTIONS
+}
+
+FloatPoint3D PlatformCALayer::position() const
+{
+ CGPoint point = [m_layer.get() position];
+ return FloatPoint3D(point.x, point.y, [m_layer.get() zPosition]);
+}
+
+void PlatformCALayer::setPosition(const FloatPoint3D& value)
+{
+ BEGIN_BLOCK_OBJC_EXCEPTIONS
+ [m_layer.get() setPosition:CGPointMake(value.x(), value.y())];
+ [m_layer.get() setZPosition:value.z()];
+ END_BLOCK_OBJC_EXCEPTIONS
+}
+
+FloatPoint3D PlatformCALayer::anchorPoint() const
+{
+ CGPoint point = [m_layer.get() anchorPoint];
+ float z = 0;
+#if HAVE_MODERN_QUARTZCORE
+ z = [m_layer.get() anchorPointZ];
+#endif
+ return FloatPoint3D(point.x, point.y, z);
+}
+
+void PlatformCALayer::setAnchorPoint(const FloatPoint3D& value)
+{
+ BEGIN_BLOCK_OBJC_EXCEPTIONS
+ [m_layer.get() setAnchorPoint:CGPointMake(value.x(), value.y())];
+#if HAVE_MODERN_QUARTZCORE
+ [m_layer.get() setAnchorPointZ:value.z()];
+#endif
+ END_BLOCK_OBJC_EXCEPTIONS
+}
+
+TransformationMatrix PlatformCALayer::transform() const
+{
+ return [m_layer.get() transform];
+}
+
+void PlatformCALayer::setTransform(const TransformationMatrix& value)
+{
+ BEGIN_BLOCK_OBJC_EXCEPTIONS
+ [m_layer.get() setTransform:value];
+ END_BLOCK_OBJC_EXCEPTIONS
+}
+
+TransformationMatrix PlatformCALayer::sublayerTransform() const
+{
+ return [m_layer.get() sublayerTransform];
+}
+
+void PlatformCALayer::setSublayerTransform(const TransformationMatrix& value)
+{
+ BEGIN_BLOCK_OBJC_EXCEPTIONS
+ [m_layer.get() setSublayerTransform:value];
+ END_BLOCK_OBJC_EXCEPTIONS
+}
+
+TransformationMatrix PlatformCALayer::contentsTransform() const
+{
+#if !HAVE_MODERN_QUARTZCORE
+ if (m_layerType != LayerTypeWebLayer)
+ return TransformationMatrix();
+
+ return [static_cast<WebLayer*>(m_layer.get()) contentsTransform];
+#else
+ return TransformationMatrix();
+#endif
+}
+
+void PlatformCALayer::setContentsTransform(const TransformationMatrix& value)
+{
+#if !HAVE_MODERN_QUARTZCORE
+ if (m_layerType != LayerTypeWebLayer)
+ return;
+
+ BEGIN_BLOCK_OBJC_EXCEPTIONS
+ [m_layer.get() setContentsTransform:value];
+ END_BLOCK_OBJC_EXCEPTIONS
+#else
+ UNUSED_PARAM(value);
+#endif
+}
+
+bool PlatformCALayer::isHidden() const
+{
+ return [m_layer.get() isHidden];
+}
+
+void PlatformCALayer::setHidden(bool value)
+{
+ BEGIN_BLOCK_OBJC_EXCEPTIONS
+ [m_layer.get() setHidden:value];
+ END_BLOCK_OBJC_EXCEPTIONS
+}
+
+bool PlatformCALayer::isGeometryFlipped() const
+{
+#if HAVE_MODERN_QUARTZCORE
+ return [m_layer.get() isGeometryFlipped];
+#else
+ return false;
+#endif
+}
+
+void PlatformCALayer::setGeometryFlipped(bool value)
+{
+#if HAVE_MODERN_QUARTZCORE
+ BEGIN_BLOCK_OBJC_EXCEPTIONS
+ [m_layer.get() setGeometryFlipped:value];
+ END_BLOCK_OBJC_EXCEPTIONS
+#else
+ UNUSED_PARAM(value);
+#endif
+}
+
+bool PlatformCALayer::isDoubleSided() const
+{
+ return [m_layer.get() isDoubleSided];
+}
+
+void PlatformCALayer::setDoubleSided(bool value)
+{
+ BEGIN_BLOCK_OBJC_EXCEPTIONS
+ [m_layer.get() setDoubleSided:value];
+ END_BLOCK_OBJC_EXCEPTIONS
+}
+
+bool PlatformCALayer::masksToBounds() const
+{
+ return [m_layer.get() masksToBounds];
+}
+
+void PlatformCALayer::setMasksToBounds(bool value)
+{
+ BEGIN_BLOCK_OBJC_EXCEPTIONS
+ [m_layer.get() setMasksToBounds:value];
+ END_BLOCK_OBJC_EXCEPTIONS
+}
+
+bool PlatformCALayer::acceleratesDrawing() const
+{
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
+ return [m_layer.get() acceleratesDrawing];
+#else
+ return false;
+#endif
+}
+
+void PlatformCALayer::setAcceleratesDrawing(bool acceleratesDrawing)
+{
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
+ BEGIN_BLOCK_OBJC_EXCEPTIONS
+ [m_layer.get() setAcceleratesDrawing:acceleratesDrawing];
+ END_BLOCK_OBJC_EXCEPTIONS
+#else
+ UNUSED_PARAM(acceleratesDrawing);
+#endif
+}
+
+void* PlatformCALayer::contents() const
+{
+ return [m_layer.get() contents];
+}
+
+void PlatformCALayer::setContents(void* value)
+{
+ BEGIN_BLOCK_OBJC_EXCEPTIONS
+ [m_layer.get() setContents:static_cast<id>(value)];
+ END_BLOCK_OBJC_EXCEPTIONS
+}
+
+FloatRect PlatformCALayer::contentsRect() const
+{
+ return [m_layer.get() contentsRect];
+}
+
+void PlatformCALayer::setContentsRect(const FloatRect& value)
+{
+ BEGIN_BLOCK_OBJC_EXCEPTIONS
+ [m_layer.get() setContentsRect:value];
+ END_BLOCK_OBJC_EXCEPTIONS
+}
+
+void PlatformCALayer::setMinificationFilter(FilterType value)
+{
+#if HAVE_MODERN_QUARTZCORE
+ BEGIN_BLOCK_OBJC_EXCEPTIONS
+ [m_layer.get() setMinificationFilter:toCAFilterType(value)];
+ END_BLOCK_OBJC_EXCEPTIONS
+#else
+ UNUSED_PARAM(value);
+#endif
+}
+
+void PlatformCALayer::setMagnificationFilter(FilterType value)
+{
+#if HAVE_MODERN_QUARTZCORE
+ BEGIN_BLOCK_OBJC_EXCEPTIONS
+ [m_layer.get() setMagnificationFilter:toCAFilterType(value)];
+ END_BLOCK_OBJC_EXCEPTIONS
+#else
+ UNUSED_PARAM(value);
+#endif
+}
+
+Color PlatformCALayer::backgroundColor() const
+{
+ return [m_layer.get() backgroundColor];
+}
+
+void PlatformCALayer::setBackgroundColor(const Color& value)
+{
+ CGFloat components[4];
+ value.getRGBA(components[0], components[1], components[2], components[3]);
+
+ RetainPtr<CGColorSpaceRef> colorSpace(AdoptCF, CGColorSpaceCreateDeviceRGB());
+ RetainPtr<CGColorRef> color(AdoptCF, CGColorCreate(colorSpace.get(), components));
+
+ BEGIN_BLOCK_OBJC_EXCEPTIONS
+ [m_layer.get() setBackgroundColor:color.get()];
+ END_BLOCK_OBJC_EXCEPTIONS
+}
+
+float PlatformCALayer::borderWidth() const
+{
+ return [m_layer.get() borderWidth];
+}
+
+void PlatformCALayer::setBorderWidth(float value)
+{
+ BEGIN_BLOCK_OBJC_EXCEPTIONS
+ [m_layer.get() setBorderWidth:value];
+ END_BLOCK_OBJC_EXCEPTIONS
+}
+
+Color PlatformCALayer::borderColor() const
+{
+ return [m_layer.get() borderColor];
+}
+
+void PlatformCALayer::setBorderColor(const Color& value)
+{
+ CGFloat components[4];
+ value.getRGBA(components[0], components[1], components[2], components[3]);
+
+ RetainPtr<CGColorSpaceRef> colorSpace(AdoptCF, CGColorSpaceCreateDeviceRGB());
+ RetainPtr<CGColorRef> color(AdoptCF, CGColorCreate(colorSpace.get(), components));
+
+ BEGIN_BLOCK_OBJC_EXCEPTIONS
+ [m_layer.get() setBorderColor:color.get()];
+ END_BLOCK_OBJC_EXCEPTIONS
+}
+
+float PlatformCALayer::opacity() const
+{
+ return [m_layer.get() opacity];
+}
+
+void PlatformCALayer::setOpacity(float value)
+{
+ BEGIN_BLOCK_OBJC_EXCEPTIONS
+ [m_layer.get() setOpacity:value];
+ END_BLOCK_OBJC_EXCEPTIONS
+}
+
+String PlatformCALayer::name() const
+{
+ return [m_layer.get() name];
+}
+
+void PlatformCALayer::setName(const String& value)
+{
+ BEGIN_BLOCK_OBJC_EXCEPTIONS
+ [m_layer.get() setName:value];
+ END_BLOCK_OBJC_EXCEPTIONS
+}
+
+FloatRect PlatformCALayer::frame() const
+{
+ return [m_layer.get() frame];
+}
+
+void PlatformCALayer::setFrame(const FloatRect& value)
+{
+ BEGIN_BLOCK_OBJC_EXCEPTIONS
+ [m_layer.get() setFrame:value];
+ END_BLOCK_OBJC_EXCEPTIONS
+}
+
+float PlatformCALayer::speed() const
+{
+ return [m_layer.get() speed];
+}
+
+void PlatformCALayer::setSpeed(float value)
+{
+ BEGIN_BLOCK_OBJC_EXCEPTIONS
+ [m_layer.get() setSpeed:value];
+ END_BLOCK_OBJC_EXCEPTIONS
+}
+
+CFTimeInterval PlatformCALayer::timeOffset() const
+{
+ return [m_layer.get() timeOffset];
+}
+
+void PlatformCALayer::setTimeOffset(CFTimeInterval value)
+{
+ BEGIN_BLOCK_OBJC_EXCEPTIONS
+ [m_layer.get() setTimeOffset:value];
+ END_BLOCK_OBJC_EXCEPTIONS
+}
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/WebCore/platform/graphics/cairo/CairoUtilities.cpp b/WebCore/platform/graphics/cairo/CairoUtilities.cpp
index 709ee8f..013a4af 100644
--- a/WebCore/platform/graphics/cairo/CairoUtilities.cpp
+++ b/WebCore/platform/graphics/cairo/CairoUtilities.cpp
@@ -130,7 +130,7 @@ void drawPatternToCairoContext(cairo_t* cr, cairo_surface_t* image, const IntSiz
if (tileRect.size() != imageSize) {
IntRect imageRect = enclosingIntRect(tileRect);
clippedImageSurface = adoptRef(cairo_image_surface_create(CAIRO_FORMAT_ARGB32, imageRect.width(), imageRect.height()));
- RefPtr<cairo_t> clippedImageContext(cairo_create(clippedImageSurface.get()));
+ RefPtr<cairo_t> clippedImageContext = adoptRef(cairo_create(clippedImageSurface.get()));
cairo_set_source_surface(clippedImageContext.get(), image, -tileRect.x(), -tileRect.y());
cairo_paint(clippedImageContext.get());
image = clippedImageSurface.get();
diff --git a/WebCore/platform/graphics/cairo/ContextShadowCairo.cpp b/WebCore/platform/graphics/cairo/ContextShadowCairo.cpp
index 8299b6a..ae91282 100644
--- a/WebCore/platform/graphics/cairo/ContextShadowCairo.cpp
+++ b/WebCore/platform/graphics/cairo/ContextShadowCairo.cpp
@@ -82,17 +82,27 @@ static cairo_surface_t* getScratchBuffer(const IntSize& size)
return scratchBuffer;
}
+TransformationMatrix ContextShadow::getTransformationMatrixFromContext(PlatformContext context)
+{
+ cairo_matrix_t transform;
+ cairo_get_matrix(context, &transform);
+ return TransformationMatrix(transform.xx, transform.yx, transform.xy,
+ transform.yy, transform.x0, transform.y0);
+}
+
PlatformContext ContextShadow::beginShadowLayer(PlatformContext context, const FloatRect& layerArea)
{
+ adjustBlurDistance(context);
+
double x1, x2, y1, y2;
cairo_clip_extents(context, &x1, &y1, &x2, &y2);
- calculateLayerBoundingRect(layerArea, IntRect(x1, y1, x2 - x1, y2 - y1));
+ IntRect layerRect = calculateLayerBoundingRect(context, layerArea, IntRect(x1, y1, x2 - x1, y2 - y1));
// Don't paint if we are totally outside the clip region.
- if (m_layerRect.isEmpty())
+ if (layerRect.isEmpty())
return 0;
- m_layerImage = getScratchBuffer(m_layerRect.size());
+ m_layerImage = getScratchBuffer(layerRect.size());
m_layerContext = cairo_create(m_layerImage);
// Always clear the surface first.
@@ -100,8 +110,7 @@ PlatformContext ContextShadow::beginShadowLayer(PlatformContext context, const F
cairo_paint(m_layerContext);
cairo_set_operator(m_layerContext, CAIRO_OPERATOR_OVER);
- cairo_translate(m_layerContext, m_offset.width(), m_offset.height());
- cairo_translate(m_layerContext, -m_layerRect.x(), -m_layerRect.y());
+ cairo_translate(m_layerContext, m_layerContextTranslation.x(), m_layerContextTranslation.y());
return m_layerContext;
}
@@ -120,7 +129,7 @@ void ContextShadow::endShadowLayer(cairo_t* cr)
cairo_save(cr);
setSourceRGBAFromColor(cr, m_color);
- cairo_mask_surface(cr, m_layerImage, m_layerRect.x(), m_layerRect.y());
+ cairo_mask_surface(cr, m_layerImage, m_layerOrigin.x(), m_layerOrigin.y());
cairo_restore(cr);
// Schedule a purge of the scratch buffer. We do not need to destroy the surface.
@@ -221,9 +230,9 @@ void ContextShadow::drawRectShadow(GraphicsContext* context, const IntRect& rect
// Reduce the size of what we have to draw with the clip area.
double x1, x2, y1, y2;
cairo_clip_extents(cr, &x1, &y1, &x2, &y2);
- calculateLayerBoundingRect(shadowRect, IntRect(x1, y1, x2 - x1, y2 - y1));
+ calculateLayerBoundingRect(cr, shadowRect, IntRect(x1, y1, x2 - x1, y2 - y1));
- if ((shadowTemplateSize.width() * shadowTemplateSize.height() > m_layerRect.width() * m_layerRect.height())) {
+ if ((shadowTemplateSize.width() * shadowTemplateSize.height() > m_sourceRect.width() * m_sourceRect.height())) {
drawRectShadowWithoutTiling(cr, rect, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius, context->getAlpha());
return;
}
diff --git a/WebCore/platform/graphics/cairo/FontCairo.cpp b/WebCore/platform/graphics/cairo/FontCairo.cpp
index 3d55c70..0d92ada 100644
--- a/WebCore/platform/graphics/cairo/FontCairo.cpp
+++ b/WebCore/platform/graphics/cairo/FontCairo.cpp
@@ -69,10 +69,10 @@ static void drawGlyphsShadow(GraphicsContext* graphicsContext, cairo_t* context,
ContextShadow* shadow = graphicsContext->contextShadow();
ASSERT(shadow);
- if (!(graphicsContext->textDrawingMode() & cTextFill) || shadow->m_type == ContextShadow::NoShadow)
+ if (!(graphicsContext->textDrawingMode() & TextModeFill) || shadow->m_type == ContextShadow::NoShadow)
return;
- if (shadow->m_type == ContextShadow::SolidShadow) {
+ if (!shadow->mustUseContextShadow(context)) {
// Optimize non-blurry shadows, by just drawing text without the ContextShadow.
cairo_save(context);
cairo_translate(context, shadow->m_offset.width(), shadow->m_offset.height());
@@ -111,7 +111,7 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons
cairo_save(cr);
prepareContextForGlyphDrawing(cr, font, point);
- if (context->textDrawingMode() & cTextFill) {
+ if (context->textDrawingMode() & TextModeFill) {
if (context->fillGradient()) {
cairo_set_source(cr, context->fillGradient()->platformGradient());
if (context->getAlpha() < 1.0f) {
@@ -141,7 +141,7 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons
// twice the size of the width of the text we will not ask cairo to stroke
// the text as even one single stroke would cover the full wdth of the text.
// See https://bugs.webkit.org/show_bug.cgi?id=33759.
- if (context->textDrawingMode() & cTextStroke && context->strokeThickness() < 2 * offset) {
+ if (context->textDrawingMode() & TextModeStroke && context->strokeThickness() < 2 * offset) {
if (context->strokeGradient()) {
cairo_set_source(cr, context->strokeGradient()->platformGradient());
if (context->getAlpha() < 1.0f) {
diff --git a/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp b/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
index 1032dc2..a6edaf7 100644
--- a/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
+++ b/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
@@ -5,6 +5,7 @@
* Copyright (C) 2008 Nuanti Ltd.
* Copyright (C) 2009 Brent Fulgham <bfulgham@webkit.org>
* Copyright (C) 2010 Igalia S.L.
+ * Copyright (C) Research In Motion Limited 2010. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -40,7 +41,6 @@
#include "FloatRect.h"
#include "Font.h"
#include "GraphicsContextPlatformPrivateCairo.h"
-#include "GraphicsContextPrivate.h"
#include "OwnPtrCairo.h"
#include "IntRect.h"
#include "NotImplemented.h"
@@ -68,49 +68,46 @@ using namespace std;
namespace WebCore {
-static inline void setColor(cairo_t* cr, const Color& col)
-{
- float red, green, blue, alpha;
- col.getRGBA(red, green, blue, alpha);
- cairo_set_source_rgba(cr, red, green, blue, alpha);
-}
-
-static inline void setPlatformFill(GraphicsContext* context, cairo_t* cr, GraphicsContextPrivate* gcp)
+static inline void setPlatformFill(GraphicsContext* context, cairo_t* cr)
{
cairo_pattern_t* pattern = 0;
cairo_save(cr);
- if (gcp->state.fillPattern) {
+
+ const GraphicsContextState& state = context->state();
+ if (state.fillPattern) {
AffineTransform affine;
- pattern = gcp->state.fillPattern->createPlatformPattern(affine);
+ pattern = state.fillPattern->createPlatformPattern(affine);
cairo_set_source(cr, pattern);
- } else if (gcp->state.fillGradient)
- cairo_set_source(cr, gcp->state.fillGradient->platformGradient());
+ } else if (state.fillGradient)
+ cairo_set_source(cr, state.fillGradient->platformGradient());
else
- setColor(cr, context->fillColor());
+ setSourceRGBAFromColor(cr, context->fillColor());
cairo_clip_preserve(cr);
- cairo_paint_with_alpha(cr, gcp->state.globalAlpha);
+ cairo_paint_with_alpha(cr, state.globalAlpha);
cairo_restore(cr);
if (pattern)
cairo_pattern_destroy(pattern);
}
-static inline void setPlatformStroke(GraphicsContext* context, cairo_t* cr, GraphicsContextPrivate* gcp)
+static inline void setPlatformStroke(GraphicsContext* context, cairo_t* cr)
{
cairo_pattern_t* pattern = 0;
cairo_save(cr);
- if (gcp->state.strokePattern) {
+
+ const GraphicsContextState& state = context->state();
+ if (state.strokePattern) {
AffineTransform affine;
- pattern = gcp->state.strokePattern->createPlatformPattern(affine);
+ pattern = state.strokePattern->createPlatformPattern(affine);
cairo_set_source(cr, pattern);
- } else if (gcp->state.strokeGradient)
- cairo_set_source(cr, gcp->state.strokeGradient->platformGradient());
+ } else if (state.strokeGradient)
+ cairo_set_source(cr, state.strokeGradient->platformGradient());
else {
- Color strokeColor = colorWithOverrideAlpha(context->strokeColor().rgb(), context->strokeColor().alpha() / 255.f * gcp->state.globalAlpha);
- setColor(cr, strokeColor);
+ Color strokeColor = colorWithOverrideAlpha(context->strokeColor().rgb(), context->strokeColor().alpha() / 255.f * state.globalAlpha);
+ setSourceRGBAFromColor(cr, strokeColor);
}
- if (gcp->state.globalAlpha < 1.0f && (gcp->state.strokePattern || gcp->state.strokeGradient)) {
+ if (state.globalAlpha < 1.0f && (state.strokePattern || state.strokeGradient)) {
cairo_push_group(cr);
- cairo_paint_with_alpha(cr, gcp->state.globalAlpha);
+ cairo_paint_with_alpha(cr, state.globalAlpha);
cairo_pop_group_to_source(cr);
}
cairo_stroke_preserve(cr);
@@ -122,7 +119,7 @@ static inline void setPlatformStroke(GraphicsContext* context, cairo_t* cr, Grap
// A fillRect helper
static inline void fillRectSourceOver(cairo_t* cr, const FloatRect& rect, const Color& col)
{
- setColor(cr, col);
+ setSourceRGBAFromColor(cr, col);
cairo_rectangle(cr, rect.x(), rect.y(), rect.width(), rect.height());
cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
cairo_fill(cr);
@@ -142,7 +139,7 @@ enum PathDrawingStyle {
FillAndStroke = Fill + Stroke
};
-static inline void drawPathShadow(GraphicsContext* context, GraphicsContextPrivate* contextPrivate, PathDrawingStyle drawingStyle)
+static inline void drawPathShadow(GraphicsContext* context, PathDrawingStyle drawingStyle)
{
ContextShadow* shadow = context->contextShadow();
ASSERT(shadow);
@@ -151,7 +148,7 @@ static inline void drawPathShadow(GraphicsContext* context, GraphicsContextPriva
// Calculate the extents of the rendered solid paths.
cairo_t* cairoContext = context->platformContext();
- cairo_path_t* path = cairo_copy_path(cairoContext);
+ OwnPtr<cairo_path_t> path(cairo_copy_path(cairoContext));
FloatRect solidFigureExtents;
double x0 = 0;
@@ -175,44 +172,42 @@ static inline void drawPathShadow(GraphicsContext* context, GraphicsContextPriva
// It's important to copy the context properties to the new shadow
// context to preserve things such as the fill rule and stroke width.
copyContextProperties(cairoContext, shadowContext);
- cairo_append_path(shadowContext, path);
+ cairo_append_path(shadowContext, path.get());
if (drawingStyle & Fill)
- setPlatformFill(context, shadowContext, contextPrivate);
+ setPlatformFill(context, shadowContext);
if (drawingStyle & Stroke)
- setPlatformStroke(context, shadowContext, contextPrivate);
+ setPlatformStroke(context, shadowContext);
shadow->endShadowLayer(cairoContext);
}
-static void fillCurrentCairoPath(GraphicsContext* context, GraphicsContextPrivate* gcp, cairo_t* cairoContext)
+static void fillCurrentCairoPath(GraphicsContext* context, cairo_t* cairoContext)
{
cairo_set_fill_rule(cairoContext, context->fillRule() == RULE_EVENODD ? CAIRO_FILL_RULE_EVEN_ODD : CAIRO_FILL_RULE_WINDING);
- drawPathShadow(context, gcp, Fill);
+ drawPathShadow(context, Fill);
- setPlatformFill(context, cairoContext, gcp);
+ setPlatformFill(context, cairoContext);
cairo_new_path(cairoContext);
}
-static void strokeCurrentCairoPath(GraphicsContext* context, GraphicsContextPrivate* gcp, cairo_t* cairoContext)
+static void strokeCurrentCairoPath(GraphicsContext* context, cairo_t* cairoContext)
{
- drawPathShadow(context, gcp, Stroke);
- setPlatformStroke(context, cairoContext, gcp);
+ drawPathShadow(context, Stroke);
+ setPlatformStroke(context, cairoContext);
cairo_new_path(cairoContext);
}
-GraphicsContext::GraphicsContext(PlatformGraphicsContext* cr)
- : m_common(createGraphicsContextPrivate())
- , m_data(new GraphicsContextPlatformPrivate)
+void GraphicsContext::platformInit(PlatformGraphicsContext* cr)
{
+ m_data = new GraphicsContextPlatformPrivate;
m_data->cr = cairo_reference(cr);
m_data->syncContext(cr);
setPaintingDisabled(!cr);
}
-GraphicsContext::~GraphicsContext()
+void GraphicsContext::platformDestroy()
{
- destroyGraphicsContextPrivate(m_common);
delete m_data;
}
@@ -262,7 +257,7 @@ void GraphicsContext::drawRect(const IntRect& rect)
fillRectSourceOver(cr, rect, fillColor());
if (strokeStyle() != NoStroke) {
- setColor(cr, strokeColor());
+ setSourceRGBAFromColor(cr, strokeColor());
FloatRect r(rect);
r.inflate(-.5f);
cairo_rectangle(cr, r.x(), r.y(), r.width(), r.height());
@@ -310,7 +305,7 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
break;
}
- setColor(cr, strokeColor());
+ setSourceRGBAFromColor(cr, strokeColor());
cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE);
@@ -380,12 +375,12 @@ void GraphicsContext::drawEllipse(const IntRect& rect)
cairo_restore(cr);
if (fillColor().alpha()) {
- setColor(cr, fillColor());
+ setSourceRGBAFromColor(cr, fillColor());
cairo_fill_preserve(cr);
}
if (strokeStyle() != NoStroke) {
- setColor(cr, strokeColor());
+ setSourceRGBAFromColor(cr, strokeColor());
cairo_set_line_width(cr, strokeThickness());
cairo_stroke(cr);
} else
@@ -434,7 +429,7 @@ void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSp
break;
}
- setColor(cr, strokeColor());
+ setSourceRGBAFromColor(cr, strokeColor());
if (patWidth) {
// Example: 80 pixels with a width of 30 pixels.
@@ -493,13 +488,13 @@ void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points
addConvexPolygonToContext(cr, npoints, points);
if (fillColor().alpha()) {
- setColor(cr, fillColor());
+ setSourceRGBAFromColor(cr, fillColor());
cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD);
cairo_fill_preserve(cr);
}
if (strokeStyle() != NoStroke) {
- setColor(cr, strokeColor());
+ setSourceRGBAFromColor(cr, strokeColor());
cairo_set_line_width(cr, strokeThickness());
cairo_stroke(cr);
} else
@@ -531,42 +526,24 @@ void GraphicsContext::clipConvexPolygon(size_t numPoints, const FloatPoint* poin
cairo_set_fill_rule(cr, savedFillRule);
}
-void GraphicsContext::fillPath()
+void GraphicsContext::fillPath(const Path& path)
{
if (paintingDisabled())
return;
cairo_t* cr = m_data->cr;
-
- setPathOnCairoContext(cr, m_data->m_pendingPath.context());
- fillCurrentCairoPath(this, m_common, cr);
+ setPathOnCairoContext(cr, path.platformPath()->context());
+ fillCurrentCairoPath(this, cr);
}
-void GraphicsContext::strokePath()
+void GraphicsContext::strokePath(const Path& path)
{
if (paintingDisabled())
return;
cairo_t* cr = m_data->cr;
- setPathOnCairoContext(cr, m_data->m_pendingPath.context());
- strokeCurrentCairoPath(this, m_common, cr);
-}
-
-void GraphicsContext::drawPath()
-{
- if (paintingDisabled())
- return;
-
- cairo_t* cr = m_data->cr;
-
- setPathOnCairoContext(cr, m_data->m_pendingPath.context());
-
- cairo_set_fill_rule(cr, fillRule() == RULE_EVENODD ? CAIRO_FILL_RULE_EVEN_ODD : CAIRO_FILL_RULE_WINDING);
- drawPathShadow(this, m_common, FillAndStroke);
-
- setPlatformFill(this, cr, m_common);
- setPlatformStroke(this, cr, m_common);
- cairo_new_path(cr);
+ setPathOnCairoContext(cr, path.platformPath()->context());
+ strokeCurrentCairoPath(this, cr);
}
void GraphicsContext::fillRect(const FloatRect& rect)
@@ -577,7 +554,7 @@ void GraphicsContext::fillRect(const FloatRect& rect)
cairo_t* cr = m_data->cr;
cairo_save(cr);
cairo_rectangle(cr, rect.x(), rect.y(), rect.width(), rect.height());
- fillCurrentCairoPath(this, m_common, cr);
+ fillCurrentCairoPath(this, cr);
cairo_restore(cr);
}
@@ -607,19 +584,57 @@ void GraphicsContext::clip(const FloatRect& rect)
m_data->clip(rect);
}
-void GraphicsContext::clipPath(WindRule clipRule)
+void GraphicsContext::clipPath(const Path& path, WindRule clipRule)
{
if (paintingDisabled())
return;
cairo_t* cr = m_data->cr;
+ setPathOnCairoContext(cr, path.platformPath()->context());
cairo_set_fill_rule(cr, clipRule == RULE_EVENODD ? CAIRO_FILL_RULE_EVEN_ODD : CAIRO_FILL_RULE_WINDING);
cairo_clip(cr);
}
-void GraphicsContext::drawFocusRing(const Path& path, int width, int offset, const Color& color)
+static inline void adjustFocusRingColor(Color& color)
{
- // FIXME: implement
+#if !PLATFORM(GTK)
+ // Force the alpha to 50%. This matches what the Mac does with outline rings.
+ color.setRGB(makeRGBA(color.red(), color.green(), color.blue(), 127));
+#endif
+}
+
+static inline void adjustFocusRingLineWidth(int& width)
+{
+#if PLATFORM(GTK)
+ width = 2;
+#endif
+}
+
+static inline StrokeStyle focusRingStrokeStyle()
+{
+#if PLATFORM(GTK)
+ return DottedStroke;
+#else
+ return SolidStroke;
+#endif
+}
+
+void GraphicsContext::drawFocusRing(const Path& path, int width, int /* offset */, const Color& color)
+{
+ // FIXME: We should draw paths that describe a rectangle with rounded corners
+ // so as to be consistent with how we draw rectangular focus rings.
+ Color ringColor = color;
+ adjustFocusRingColor(ringColor);
+ adjustFocusRingLineWidth(width);
+
+ cairo_t* cr = m_data->cr;
+ cairo_save(cr);
+ appendWebCorePathToCairoContext(cr, path);
+ setSourceRGBAFromColor(cr, ringColor);
+ cairo_set_line_width(cr, width);
+ setPlatformStrokeStyle(focusRingStrokeStyle());
+ cairo_stroke(cr);
+ cairo_restore(cr);
}
void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int width, int /* offset */, const Color& color)
@@ -656,10 +671,6 @@ void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int width, int
#else
cairo_region_destroy(reg);
#endif
-
- setColor(cr, color);
- cairo_set_line_width(cr, 2.0f);
- setPlatformStrokeStyle(DottedStroke);
#else
int radius = (width - 1) / 2;
Path path;
@@ -669,13 +680,13 @@ void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int width, int
path.addRoundedRect(rects[i], FloatSize(radius, radius));
appendWebCorePathToCairoContext(cr, path);
}
-
- // Force the alpha to 50%. This matches what the Mac does with outline rings.
- Color ringColor(color.red(), color.green(), color.blue(), 127);
- setColor(cr, ringColor);
- cairo_set_line_width(cr, width);
- setPlatformStrokeStyle(SolidStroke);
#endif
+ Color ringColor = color;
+ adjustFocusRingColor(ringColor);
+ adjustFocusRingLineWidth(width);
+ setSourceRGBAFromColor(cr, ringColor);
+ cairo_set_line_width(cr, width);
+ setPlatformStrokeStyle(focusRingStrokeStyle());
cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
cairo_stroke_preserve(cr);
@@ -853,13 +864,15 @@ void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness
void GraphicsContext::setPlatformShadow(FloatSize const& size, float blur, Color const& color, ColorSpace)
{
// Cairo doesn't support shadows natively, they are drawn manually in the draw* functions
- if (m_common->state.shadowsIgnoreTransforms) {
+ if (m_state.shadowsIgnoreTransforms) {
// Meaning that this graphics context is associated with a CanvasRenderingContext
// We flip the height since CG and HTML5 Canvas have opposite Y axis
- m_common->state.shadowOffset = FloatSize(size.width(), -size.height());
+ m_state.shadowOffset = FloatSize(size.width(), -size.height());
m_data->shadow = ContextShadow(color, blur, FloatSize(size.width(), -size.height()));
} else
m_data->shadow = ContextShadow(color, blur, FloatSize(size.width(), size.height()));
+
+ m_data->shadow.setShadowsIgnoreTransforms(m_state.shadowsIgnoreTransforms);
}
ContextShadow* GraphicsContext::contextShadow()
@@ -919,7 +932,7 @@ void GraphicsContext::strokeRect(const FloatRect& rect, float width)
cairo_save(cr);
cairo_rectangle(cr, rect.x(), rect.y(), rect.width(), rect.height());
cairo_set_line_width(cr, width);
- strokeCurrentCairoPath(this, m_common, cr);
+ strokeCurrentCairoPath(this, cr);
cairo_restore(cr);
}
@@ -978,15 +991,15 @@ void GraphicsContext::setMiterLimit(float miter)
void GraphicsContext::setAlpha(float alpha)
{
- m_common->state.globalAlpha = alpha;
+ m_state.globalAlpha = alpha;
}
float GraphicsContext::getAlpha()
{
- return m_common->state.globalAlpha;
+ return m_state.globalAlpha;
}
-void GraphicsContext::setCompositeOperation(CompositeOperator op)
+void GraphicsContext::setPlatformCompositeOperation(CompositeOperator op)
{
if (paintingDisabled())
return;
@@ -994,25 +1007,6 @@ void GraphicsContext::setCompositeOperation(CompositeOperator op)
cairo_set_operator(m_data->cr, toCairoOperator(op));
}
-void GraphicsContext::beginPath()
-{
- if (paintingDisabled())
- return;
-
- cairo_new_path(m_data->m_pendingPath.context());
-}
-
-void GraphicsContext::addPath(const Path& path)
-{
- if (paintingDisabled())
- return;
-
- cairo_matrix_t currentMatrix;
- cairo_get_matrix(m_data->cr, &currentMatrix);
- cairo_set_matrix(m_data->m_pendingPath.context(), &currentMatrix);
- appendWebCorePathToCairoContext(m_data->m_pendingPath.context(), path);
-}
-
void GraphicsContext::clip(const Path& path)
{
if (paintingDisabled())
@@ -1105,7 +1099,7 @@ void GraphicsContext::fillRoundedRect(const IntRect& r, const IntSize& topLeft,
Path path;
path.addRoundedRect(r, topLeft, topRight, bottomLeft, bottomRight);
appendWebCorePathToCairoContext(cr, path);
- setColor(cr, color);
+ setSourceRGBAFromColor(cr, color);
cairo_fill(cr);
cairo_restore(cr);
}
@@ -1121,12 +1115,12 @@ GdkEventExpose* GraphicsContext::gdkExposeEvent() const
return m_data->expose;
}
-GdkDrawable* GraphicsContext::gdkDrawable() const
+GdkWindow* GraphicsContext::gdkWindow() const
{
if (!m_data->expose)
return 0;
- return GDK_DRAWABLE(m_data->expose->window);
+ return m_data->expose->window;
}
#endif
diff --git a/WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h b/WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h
index 527cb72..494b40d 100644
--- a/WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h
+++ b/WebCore/platform/graphics/cairo/GraphicsContextPlatformPrivateCairo.h
@@ -27,7 +27,6 @@
#include "GraphicsContext.h"
-#include "CairoPath.h"
#include "ContextShadow.h"
#include <cairo.h>
#include <math.h>
@@ -97,7 +96,6 @@ public:
cairo_t* cr;
Vector<float> layers;
- CairoPath m_pendingPath;
ContextShadow shadow;
Vector<ContextShadow> shadowStack;
diff --git a/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp b/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp
index d452c3a..b353943 100644
--- a/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp
+++ b/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp
@@ -69,7 +69,7 @@ ImageBufferData::ImageBufferData(const IntSize& size)
{
}
-ImageBuffer::ImageBuffer(const IntSize& size, ColorSpace, bool& success)
+ImageBuffer::ImageBuffer(const IntSize& size, ColorSpace, RenderingMode, bool& success)
: m_data(size)
, m_size(size)
{
diff --git a/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp b/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp
index 7a58eed..f997277 100644
--- a/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp
+++ b/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp
@@ -99,7 +99,8 @@ bool GraphicsContext3D::getImageData(Image* image,
CGImageRef cgImage;
RetainPtr<CGImageRef> decodedImage;
if (image->data()) {
- ImageSource decoder(false, ignoreGammaAndColorProfile);
+ ImageSource decoder(ImageSource::AlphaNotPremultiplied,
+ ignoreGammaAndColorProfile ? ImageSource::GammaAndColorProfileIgnored : ImageSource::GammaAndColorProfileApplied);
decoder.setData(image->data(), true);
if (!decoder.frameCount())
return false;
diff --git a/WebCore/platform/graphics/cg/GraphicsContextCG.cpp b/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
index 8d72b85..7898d62 100644
--- a/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
+++ b/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
@@ -31,7 +31,6 @@
#include "AffineTransform.h"
#include "FloatConversion.h"
#include "GraphicsContextPlatformPrivateCG.h"
-#include "GraphicsContextPrivate.h"
#include "ImageBuffer.h"
#include "KURL.h"
#include "Path.h"
@@ -42,6 +41,7 @@
#include <wtf/MathExtras.h>
#include <wtf/OwnArrayPtr.h>
#include <wtf/RetainPtr.h>
+#include <wtf/UnusedParam.h>
#if PLATFORM(MAC) || PLATFORM(CHROMIUM)
#include "WebCoreSystemInterface.h"
@@ -107,10 +107,9 @@ CGColorSpaceRef linearRGBColorSpaceRef()
#endif
}
-GraphicsContext::GraphicsContext(CGContextRef cgContext)
- : m_common(createGraphicsContextPrivate())
- , m_data(new GraphicsContextPlatformPrivate(cgContext))
+void GraphicsContext::platformInit(CGContextRef cgContext)
{
+ m_data = new GraphicsContextPlatformPrivate(cgContext);
setPaintingDisabled(!cgContext);
if (cgContext) {
// Make sure the context starts in sync with our state.
@@ -119,9 +118,8 @@ GraphicsContext::GraphicsContext(CGContextRef cgContext)
}
}
-GraphicsContext::~GraphicsContext()
+void GraphicsContext::platformDestroy()
{
- destroyGraphicsContextPrivate(m_common);
delete m_data;
}
@@ -299,21 +297,12 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
// This method is only used to draw the little circles used in lists.
void GraphicsContext::drawEllipse(const IntRect& rect)
{
- // FIXME: CG added CGContextAddEllipseinRect in Tiger, so we should be able to quite easily draw an ellipse.
- // This code can only handle circles, not ellipses. But khtml only
- // uses it for circles.
- ASSERT(rect.width() == rect.height());
-
if (paintingDisabled())
return;
- CGContextRef context = platformContext();
- CGContextBeginPath(context);
- float r = (float)rect.width() / 2;
- CGContextAddArc(context, rect.x() + r, rect.y() + r, r, 0.0f, 2.0f * piFloat, 0);
- CGContextClosePath(context);
-
- drawPath();
+ Path path;
+ path.addEllipse(rect);
+ drawPath(path);
}
@@ -405,21 +394,22 @@ void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSp
CGContextRestoreGState(context);
}
-static void addConvexPolygonToContext(CGContextRef context, size_t numPoints, const FloatPoint* points)
+static void addConvexPolygonToPath(Path& path, size_t numberOfPoints, const FloatPoint* points)
{
- CGContextBeginPath(context);
- CGContextMoveToPoint(context, points[0].x(), points[0].y());
- for (size_t i = 1; i < numPoints; i++)
- CGContextAddLineToPoint(context, points[i].x(), points[i].y());
- CGContextClosePath(context);
+ ASSERT(numberOfPoints > 0);
+
+ path.moveTo(points[0]);
+ for (size_t i = 1; i < numberOfPoints; ++i)
+ path.addLineTo(points[i]);
+ path.closeSubpath();
}
-void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points, bool antialiased)
+void GraphicsContext::drawConvexPolygon(size_t numberOfPoints, const FloatPoint* points, bool antialiased)
{
if (paintingDisabled())
return;
- if (npoints <= 1)
+ if (numberOfPoints <= 1)
return;
CGContextRef context = platformContext();
@@ -427,28 +417,30 @@ void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points
if (antialiased != shouldAntialias())
CGContextSetShouldAntialias(context, antialiased);
- addConvexPolygonToContext(context, npoints, points);
- drawPath();
+ Path path;
+ addConvexPolygonToPath(path, numberOfPoints, points);
+ drawPath(path);
if (antialiased != shouldAntialias())
CGContextSetShouldAntialias(context, shouldAntialias());
}
-void GraphicsContext::clipConvexPolygon(size_t numPoints, const FloatPoint* points, bool antialias)
+void GraphicsContext::clipConvexPolygon(size_t numberOfPoints, const FloatPoint* points, bool antialias)
{
if (paintingDisabled())
return;
- if (numPoints <= 1)
+ if (numberOfPoints <= 1)
return;
CGContextRef context = platformContext();
if (antialias != shouldAntialias())
CGContextSetShouldAntialias(context, antialias);
-
- addConvexPolygonToContext(context, numPoints, points);
- clipPath(RULE_NONZERO);
+
+ Path path;
+ addConvexPolygonToPath(path, numberOfPoints, points);
+ clipPath(path, RULE_NONZERO);
if (antialias != shouldAntialias())
CGContextSetShouldAntialias(context, shouldAntialias());
@@ -458,7 +450,7 @@ void GraphicsContext::applyStrokePattern()
{
CGContextRef cgContext = platformContext();
- RetainPtr<CGPatternRef> platformPattern(AdoptCF, m_common->state.strokePattern->createPlatformPattern(getCTM()));
+ RetainPtr<CGPatternRef> platformPattern(AdoptCF, m_state.strokePattern->createPlatformPattern(getCTM()));
if (!platformPattern)
return;
@@ -473,7 +465,7 @@ void GraphicsContext::applyFillPattern()
{
CGContextRef cgContext = platformContext();
- RetainPtr<CGPatternRef> platformPattern(AdoptCF, m_common->state.fillPattern->createPlatformPattern(getCTM()));
+ RetainPtr<CGPatternRef> platformPattern(AdoptCF, m_state.fillPattern->createPlatformPattern(getCTM()));
if (!platformPattern)
return;
@@ -511,21 +503,25 @@ static inline bool calculateDrawingMode(const GraphicsContextState& state, CGPat
return shouldFill || shouldStroke;
}
-void GraphicsContext::drawPath()
+void GraphicsContext::drawPath(const Path& path)
{
if (paintingDisabled())
return;
CGContextRef context = platformContext();
- const GraphicsContextState& state = m_common->state;
+ const GraphicsContextState& state = m_state;
if (state.fillGradient || state.strokeGradient) {
// We don't have any optimized way to fill & stroke a path using gradients
- fillPath();
- strokePath();
+ // FIXME: Be smarter about this.
+ fillPath(path);
+ strokePath(path);
return;
}
+ CGContextBeginPath(context);
+ CGContextAddPath(context, path.platformPath());
+
if (state.fillPattern)
applyFillPattern();
if (state.strokePattern)
@@ -544,48 +540,54 @@ static inline void fillPathWithFillRule(CGContextRef context, WindRule fillRule)
CGContextFillPath(context);
}
-void GraphicsContext::fillPath()
+void GraphicsContext::fillPath(const Path& path)
{
if (paintingDisabled())
return;
CGContextRef context = platformContext();
- if (m_common->state.fillGradient) {
+ CGContextBeginPath(context);
+ CGContextAddPath(context, path.platformPath());
+
+ if (m_state.fillGradient) {
CGContextSaveGState(context);
if (fillRule() == RULE_EVENODD)
CGContextEOClip(context);
else
CGContextClip(context);
- CGContextConcatCTM(context, m_common->state.fillGradient->gradientSpaceTransform());
- m_common->state.fillGradient->paint(this);
+ CGContextConcatCTM(context, m_state.fillGradient->gradientSpaceTransform());
+ m_state.fillGradient->paint(this);
CGContextRestoreGState(context);
return;
}
- if (m_common->state.fillPattern)
+ if (m_state.fillPattern)
applyFillPattern();
fillPathWithFillRule(context, fillRule());
}
-void GraphicsContext::strokePath()
+void GraphicsContext::strokePath(const Path& path)
{
if (paintingDisabled())
return;
CGContextRef context = platformContext();
- if (m_common->state.strokeGradient) {
+ CGContextBeginPath(context);
+ CGContextAddPath(context, path.platformPath());
+
+ if (m_state.strokeGradient) {
CGContextSaveGState(context);
CGContextReplacePathWithStrokedPath(context);
CGContextClip(context);
- CGContextConcatCTM(context, m_common->state.strokeGradient->gradientSpaceTransform());
- m_common->state.strokeGradient->paint(this);
+ CGContextConcatCTM(context, m_state.strokeGradient->gradientSpaceTransform());
+ m_state.strokeGradient->paint(this);
CGContextRestoreGState(context);
return;
}
- if (m_common->state.strokePattern)
+ if (m_state.strokePattern)
applyStrokePattern();
CGContextStrokePath(context);
}
@@ -597,16 +599,16 @@ void GraphicsContext::fillRect(const FloatRect& rect)
CGContextRef context = platformContext();
- if (m_common->state.fillGradient) {
+ if (m_state.fillGradient) {
CGContextSaveGState(context);
CGContextClipToRect(context, rect);
- CGContextConcatCTM(context, m_common->state.fillGradient->gradientSpaceTransform());
- m_common->state.fillGradient->paint(this);
+ CGContextConcatCTM(context, m_state.fillGradient->gradientSpaceTransform());
+ m_state.fillGradient->paint(this);
CGContextRestoreGState(context);
return;
}
- if (m_common->state.fillPattern)
+ if (m_state.fillPattern)
applyFillPattern();
CGContextFillRect(context, rect);
}
@@ -643,8 +645,7 @@ void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLef
Path path;
path.addRoundedRect(rect, topLeft, topRight, bottomLeft, bottomRight);
- addPath(path);
- fillPath();
+ fillPath(path);
if (oldFillColor != color || oldColorSpace != colorSpace)
setCGFillColor(context, oldFillColor, oldColorSpace);
@@ -669,19 +670,23 @@ void GraphicsContext::clipOut(const IntRect& rect)
CGContextEOClip(platformContext());
}
-void GraphicsContext::clipPath(WindRule clipRule)
+void GraphicsContext::clipPath(const Path& path, WindRule clipRule)
{
if (paintingDisabled())
return;
+ if (path.isEmpty())
+ return;
+
CGContextRef context = platformContext();
- if (!CGContextIsPathEmpty(context)) {
- if (clipRule == RULE_EVENODD)
- CGContextEOClip(context);
- else
- CGContextClip(context);
- }
+ CGContextBeginPath(platformContext());
+ CGContextAddPath(platformContext(), path.platformPath());
+
+ if (clipRule == RULE_EVENODD)
+ CGContextEOClip(context);
+ else
+ CGContextClip(context);
}
void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness)
@@ -733,7 +738,7 @@ void GraphicsContext::setPlatformShadow(const FloatSize& offset, float blur, con
CGFloat blurRadius = blur;
CGContextRef context = platformContext();
- if (!m_common->state.shadowsIgnoreTransforms) {
+ if (!m_state.shadowsIgnoreTransforms) {
CGAffineTransform userToBaseCTM = wkGetUserToBaseCTM(context);
CGFloat A = userToBaseCTM.a * userToBaseCTM.a + userToBaseCTM.b * userToBaseCTM.b;
@@ -808,18 +813,18 @@ void GraphicsContext::strokeRect(const FloatRect& r, float lineWidth)
CGContextRef context = platformContext();
- if (m_common->state.strokeGradient) {
+ if (m_state.strokeGradient) {
CGContextSaveGState(context);
setStrokeThickness(lineWidth);
CGContextAddRect(context, r);
CGContextReplacePathWithStrokedPath(context);
CGContextClip(context);
- m_common->state.strokeGradient->paint(this);
+ m_state.strokeGradient->paint(this);
CGContextRestoreGState(context);
return;
}
- if (m_common->state.strokePattern)
+ if (m_state.strokePattern)
applyStrokePattern();
CGContextStrokeRectWithWidth(context, r, lineWidth);
}
@@ -863,16 +868,6 @@ void GraphicsContext::setLineJoin(LineJoin join)
}
}
-void GraphicsContext::beginPath()
-{
- CGContextBeginPath(platformContext());
-}
-
-void GraphicsContext::addPath(const Path& path)
-{
- CGContextAddPath(platformContext(), path.platformPath());
-}
-
void GraphicsContext::clip(const Path& path)
{
if (paintingDisabled())
@@ -1119,7 +1114,16 @@ InterpolationQuality GraphicsContext::imageInterpolationQuality() const
return InterpolationDefault;
}
-void GraphicsContext::setPlatformTextDrawingMode(int mode)
+void GraphicsContext::setAllowsFontSmoothing(bool allowsFontSmoothing)
+{
+ UNUSED_PARAM(allowsFontSmoothing);
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+ CGContextRef context = platformContext();
+ CGContextSetAllowsFontSmoothing(context, allowsFontSmoothing);
+#endif
+}
+
+void GraphicsContext::setPlatformTextDrawingMode(TextDrawingModeFlags mode)
{
if (paintingDisabled())
return;
@@ -1127,28 +1131,28 @@ void GraphicsContext::setPlatformTextDrawingMode(int mode)
// Wow, wish CG had used bits here.
CGContextRef context = platformContext();
switch (mode) {
- case cTextInvisible: // Invisible
+ case TextModeInvisible:
CGContextSetTextDrawingMode(context, kCGTextInvisible);
break;
- case cTextFill: // Fill
+ case TextModeFill:
CGContextSetTextDrawingMode(context, kCGTextFill);
break;
- case cTextStroke: // Stroke
+ case TextModeStroke:
CGContextSetTextDrawingMode(context, kCGTextStroke);
break;
- case 3: // Fill | Stroke
+ case TextModeFill | TextModeStroke:
CGContextSetTextDrawingMode(context, kCGTextFillStroke);
break;
- case cTextClip: // Clip
+ case TextModeClip:
CGContextSetTextDrawingMode(context, kCGTextClip);
break;
- case 5: // Fill | Clip
+ case TextModeFill | TextModeClip:
CGContextSetTextDrawingMode(context, kCGTextFillClip);
break;
- case 6: // Stroke | Clip
+ case TextModeStroke | TextModeClip:
CGContextSetTextDrawingMode(context, kCGTextStrokeClip);
break;
- case 7: // Fill | Stroke | Clip
+ case TextModeFill | TextModeStroke | TextModeClip:
CGContextSetTextDrawingMode(context, kCGTextFillStrokeClip);
break;
default:
@@ -1184,8 +1188,15 @@ void GraphicsContext::setPlatformShouldAntialias(bool enable)
CGContextSetShouldAntialias(platformContext(), enable);
}
-#ifndef BUILDING_ON_TIGER // Tiger's setCompositeOperation() is defined in GraphicsContextMac.mm.
-void GraphicsContext::setCompositeOperation(CompositeOperator mode)
+void GraphicsContext::setPlatformShouldSmoothFonts(bool enable)
+{
+ if (paintingDisabled())
+ return;
+ CGContextSetShouldSmoothFonts(platformContext(), enable);
+}
+
+#ifndef BUILDING_ON_TIGER // Tiger's setPlatformCompositeOperation() is defined in GraphicsContextMac.mm.
+void GraphicsContext::setPlatformCompositeOperation(CompositeOperator mode)
{
if (paintingDisabled())
return;
diff --git a/WebCore/platform/graphics/cg/ImageBufferCG.cpp b/WebCore/platform/graphics/cg/ImageBufferCG.cpp
index 640692a..7bc47f2 100644
--- a/WebCore/platform/graphics/cg/ImageBufferCG.cpp
+++ b/WebCore/platform/graphics/cg/ImageBufferCG.cpp
@@ -42,10 +42,57 @@
#include <wtf/Threading.h>
#include <math.h>
+#if defined(USE_IOSURFACE)
+#include <IOSurface/IOSurface.h>
+#endif
+
+#if PLATFORM(MAC) || PLATFORM(CHROMIUM)
+#include "WebCoreSystemInterface.h"
+#endif
+
using namespace std;
namespace WebCore {
+#if defined(USE_IOSURFACE)
+static RetainPtr<IOSurfaceRef> createIOSurface(const IntSize& size)
+{
+ unsigned pixelFormat = 'BGRA';
+ unsigned bytesPerElement = 4;
+ int width = size.width();
+ int height = size.height();
+
+ unsigned long bytesPerRow = IOSurfaceAlignProperty(kIOSurfaceBytesPerRow, size.width() * bytesPerElement);
+ if (!bytesPerRow)
+ return 0;
+
+ unsigned long allocSize = IOSurfaceAlignProperty(kIOSurfaceAllocSize, size.height() * bytesPerRow);
+ if (!allocSize)
+ return 0;
+
+ const void *keys[6];
+ const void *values[6];
+ keys[0] = kIOSurfaceWidth;
+ values[0] = CFNumberCreate(0, kCFNumberIntType, &width);
+ keys[1] = kIOSurfaceHeight;
+ values[1] = CFNumberCreate(0, kCFNumberIntType, &height);
+ keys[2] = kIOSurfacePixelFormat;
+ values[2] = CFNumberCreate(0, kCFNumberIntType, &pixelFormat);
+ keys[3] = kIOSurfaceBytesPerElement;
+ values[3] = CFNumberCreate(0, kCFNumberIntType, &bytesPerElement);
+ keys[4] = kIOSurfaceBytesPerRow;
+ values[4] = CFNumberCreate(0, kCFNumberLongType, &bytesPerRow);
+ keys[5] = kIOSurfaceAllocSize;
+ values[5] = CFNumberCreate(0, kCFNumberLongType, &allocSize);
+
+ RetainPtr<CFDictionaryRef> dict(AdoptCF, CFDictionaryCreate(0, keys, values, 6, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
+ for (unsigned i = 0; i < 6; i++)
+ CFRelease(values[i]);
+
+ return RetainPtr<IOSurfaceRef>(AdoptCF, IOSurfaceCreate(dict.get()));
+}
+#endif
+
static void releaseImageData(void*, const void* data, size_t)
{
fastFree(const_cast<void*>(data));
@@ -53,32 +100,32 @@ static void releaseImageData(void*, const void* data, size_t)
ImageBufferData::ImageBufferData(const IntSize&)
: m_data(0)
+#if defined(USE_IOSURFACE)
+ , m_surface(0)
+#endif
{
}
-ImageBuffer::ImageBuffer(const IntSize& size, ColorSpace imageColorSpace, bool& success)
+ImageBuffer::ImageBuffer(const IntSize& size, ColorSpace imageColorSpace, RenderingMode renderingMode, bool& success)
: m_data(size)
, m_size(size)
+ , m_accelerateRendering(renderingMode == Accelerated)
{
+#if !defined(USE_IOSURFACE)
+ ASSERT(renderingMode == Unaccelerated);
+#endif
success = false; // Make early return mean failure.
if (size.width() < 0 || size.height() < 0)
return;
unsigned bytesPerRow = size.width();
-
- // Protect against overflow
- if (bytesPerRow > 0x3FFFFFFF)
+ if (bytesPerRow > 0x3FFFFFFF) // Protect against overflow
return;
bytesPerRow *= 4;
m_data.m_bytesPerRow = bytesPerRow;
-
size_t dataSize = size.height() * bytesPerRow;
- if (!tryFastCalloc(size.height(), bytesPerRow).getValue(m_data.m_data))
- return;
-
- ASSERT((reinterpret_cast<size_t>(m_data.m_data) & 2) == 0);
- switch(imageColorSpace) {
+ switch (imageColorSpace) {
case ColorSpaceDeviceRGB:
m_data.m_colorSpace = deviceRGBColorSpaceRef();
break;
@@ -90,9 +137,25 @@ ImageBuffer::ImageBuffer(const IntSize& size, ColorSpace imageColorSpace, bool&
break;
}
- m_data.m_bitmapInfo = kCGImageAlphaPremultipliedLast;
- RetainPtr<CGContextRef> cgContext(AdoptCF, CGBitmapContextCreate(m_data.m_data, size.width(), size.height(), 8, bytesPerRow,
- m_data.m_colorSpace, m_data.m_bitmapInfo));
+ RetainPtr<CGContextRef> cgContext;
+ if (!m_accelerateRendering) {
+ if (!tryFastCalloc(size.height(), bytesPerRow).getValue(m_data.m_data))
+ return;
+ ASSERT(!(reinterpret_cast<size_t>(m_data.m_data) & 2));
+
+ m_data.m_bitmapInfo = kCGImageAlphaPremultipliedLast;
+ cgContext.adoptCF(CGBitmapContextCreate(m_data.m_data, size.width(), size.height(), 8, bytesPerRow, m_data.m_colorSpace, m_data.m_bitmapInfo));
+ // Create a live image that wraps the data.
+ m_data.m_dataProvider.adoptCF(CGDataProviderCreateWithData(0, m_data.m_data, dataSize, releaseImageData));
+ } else {
+#if defined(USE_IOSURFACE)
+ m_data.m_surface = createIOSurface(size);
+ cgContext.adoptCF(wkIOSurfaceContextCreate(m_data.m_surface.get(), size.width(), size.height(), m_data.m_colorSpace));
+#else
+ m_accelerateRendering = false; // Force to false on older platforms
+#endif
+ }
+
if (!cgContext)
return;
@@ -100,9 +163,6 @@ ImageBuffer::ImageBuffer(const IntSize& size, ColorSpace imageColorSpace, bool&
m_context->scale(FloatSize(1, -1));
m_context->translate(0, -size.height());
success = true;
-
- // Create a live image that wraps the data.
- m_data.m_dataProvider.adoptCF(CGDataProviderCreateWithData(0, m_data.m_data, dataSize, releaseImageData));
}
ImageBuffer::~ImageBuffer()
@@ -122,7 +182,14 @@ bool ImageBuffer::drawsUsingCopy() const
PassRefPtr<Image> ImageBuffer::copyImage() const
{
// BitmapImage will release the passed in CGImage on destruction
- return BitmapImage::create(CGBitmapContextCreateImage(context()->platformContext()));
+ CGImageRef ctxImage = 0;
+ if (!m_accelerateRendering)
+ ctxImage = CGBitmapContextCreateImage(context()->platformContext());
+#if defined(USE_IOSURFACE)
+ else
+ ctxImage = wkIOSurfaceContextCreateImage(context()->platformContext());
+#endif
+ return BitmapImage::create(ctxImage);
}
static CGImageRef cgImage(const IntSize& size, const ImageBufferData& data)
@@ -134,34 +201,50 @@ static CGImageRef cgImage(const IntSize& size, const ImageBufferData& data)
void ImageBuffer::draw(GraphicsContext* destContext, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect,
CompositeOperator op, bool useLowQualityScale)
{
- if (destContext == context()) {
- // We're drawing into our own buffer. In order for this to work, we need to copy the source buffer first.
- RefPtr<Image> copy = copyImage();
- destContext->drawImage(copy.get(), ColorSpaceDeviceRGB, destRect, srcRect, op, useLowQualityScale);
+ if (!m_accelerateRendering) {
+ if (destContext == context()) {
+ // We're drawing into our own buffer. In order for this to work, we need to copy the source buffer first.
+ RefPtr<Image> copy = copyImage();
+ destContext->drawImage(copy.get(), ColorSpaceDeviceRGB, destRect, srcRect, op, useLowQualityScale);
+ } else {
+ RefPtr<Image> imageForRendering = BitmapImage::create(cgImage(m_size, m_data));
+ destContext->drawImage(imageForRendering.get(), styleColorSpace, destRect, srcRect, op, useLowQualityScale);
+ }
} else {
- RefPtr<Image> imageForRendering = BitmapImage::create(cgImage(m_size, m_data));
- destContext->drawImage(imageForRendering.get(), styleColorSpace, destRect, srcRect, op, useLowQualityScale);
+ RefPtr<Image> copy = copyImage();
+ ColorSpace colorSpace = (destContext == context()) ? ColorSpaceDeviceRGB : styleColorSpace;
+ destContext->drawImage(copy.get(), colorSpace, destRect, srcRect, op, useLowQualityScale);
}
}
void ImageBuffer::drawPattern(GraphicsContext* destContext, const FloatRect& srcRect, const AffineTransform& patternTransform,
const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRect)
{
- if (destContext == context()) {
- // We're drawing into our own buffer. In order for this to work, we need to copy the source buffer first.
+ if (!m_accelerateRendering) {
+ if (destContext == context()) {
+ // We're drawing into our own buffer. In order for this to work, we need to copy the source buffer first.
+ RefPtr<Image> copy = copyImage();
+ copy->drawPattern(destContext, srcRect, patternTransform, phase, styleColorSpace, op, destRect);
+ } else {
+ RefPtr<Image> imageForRendering = BitmapImage::create(cgImage(m_size, m_data));
+ imageForRendering->drawPattern(destContext, srcRect, patternTransform, phase, styleColorSpace, op, destRect);
+ }
+ } else {
RefPtr<Image> copy = copyImage();
copy->drawPattern(destContext, srcRect, patternTransform, phase, styleColorSpace, op, destRect);
- } else {
- RefPtr<Image> imageForRendering = BitmapImage::create(cgImage(m_size, m_data));
- imageForRendering->drawPattern(destContext, srcRect, patternTransform, phase, styleColorSpace, op, destRect);
}
}
void ImageBuffer::clip(GraphicsContext* context, const FloatRect& rect) const
{
- RetainPtr<CGImageRef> image(AdoptCF, cgImage(m_size, m_data));
-
CGContextRef platformContext = context->platformContext();
+ RetainPtr<CGImageRef> image;
+ if (!m_accelerateRendering)
+ image.adoptCF(cgImage(m_size, m_data));
+#if defined(USE_IOSURFACE)
+ else
+ image.adoptCF(wkIOSurfaceContextCreateImage(platformContext));
+#endif
CGContextTranslateCTM(platformContext, rect.x(), rect.y() + rect.height());
CGContextScaleCTM(platformContext, 1, -1);
CGContextClipToMask(platformContext, FloatRect(FloatPoint(), rect.size()), image.get());
@@ -170,7 +253,7 @@ void ImageBuffer::clip(GraphicsContext* context, const FloatRect& rect) const
}
template <Multiply multiplied>
-PassRefPtr<ImageData> getImageData(const IntRect& rect, const ImageBufferData& imageData, const IntSize& size)
+PassRefPtr<ImageData> getImageData(const IntRect& rect, const ImageBufferData& imageData, const IntSize& size, bool accelerateRendering)
{
PassRefPtr<ImageData> result = ImageData::create(rect.width(), rect.height());
unsigned char* data = result->data()->data()->data();
@@ -199,43 +282,83 @@ PassRefPtr<ImageData> getImageData(const IntRect& rect, const ImageBufferData& i
if (endy > size.height())
endy = size.height();
int numRows = endy - originy;
-
- unsigned srcBytesPerRow = 4 * size.width();
+
unsigned destBytesPerRow = 4 * rect.width();
-
- // ::create ensures that all ImageBuffers have valid data, so we don't need to check it here.
- unsigned char* srcRows = reinterpret_cast<unsigned char*>(imageData.m_data) + originy * srcBytesPerRow + originx * 4;
unsigned char* destRows = data + desty * destBytesPerRow + destx * 4;
- for (int y = 0; y < numRows; ++y) {
- for (int x = 0; x < numColumns; x++) {
- int basex = x * 4;
- unsigned char alpha = srcRows[basex + 3];
- if (multiplied == Unmultiplied && alpha) {
- destRows[basex] = (srcRows[basex] * 255) / alpha;
- destRows[basex + 1] = (srcRows[basex + 1] * 255) / alpha;
- destRows[basex + 2] = (srcRows[basex + 2] * 255) / alpha;
- destRows[basex + 3] = alpha;
- } else
- reinterpret_cast<uint32_t*>(destRows + basex)[0] = reinterpret_cast<uint32_t*>(srcRows + basex)[0];
+
+ unsigned srcBytesPerRow;
+ unsigned char* srcRows;
+
+ if (!accelerateRendering) {
+ srcBytesPerRow = 4 * size.width();
+ srcRows = reinterpret_cast<unsigned char*>(imageData.m_data) + originy * srcBytesPerRow + originx * 4;
+
+ for (int y = 0; y < numRows; ++y) {
+ for (int x = 0; x < numColumns; x++) {
+ int basex = x * 4;
+ unsigned char alpha = srcRows[basex + 3];
+ if (multiplied == Unmultiplied && alpha) {
+ destRows[basex] = (srcRows[basex] * 255) / alpha;
+ destRows[basex + 1] = (srcRows[basex + 1] * 255) / alpha;
+ destRows[basex + 2] = (srcRows[basex + 2] * 255) / alpha;
+ destRows[basex + 3] = alpha;
+ } else
+ reinterpret_cast<uint32_t*>(destRows + basex)[0] = reinterpret_cast<uint32_t*>(srcRows + basex)[0];
+ }
+ srcRows += srcBytesPerRow;
+ destRows += destBytesPerRow;
+ }
+ } else {
+#if defined(USE_IOSURFACE)
+ IOSurfaceRef surface = imageData.m_surface.get();
+ IOSurfaceLock(surface, kIOSurfaceLockReadOnly, 0);
+ srcBytesPerRow = IOSurfaceGetBytesPerRow(surface);
+ srcRows = (unsigned char*)(IOSurfaceGetBaseAddress(surface)) + originy * srcBytesPerRow + originx * 4;
+
+ for (int y = 0; y < numRows; ++y) {
+ for (int x = 0; x < numColumns; x++) {
+ int basex = x * 4;
+ unsigned char alpha = srcRows[basex + 3];
+ if (multiplied == Unmultiplied && alpha) {
+ destRows[basex] = (srcRows[basex + 2] * 255) / alpha;
+ destRows[basex + 1] = (srcRows[basex + 1] * 255) / alpha;
+ destRows[basex + 2] = (srcRows[basex] * 255) / alpha;
+ destRows[basex + 3] = alpha;
+ } else {
+ destRows[basex] = srcRows[basex + 2];
+ destRows[basex + 1] = srcRows[basex + 1];
+ destRows[basex + 2] = srcRows[basex];
+ destRows[basex + 3] = alpha;
+ }
+ }
+ srcRows += srcBytesPerRow;
+ destRows += destBytesPerRow;
}
- srcRows += srcBytesPerRow;
- destRows += destBytesPerRow;
+ IOSurfaceUnlock(surface, kIOSurfaceLockReadOnly, 0);
+#else
+ ASSERT_NOT_REACHED();
+#endif
}
+
return result;
}
PassRefPtr<ImageData> ImageBuffer::getUnmultipliedImageData(const IntRect& rect) const
{
- return getImageData<Unmultiplied>(rect, m_data, m_size);
+ if (m_accelerateRendering)
+ CGContextFlush(context()->platformContext());
+ return getImageData<Unmultiplied>(rect, m_data, m_size, m_accelerateRendering);
}
PassRefPtr<ImageData> ImageBuffer::getPremultipliedImageData(const IntRect& rect) const
{
- return getImageData<Premultiplied>(rect, m_data, m_size);
+ if (m_accelerateRendering)
+ CGContextFlush(context()->platformContext());
+ return getImageData<Premultiplied>(rect, m_data, m_size, m_accelerateRendering);
}
template <Multiply multiplied>
-void putImageData(ImageData*& source, const IntRect& sourceRect, const IntPoint& destPoint, ImageBufferData& imageData, const IntSize& size)
+void putImageData(ImageData*& source, const IntRect& sourceRect, const IntPoint& destPoint, ImageBufferData& imageData, const IntSize& size, bool accelerateRendering)
{
ASSERT(sourceRect.width() > 0);
ASSERT(sourceRect.height() > 0);
@@ -264,35 +387,73 @@ void putImageData(ImageData*& source, const IntRect& sourceRect, const IntPoint&
int numRows = endy - desty;
unsigned srcBytesPerRow = 4 * source->width();
- unsigned destBytesPerRow = 4 * size.width();
-
unsigned char* srcRows = source->data()->data()->data() + originy * srcBytesPerRow + originx * 4;
- unsigned char* destRows = reinterpret_cast<unsigned char*>(imageData.m_data) + desty * destBytesPerRow + destx * 4;
- for (int y = 0; y < numRows; ++y) {
- for (int x = 0; x < numColumns; x++) {
- int basex = x * 4;
- unsigned char alpha = srcRows[basex + 3];
- if (multiplied == Unmultiplied && alpha != 255) {
- destRows[basex] = (srcRows[basex] * alpha + 254) / 255;
- destRows[basex + 1] = (srcRows[basex + 1] * alpha + 254) / 255;
- destRows[basex + 2] = (srcRows[basex + 2] * alpha + 254) / 255;
- destRows[basex + 3] = alpha;
- } else
- reinterpret_cast<uint32_t*>(destRows + basex)[0] = reinterpret_cast<uint32_t*>(srcRows + basex)[0];
+ unsigned destBytesPerRow;
+ unsigned char* destRows;
+
+ if (!accelerateRendering) {
+ destBytesPerRow = 4 * size.width();
+ destRows = reinterpret_cast<unsigned char*>(imageData.m_data) + desty * destBytesPerRow + destx * 4;
+ for (int y = 0; y < numRows; ++y) {
+ for (int x = 0; x < numColumns; x++) {
+ int basex = x * 4;
+ unsigned char alpha = srcRows[basex + 3];
+ if (multiplied == Unmultiplied && alpha != 255) {
+ destRows[basex] = (srcRows[basex] * alpha + 254) / 255;
+ destRows[basex + 1] = (srcRows[basex + 1] * alpha + 254) / 255;
+ destRows[basex + 2] = (srcRows[basex + 2] * alpha + 254) / 255;
+ destRows[basex + 3] = alpha;
+ } else
+ reinterpret_cast<uint32_t*>(destRows + basex)[0] = reinterpret_cast<uint32_t*>(srcRows + basex)[0];
+ }
+ destRows += destBytesPerRow;
+ srcRows += srcBytesPerRow;
+ }
+ } else {
+#if defined(USE_IOSURFACE)
+ IOSurfaceRef surface = imageData.m_surface.get();
+ IOSurfaceLock(surface, 0, 0);
+ destBytesPerRow = IOSurfaceGetBytesPerRow(surface);
+ destRows = (unsigned char*)(IOSurfaceGetBaseAddress(surface)) + desty * destBytesPerRow + destx * 4;
+
+ for (int y = 0; y < numRows; ++y) {
+ for (int x = 0; x < numColumns; x++) {
+ int basex = x * 4;
+ unsigned char alpha = srcRows[basex + 3];
+ if (multiplied == Unmultiplied && alpha != 255) {
+ destRows[basex] = (srcRows[basex + 2] * alpha + 254) / 255;
+ destRows[basex + 1] = (srcRows[basex + 1] * alpha + 254) / 255;
+ destRows[basex + 2] = (srcRows[basex] * alpha + 254) / 255;
+ destRows[basex + 3] = alpha;
+ } else {
+ destRows[basex] = srcRows[basex + 2];
+ destRows[basex + 1] = srcRows[basex + 1];
+ destRows[basex + 2] = srcRows[basex];
+ destRows[basex + 3] = alpha;
+ }
+ }
+ destRows += destBytesPerRow;
+ srcRows += srcBytesPerRow;
}
- destRows += destBytesPerRow;
- srcRows += srcBytesPerRow;
+ IOSurfaceUnlock(surface, 0, 0);
+#else
+ ASSERT_NOT_REACHED();
+#endif
}
}
void ImageBuffer::putUnmultipliedImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint)
{
- putImageData<Unmultiplied>(source, sourceRect, destPoint, m_data, m_size);
+ if (m_accelerateRendering)
+ CGContextFlush(context()->platformContext());
+ putImageData<Unmultiplied>(source, sourceRect, destPoint, m_data, m_size, m_accelerateRendering);
}
void ImageBuffer::putPremultipliedImageData(ImageData* source, const IntRect& sourceRect, const IntPoint& destPoint)
{
- putImageData<Premultiplied>(source, sourceRect, destPoint, m_data, m_size);
+ if (m_accelerateRendering)
+ CGContextFlush(context()->platformContext());
+ putImageData<Premultiplied>(source, sourceRect, destPoint, m_data, m_size, m_accelerateRendering);
}
static inline CFStringRef jpegUTI()
@@ -332,7 +493,14 @@ String ImageBuffer::toDataURL(const String& mimeType, const double* quality) con
{
ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType));
- RetainPtr<CGImageRef> image(AdoptCF, CGBitmapContextCreateImage(context()->platformContext()));
+ RetainPtr<CGImageRef> image;
+ if (!m_accelerateRendering)
+ image.adoptCF(CGBitmapContextCreateImage(context()->platformContext()));
+#if defined(USE_IOSURFACE)
+ else
+ image.adoptCF(wkIOSurfaceContextCreateImage(context()->platformContext()));
+#endif
+
if (!image)
return "data:,";
@@ -361,9 +529,7 @@ String ImageBuffer::toDataURL(const String& mimeType, const double* quality) con
Vector<char> out;
base64Encode(reinterpret_cast<const char*>(CFDataGetBytePtr(data.get())), CFDataGetLength(data.get()), out);
- out.append('\0');
- return makeString("data:", mimeType, ";base64,", out.data());
+ return makeString("data:", mimeType, ";base64,", out);
}
-
} // namespace WebCore
diff --git a/WebCore/platform/graphics/cg/ImageBufferData.h b/WebCore/platform/graphics/cg/ImageBufferData.h
index 456c934..1f706ec 100644
--- a/WebCore/platform/graphics/cg/ImageBufferData.h
+++ b/WebCore/platform/graphics/cg/ImageBufferData.h
@@ -30,6 +30,7 @@
#include <wtf/RefPtr.h>
#include <wtf/RetainPtr.h>
+typedef struct __IOSurface *IOSurfaceRef;
typedef struct CGColorSpace *CGColorSpaceRef;
typedef struct CGDataProvider *CGDataProviderRef;
typedef uint32_t CGBitmapInfo;
@@ -48,6 +49,7 @@ public:
CGBitmapInfo m_bitmapInfo;
unsigned m_bytesPerRow;
CGColorSpaceRef m_colorSpace;
+ RetainPtr<IOSurfaceRef> m_surface;
};
} // namespace WebCore
diff --git a/WebCore/platform/graphics/cg/ImageSourceCG.cpp b/WebCore/platform/graphics/cg/ImageSourceCG.cpp
index f01c442..4ed8684 100644
--- a/WebCore/platform/graphics/cg/ImageSourceCG.cpp
+++ b/WebCore/platform/graphics/cg/ImageSourceCG.cpp
@@ -63,11 +63,11 @@ void sharedBufferRelease(void* info)
}
#endif
-ImageSource::ImageSource(bool premultiplyAlpha, bool ignoreGammaAndColorProfile)
+ImageSource::ImageSource(ImageSource::AlphaOption alphaOption, ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption)
: m_decoder(0)
// FIXME: m_premultiplyAlpha is ignored in cg at the moment.
- , m_premultiplyAlpha(premultiplyAlpha)
- , m_ignoreGammaAndColorProfile(ignoreGammaAndColorProfile)
+ , m_alphaOption(alphaOption)
+ , m_gammaAndColorProfileOption(gammaAndColorProfileOption)
{
}
@@ -308,9 +308,10 @@ float ImageSource::frameDurationAtIndex(size_t index)
}
// Many annoying ads specify a 0 duration to make an image flash as quickly as possible.
- // We follow WinIE's behavior and use a duration of 100 ms for any frames that specify
- // a duration of <= 50 ms. See <http://bugs.webkit.org/show_bug.cgi?id=14413> or Radar 4051389 for more.
- if (duration < 0.051f)
+ // We follow Firefox's behavior and use a duration of 100 ms for any frames that specify
+ // a duration of <= 10 ms. See <rdar://problem/7689300> and <http://webkit.org/b/36082>
+ // for more information.
+ if (duration < 0.011f)
return 0.100f;
return duration;
}
diff --git a/WebCore/platform/graphics/cg/TransformationMatrixCG.cpp b/WebCore/platform/graphics/cg/TransformationMatrixCG.cpp
index 5fe2122..ec40836 100644
--- a/WebCore/platform/graphics/cg/TransformationMatrixCG.cpp
+++ b/WebCore/platform/graphics/cg/TransformationMatrixCG.cpp
@@ -34,6 +34,16 @@
namespace WebCore {
+TransformationMatrix::TransformationMatrix(const CGAffineTransform& t)
+{
+ setA(t.a);
+ setB(t.b);
+ setC(t.c);
+ setD(t.d);
+ setE(t.tx);
+ setF(t.ty);
+}
+
TransformationMatrix::operator CGAffineTransform() const
{
return CGAffineTransformMake(narrowPrecisionToCGFloat(a()),
diff --git a/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.cpp b/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.cpp
index c2cde19..ad961aa 100644
--- a/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.cpp
+++ b/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.cpp
@@ -56,9 +56,9 @@ Canvas2DLayerChromium::~Canvas2DLayerChromium()
layerRendererContext()->deleteTexture(m_textureId);
}
-void Canvas2DLayerChromium::updateContents()
+void Canvas2DLayerChromium::updateContentsIfDirty()
{
- if (!m_drawingBuffer)
+ if (!m_contentsDirty || !m_drawingBuffer)
return;
if (m_textureChanged) { // We have to generate a new backing texture.
GraphicsContext3D* context = layerRendererContext();
@@ -68,7 +68,7 @@ void Canvas2DLayerChromium::updateContents()
context->activeTexture(GraphicsContext3D::TEXTURE0);
context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textureId);
IntSize size = m_drawingBuffer->size();
- context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, size.width(), size.height(), 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, 0);
+ context->texImage2DResourceSafe(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, size.width(), size.height(), 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE);
// Set the min-mag filters to linear and wrap modes to GraphicsContext3D::CLAMP_TO_EDGE
// to get around NPOT texture limitations of GLES.
context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR);
diff --git a/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.h b/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.h
index 0031229..44ef050 100644
--- a/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.h
+++ b/WebCore/platform/graphics/chromium/Canvas2DLayerChromium.h
@@ -46,7 +46,7 @@ public:
static PassRefPtr<Canvas2DLayerChromium> create(DrawingBuffer*, GraphicsLayerChromium* owner);
virtual ~Canvas2DLayerChromium();
virtual bool drawsContent() { return true; }
- virtual void updateContents();
+ virtual void updateContentsIfDirty();
void setTextureChanged();
unsigned textureId() const;
diff --git a/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp b/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp
index 375a74b..d00faf8 100644
--- a/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp
+++ b/WebCore/platform/graphics/chromium/ContentLayerChromium.cpp
@@ -36,11 +36,13 @@
#include "GraphicsContext3D.h"
#include "LayerRendererChromium.h"
+#include "LayerTexture.h"
#include "RenderLayerBacking.h"
#if PLATFORM(SKIA)
#include "NativeImageSkia.h"
#include "PlatformContextSkia.h"
+#include "SkColorPriv.h"
#include "skia/ext/platform_canvas.h"
#elif PLATFORM(CG)
#include <CoreGraphics/CGBitmapContext.h>
@@ -68,8 +70,22 @@ ContentLayerChromium::SharedValues::SharedValues(GraphicsContext3D* context)
" v_texCoord = a_texCoord; \n"
"} \n";
+#if PLATFORM(SKIA)
+ // Color is in RGBA order.
+ char rgbaFragmentShaderString[] =
+ "precision mediump float; \n"
+ "varying vec2 v_texCoord; \n"
+ "uniform sampler2D s_texture; \n"
+ "uniform float alpha; \n"
+ "void main() \n"
+ "{ \n"
+ " vec4 texColor = texture2D(s_texture, v_texCoord); \n"
+ " gl_FragColor = texColor * alpha; \n"
+ "} \n";
+#endif
+
// Color is in BGRA order.
- char fragmentShaderString[] =
+ char bgraFragmentShaderString[] =
"precision mediump float; \n"
"varying vec2 v_texCoord; \n"
"uniform sampler2D s_texture; \n"
@@ -80,6 +96,12 @@ ContentLayerChromium::SharedValues::SharedValues(GraphicsContext3D* context)
" gl_FragColor = vec4(texColor.z, texColor.y, texColor.x, texColor.w) * alpha; \n"
"} \n";
+#if PLATFORM(SKIA)
+ // Assuming the packing is either Skia default RGBA or Chromium default BGRA.
+ char* fragmentShaderString = SK_B32_SHIFT ? rgbaFragmentShaderString : bgraFragmentShaderString;
+#else
+ char* fragmentShaderString = bgraFragmentShaderString;
+#endif
m_contentShaderProgram = createShaderProgram(m_context, vertexShaderString, fragmentShaderString);
if (!m_contentShaderProgram) {
LOG_ERROR("ContentLayerChromium: Failed to create shader program");
@@ -123,12 +145,7 @@ ContentLayerChromium::~ContentLayerChromium()
void ContentLayerChromium::cleanupResources()
{
LayerChromium::cleanupResources();
- if (layerRenderer()) {
- if (m_contentsTexture) {
- layerRenderer()->deleteLayerTexture(m_contentsTexture);
- m_contentsTexture = 0;
- }
- }
+ m_contentsTexture.clear();
}
bool ContentLayerChromium::requiresClippedUpdateRect() const
@@ -142,33 +159,7 @@ bool ContentLayerChromium::requiresClippedUpdateRect() const
|| !layerRenderer()->checkTextureSize(m_bounds));
}
-void ContentLayerChromium::calculateClippedUpdateRect(IntRect& dirtyRect, IntRect& drawRect) const
-{
- // For the given layer size and content rect, calculate:
- // 1) The minimal texture space rectangle to be uploaded, returned in dirtyRect.
- // 2) The rectangle to draw this texture in relative to the target render surface, returned in drawRect.
-
- ASSERT(m_targetRenderSurface);
- const IntRect clipRect = m_targetRenderSurface->contentRect();
-
- TransformationMatrix layerOriginTransform = drawTransform();
- layerOriginTransform.translate3d(-0.5 * m_bounds.width(), -0.5 * m_bounds.height(), 0);
-
- // For now we apply the large layer treatment only for layers that are either untransformed
- // or are purely translated. Their matrix is expected to be invertible.
- ASSERT(layerOriginTransform.isInvertible());
-
- TransformationMatrix targetToLayerMatrix = layerOriginTransform.inverse();
- IntRect clipRectInLayerCoords = targetToLayerMatrix.mapRect(clipRect);
- clipRectInLayerCoords.intersect(IntRect(0, 0, m_bounds.width(), m_bounds.height()));
-
- dirtyRect = clipRectInLayerCoords;
-
- // Map back to the target surface coordinate system.
- drawRect = layerOriginTransform.mapRect(dirtyRect);
-}
-
-void ContentLayerChromium::updateContents()
+void ContentLayerChromium::updateContentsIfDirty()
{
RenderLayerBacking* backing = static_cast<RenderLayerBacking*>(m_owner->client());
if (!backing || backing->paintingGoesToWindow())
@@ -183,6 +174,7 @@ void ContentLayerChromium::updateContents()
IntRect updateRect;
IntSize requiredTextureSize;
IntSize bitmapSize;
+ IntRect boundsRect(IntPoint(0, 0), m_bounds);
// FIXME: Remove this test when tiled layers are implemented.
if (requiresClippedUpdateRect()) {
@@ -194,33 +186,57 @@ void ContentLayerChromium::updateContents()
return;
}
- calculateClippedUpdateRect(dirtyRect, m_largeLayerDrawRect);
- if (!layerRenderer()->checkTextureSize(m_largeLayerDrawRect.size())) {
+ // Calculate the region of this layer that is currently visible.
+ const IntRect clipRect = m_targetRenderSurface->contentRect();
+
+ TransformationMatrix layerOriginTransform = drawTransform();
+ layerOriginTransform.translate3d(-0.5 * m_bounds.width(), -0.5 * m_bounds.height(), 0);
+
+ // For now we apply the large layer treatment only for layers that are either untransformed
+ // or are purely translated. Their matrix is expected to be invertible.
+ ASSERT(layerOriginTransform.isInvertible());
+
+ TransformationMatrix targetToLayerMatrix = layerOriginTransform.inverse();
+ IntRect visibleRectInLayerCoords = targetToLayerMatrix.mapRect(clipRect);
+ visibleRectInLayerCoords.intersect(IntRect(0, 0, m_bounds.width(), m_bounds.height()));
+
+ // For normal layers, the center of the texture corresponds with the center of the layer.
+ // In large layers the center of the texture is the center of the visible region so we have
+ // to keep track of the offset in order to render correctly.
+ IntRect visibleRectInSurfaceCoords = layerOriginTransform.mapRect(visibleRectInLayerCoords);
+ m_layerCenterInSurfaceCoords = FloatRect(visibleRectInSurfaceCoords).center();
+
+ // If this is still too large to render, then skip the layer completely.
+ if (!layerRenderer()->checkTextureSize(visibleRectInLayerCoords.size())) {
m_skipsDraw = true;
return;
}
- // If the portion of the large layer that's visible hasn't changed
- // then we don't need to update it, _unless_ its contents have changed
- // in which case we only update the dirty bits.
- if (m_largeLayerDirtyRect == dirtyRect) {
- if (!m_dirtyRect.intersects(dirtyRect))
- return;
- dirtyRect.intersect(IntRect(m_dirtyRect));
- updateRect = dirtyRect;
- requiredTextureSize = m_largeLayerDirtyRect.size();
- } else {
- m_largeLayerDirtyRect = dirtyRect;
- requiredTextureSize = dirtyRect.size();
- updateRect = IntRect(IntPoint(0, 0), dirtyRect.size());
- }
+ // If the visible portion of the layer is different from the last upload, or if our backing
+ // texture has been evicted, then the whole layer is considered dirty.
+ if (visibleRectInLayerCoords != m_visibleRectInLayerCoords || !m_contentsTexture || !m_contentsTexture->isValid(requiredTextureSize, GraphicsContext3D::RGBA))
+ m_dirtyRect = boundsRect;
+ m_visibleRectInLayerCoords = visibleRectInLayerCoords;
+
+ // Calculate the portion of the dirty rectangle that is visible. m_dirtyRect is in layer space.
+ IntRect visibleDirtyRectInLayerSpace = enclosingIntRect(m_dirtyRect);
+ visibleDirtyRectInLayerSpace.intersect(visibleRectInLayerCoords);
+
+ // What the rectangles mean:
+ // dirtyRect: The region of this layer that will be updated.
+ // updateRect: The region of the layer's texture that will be uploaded into.
+ // requiredTextureSize: is the required size of this layer's texture.
+ dirtyRect = visibleDirtyRectInLayerSpace;
+ updateRect = dirtyRect;
+ IntSize visibleRectOffsetInLayerCoords(visibleRectInLayerCoords.x(), visibleRectInLayerCoords.y());
+ updateRect.move(-visibleRectOffsetInLayerCoords);
+ requiredTextureSize = visibleRectInLayerCoords.size();
} else {
dirtyRect = IntRect(m_dirtyRect);
- IntRect boundsRect(IntPoint(0, 0), m_bounds);
requiredTextureSize = m_bounds;
// If the texture needs to be reallocated then we must redraw the entire
// contents of the layer.
- if (requiredTextureSize != m_allocatedTextureSize)
+ if (!m_contentsTexture || !m_contentsTexture->isValid(requiredTextureSize, GraphicsContext3D::RGBA))
dirtyRect = boundsRect;
else {
// Clip the dirtyRect to the size of the layer to avoid drawing
@@ -289,36 +305,28 @@ void ContentLayerChromium::updateContents()
#error "Need to implement for your platform."
#endif
- unsigned textureId = m_contentsTexture;
- if (!textureId)
- textureId = layerRenderer()->createLayerTexture();
-
if (pixels)
- updateTextureRect(pixels, bitmapSize, requiredTextureSize, updateRect, textureId);
+ updateTextureRect(pixels, requiredTextureSize, updateRect);
}
-void ContentLayerChromium::updateTextureRect(void* pixels, const IntSize& bitmapSize, const IntSize& requiredTextureSize, const IntRect& updateRect, unsigned textureId)
+void ContentLayerChromium::updateTextureRect(void* pixels, const IntSize& requiredTextureSize, const IntRect& updateRect)
{
if (!pixels)
return;
GraphicsContext3D* context = layerRendererContext();
- context->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId);
+ if (!m_contentsTexture)
+ m_contentsTexture = LayerTexture::create(context, layerRenderer()->textureManager());
- // If the texture id or size changed since last time then we need to tell GL
- // to re-allocate a texture.
- if (m_contentsTexture != textureId || requiredTextureSize != m_allocatedTextureSize) {
- ASSERT(bitmapSize == requiredTextureSize);
- GLC(context, context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, requiredTextureSize.width(), requiredTextureSize.height(), 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, pixels));
-
- m_contentsTexture = textureId;
- m_allocatedTextureSize = requiredTextureSize;
- } else {
- ASSERT(updateRect.width() <= m_allocatedTextureSize.width() && updateRect.height() <= m_allocatedTextureSize.height());
- ASSERT(updateRect.width() == bitmapSize.width() && updateRect.height() == bitmapSize.height());
- GLC(context, context->texSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, updateRect.x(), updateRect.y(), updateRect.width(), updateRect.height(), GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, pixels));
+ if (!m_contentsTexture->reserve(requiredTextureSize, GraphicsContext3D::RGBA)) {
+ m_skipsDraw = true;
+ return;
}
+ m_contentsTexture->bindTexture();
+
+ GLC(context, context->texSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, updateRect.x(), updateRect.y(), updateRect.width(), updateRect.height(), GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, pixels));
+
m_dirtyRect.setSize(FloatSize());
// Large layers always stay dirty, because they need to update when the content rect changes.
m_contentsDirty = requiresClippedUpdateRect();
@@ -330,21 +338,22 @@ void ContentLayerChromium::draw()
return;
ASSERT(layerRenderer());
+
const ContentLayerChromium::SharedValues* sv = layerRenderer()->contentLayerSharedValues();
ASSERT(sv && sv->initialized());
GraphicsContext3D* context = layerRendererContext();
GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0));
- GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_contentsTexture));
+ m_contentsTexture->bindTexture();
layerRenderer()->useShader(sv->contentShaderProgram());
GLC(context, context->uniform1i(sv->shaderSamplerLocation(), 0));
if (requiresClippedUpdateRect()) {
float m43 = drawTransform().m43();
TransformationMatrix transform;
- transform.translate3d(m_largeLayerDrawRect.center().x(), m_largeLayerDrawRect.center().y(), m43);
+ transform.translate3d(m_layerCenterInSurfaceCoords.x(), m_layerCenterInSurfaceCoords.y(), m43);
drawTexturedQuad(context, layerRenderer()->projectionMatrix(),
- transform, m_largeLayerDrawRect.width(),
- m_largeLayerDrawRect.height(), drawOpacity(),
+ transform, m_visibleRectInLayerCoords.width(),
+ m_visibleRectInLayerCoords.height(), drawOpacity(),
sv->shaderMatrixLocation(), sv->shaderAlphaLocation());
} else {
drawTexturedQuad(context, layerRenderer()->projectionMatrix(),
@@ -352,6 +361,7 @@ void ContentLayerChromium::draw()
drawOpacity(), sv->shaderMatrixLocation(),
sv->shaderAlphaLocation());
}
+ m_contentsTexture->unreserve();
}
}
diff --git a/WebCore/platform/graphics/chromium/ContentLayerChromium.h b/WebCore/platform/graphics/chromium/ContentLayerChromium.h
index 32c2c49..dc1630b 100644
--- a/WebCore/platform/graphics/chromium/ContentLayerChromium.h
+++ b/WebCore/platform/graphics/chromium/ContentLayerChromium.h
@@ -35,9 +35,12 @@
#if USE(ACCELERATED_COMPOSITING)
#include "LayerChromium.h"
+#include "TextureManager.h"
namespace WebCore {
+class LayerTexture;
+
// A Layer that requires a GraphicsContext to render its contents.
class ContentLayerChromium : public LayerChromium {
friend class LayerRendererChromium;
@@ -46,7 +49,7 @@ public:
virtual ~ContentLayerChromium();
- virtual void updateContents();
+ virtual void updateContentsIfDirty();
virtual void draw();
virtual bool drawsContent() { return m_owner && m_owner->drawsContent(); }
@@ -74,22 +77,20 @@ public:
};
protected:
- ContentLayerChromium(GraphicsLayerChromium* owner);
+ explicit ContentLayerChromium(GraphicsLayerChromium* owner);
- void updateTextureRect(void* pixels, const IntSize& bitmapSize, const IntSize& requiredTextureSize,
- const IntRect& updateRect, unsigned textureId);
+ void updateTextureRect(void* pixels, const IntSize& requiredTextureSize, const IntRect& updateRect);
virtual void cleanupResources();
bool requiresClippedUpdateRect() const;
- unsigned m_contentsTexture;
- IntSize m_allocatedTextureSize;
+ OwnPtr<LayerTexture> m_contentsTexture;
bool m_skipsDraw;
private:
- void calculateClippedUpdateRect(IntRect& dirtyRect, IntRect& drawRect) const;
- IntRect m_largeLayerDrawRect;
- IntRect m_largeLayerDirtyRect;
+
+ IntRect m_visibleRectInLayerCoords;
+ FloatPoint m_layerCenterInSurfaceCoords;
};
}
diff --git a/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp b/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp
index 0395bc2..507c227 100644
--- a/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp
+++ b/WebCore/platform/graphics/chromium/DrawingBufferChromium.cpp
@@ -60,7 +60,7 @@ static unsigned generateColorTexture(GraphicsContext3D* context, const IntSize&
context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::NEAREST);
context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE);
context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE);
- context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, size.width(), size.height(), 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, 0);
+ context->texImage2DResourceSafe(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, size.width(), size.height(), 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE);
context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, offscreenColorTexture, 0);
return offscreenColorTexture;
diff --git a/WebCore/platform/graphics/chromium/Extensions3DChromium.h b/WebCore/platform/graphics/chromium/Extensions3DChromium.h
index 5fda020..d120424 100644
--- a/WebCore/platform/graphics/chromium/Extensions3DChromium.h
+++ b/WebCore/platform/graphics/chromium/Extensions3DChromium.h
@@ -42,6 +42,7 @@ public:
// Extensions3D methods.
virtual bool supports(const String&);
+ virtual void ensureEnabled(const String&);
virtual int getGraphicsResetStatusARB();
virtual void blitFramebuffer(long srcX0, long srcY0, long srcX1, long srcY1, long dstX0, long dstY0, long dstX1, long dstY1, unsigned long mask, unsigned long filter) { }
virtual void renderbufferStorageMultisample(unsigned long target, unsigned long samples, unsigned long internalformat, unsigned long width, unsigned long height) { }
diff --git a/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp b/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp
index 347a3fb..2c79815 100644
--- a/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp
+++ b/WebCore/platform/graphics/chromium/FontCacheChromiumWin.cpp
@@ -50,11 +50,6 @@ using std::min;
namespace WebCore
{
-void FontCache::platformInit()
-{
- // Not needed on Windows.
-}
-
// FIXME: consider adding to WebKit String class
static bool charactersAreAllASCII(const String& s)
{
@@ -329,6 +324,86 @@ static bool fontContainsCharacter(const FontPlatformData* fontData,
return cmap->contains(character);
}
+// Tries the given font and save it |outFontFamilyName| if it succeeds.
+static SimpleFontData* fontDataFromDescriptionAndLogFont(FontCache* fontCache, const FontDescription& fontDescription, const LOGFONT& font, wchar_t* outFontFamilyName)
+{
+ SimpleFontData* fontData = fontCache->getCachedFontData(fontDescription, font.lfFaceName);
+ if (fontData)
+ memcpy(outFontFamilyName, font.lfFaceName, sizeof(font.lfFaceName));
+ return fontData;
+}
+
+static LONG toGDIFontWeight(FontWeight fontWeight)
+{
+ static LONG gdiFontWeights[] = {
+ FW_THIN, // FontWeight100
+ FW_EXTRALIGHT, // FontWeight200
+ FW_LIGHT, // FontWeight300
+ FW_NORMAL, // FontWeight400
+ FW_MEDIUM, // FontWeight500
+ FW_SEMIBOLD, // FontWeight600
+ FW_BOLD, // FontWeight700
+ FW_EXTRABOLD, // FontWeight800
+ FW_HEAVY // FontWeight900
+ };
+ return gdiFontWeights[fontWeight];
+}
+
+static void FillLogFont(const FontDescription& fontDescription, LOGFONT* winfont)
+{
+ // The size here looks unusual. The negative number is intentional.
+ // Unlike WebKit trunk, we don't multiply the size by 32. That seems to be
+ // some kind of artifact of their CG backend, or something.
+ winfont->lfHeight = -fontDescription.computedPixelSize();
+ winfont->lfWidth = 0;
+ winfont->lfEscapement = 0;
+ winfont->lfOrientation = 0;
+ winfont->lfUnderline = false;
+ winfont->lfStrikeOut = false;
+ winfont->lfCharSet = DEFAULT_CHARSET;
+ winfont->lfOutPrecision = OUT_TT_ONLY_PRECIS;
+ winfont->lfQuality = ChromiumBridge::layoutTestMode() ? NONANTIALIASED_QUALITY : DEFAULT_QUALITY; // Honor user's desktop settings.
+ winfont->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
+ winfont->lfItalic = fontDescription.italic();
+ winfont->lfWeight = toGDIFontWeight(fontDescription.weight());
+}
+
+struct TraitsInFamilyProcData {
+ TraitsInFamilyProcData(const AtomicString& familyName)
+ : m_familyName(familyName)
+ {
+ }
+
+ const AtomicString& m_familyName;
+ HashSet<unsigned> m_traitsMasks;
+};
+
+static int CALLBACK traitsInFamilyEnumProc(CONST LOGFONT* logFont, CONST TEXTMETRIC* metrics, DWORD fontType, LPARAM lParam)
+{
+ TraitsInFamilyProcData* procData = reinterpret_cast<TraitsInFamilyProcData*>(lParam);
+
+ unsigned traitsMask = 0;
+ traitsMask |= logFont->lfItalic ? FontStyleItalicMask : FontStyleNormalMask;
+ traitsMask |= FontVariantNormalMask;
+ LONG weight = logFont->lfWeight;
+ traitsMask |= weight == FW_THIN ? FontWeight100Mask :
+ weight == FW_EXTRALIGHT ? FontWeight200Mask :
+ weight == FW_LIGHT ? FontWeight300Mask :
+ weight == FW_NORMAL ? FontWeight400Mask :
+ weight == FW_MEDIUM ? FontWeight500Mask :
+ weight == FW_SEMIBOLD ? FontWeight600Mask :
+ weight == FW_BOLD ? FontWeight700Mask :
+ weight == FW_EXTRABOLD ? FontWeight800Mask :
+ FontWeight900Mask;
+ procData->m_traitsMasks.add(traitsMask);
+ return 1;
+}
+
+void FontCache::platformInit()
+{
+ // Not needed on Windows.
+}
+
// Given the desired base font, this will create a SimpleFontData for a specific
// font that can be used to render the given range of characters.
const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length)
@@ -438,73 +513,43 @@ SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& desc
else if (generic == FontDescription::MonospaceFamily)
fontStr = courierStr;
- return getCachedFontData(description, fontStr);
-}
-
-static LONG toGDIFontWeight(FontWeight fontWeight)
-{
- static LONG gdiFontWeights[] = {
- FW_THIN, // FontWeight100
- FW_EXTRALIGHT, // FontWeight200
- FW_LIGHT, // FontWeight300
- FW_NORMAL, // FontWeight400
- FW_MEDIUM, // FontWeight500
- FW_SEMIBOLD, // FontWeight600
- FW_BOLD, // FontWeight700
- FW_EXTRABOLD, // FontWeight800
- FW_HEAVY // FontWeight900
- };
- return gdiFontWeights[fontWeight];
-}
-
-static void FillLogFont(const FontDescription& fontDescription, LOGFONT* winfont)
-{
- // The size here looks unusual. The negative number is intentional.
- // Unlike WebKit trunk, we don't multiply the size by 32. That seems to be
- // some kind of artifact of their CG backend, or something.
- winfont->lfHeight = -fontDescription.computedPixelSize();
- winfont->lfWidth = 0;
- winfont->lfEscapement = 0;
- winfont->lfOrientation = 0;
- winfont->lfUnderline = false;
- winfont->lfStrikeOut = false;
- winfont->lfCharSet = DEFAULT_CHARSET;
- winfont->lfOutPrecision = OUT_TT_ONLY_PRECIS;
- winfont->lfQuality = ChromiumBridge::layoutTestMode() ? NONANTIALIASED_QUALITY : DEFAULT_QUALITY; // Honor user's desktop settings.
- winfont->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
- winfont->lfItalic = fontDescription.italic();
- winfont->lfWeight = toGDIFontWeight(fontDescription.weight());
-}
-
-struct TraitsInFamilyProcData {
- TraitsInFamilyProcData(const AtomicString& familyName)
- : m_familyName(familyName)
- {
+ SimpleFontData* simpleFont = getCachedFontData(description, fontStr);
+ if (simpleFont)
+ return simpleFont;
+
+ // Fall back to system fonts as Win Safari does because this function must
+ // return a valid font. Once we find a valid system font, we save its name
+ // to a static variable and use it to prevent trying system fonts again.
+ static wchar_t fallbackFontName[LF_FACESIZE] = {0};
+ if (fallbackFontName[0])
+ return getCachedFontData(description, fallbackFontName);
+
+ // Fall back to the DEFAULT_GUI_FONT if no known Unicode fonts are available.
+ if (HFONT defaultGUIFont = static_cast<HFONT>(GetStockObject(DEFAULT_GUI_FONT))) {
+ LOGFONT defaultGUILogFont;
+ GetObject(defaultGUIFont, sizeof(defaultGUILogFont), &defaultGUILogFont);
+ if (simpleFont = fontDataFromDescriptionAndLogFont(this, description, defaultGUILogFont, fallbackFontName))
+ return simpleFont;
}
- const AtomicString& m_familyName;
- HashSet<unsigned> m_traitsMasks;
-};
-
-static int CALLBACK traitsInFamilyEnumProc(CONST LOGFONT* logFont, CONST TEXTMETRIC* metrics, DWORD fontType, LPARAM lParam)
-{
- TraitsInFamilyProcData* procData = reinterpret_cast<TraitsInFamilyProcData*>(lParam);
+ // Fall back to Non-client metrics fonts.
+ NONCLIENTMETRICS nonClientMetrics = {0};
+ nonClientMetrics.cbSize = sizeof(nonClientMetrics);
+ if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(nonClientMetrics), &nonClientMetrics, 0)) {
+ if (simpleFont = fontDataFromDescriptionAndLogFont(this, description, nonClientMetrics.lfMessageFont, fallbackFontName))
+ return simpleFont;
+ if (simpleFont = fontDataFromDescriptionAndLogFont(this, description, nonClientMetrics.lfMenuFont, fallbackFontName))
+ return simpleFont;
+ if (simpleFont = fontDataFromDescriptionAndLogFont(this, description, nonClientMetrics.lfStatusFont, fallbackFontName))
+ return simpleFont;
+ if (simpleFont = fontDataFromDescriptionAndLogFont(this, description, nonClientMetrics.lfCaptionFont, fallbackFontName))
+ return simpleFont;
+ if (simpleFont = fontDataFromDescriptionAndLogFont(this, description, nonClientMetrics.lfSmCaptionFont, fallbackFontName))
+ return simpleFont;
+ }
- unsigned traitsMask = 0;
- traitsMask |= logFont->lfItalic ? FontStyleItalicMask : FontStyleNormalMask;
- traitsMask |= FontVariantNormalMask;
- LONG weight = logFont->lfWeight;
- traitsMask |= weight == FW_THIN ? FontWeight100Mask :
- weight == FW_EXTRALIGHT ? FontWeight200Mask :
- weight == FW_LIGHT ? FontWeight300Mask :
- weight == FW_NORMAL ? FontWeight400Mask :
- weight == FW_MEDIUM ? FontWeight500Mask :
- weight == FW_SEMIBOLD ? FontWeight600Mask :
- weight == FW_BOLD ? FontWeight700Mask :
- weight == FW_EXTRABOLD ? FontWeight800Mask :
- FontWeight900Mask;
- procData->m_traitsMasks.add(traitsMask);
- return 1;
+ ASSERT_NOT_REACHED();
+ return 0;
}
void FontCache::getTraitsInFamily(const AtomicString& familyName, Vector<unsigned>& traitsMasks)
diff --git a/WebCore/platform/graphics/chromium/FontCacheLinux.cpp b/WebCore/platform/graphics/chromium/FontCacheLinux.cpp
index 4399d35..bd33927 100644
--- a/WebCore/platform/graphics/chromium/FontCacheLinux.cpp
+++ b/WebCore/platform/graphics/chromium/FontCacheLinux.cpp
@@ -150,7 +150,8 @@ FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontD
name,
fontDescription.computedSize(),
(style & SkTypeface::kBold) && !tf->isBold(),
- (style & SkTypeface::kItalic) && !tf->isItalic());
+ (style & SkTypeface::kItalic) && !tf->isItalic(),
+ fontDescription.orientation());
tf->unref();
return result;
}
diff --git a/WebCore/platform/graphics/chromium/FontChromiumWin.cpp b/WebCore/platform/graphics/chromium/FontChromiumWin.cpp
index 8a77501..1a00833 100644
--- a/WebCore/platform/graphics/chromium/FontChromiumWin.cpp
+++ b/WebCore/platform/graphics/chromium/FontChromiumWin.cpp
@@ -35,6 +35,7 @@
#include "ChromiumBridge.h"
#include "FontFallbackList.h"
#include "GlyphBuffer.h"
+#include "NotImplemented.h"
#include "PlatformContextSkia.h"
#include "SimpleFontData.h"
#include "SkiaFontWin.h"
@@ -276,7 +277,8 @@ bool TransparencyAwareGlyphPainter::drawGlyphs(int numGlyphs,
FloatSize shadowOffset;
float shadowBlur;
Color shadowColor;
- if (m_graphicsContext->getShadow(shadowOffset, shadowBlur, shadowColor)) {
+ ColorSpace shadowColorSpace;
+ if (m_graphicsContext->getShadow(shadowOffset, shadowBlur, shadowColor, shadowColorSpace)) {
// If there is a shadow and this code is reached, windowsCanHandleDrawTextShadow()
// will have already returned true during the ctor initiatization of m_useGDI
ASSERT(shadowColor.alpha() == 255);
@@ -488,7 +490,8 @@ void Font::drawComplexText(GraphicsContext* graphicsContext,
FloatSize shadowOffset;
float shadowBlur;
Color shadowColor;
- if (graphicsContext->getShadow(shadowOffset, shadowBlur, shadowColor) && windowsCanHandleDrawTextShadow(graphicsContext)) {
+ ColorSpace shadowColorSpace;
+ if (graphicsContext->getShadow(shadowOffset, shadowBlur, shadowColor, shadowColorSpace) && windowsCanHandleDrawTextShadow(graphicsContext)) {
COLORREF textColor = skia::SkColorToCOLORREF(SkColorSetARGB(255, shadowColor.red(), shadowColor.green(), shadowColor.blue()));
COLORREF savedTextColor = GetTextColor(hdc);
SetTextColor(hdc, textColor);
@@ -505,6 +508,11 @@ void Font::drawComplexText(GraphicsContext* graphicsContext,
context->canvas()->endPlatformPaint();
}
+void Font::drawEmphasisMarksForComplexText(GraphicsContext* /* context */, const TextRun& /* run */, const AtomicString& /* mark */, const FloatPoint& /* point */, int /* from */, int /* to */) const
+{
+ notImplemented();
+}
+
float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* /* fallbackFonts */, GlyphOverflow* /* glyphOverflow */) const
{
UniscribeHelperTextRun state(run, *this);
diff --git a/WebCore/platform/graphics/chromium/FontLinux.cpp b/WebCore/platform/graphics/chromium/FontLinux.cpp
index 79b2caf..5e3e5b2 100644
--- a/WebCore/platform/graphics/chromium/FontLinux.cpp
+++ b/WebCore/platform/graphics/chromium/FontLinux.cpp
@@ -91,32 +91,50 @@ void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font,
// patches may be upstreamed to WebKit so we always use the slower path
// here.
const GlyphBufferAdvance* adv = glyphBuffer.advances(from);
- SkAutoSTMalloc<32, SkPoint> storage(numGlyphs);
+ SkAutoSTMalloc<32, SkPoint> storage(numGlyphs), storage2(numGlyphs), storage3(numGlyphs);
SkPoint* pos = storage.get();
+ SkPoint* vPosBegin = storage2.get();
+ SkPoint* vPosEnd = storage3.get();
+ bool isVertical = font->orientation() == Vertical;
for (int i = 0; i < numGlyphs; i++) {
+ SkScalar myWidth = SkFloatToScalar(adv[i].width());
pos[i].set(x, y);
- x += SkFloatToScalar(adv[i].width());
+ if (isVertical) {
+ vPosBegin[i].set(x + myWidth, y);
+ vPosEnd[i].set(x + myWidth, y - myWidth);
+ }
+ x += myWidth;
y += SkFloatToScalar(adv[i].height());
}
gc->platformContext()->prepareForSoftwareDraw();
SkCanvas* canvas = gc->platformContext()->canvas();
- int textMode = gc->platformContext()->getTextDrawingMode();
+ TextDrawingModeFlags textMode = gc->platformContext()->getTextDrawingMode();
// We draw text up to two times (once for fill, once for stroke).
- if (textMode & cTextFill) {
+ if (textMode & TextModeFill) {
SkPaint paint;
gc->platformContext()->setupPaintForFilling(&paint);
font->platformData().setupPaint(&paint);
adjustTextRenderMode(&paint, gc->platformContext());
paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
paint.setColor(gc->fillColor().rgb());
- canvas->drawPosText(glyphs, numGlyphs << 1, pos, paint);
+
+ if (isVertical) {
+ SkPath path;
+ for (int i = 0; i < numGlyphs; ++i) {
+ path.reset();
+ path.moveTo(vPosBegin[i]);
+ path.lineTo(vPosEnd[i]);
+ canvas->drawTextOnPath(glyphs + i, 2, path, 0, paint);
+ }
+ } else
+ canvas->drawPosText(glyphs, numGlyphs << 1, pos, paint);
}
- if ((textMode & cTextStroke)
+ if ((textMode & TextModeStroke)
&& gc->platformContext()->getStrokeStyle() != NoStroke
&& gc->platformContext()->getStrokeThickness() > 0) {
@@ -127,13 +145,22 @@ void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font,
paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
paint.setColor(gc->strokeColor().rgb());
- if (textMode & cTextFill) {
+ if (textMode & TextModeFill) {
// If we also filled, we don't want to draw shadows twice.
// See comment in FontChromiumWin.cpp::paintSkiaText() for more details.
SkSafeUnref(paint.setLooper(0));
}
- canvas->drawPosText(glyphs, numGlyphs << 1, pos, paint);
+ if (isVertical) {
+ SkPath path;
+ for (int i = 0; i < numGlyphs; ++i) {
+ path.reset();
+ path.moveTo(vPosBegin[i]);
+ path.lineTo(vPosEnd[i]);
+ canvas->drawTextOnPath(glyphs + i, 2, path, 0, paint);
+ }
+ } else
+ canvas->drawPosText(glyphs, numGlyphs << 1, pos, paint);
}
}
@@ -341,7 +368,6 @@ void TextRunWalker::setPadding(int padding)
// amount to each space. The last space gets the smaller amount, if
// any.
unsigned numWordBreaks = 0;
- bool isRTL = m_iterateBackwards;
for (unsigned i = 0; i < m_item.stringLength; i++) {
if (isWordBreak(i))
@@ -382,7 +408,7 @@ bool TextRunWalker::nextScriptRun()
// (and the glyphs in each A, C and T section are backwards too)
if (!hb_utf16_script_run_prev(&m_numCodePoints, &m_item.item, m_run.characters(), m_run.length(), &m_indexOfNextScriptRun))
return false;
- m_currentFontData = m_font->glyphDataForCharacter(m_item.string[m_item.item.pos], false, false).fontData;
+ m_currentFontData = m_font->glyphDataForCharacter(m_item.string[m_item.item.pos], false).fontData;
} else {
if (!hb_utf16_script_run_next(&m_numCodePoints, &m_item.item, m_run.characters(), m_run.length(), &m_indexOfNextScriptRun))
return false;
@@ -394,10 +420,10 @@ bool TextRunWalker::nextScriptRun()
// in the harfbuzz data structures to e.g. pick the correct script's shaper.
// So we allow that to run first, then do a second pass over the range it
// found and take the largest subregion that stays within a single font.
- m_currentFontData = m_font->glyphDataForCharacter(m_item.string[m_item.item.pos], false, false).fontData;
+ m_currentFontData = m_font->glyphDataForCharacter(m_item.string[m_item.item.pos], false).fontData;
unsigned endOfRun;
for (endOfRun = 1; endOfRun < m_item.item.length; ++endOfRun) {
- const SimpleFontData* nextFontData = m_font->glyphDataForCharacter(m_item.string[m_item.item.pos + endOfRun], false, false).fontData;
+ const SimpleFontData* nextFontData = m_font->glyphDataForCharacter(m_item.string[m_item.item.pos + endOfRun], false).fontData;
if (nextFontData != m_currentFontData)
break;
}
@@ -423,7 +449,7 @@ float TextRunWalker::widthOfFullRun()
void TextRunWalker::setupFontForScriptRun()
{
- const FontData* fontData = m_font->glyphDataForCharacter(m_item.string[m_item.item.pos], false, false).fontData;
+ const FontData* fontData = m_font->glyphDataForCharacter(m_item.string[m_item.item.pos], false).fontData;
const FontPlatformData& platformData = fontData->fontDataForCharacter(' ')->platformData();
m_item.face = platformData.harfbuzzFace();
void* opaquePlatformData = const_cast<FontPlatformData*>(&platformData);
@@ -524,7 +550,7 @@ void TextRunWalker::setGlyphXPositions(bool isRTL)
// Whitespace must be laid out in logical order, so when inserting
// spaces in RTL (but iterating in LTR order) we must insert spaces
// _before_ the next glyph.
- if (i + 1 >= m_item.num_glyphs || m_item.attributes[i + 1].clusterStart)
+ if (static_cast<unsigned>(i + 1) >= m_item.num_glyphs || m_item.attributes[i + 1].clusterStart)
position += m_letterSpacing;
position += determineWordBreakSpacing(logClustersIndex);
@@ -541,7 +567,7 @@ void TextRunWalker::setGlyphXPositions(bool isRTL)
position += truncateFixedPointToInteger(m_item.advances[i]);
}
} else {
- for (int i = 0; i < m_item.num_glyphs; ++i) {
+ for (size_t i = 0; i < m_item.num_glyphs; ++i) {
m_glyphs16[i] = m_item.glyphs[i];
double offsetX = truncateFixedPointToInteger(m_item.offsets[i].x);
m_xPositions[i] = m_offsetX + position + offsetX;
@@ -556,7 +582,7 @@ void TextRunWalker::setGlyphXPositions(bool isRTL)
if (m_item.attributes[i].clusterStart)
advance += m_letterSpacing;
- while (logClustersIndex < m_item.item.length && logClusters()[logClustersIndex] == i)
+ while (static_cast<unsigned>(logClustersIndex) < m_item.item.length && logClusters()[logClustersIndex] == i)
logClustersIndex++;
position += advance;
@@ -652,9 +678,9 @@ void Font::drawComplexText(GraphicsContext* gc, const TextRun& run,
return;
SkCanvas* canvas = gc->platformContext()->canvas();
- int textMode = gc->platformContext()->getTextDrawingMode();
- bool fill = textMode & cTextFill;
- bool stroke = (textMode & cTextStroke)
+ TextDrawingModeFlags textMode = gc->platformContext()->getTextDrawingMode();
+ bool fill = textMode & TextModeFill;
+ bool stroke = (textMode & TextModeStroke)
&& gc->platformContext()->getStrokeStyle() != NoStroke
&& gc->platformContext()->getStrokeThickness() > 0;
@@ -691,6 +717,11 @@ void Font::drawComplexText(GraphicsContext* gc, const TextRun& run,
}
}
+void Font::drawEmphasisMarksForComplexText(GraphicsContext* /* context */, const TextRun& /* run */, const AtomicString& /* mark */, const FloatPoint& /* point */, int /* from */, int /* to */) const
+{
+ notImplemented();
+}
+
float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* /* fallbackFonts */, GlyphOverflow* /* glyphOverflow */) const
{
TextRunWalker walker(run, 0, this);
@@ -708,7 +739,7 @@ static int glyphIndexForXPositionInScriptRun(const TextRunWalker& walker, int x)
for (glyphIndex = walker.length() - 1; glyphIndex >= 0; --glyphIndex) {
// When iterating LTR over RTL text, we must include the whitespace
// _before_ the glyph, so no + 1 here.
- if (x < (walker.length() - glyphIndex) * letterSpacing + truncateFixedPointToInteger(advances[glyphIndex]))
+ if (x < (static_cast<int>(walker.length()) - glyphIndex) * letterSpacing + truncateFixedPointToInteger(advances[glyphIndex]))
break;
x -= truncateFixedPointToInteger(advances[glyphIndex]);
}
diff --git a/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp b/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp
index 3944775..42942cc 100644
--- a/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp
+++ b/WebCore/platform/graphics/chromium/FontPlatformDataLinux.cpp
@@ -73,18 +73,20 @@ FontPlatformData::FontPlatformData(const FontPlatformData& src)
, m_textSize(src.m_textSize)
, m_fakeBold(src.m_fakeBold)
, m_fakeItalic(src.m_fakeItalic)
+ , m_orientation(src.m_orientation)
, m_style(src.m_style)
, m_harfbuzzFace(src.m_harfbuzzFace)
{
SkSafeRef(m_typeface);
}
-FontPlatformData::FontPlatformData(SkTypeface* tf, const char* family, float textSize, bool fakeBold, bool fakeItalic)
+FontPlatformData::FontPlatformData(SkTypeface* tf, const char* family, float textSize, bool fakeBold, bool fakeItalic, FontOrientation orientation)
: m_typeface(tf)
, m_family(family)
, m_textSize(textSize)
, m_fakeBold(fakeBold)
, m_fakeItalic(fakeItalic)
+ , m_orientation(orientation)
{
SkSafeRef(m_typeface);
querySystemForRenderStyle();
@@ -116,6 +118,7 @@ FontPlatformData& FontPlatformData::operator=(const FontPlatformData& src)
m_fakeBold = src.m_fakeBold;
m_fakeItalic = src.m_fakeItalic;
m_harfbuzzFace = src.m_harfbuzzFace;
+ m_orientation = src.m_orientation;
m_style = src.m_style;
return *this;
@@ -179,13 +182,14 @@ bool FontPlatformData::operator==(const FontPlatformData& a) const
&& m_textSize == a.m_textSize
&& m_fakeBold == a.m_fakeBold
&& m_fakeItalic == a.m_fakeItalic
+ && m_orientation == a.m_orientation
&& m_style == a.m_style;
}
unsigned FontPlatformData::hash() const
{
unsigned h = SkTypeface::UniqueID(m_typeface);
- h ^= 0x01010101 * ((static_cast<int>(m_fakeBold) << 1) | static_cast<int>(m_fakeItalic));
+ h ^= 0x01010101 * ((static_cast<int>(m_orientation) << 2) | (static_cast<int>(m_fakeBold) << 1) | static_cast<int>(m_fakeItalic));
// This memcpy is to avoid a reinterpret_cast that breaks strict-aliasing
// rules. Memcpy is generally optimized enough so that performance doesn't
diff --git a/WebCore/platform/graphics/chromium/FontPlatformDataLinux.h b/WebCore/platform/graphics/chromium/FontPlatformDataLinux.h
index 694a945..43771d7 100644
--- a/WebCore/platform/graphics/chromium/FontPlatformDataLinux.h
+++ b/WebCore/platform/graphics/chromium/FontPlatformDataLinux.h
@@ -72,6 +72,7 @@ public:
, m_textSize(0)
, m_fakeBold(false)
, m_fakeItalic(false)
+ , m_orientation(Horizontal)
{ }
FontPlatformData(float textSize, bool fakeBold, bool fakeItalic)
@@ -79,10 +80,11 @@ public:
, m_textSize(textSize)
, m_fakeBold(fakeBold)
, m_fakeItalic(fakeItalic)
+ , m_orientation(Horizontal)
{ }
FontPlatformData(const FontPlatformData&);
- FontPlatformData(SkTypeface*, const char* name, float textSize, bool fakeBold, bool fakeItalic);
+ FontPlatformData(SkTypeface*, const char* name, float textSize, bool fakeBold, bool fakeItalic, FontOrientation orientation = Horizontal);
FontPlatformData(const FontPlatformData& src, float textSize);
~FontPlatformData();
@@ -106,7 +108,7 @@ public:
unsigned hash() const;
float size() const { return m_textSize; }
- FontOrientation orientation() const { return Horizontal; } // FIXME: Implement.
+ FontOrientation orientation() const { return m_orientation; }
bool operator==(const FontPlatformData&) const;
FontPlatformData& operator=(const FontPlatformData&);
@@ -153,6 +155,7 @@ private:
float m_textSize;
bool m_fakeBold;
bool m_fakeItalic;
+ FontOrientation m_orientation;
FontRenderStyle m_style;
mutable RefPtr<RefCountedHarfbuzzFace> m_harfbuzzFace;
diff --git a/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp b/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp
index 21dcd8e..5e8d148 100644
--- a/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp
+++ b/WebCore/platform/graphics/chromium/GraphicsLayerChromium.cpp
@@ -115,11 +115,6 @@ void GraphicsLayerChromium::setName(const String& inName)
GraphicsLayer::setName(name);
}
-NativeLayer GraphicsLayerChromium::nativeLayer() const
-{
- return m_layer.get();
-}
-
bool GraphicsLayerChromium::setChildren(const Vector<GraphicsLayer*>& children)
{
bool childrenChanged = GraphicsLayer::setChildren(children);
diff --git a/WebCore/platform/graphics/chromium/GraphicsLayerChromium.h b/WebCore/platform/graphics/chromium/GraphicsLayerChromium.h
index 214058d..130c25c 100644
--- a/WebCore/platform/graphics/chromium/GraphicsLayerChromium.h
+++ b/WebCore/platform/graphics/chromium/GraphicsLayerChromium.h
@@ -47,9 +47,6 @@ public:
virtual void setName(const String&);
- // for hosting this GraphicsLayer in a native layer hierarchy
- virtual NativeLayer nativeLayer() const;
-
virtual bool setChildren(const Vector<GraphicsLayer*>&);
virtual void addChild(GraphicsLayer*);
virtual void addChildAtIndex(GraphicsLayer*, int index);
diff --git a/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp b/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp
index adcbb82..cd299c1 100644
--- a/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp
+++ b/WebCore/platform/graphics/chromium/ImageLayerChromium.cpp
@@ -36,6 +36,7 @@
#include "Image.h"
#include "LayerRendererChromium.h"
+#include "LayerTexture.h"
#if PLATFORM(SKIA)
#include "NativeImageSkia.h"
@@ -71,7 +72,7 @@ void ImageLayerChromium::setContents(Image* contents)
setNeedsDisplay();
}
-void ImageLayerChromium::updateContents()
+void ImageLayerChromium::updateContentsIfDirty()
{
ASSERT(layerRenderer());
@@ -79,12 +80,11 @@ void ImageLayerChromium::updateContents()
if (requiresClippedUpdateRect()) {
// Use the base version of updateContents which draws a subset of the
// image to a bitmap, as the pixel contents can't be uploaded directly.
- ContentLayerChromium::updateContents();
+ ContentLayerChromium::updateContentsIfDirty();
return;
}
void* pixels = 0;
- IntSize requiredTextureSize;
IntSize bitmapSize;
NativeImagePtr nativeImage = m_contents->nativeImageForCurrentFrame();
@@ -93,22 +93,33 @@ void ImageLayerChromium::updateContents()
// The layer contains an Image.
NativeImageSkia* skiaImage = static_cast<NativeImageSkia*>(nativeImage);
const SkBitmap* skiaBitmap = skiaImage;
- requiredTextureSize = IntSize(skiaBitmap->width(), skiaBitmap->height());
+ bitmapSize = IntSize(skiaBitmap->width(), skiaBitmap->height());
ASSERT(skiaBitmap);
+#elif PLATFORM(CG)
+ // NativeImagePtr is a CGImageRef on Mac OS X.
+ int width = CGImageGetWidth(nativeImage);
+ int height = CGImageGetHeight(nativeImage);
+ bitmapSize = IntSize(width, height);
+#endif
+
+ // Clip the dirty rect to the bitmap dimensions.
+ IntRect dirtyRect(m_dirtyRect);
+ dirtyRect.intersect(IntRect(IntPoint(0, 0), bitmapSize));
+
+ if (!m_contentsTexture || !m_contentsTexture->isValid(bitmapSize, GraphicsContext3D::RGBA))
+ dirtyRect = IntRect(IntPoint(0, 0), bitmapSize);
+ else if (!m_contentsDirty) {
+ m_contentsTexture->reserve(bitmapSize, GraphicsContext3D::RGBA);
+ return;
+ }
+#if PLATFORM(SKIA)
SkAutoLockPixels lock(*skiaBitmap);
SkBitmap::Config skiaConfig = skiaBitmap->config();
// FIXME: do we need to support more image configurations?
- if (skiaConfig == SkBitmap::kARGB_8888_Config) {
+ if (skiaConfig == SkBitmap::kARGB_8888_Config)
pixels = skiaBitmap->getPixels();
- bitmapSize = IntSize(skiaBitmap->width(), skiaBitmap->height());
- }
#elif PLATFORM(CG)
- // NativeImagePtr is a CGImageRef on Mac OS X.
- int width = CGImageGetWidth(nativeImage);
- int height = CGImageGetHeight(nativeImage);
- requiredTextureSize = IntSize(width, height);
- bitmapSize = requiredTextureSize;
// FIXME: we should get rid of this temporary copy where possible.
int tempRowBytes = width * 4;
Vector<uint8_t> tempVector;
@@ -145,16 +156,8 @@ void ImageLayerChromium::updateContents()
#error "Need to implement for your platform."
#endif
- unsigned textureId = m_contentsTexture;
- if (!textureId)
- textureId = layerRenderer()->createLayerTexture();
-
- // Clip the dirty rect to the bitmap dimensions.
- IntRect dirtyRect(m_dirtyRect);
- dirtyRect.intersect(IntRect(IntPoint(0, 0), bitmapSize));
-
if (pixels)
- updateTextureRect(pixels, bitmapSize, requiredTextureSize, dirtyRect, textureId);
+ updateTextureRect(pixels, bitmapSize, dirtyRect);
}
}
diff --git a/WebCore/platform/graphics/chromium/ImageLayerChromium.h b/WebCore/platform/graphics/chromium/ImageLayerChromium.h
index b91f04a..a5c1450 100644
--- a/WebCore/platform/graphics/chromium/ImageLayerChromium.h
+++ b/WebCore/platform/graphics/chromium/ImageLayerChromium.h
@@ -49,7 +49,7 @@ class ImageLayerChromium : public ContentLayerChromium {
public:
static PassRefPtr<ImageLayerChromium> create(GraphicsLayerChromium* owner = 0);
- virtual void updateContents();
+ virtual void updateContentsIfDirty();
virtual bool drawsContent() { return m_contents; }
void setContents(Image* image);
diff --git a/WebCore/platform/graphics/chromium/LayerChromium.cpp b/WebCore/platform/graphics/chromium/LayerChromium.cpp
index fab5d7b..b7ab098 100644
--- a/WebCore/platform/graphics/chromium/LayerChromium.cpp
+++ b/WebCore/platform/graphics/chromium/LayerChromium.cpp
@@ -59,7 +59,7 @@ static unsigned loadShader(GraphicsContext3D* context, unsigned type, const char
String sourceString(shaderSource);
GLC(context, context->shaderSource(shader, sourceString));
GLC(context, context->compileShader(shader));
- int compiled;
+ int compiled = 0;
GLC(context, context->getShaderiv(shader, GraphicsContext3D::COMPILE_STATUS, &compiled));
if (!compiled) {
GLC(context, context->deleteShader(shader));
@@ -228,7 +228,7 @@ unsigned LayerChromium::createShaderProgram(GraphicsContext3D* context, const ch
GLC(context, context->bindAttribLocation(programObject, s_texCoordAttribLocation, "a_texCoord"));
GLC(context, context->linkProgram(programObject));
- int linked;
+ int linked = 0;
GLC(context, context->getProgramiv(programObject, GraphicsContext3D::LINK_STATUS, &linked));
if (!linked) {
LOG_ERROR("Failed to link shader program");
diff --git a/WebCore/platform/graphics/chromium/LayerChromium.h b/WebCore/platform/graphics/chromium/LayerChromium.h
index 86f3580..ac95285 100644
--- a/WebCore/platform/graphics/chromium/LayerChromium.h
+++ b/WebCore/platform/graphics/chromium/LayerChromium.h
@@ -151,15 +151,13 @@ public:
void setOwner(GraphicsLayerChromium* owner) { m_owner = owner; }
- bool contentsDirty() { return m_contentsDirty; }
-
// Returns the rect containtaining this layer in the current view's coordinate system.
const IntRect getDrawRect() const;
// These methods typically need to be overwritten by derived classes.
virtual bool drawsContent() { return false; }
- virtual void updateContents() { };
- virtual void draw() { };
+ virtual void updateContentsIfDirty() { }
+ virtual void draw() { }
void drawDebugBorder();
@@ -197,6 +195,12 @@ public:
LayerRendererChromium* layerRenderer() const { return m_layerRenderer.get(); }
+ static unsigned createShaderProgram(GraphicsContext3D*, const char* vertexShaderSource, const char* fragmentShaderSource);
+
+ static void drawTexturedQuad(GraphicsContext3D*, const TransformationMatrix& projectionMatrix, const TransformationMatrix& layerMatrix,
+ float width, float height, float opacity,
+ int matrixLocation, int alphaLocation);
+
protected:
GraphicsLayerChromium* m_owner;
LayerChromium(GraphicsLayerChromium* owner);
@@ -211,14 +215,8 @@ protected:
// Returns true if any of the layer's descendants has content to draw.
bool descendantsDrawContent();
- static void drawTexturedQuad(GraphicsContext3D*, const TransformationMatrix& projectionMatrix, const TransformationMatrix& layerMatrix,
- float width, float height, float opacity,
- int matrixLocation, int alphaLocation);
-
static void toGLMatrix(float*, const TransformationMatrix&);
- static unsigned createShaderProgram(GraphicsContext3D*, const char* vertexShaderSource, const char* fragmentShaderSource);
-
IntSize m_bounds;
FloatRect m_dirtyRect;
bool m_contentsDirty;
diff --git a/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp b/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp
index 91580cc..882baae 100644
--- a/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp
+++ b/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp
@@ -37,7 +37,9 @@
#include "Canvas2DLayerChromium.h"
#include "GraphicsContext3D.h"
#include "LayerChromium.h"
+#include "LayerTexture.h"
#include "NotImplemented.h"
+#include "TextureManager.h"
#include "WebGLLayerChromium.h"
#if PLATFORM(SKIA)
#include "NativeImageSkia.h"
@@ -48,6 +50,9 @@
namespace WebCore {
+// FIXME: Make this limit adjustable and give it a useful value.
+static size_t textureMemoryLimitBytes = 64 * 1024 * 1024;
+
static TransformationMatrix orthoMatrix(float left, float right, float bottom, float top)
{
float deltaX = right - left;
@@ -98,7 +103,6 @@ LayerRendererChromium::LayerRendererChromium(PassRefPtr<GraphicsContext3D> conte
: m_rootLayerTextureId(0)
, m_rootLayerTextureWidth(0)
, m_rootLayerTextureHeight(0)
- , m_textureLayerShaderProgram(0)
, m_rootLayer(0)
, m_scrollPosition(IntPoint(-1, -1))
, m_currentShader(0)
@@ -164,7 +168,7 @@ void LayerRendererChromium::setRootLayerCanvasSize(const IntSize& size)
void LayerRendererChromium::useShader(unsigned programId)
{
if (programId != m_currentShader) {
- GLC(m_context, m_context->useProgram(programId));
+ GLC(m_context.get(), m_context->useProgram(programId));
m_currentShader = programId;
}
}
@@ -173,7 +177,7 @@ void LayerRendererChromium::useShader(unsigned programId)
// root layer texture. It resizes the root layer texture and scrolls its
// contents as needed. It also sets up common GL state used by the rest
// of the layer drawing code.
-void LayerRendererChromium::prepareToDrawLayers(const IntRect& visibleRect, const IntRect& contentRect,
+void LayerRendererChromium::prepareToDrawLayers(const IntRect& visibleRect, const IntRect& contentRect,
const IntPoint& scrollPosition)
{
ASSERT(m_hardwareCompositing);
@@ -183,8 +187,8 @@ void LayerRendererChromium::prepareToDrawLayers(const IntRect& visibleRect, cons
makeContextCurrent();
- GLC(m_context, m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_rootLayerTextureId));
-
+ GLC(m_context.get(), m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_rootLayerTextureId));
+
bool skipScroll = false;
// If the size of the visible area has changed then allocate a new texture
@@ -195,8 +199,7 @@ void LayerRendererChromium::prepareToDrawLayers(const IntRect& visibleRect, cons
if (visibleRectWidth != m_rootLayerTextureWidth || visibleRectHeight != m_rootLayerTextureHeight) {
m_rootLayerTextureWidth = visibleRectWidth;
m_rootLayerTextureHeight = visibleRectHeight;
-
- GLC(m_context, m_context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, m_rootLayerTextureWidth, m_rootLayerTextureHeight, 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, 0));
+ GLC(m_context.get(), m_context->texImage2DResourceSafe(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, m_rootLayerTextureWidth, m_rootLayerTextureHeight, 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE));
// Reset the current render surface to force an update of the viewport and
// projection matrix next time useRenderSurface is called.
@@ -208,17 +211,17 @@ void LayerRendererChromium::prepareToDrawLayers(const IntRect& visibleRect, cons
}
// The GL viewport covers the entire visible area, including the scrollbars.
- GLC(m_context, m_context->viewport(0, 0, visibleRectWidth, visibleRectHeight));
+ GLC(m_context.get(), m_context->viewport(0, 0, visibleRectWidth, visibleRectHeight));
// Bind the common vertex attributes used for drawing all the layers.
LayerChromium::prepareForDraw(layerSharedValues());
// FIXME: These calls can be made once, when the compositor context is initialized.
- GLC(m_context, m_context->disable(GraphicsContext3D::DEPTH_TEST));
- GLC(m_context, m_context->disable(GraphicsContext3D::CULL_FACE));
+ GLC(m_context.get(), m_context->disable(GraphicsContext3D::DEPTH_TEST));
+ GLC(m_context.get(), m_context->disable(GraphicsContext3D::CULL_FACE));
- // Blending disabled by default. Root layer alpha channel on Windows is incorrect when Skia uses ClearType.
- GLC(m_context, m_context->disable(GraphicsContext3D::BLEND));
+ // Blending disabled by default. Root layer alpha channel on Windows is incorrect when Skia uses ClearType.
+ GLC(m_context.get(), m_context->disable(GraphicsContext3D::BLEND));
if (m_scrollPosition == IntPoint(-1, -1)) {
m_scrollPosition = scrollPosition;
@@ -244,13 +247,14 @@ void LayerRendererChromium::prepareToDrawLayers(const IntRect& visibleRect, cons
0.5 * visibleRect.height() + scrollDelta.y(), 0);
scrolledLayerMatrix.scale3d(1, -1, 1);
- useShader(m_textureLayerShaderProgram);
- GLC(m_context, m_context->uniform1i(m_textureLayerShaderSamplerLocation, 0));
+ const RenderSurfaceChromium::SharedValues* rsv = renderSurfaceSharedValues();
+ useShader(rsv->shaderProgram());
+ GLC(m_context.get(), m_context->uniform1i(rsv->shaderSamplerLocation(), 0));
LayerChromium::drawTexturedQuad(m_context.get(), m_projectionMatrix, scrolledLayerMatrix,
visibleRect.width(), visibleRect.height(), 1,
- m_textureLayerShaderMatrixLocation, m_textureLayerShaderAlphaLocation);
+ rsv->shaderMatrixLocation(), rsv->shaderAlphaLocation());
- GLC(m_context, m_context->copyTexSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, 0, 0, 0, 0, contentRect.width(), contentRect.height()));
+ GLC(m_context.get(), m_context->copyTexSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, 0, 0, 0, 0, contentRect.width(), contentRect.height()));
}
m_scrollPosition = scrollPosition;
@@ -263,7 +267,7 @@ void LayerRendererChromium::updateRootLayerTextureRect(const IntRect& updateRect
if (!m_rootLayer)
return;
- GLC(m_context, m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_rootLayerTextureId));
+ GLC(m_context.get(), m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_rootLayerTextureId));
// Update the root layer texture.
ASSERT((updateRect.right() <= m_rootLayerTextureWidth)
@@ -282,7 +286,7 @@ void LayerRendererChromium::updateRootLayerTextureRect(const IntRect& updateRect
#error "Need to implement for your platform."
#endif
// Copy the contents of the updated rect to the root layer texture.
- GLC(m_context, m_context->texSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, updateRect.x(), updateRect.y(), updateRect.width(), updateRect.height(), GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, pixels));
+ GLC(m_context.get(), m_context->texSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, updateRect.x(), updateRect.y(), updateRect.width(), updateRect.height(), GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, pixels));
}
void LayerRendererChromium::drawLayers(const IntRect& visibleRect, const IntRect& contentRect)
@@ -300,22 +304,22 @@ void LayerRendererChromium::drawLayers(const IntRect& visibleRect, const IntRect
m_context->clearColor(0, 0, 1, 1);
m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT);
- GLC(m_context, m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_rootLayerTextureId));
+ GLC(m_context.get(), m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_rootLayerTextureId));
// Render the root layer using a quad that takes up the entire visible area of the window.
// We reuse the shader program used by ContentLayerChromium.
const ContentLayerChromium::SharedValues* contentLayerValues = contentLayerSharedValues();
useShader(contentLayerValues->contentShaderProgram());
- GLC(m_context, m_context->uniform1i(contentLayerValues->shaderSamplerLocation(), 0));
+ GLC(m_context.get(), m_context->uniform1i(contentLayerValues->shaderSamplerLocation(), 0));
// Mask out writes to alpha channel: ClearType via Skia results in invalid
// zero alpha values on text glyphs. The root layer is always opaque.
- GLC(m_context, m_context->colorMask(true, true, true, false));
+ GLC(m_context.get(), m_context->colorMask(true, true, true, false));
TransformationMatrix layerMatrix;
layerMatrix.translate3d(visibleRect.width() * 0.5f, visibleRect.height() * 0.5f, 0);
LayerChromium::drawTexturedQuad(m_context.get(), m_projectionMatrix, layerMatrix,
visibleRect.width(), visibleRect.height(), 1,
contentLayerValues->shaderMatrixLocation(), contentLayerValues->shaderAlphaLocation());
- GLC(m_context, m_context->colorMask(true, true, true, true));
+ GLC(m_context.get(), m_context->colorMask(true, true, true, true));
// Set the root visible/content rects --- used by subsequent drawLayers calls.
m_rootVisibleRect = visibleRect;
@@ -336,9 +340,9 @@ void LayerRendererChromium::drawLayers(const IntRect& visibleRect, const IntRect
// The shader used to render layers returns pre-multiplied alpha colors
// so we need to send the blending mode appropriately.
- GLC(m_context, m_context->enable(GraphicsContext3D::BLEND));
- GLC(m_context, m_context->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE_MINUS_SRC_ALPHA));
- GLC(m_context, m_context->enable(GraphicsContext3D::SCISSOR_TEST));
+ GLC(m_context.get(), m_context->enable(GraphicsContext3D::BLEND));
+ GLC(m_context.get(), m_context->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE_MINUS_SRC_ALPHA));
+ GLC(m_context.get(), m_context->enable(GraphicsContext3D::SCISSOR_TEST));
// Update the contents of the render surfaces. We traverse the array from
// back to front to guarantee that nested render surfaces get rendered in the
@@ -352,22 +356,23 @@ void LayerRendererChromium::drawLayers(const IntRect& visibleRect, const IntRect
if (!renderSurfaceLayer->m_renderSurface->m_layerList.size())
continue;
- useRenderSurface(renderSurfaceLayer->m_renderSurface.get());
- if (renderSurfaceLayer != m_rootLayer) {
- GLC(m_context, m_context->disable(GraphicsContext3D::SCISSOR_TEST));
- GLC(m_context, m_context->clearColor(0, 0, 0, 0));
- GLC(m_context, m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT));
- GLC(m_context, m_context->enable(GraphicsContext3D::SCISSOR_TEST));
+ if (useRenderSurface(renderSurfaceLayer->m_renderSurface.get())) {
+ if (renderSurfaceLayer != m_rootLayer) {
+ GLC(m_context.get(), m_context->disable(GraphicsContext3D::SCISSOR_TEST));
+ GLC(m_context.get(), m_context->clearColor(0, 0, 0, 0));
+ GLC(m_context.get(), m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT));
+ GLC(m_context.get(), m_context->enable(GraphicsContext3D::SCISSOR_TEST));
+ }
+
+ Vector<LayerChromium*>& layerList = renderSurfaceLayer->m_renderSurface->m_layerList;
+ ASSERT(layerList.size());
+ for (unsigned layerIndex = 0; layerIndex < layerList.size(); ++layerIndex)
+ drawLayer(layerList[layerIndex], renderSurfaceLayer->m_renderSurface.get());
}
-
- Vector<LayerChromium*>& layerList = renderSurfaceLayer->m_renderSurface->m_layerList;
- ASSERT(layerList.size());
- for (unsigned layerIndex = 0; layerIndex < layerList.size(); ++layerIndex)
- drawLayer(layerList[layerIndex], renderSurfaceLayer->m_renderSurface.get());
}
- GLC(m_context, m_context->disable(GraphicsContext3D::SCISSOR_TEST));
- GLC(m_context, m_context->disable(GraphicsContext3D::BLEND));
+ GLC(m_context.get(), m_context->disable(GraphicsContext3D::SCISSOR_TEST));
+ GLC(m_context.get(), m_context->disable(GraphicsContext3D::BLEND));
}
void LayerRendererChromium::finish()
@@ -394,7 +399,7 @@ void LayerRendererChromium::getFramebufferPixels(void *pixels, const IntRect& re
makeContextCurrent();
- GLC(m_context, m_context->readPixels(rect.x(), rect.y(), rect.width(), rect.height(),
+ GLC(m_context.get(), m_context->readPixels(rect.x(), rect.y(), rect.width(), rect.height(),
GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, pixels));
}
@@ -402,14 +407,14 @@ void LayerRendererChromium::getFramebufferPixels(void *pixels, const IntRect& re
unsigned LayerRendererChromium::createLayerTexture()
{
unsigned textureId = 0;
- GLC(m_context, textureId = m_context->createTexture());
- GLC(m_context, m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId));
+ GLC(m_context.get(), textureId = m_context->createTexture());
+ GLC(m_context.get(), m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId));
// Do basic linear filtering on resize.
- GLC(m_context, m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR));
- GLC(m_context, m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR));
+ GLC(m_context.get(), m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR));
+ GLC(m_context.get(), m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR));
// NPOT textures in GL ES only work when the wrap mode is set to GraphicsContext3D::CLAMP_TO_EDGE.
- GLC(m_context, m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE));
- GLC(m_context, m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE));
+ GLC(m_context.get(), m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE));
+ GLC(m_context.get(), m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE));
return textureId;
}
@@ -418,7 +423,7 @@ void LayerRendererChromium::deleteLayerTexture(unsigned textureId)
if (!textureId)
return;
- GLC(m_context, m_context->deleteTexture(textureId));
+ GLC(m_context.get(), m_context->deleteTexture(textureId));
}
// Returns true if any part of the layer falls within the visibleRect
@@ -507,7 +512,7 @@ void LayerRendererChromium::updateLayersRecursive(LayerChromium* layer, const Tr
// Layer's opacity will be applied when drawing the render surface.
renderSurface->m_drawOpacity = layer->opacity();
if (layer->superlayer()->preserves3D())
- renderSurface->m_drawOpacity *= layer->superlayer()->m_drawOpacity;
+ renderSurface->m_drawOpacity *= layer->superlayer()->drawOpacity();
layer->m_drawOpacity = 1;
TransformationMatrix layerOriginTransform = combinedTransform;
@@ -598,7 +603,7 @@ void LayerRendererChromium::updateLayersRecursive(LayerChromium* layer, const Tr
if (sublayer->m_renderSurface) {
RenderSurfaceChromium* sublayerRenderSurface = sublayer->m_renderSurface.get();
- const IntRect& contentRect = sublayerRenderSurface->m_contentRect;
+ const IntRect& contentRect = sublayerRenderSurface->contentRect();
FloatRect sublayerRect(-0.5 * contentRect.width(), -0.5 * contentRect.height(),
contentRect.width(), contentRect.height());
layer->m_drawableContentRect.unite(enclosingIntRect(sublayerRenderSurface->m_drawTransform.mapRect(sublayerRect)));
@@ -664,17 +669,17 @@ bool LayerRendererChromium::useRenderSurface(RenderSurfaceChromium* renderSurfac
m_currentRenderSurface = renderSurface;
if (renderSurface == m_defaultRenderSurface) {
- GLC(m_context, m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0));
+ GLC(m_context.get(), m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0));
setDrawViewportRect(renderSurface->m_contentRect, true);
return true;
}
- GLC(m_context, m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_offscreenFramebufferId));
+ GLC(m_context.get(), m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_offscreenFramebufferId));
- renderSurface->prepareContentsTexture();
+ if (!renderSurface->prepareContentsTexture())
+ return false;
- GLC(m_context, m_context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0,
- GraphicsContext3D::TEXTURE_2D, renderSurface->m_contentsTextureId, 0));
+ renderSurface->m_contentsTexture->framebufferTexture2D();
#if !defined ( NDEBUG )
if (m_context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE) {
@@ -690,15 +695,7 @@ bool LayerRendererChromium::useRenderSurface(RenderSurfaceChromium* renderSurfac
void LayerRendererChromium::drawLayer(LayerChromium* layer, RenderSurfaceChromium* targetSurface)
{
if (layer->m_renderSurface && layer->m_renderSurface != targetSurface) {
- GLC(m_context, m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, layer->m_renderSurface->m_contentsTextureId));
- useShader(m_textureLayerShaderProgram);
-
- setScissorToRect(layer->m_renderSurface->m_scissorRect);
-
- IntRect contentRect = layer->m_renderSurface->m_contentRect;
- LayerChromium::drawTexturedQuad(m_context.get(), m_projectionMatrix, layer->m_renderSurface->m_drawTransform,
- contentRect.width(), contentRect.height(), layer->m_renderSurface->m_drawOpacity,
- m_textureLayerShaderMatrixLocation, m_textureLayerShaderAlphaLocation);
+ layer->m_renderSurface->draw();
return;
}
@@ -721,12 +718,8 @@ void LayerRendererChromium::drawLayer(LayerChromium* layer, RenderSurfaceChromiu
if (layer->drawsContent()) {
// Update the contents of the layer if necessary.
- if (layer->contentsDirty()) {
- // Update the backing texture contents for any dirty portion of the layer.
- layer->updateContents();
- m_context->makeContextCurrent();
- }
-
+ layer->updateContentsIfDirty();
+ m_context->makeContextCurrent();
layer->draw();
}
@@ -748,7 +741,7 @@ void LayerRendererChromium::setScissorToRect(const IntRect& scissorRect)
scissorY = m_currentRenderSurface->m_contentRect.height() - (scissorRect.bottom() - m_currentRenderSurface->m_contentRect.y());
else
scissorY = scissorRect.y() - m_currentRenderSurface->m_contentRect.y();
- GLC(m_context, m_context->scissor(scissorX, scissorY, scissorRect.width(), scissorRect.height()));
+ GLC(m_context.get(), m_context->scissor(scissorX, scissorY, scissorRect.width(), scissorRect.height()));
}
bool LayerRendererChromium::makeContextCurrent()
@@ -774,7 +767,7 @@ void LayerRendererChromium::setDrawViewportRect(const IntRect& drawRect, bool fl
m_projectionMatrix = orthoMatrix(drawRect.x(), drawRect.right(), drawRect.bottom(), drawRect.y());
else
m_projectionMatrix = orthoMatrix(drawRect.x(), drawRect.right(), drawRect.y(), drawRect.bottom());
- GLC(m_context, m_context->viewport(0, 0, drawRect.width(), drawRect.height()));
+ GLC(m_context.get(), m_context->viewport(0, 0, drawRect.width(), drawRect.height()));
}
@@ -789,46 +782,6 @@ bool LayerRendererChromium::initializeSharedObjects()
{
makeContextCurrent();
- // The following program composites layers whose contents are the results of a previous
- // render operation and therefore doesn't perform any color swizzling. It is used
- // in scrolling and for compositing offscreen textures.
- char textureLayerVertexShaderString[] =
- "attribute vec4 a_position; \n"
- "attribute vec2 a_texCoord; \n"
- "uniform mat4 matrix; \n"
- "varying vec2 v_texCoord; \n"
- "void main() \n"
- "{ \n"
- " gl_Position = matrix * a_position; \n"
- " v_texCoord = a_texCoord; \n"
- "} \n";
- char textureLayerFragmentShaderString[] =
- "precision mediump float; \n"
- "varying vec2 v_texCoord; \n"
- "uniform sampler2D s_texture; \n"
- "uniform float alpha; \n"
- "void main() \n"
- "{ \n"
- " vec4 texColor = texture2D(s_texture, v_texCoord); \n"
- " gl_FragColor = vec4(texColor.x, texColor.y, texColor.z, texColor.w) * alpha; \n"
- "} \n";
-
- m_textureLayerShaderProgram = LayerChromium::createShaderProgram(m_context.get(), textureLayerVertexShaderString, textureLayerFragmentShaderString);
- if (!m_textureLayerShaderProgram) {
- LOG_ERROR("LayerRendererChromium: Failed to create scroll shader program");
- cleanupSharedObjects();
- return false;
- }
-
- GLC(m_context, m_textureLayerShaderSamplerLocation = m_context->getUniformLocation(m_textureLayerShaderProgram, "s_texture"));
- GLC(m_context, m_textureLayerShaderMatrixLocation = m_context->getUniformLocation(m_textureLayerShaderProgram, "matrix"));
- GLC(m_context, m_textureLayerShaderAlphaLocation = m_context->getUniformLocation(m_textureLayerShaderProgram, "alpha"));
- if (m_textureLayerShaderSamplerLocation == -1 || m_textureLayerShaderMatrixLocation == -1 || m_textureLayerShaderAlphaLocation == -1) {
- LOG_ERROR("Failed to initialize texture layer shader.");
- cleanupSharedObjects();
- return false;
- }
-
// Create a texture object to hold the contents of the root layer.
m_rootLayerTextureId = createLayerTexture();
if (!m_rootLayerTextureId) {
@@ -838,28 +791,31 @@ bool LayerRendererChromium::initializeSharedObjects()
}
// Turn off filtering for the root layer to avoid blurring from the repeated
// writes and reads to the framebuffer that happen while scrolling.
- GLC(m_context, m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_rootLayerTextureId));
- GLC(m_context, m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::NEAREST));
- GLC(m_context, m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::NEAREST));
+ GLC(m_context.get(), m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_rootLayerTextureId));
+ GLC(m_context.get(), m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::NEAREST));
+ GLC(m_context.get(), m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::NEAREST));
// Get the max texture size supported by the system.
- GLC(m_context, m_context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &m_maxTextureSize));
+ m_maxTextureSize = 0;
+ GLC(m_context.get(), m_context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &m_maxTextureSize));
// Create an FBO for doing offscreen rendering.
- GLC(m_context, m_offscreenFramebufferId = m_context->createFramebuffer());
+ GLC(m_context.get(), m_offscreenFramebufferId = m_context->createFramebuffer());
m_layerSharedValues = adoptPtr(new LayerChromium::SharedValues(m_context.get()));
m_contentLayerSharedValues = adoptPtr(new ContentLayerChromium::SharedValues(m_context.get()));
m_canvasLayerSharedValues = adoptPtr(new CanvasLayerChromium::SharedValues(m_context.get()));
m_videoLayerSharedValues = adoptPtr(new VideoLayerChromium::SharedValues(m_context.get()));
m_pluginLayerSharedValues = adoptPtr(new PluginLayerChromium::SharedValues(m_context.get()));
+ m_renderSurfaceSharedValues = adoptPtr(new RenderSurfaceChromium::SharedValues(m_context.get()));
if (!m_layerSharedValues->initialized() || !m_contentLayerSharedValues->initialized() || !m_canvasLayerSharedValues->initialized()
- || !m_videoLayerSharedValues->initialized() || !m_pluginLayerSharedValues->initialized()) {
+ || !m_videoLayerSharedValues->initialized() || !m_pluginLayerSharedValues->initialized() || !m_renderSurfaceSharedValues->initialized()) {
cleanupSharedObjects();
return false;
}
+ m_textureManager = TextureManager::create(m_context.get(), textureMemoryLimitBytes, m_maxTextureSize);
return true;
}
@@ -872,11 +828,7 @@ void LayerRendererChromium::cleanupSharedObjects()
m_canvasLayerSharedValues.clear();
m_videoLayerSharedValues.clear();
m_pluginLayerSharedValues.clear();
-
- if (m_textureLayerShaderProgram) {
- GLC(m_context, m_context->deleteProgram(m_textureLayerShaderProgram));
- m_textureLayerShaderProgram = 0;
- }
+ m_renderSurfaceSharedValues.clear();
if (m_rootLayerTextureId) {
deleteLayerTexture(m_rootLayerTextureId);
@@ -884,7 +836,9 @@ void LayerRendererChromium::cleanupSharedObjects()
}
if (m_offscreenFramebufferId)
- GLC(m_context, m_context->deleteFramebuffer(m_offscreenFramebufferId));
+ GLC(m_context.get(), m_context->deleteFramebuffer(m_offscreenFramebufferId));
+
+ m_textureManager.clear();
}
} // namespace WebCore
diff --git a/WebCore/platform/graphics/chromium/LayerRendererChromium.h b/WebCore/platform/graphics/chromium/LayerRendererChromium.h
index 531d652..c0e610a 100644
--- a/WebCore/platform/graphics/chromium/LayerRendererChromium.h
+++ b/WebCore/platform/graphics/chromium/LayerRendererChromium.h
@@ -108,6 +108,7 @@ public:
const CanvasLayerChromium::SharedValues* canvasLayerSharedValues() const { return m_canvasLayerSharedValues.get(); }
const VideoLayerChromium::SharedValues* videoLayerSharedValues() const { return m_videoLayerSharedValues.get(); }
const PluginLayerChromium::SharedValues* pluginLayerSharedValues() const { return m_pluginLayerSharedValues.get(); }
+ const RenderSurfaceChromium::SharedValues* renderSurfaceSharedValues() const { return m_renderSurfaceSharedValues.get(); }
void resizeOnscreenContent(const IntSize&);
@@ -115,6 +116,10 @@ public:
IntRect rootLayerContentRect() const { return m_rootContentRect; }
void getFramebufferPixels(void *pixels, const IntRect& rect);
+ TextureManager* textureManager() const { return m_textureManager.get(); }
+
+ void setScissorToRect(const IntRect&);
+
private:
explicit LayerRendererChromium(PassRefPtr<GraphicsContext3D> graphicsContext3D);
void updateLayersRecursive(LayerChromium* layer, const TransformationMatrix& parentMatrix, Vector<LayerChromium*>& renderSurfaceLayerList, Vector<LayerChromium*>& layerList);
@@ -123,8 +128,6 @@ private:
bool isLayerVisible(LayerChromium*, const TransformationMatrix&, const IntRect& visibleRect);
- void setScissorToRect(const IntRect&);
-
void setDrawViewportRect(const IntRect&, bool flipY);
bool useRenderSurface(RenderSurfaceChromium*);
@@ -140,13 +143,6 @@ private:
int m_rootLayerTextureWidth;
int m_rootLayerTextureHeight;
- // Shader uniform locations used by layers whose contents are the results of a
- // previous rendering operation.
- unsigned m_textureLayerShaderProgram;
- int m_textureLayerShaderSamplerLocation;
- int m_textureLayerShaderMatrixLocation;
- int m_textureLayerShaderAlphaLocation;
-
TransformationMatrix m_projectionMatrix;
RefPtr<LayerChromium> m_rootLayer;
@@ -186,6 +182,9 @@ private:
OwnPtr<CanvasLayerChromium::SharedValues> m_canvasLayerSharedValues;
OwnPtr<VideoLayerChromium::SharedValues> m_videoLayerSharedValues;
OwnPtr<PluginLayerChromium::SharedValues> m_pluginLayerSharedValues;
+ OwnPtr<RenderSurfaceChromium::SharedValues> m_renderSurfaceSharedValues;
+
+ OwnPtr<TextureManager> m_textureManager;
RefPtr<GraphicsContext3D> m_context;
diff --git a/WebCore/platform/graphics/chromium/LayerTexture.cpp b/WebCore/platform/graphics/chromium/LayerTexture.cpp
new file mode 100644
index 0000000..32bfa0b
--- /dev/null
+++ b/WebCore/platform/graphics/chromium/LayerTexture.cpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2010, Google 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. AND ITS CONTRIBUTORS ``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 ITS 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"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "LayerTexture.h"
+
+#include "GraphicsContext3D.h"
+#include "TextureManager.h"
+
+namespace WebCore {
+
+LayerTexture::LayerTexture(GraphicsContext3D* context, TextureManager* manager)
+ : m_context(context)
+ , m_textureManager(manager)
+ , m_token(0)
+ , m_format(0)
+ , m_textureId(0)
+{
+}
+
+LayerTexture::~LayerTexture()
+{
+ if (m_token)
+ m_textureManager->releaseToken(m_token);
+}
+
+bool LayerTexture::isValid(const IntSize& size, unsigned format)
+{
+ return m_token && size == m_size && format == m_format && m_textureManager->hasTexture(m_token);
+}
+
+bool LayerTexture::reserve(const IntSize& size, unsigned format)
+{
+ if (!m_token)
+ m_token = m_textureManager->getToken();
+
+ if (size == m_size && format == m_format && m_textureManager->hasTexture(m_token))
+ m_textureManager->protectTexture(m_token);
+ else {
+ m_textureId = m_textureManager->requestTexture(m_token, size, format);
+ if (m_textureId) {
+ m_size = size;
+ m_format = format;
+ }
+ }
+
+ return m_textureId;
+}
+
+void LayerTexture::unreserve()
+{
+ if (m_token)
+ m_textureManager->unprotectTexture(m_token);
+}
+
+void LayerTexture::bindTexture()
+{
+ m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_textureId);
+}
+
+void LayerTexture::framebufferTexture2D()
+{
+ m_context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, m_textureId, 0);
+}
+
+}
+
+#endif // USE(ACCELERATED_COMPOSITING)
+
diff --git a/WebCore/platform/graphics/chromium/LayerTexture.h b/WebCore/platform/graphics/chromium/LayerTexture.h
new file mode 100644
index 0000000..312adfa
--- /dev/null
+++ b/WebCore/platform/graphics/chromium/LayerTexture.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2010, Google 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. AND ITS CONTRIBUTORS ``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 ITS 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.
+ */
+
+#ifndef LayerTexture_h
+#define LayerTexture_h
+
+#include "IntSize.h"
+#include "TextureManager.h"
+
+#include <wtf/Noncopyable.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class GraphicsContext3D;
+class TextureManager;
+
+class LayerTexture : public Noncopyable {
+public:
+ static PassOwnPtr<LayerTexture> create(GraphicsContext3D* context, TextureManager* manager)
+ {
+ return adoptPtr(new LayerTexture(context, manager));
+ }
+ ~LayerTexture();
+
+ bool isValid(const IntSize&, unsigned format);
+ bool reserve(const IntSize&, unsigned format);
+ void unreserve();
+
+ void bindTexture();
+ void framebufferTexture2D();
+
+private:
+ LayerTexture(GraphicsContext3D*, TextureManager*);
+
+ RefPtr<GraphicsContext3D> m_context;
+ TextureManager* m_textureManager;
+ TextureToken m_token;
+ IntSize m_size;
+ unsigned m_format;
+ unsigned m_textureId;
+};
+
+}
+
+#endif
+
diff --git a/WebCore/platform/graphics/chromium/PluginLayerChromium.cpp b/WebCore/platform/graphics/chromium/PluginLayerChromium.cpp
index 2d1852f..878c142 100644
--- a/WebCore/platform/graphics/chromium/PluginLayerChromium.cpp
+++ b/WebCore/platform/graphics/chromium/PluginLayerChromium.cpp
@@ -102,7 +102,7 @@ void PluginLayerChromium::setTextureId(unsigned id)
m_textureId = id;
}
-void PluginLayerChromium::updateContents()
+void PluginLayerChromium::updateContentsIfDirty()
{
}
diff --git a/WebCore/platform/graphics/chromium/PluginLayerChromium.h b/WebCore/platform/graphics/chromium/PluginLayerChromium.h
index 44a6cc9..853b328 100644
--- a/WebCore/platform/graphics/chromium/PluginLayerChromium.h
+++ b/WebCore/platform/graphics/chromium/PluginLayerChromium.h
@@ -38,7 +38,7 @@ class PluginLayerChromium : public LayerChromium {
public:
static PassRefPtr<PluginLayerChromium> create(GraphicsLayerChromium* owner = 0);
virtual bool drawsContent() { return true; }
- virtual void updateContents();
+ virtual void updateContentsIfDirty();
virtual void draw();
void setTextureId(unsigned textureId);
diff --git a/WebCore/platform/graphics/chromium/RenderSurfaceChromium.cpp b/WebCore/platform/graphics/chromium/RenderSurfaceChromium.cpp
index 816fd3d..e8b9a12 100644
--- a/WebCore/platform/graphics/chromium/RenderSurfaceChromium.cpp
+++ b/WebCore/platform/graphics/chromium/RenderSurfaceChromium.cpp
@@ -31,12 +31,67 @@
#include "GraphicsContext3D.h"
#include "LayerRendererChromium.h"
+#include "LayerTexture.h"
namespace WebCore {
+RenderSurfaceChromium::SharedValues::SharedValues(GraphicsContext3D* context)
+ : m_context(context)
+ , m_shaderProgram(0)
+ , m_shaderSamplerLocation(-1)
+ , m_shaderMatrixLocation(-1)
+ , m_shaderAlphaLocation(-1)
+ , m_initialized(false)
+{
+ // The following program composites layers whose contents are the results of a previous
+ // render operation and therefore doesn't perform any color swizzling. It is used
+ // in scrolling and for compositing offscreen textures.
+ char renderSurfaceVertexShaderString[] =
+ "attribute vec4 a_position; \n"
+ "attribute vec2 a_texCoord; \n"
+ "uniform mat4 matrix; \n"
+ "varying vec2 v_texCoord; \n"
+ "void main() \n"
+ "{ \n"
+ " gl_Position = matrix * a_position; \n"
+ " v_texCoord = a_texCoord; \n"
+ "} \n";
+ char renderSurfaceFragmentShaderString[] =
+ "precision mediump float; \n"
+ "varying vec2 v_texCoord; \n"
+ "uniform sampler2D s_texture; \n"
+ "uniform float alpha; \n"
+ "void main() \n"
+ "{ \n"
+ " vec4 texColor = texture2D(s_texture, v_texCoord); \n"
+ " gl_FragColor = vec4(texColor.x, texColor.y, texColor.z, texColor.w) * alpha; \n"
+ "} \n";
+
+ m_shaderProgram = LayerChromium::createShaderProgram(m_context, renderSurfaceVertexShaderString, renderSurfaceFragmentShaderString);
+ if (!m_shaderProgram) {
+ LOG_ERROR("RenderSurfaceChromium: Failed to create shader program");
+ return;
+ }
+
+ GLC(m_context, m_shaderSamplerLocation = m_context->getUniformLocation(m_shaderProgram, "s_texture"));
+ GLC(m_context, m_shaderMatrixLocation = m_context->getUniformLocation(m_shaderProgram, "matrix"));
+ GLC(m_context, m_shaderAlphaLocation = m_context->getUniformLocation(m_shaderProgram, "alpha"));
+ if (m_shaderSamplerLocation == -1 || m_shaderMatrixLocation == -1 || m_shaderAlphaLocation == -1) {
+ LOG_ERROR("Failed to initialize texture layer shader.");
+ return;
+ }
+ m_initialized = true;
+}
+
+RenderSurfaceChromium::SharedValues::~SharedValues()
+{
+ if (m_shaderProgram)
+ GLC(m_context, m_context->deleteProgram(m_shaderProgram));
+}
+
RenderSurfaceChromium::RenderSurfaceChromium(LayerChromium* owningLayer)
: m_owningLayer(owningLayer)
- , m_contentsTextureId(0)
+ , m_skipsDraw(false)
{
}
@@ -47,14 +102,12 @@ RenderSurfaceChromium::~RenderSurfaceChromium()
void RenderSurfaceChromium::cleanupResources()
{
- if (!m_contentsTextureId)
+ if (!m_contentsTexture)
return;
ASSERT(layerRenderer());
- layerRenderer()->deleteLayerTexture(m_contentsTextureId);
- m_contentsTextureId = 0;
- m_allocatedTextureSize = IntSize();
+ m_contentsTexture.clear();
}
LayerRendererChromium* RenderSurfaceChromium::layerRenderer()
@@ -63,25 +116,41 @@ LayerRendererChromium* RenderSurfaceChromium::layerRenderer()
return m_owningLayer->layerRenderer();
}
-void RenderSurfaceChromium::prepareContentsTexture()
+bool RenderSurfaceChromium::prepareContentsTexture()
{
- ASSERT(m_owningLayer);
+ IntSize requiredSize(m_contentRect.size());
+ TextureManager* textureManager = layerRenderer()->textureManager();
- if (!m_contentsTextureId) {
- m_contentsTextureId = layerRenderer()->createLayerTexture();
- ASSERT(m_contentsTextureId);
- m_allocatedTextureSize = IntSize();
- }
+ if (!m_contentsTexture)
+ m_contentsTexture = LayerTexture::create(layerRenderer()->context(), textureManager);
- IntSize requiredSize(m_contentRect.width(), m_contentRect.height());
- if (m_allocatedTextureSize != requiredSize) {
- GraphicsContext3D* context = m_owningLayer->layerRenderer()->context();
- GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_contentsTextureId));
- GLC(context, context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA,
- requiredSize.width(), requiredSize.height(), 0, GraphicsContext3D::RGBA,
- GraphicsContext3D::UNSIGNED_BYTE, 0));
- m_allocatedTextureSize = requiredSize;
+ if (!m_contentsTexture->reserve(requiredSize, GraphicsContext3D::RGBA)) {
+ m_skipsDraw = true;
+ return false;
}
+
+ m_skipsDraw = false;
+ return true;
+}
+
+void RenderSurfaceChromium::draw()
+{
+ if (m_skipsDraw || !m_contentsTexture)
+ return;
+
+ m_contentsTexture->bindTexture();
+
+ const RenderSurfaceChromium::SharedValues* sv = layerRenderer()->renderSurfaceSharedValues();
+ ASSERT(sv && sv->initialized());
+
+ layerRenderer()->useShader(sv->shaderProgram());
+ layerRenderer()->setScissorToRect(m_scissorRect);
+
+ LayerChromium::drawTexturedQuad(layerRenderer()->context(), layerRenderer()->projectionMatrix(), m_drawTransform,
+ m_contentRect.width(), m_contentRect.height(), m_drawOpacity,
+ sv->shaderMatrixLocation(), sv->shaderAlphaLocation());
+
+ m_contentsTexture->unreserve();
}
}
diff --git a/WebCore/platform/graphics/chromium/RenderSurfaceChromium.h b/WebCore/platform/graphics/chromium/RenderSurfaceChromium.h
index 1f33527..a93218f 100644
--- a/WebCore/platform/graphics/chromium/RenderSurfaceChromium.h
+++ b/WebCore/platform/graphics/chromium/RenderSurfaceChromium.h
@@ -31,13 +31,15 @@
#include "FloatRect.h"
#include "IntRect.h"
+#include "TextureManager.h"
#include "TransformationMatrix.h"
#include <wtf/Noncopyable.h>
namespace WebCore {
-class LayerRendererChromium;
class LayerChromium;
+class LayerRendererChromium;
+class LayerTexture;
class RenderSurfaceChromium : public Noncopyable {
friend class LayerRendererChromium;
@@ -45,20 +47,45 @@ public:
explicit RenderSurfaceChromium(LayerChromium*);
~RenderSurfaceChromium();
- void prepareContentsTexture();
+ bool prepareContentsTexture();
void cleanupResources();
+ void draw();
FloatPoint contentRectCenter() const { return FloatRect(m_contentRect).center(); }
IntRect contentRect() const { return m_contentRect; }
+ // Stores values that are shared between instances of this class that are
+ // associated with the same LayerRendererChromium (and hence the same GL
+ // context).
+ class SharedValues {
+ public:
+ explicit SharedValues(GraphicsContext3D*);
+ ~SharedValues();
+
+ unsigned shaderProgram() const { return m_shaderProgram; }
+ int shaderSamplerLocation() const { return m_shaderSamplerLocation; }
+ int shaderMatrixLocation() const { return m_shaderMatrixLocation; }
+ int shaderAlphaLocation() const { return m_shaderAlphaLocation; }
+ bool initialized() const { return m_initialized; }
+
+ private:
+ GraphicsContext3D* m_context;
+
+ unsigned m_shaderProgram;
+ int m_shaderSamplerLocation;
+ int m_shaderMatrixLocation;
+ int m_shaderAlphaLocation;
+ bool m_initialized;
+ };
+
private:
LayerRendererChromium* layerRenderer();
LayerChromium* m_owningLayer;
IntRect m_contentRect;
- unsigned m_contentsTextureId;
+ bool m_skipsDraw;
+ OwnPtr<LayerTexture> m_contentsTexture;
float m_drawOpacity;
- IntSize m_allocatedTextureSize;
TransformationMatrix m_drawTransform;
TransformationMatrix m_originTransform;
IntRect m_scissorRect;
diff --git a/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp b/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp
index bcef1fe..204c565 100644
--- a/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp
+++ b/WebCore/platform/graphics/chromium/SimpleFontDataChromiumWin.cpp
@@ -112,20 +112,34 @@ void SimpleFontData::platformDestroy()
{
}
+SimpleFontData* SimpleFontData::scaledFontData(const FontDescription& fontDescription, float scaleFactor) const
+{
+ LOGFONT winFont;
+ GetObject(m_platformData.hfont(), sizeof(LOGFONT), &winFont);
+ float scaledSize = scaleFactor * fontDescription.computedSize();
+ winFont.lfHeight = -lroundf(scaledSize);
+ HFONT hfont = CreateFontIndirect(&winFont);
+ return new SimpleFontData(FontPlatformData(hfont, scaledSize), isCustomFont(), false);
+}
+
SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const
{
- if (!m_smallCapsFontData) {
- LOGFONT winFont;
- GetObject(m_platformData.hfont(), sizeof(LOGFONT), &winFont);
- float smallCapsSize = 0.70f * fontDescription.computedSize();
- // Unlike WebKit trunk, we don't multiply the size by 32. That seems
- // to be some kind of artifact of their CG backend, or something.
- winFont.lfHeight = -lroundf(smallCapsSize);
- HFONT hfont = CreateFontIndirect(&winFont);
- m_smallCapsFontData =
- new SimpleFontData(FontPlatformData(hfont, smallCapsSize), isCustomFont(), false);
- }
- return m_smallCapsFontData;
+ if (!m_derivedFontData)
+ m_derivedFontData = DerivedFontData::create(isCustomFont());
+ if (!m_derivedFontData->smallCaps)
+ m_derivedFontData->smallCaps = scaledFontData(fontDescription, .7);
+
+ return m_derivedFontData->smallCaps.get();
+}
+
+SimpleFontData* SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const
+{
+ if (!m_derivedFontData)
+ m_derivedFontData = DerivedFontData::create(isCustomFont());
+ if (!m_derivedFontData->emphasisMark)
+ m_derivedFontData->emphasisMark = scaledFontData(fontDescription, .5);
+
+ return m_derivedFontData->emphasisMark.get();
}
bool SimpleFontData::containsCharacters(const UChar* characters, int length) const
diff --git a/WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp b/WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp
index c5190fc..355d837 100644
--- a/WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp
+++ b/WebCore/platform/graphics/chromium/SimpleFontDataLinux.cpp
@@ -48,6 +48,7 @@ namespace WebCore {
// Smallcaps versions of fonts are 70% the size of the normal font.
static const float smallCapsFraction = 0.7f;
+static const float emphasisMarkFraction = .5;
// This is the largest VDMX table which we'll try to load and parse.
static const size_t maxVDMXTableSize = 1024 * 1024; // 1 MB
@@ -108,6 +109,15 @@ void SimpleFontData::platformInit()
m_lineGap = SkScalarRound(metrics.fLeading);
m_lineSpacing = m_ascent + m_descent + m_lineGap;
+ if (m_orientation == Vertical) {
+ static const uint32_t vheaTag = SkSetFourByteTag('v', 'h', 'e', 'a');
+ static const uint32_t vorgTag = SkSetFourByteTag('V', 'O', 'R', 'G');
+ size_t vheaSize = SkFontHost::GetTableSize(fontID, vheaTag);
+ size_t vorgSize = SkFontHost::GetTableSize(fontID, vorgTag);
+ if ((vheaSize <= 0) && (vorgSize <= 0))
+ m_orientation = Horizontal;
+ }
+
// In WebKit/WebCore/platform/graphics/SimpleFontData.cpp, m_spaceWidth is
// calculated for us, but we need to calculate m_maxCharWidth and
// m_avgCharWidth in order for text entry widgets to be sized correctly.
@@ -141,14 +151,30 @@ void SimpleFontData::platformDestroy()
{
}
+SimpleFontData* SimpleFontData::scaledFontData(const FontDescription& fontDescription, float scaleFactor) const
+{
+ const float scaledSize = lroundf(fontDescription.computedSize() * scaleFactor);
+ return new SimpleFontData(FontPlatformData(m_platformData, scaledSize), isCustomFont(), false);
+}
+
SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const
{
- if (!m_smallCapsFontData) {
- const float smallCapsSize = lroundf(fontDescription.computedSize() * smallCapsFraction);
- m_smallCapsFontData = new SimpleFontData(FontPlatformData(m_platformData, smallCapsSize), isCustomFont(), false);
- }
+ if (!m_derivedFontData)
+ m_derivedFontData = DerivedFontData::create(isCustomFont());
+ if (!m_derivedFontData->smallCaps)
+ m_derivedFontData->smallCaps = scaledFontData(fontDescription, smallCapsFraction);
+
+ return m_derivedFontData->smallCaps.get();
+}
+
+SimpleFontData* SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const
+{
+ if (!m_derivedFontData)
+ m_derivedFontData = DerivedFontData::create(isCustomFont());
+ if (!m_derivedFontData->emphasisMark)
+ m_derivedFontData->emphasisMark = scaledFontData(fontDescription, emphasisMarkFraction);
- return m_smallCapsFontData;
+ return m_derivedFontData->emphasisMark.get();
}
bool SimpleFontData::containsCharacters(const UChar* characters, int length) const
diff --git a/WebCore/platform/graphics/chromium/TextureManager.cpp b/WebCore/platform/graphics/chromium/TextureManager.cpp
new file mode 100644
index 0000000..9579ef9
--- /dev/null
+++ b/WebCore/platform/graphics/chromium/TextureManager.cpp
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2010, Google 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. AND ITS CONTRIBUTORS ``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 ITS 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"
+
+#if USE(ACCELERATED_COMPOSITING)
+
+#include "TextureManager.h"
+
+#include "LayerRendererChromium.h"
+
+namespace WebCore {
+
+static size_t memoryUseBytes(IntSize size, unsigned textureFormat)
+{
+ // FIXME: This assumes all textures are 4 bytes/pixel, like RGBA.
+ return size.width() * size.height() * 4;
+}
+
+TextureManager::TextureManager(GraphicsContext3D* context, size_t memoryLimitBytes, int maxTextureSize)
+ : m_context(context)
+ , m_memoryLimitBytes(memoryLimitBytes)
+ , m_memoryUseBytes(0)
+ , m_maxTextureSize(maxTextureSize)
+ , m_nextToken(1)
+{
+}
+
+TextureToken TextureManager::getToken()
+{
+ return m_nextToken++;
+}
+
+void TextureManager::releaseToken(TextureToken token)
+{
+ TextureMap::iterator it = m_textures.find(token);
+ if (it != m_textures.end())
+ removeTexture(token, it->second);
+}
+
+bool TextureManager::hasTexture(TextureToken token)
+{
+ if (m_textures.contains(token)) {
+ // If someone asks about a texture put it at the end of the LRU list.
+ m_textureLRUSet.remove(token);
+ m_textureLRUSet.add(token);
+ return true;
+ }
+ return false;
+}
+
+void TextureManager::protectTexture(TextureToken token)
+{
+ ASSERT(hasTexture(token));
+ ASSERT(!m_textures.get(token).isProtected);
+ TextureInfo info = m_textures.take(token);
+ info.isProtected = true;
+ m_textures.add(token, info);
+}
+
+void TextureManager::unprotectTexture(TextureToken token)
+{
+ TextureMap::iterator it = m_textures.find(token);
+ if (it != m_textures.end()) {
+ TextureInfo info = it->second;
+ if (info.isProtected) {
+ info.isProtected = false;
+ m_textures.remove(it);
+ m_textures.add(token, info);
+ }
+ }
+}
+
+bool TextureManager::reduceMemoryToLimit(size_t limit)
+{
+ while (m_memoryUseBytes > limit) {
+ ASSERT(!m_textureLRUSet.isEmpty());
+ bool foundCandidate = false;
+ for (ListHashSet<TextureToken>::iterator lruIt = m_textureLRUSet.begin(); lruIt != m_textureLRUSet.end(); ++lruIt) {
+ TextureToken token = *lruIt;
+ TextureInfo info = m_textures.get(token);
+ if (info.isProtected)
+ continue;
+ removeTexture(token, info);
+ foundCandidate = true;
+ break;
+ }
+ if (!foundCandidate)
+ return false;
+ }
+ return true;
+}
+
+void TextureManager::addTexture(TextureToken token, TextureInfo info)
+{
+ ASSERT(!m_textureLRUSet.contains(token));
+ ASSERT(!m_textures.contains(token));
+ m_memoryUseBytes += memoryUseBytes(info.size, info.format);
+ m_textures.set(token, info);
+ m_textureLRUSet.add(token);
+}
+
+void TextureManager::removeTexture(TextureToken token, TextureInfo info)
+{
+ ASSERT(m_textureLRUSet.contains(token));
+ ASSERT(m_textures.contains(token));
+ m_memoryUseBytes -= memoryUseBytes(info.size, info.format);
+ m_textures.remove(token);
+ ASSERT(m_textureLRUSet.contains(token));
+ m_textureLRUSet.remove(token);
+ GLC(m_context.get(), m_context->deleteTexture(info.textureId));
+}
+
+unsigned TextureManager::requestTexture(TextureToken token, IntSize size, unsigned format, bool* newTexture)
+{
+ if (size.width() > m_maxTextureSize || size.height() > m_maxTextureSize)
+ return 0;
+
+ TextureMap::iterator it = m_textures.find(token);
+ if (it != m_textures.end()) {
+ ASSERT(it->second.size != size || it->second.format != format);
+ removeTexture(token, it->second);
+ }
+
+ size_t memoryRequiredBytes = memoryUseBytes(size, format);
+ if (memoryRequiredBytes > m_memoryLimitBytes || !reduceMemoryToLimit(m_memoryLimitBytes - memoryRequiredBytes))
+ return 0;
+
+ unsigned textureId = m_context->createTexture();
+ GLC(m_context.get(), textureId = m_context->createTexture());
+ GLC(m_context.get(), m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId));
+ // Do basic linear filtering on resize.
+ GLC(m_context.get(), m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR));
+ GLC(m_context.get(), m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR));
+ // NPOT textures in GL ES only work when the wrap mode is set to GraphicsContext3D::CLAMP_TO_EDGE.
+ GLC(m_context.get(), m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE));
+ GLC(m_context.get(), m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE));
+ GLC(m_context.get(), m_context->texImage2DResourceSafe(GraphicsContext3D::TEXTURE_2D, 0, format, size.width(), size.height(), 0, format, GraphicsContext3D::UNSIGNED_BYTE));
+ TextureInfo info;
+ info.size = size;
+ info.format = format;
+ info.textureId = textureId;
+ info.isProtected = true;
+ addTexture(token, info);
+ return textureId;
+}
+
+}
+
+#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/WebCore/platform/graphics/chromium/TextureManager.h b/WebCore/platform/graphics/chromium/TextureManager.h
new file mode 100644
index 0000000..1e850cd
--- /dev/null
+++ b/WebCore/platform/graphics/chromium/TextureManager.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2010, Google 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. AND ITS CONTRIBUTORS ``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 ITS 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.
+ */
+
+#ifndef TextureManager_h
+#define TextureManager_h
+
+#include "GraphicsContext3D.h"
+#include "IntRect.h"
+#include "IntSize.h"
+
+#include <wtf/HashMap.h>
+#include <wtf/ListHashSet.h>
+
+namespace WebCore {
+
+typedef int TextureToken;
+
+class TextureManager : public Noncopyable {
+public:
+ static PassOwnPtr<TextureManager> create(GraphicsContext3D* context, size_t memoryLimitBytes, int maxTextureSize)
+ {
+ return adoptPtr(new TextureManager(context, memoryLimitBytes, maxTextureSize));
+ }
+
+ TextureToken getToken();
+ void releaseToken(TextureToken);
+ bool hasTexture(TextureToken);
+
+ unsigned requestTexture(TextureToken, IntSize, unsigned textureFormat, bool* newTexture = 0);
+
+ void protectTexture(TextureToken);
+ void unprotectTexture(TextureToken);
+
+private:
+ TextureManager(GraphicsContext3D*, size_t memoryLimitBytes, int maxTextureSize);
+
+ struct TextureInfo {
+ IntSize size;
+ unsigned format;
+ unsigned textureId;
+ bool isProtected;
+ };
+
+ bool reduceMemoryToLimit(size_t);
+ void addTexture(TextureToken, TextureInfo);
+ void removeTexture(TextureToken, TextureInfo);
+
+ RefPtr<GraphicsContext3D> m_context;
+
+ typedef HashMap<TextureToken, TextureInfo> TextureMap;
+ TextureMap m_textures;
+ ListHashSet<TextureToken> m_textureLRUSet;
+
+ size_t m_memoryLimitBytes;
+ size_t m_memoryUseBytes;
+ int m_maxTextureSize;
+ TextureToken m_nextToken;
+};
+
+}
+
+#endif
diff --git a/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp b/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp
index feb7ebc..24fd732 100644
--- a/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp
+++ b/WebCore/platform/graphics/chromium/VideoLayerChromium.cpp
@@ -200,8 +200,11 @@ void VideoLayerChromium::cleanupResources()
}
}
-void VideoLayerChromium::updateContents()
+void VideoLayerChromium::updateContentsIfDirty()
{
+ if (!m_contentsDirty)
+ return;
+
RenderLayerBacking* backing = static_cast<RenderLayerBacking*>(m_owner->client());
if (!backing || backing->paintingGoesToWindow())
return;
@@ -297,7 +300,7 @@ bool VideoLayerChromium::allocateTexturesIfNeeded(GraphicsContext3D* context, Vi
void VideoLayerChromium::allocateTexture(GraphicsContext3D* context, unsigned textureId, const IntSize& dimensions, unsigned textureFormat)
{
GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId));
- GLC(context, context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, textureFormat, dimensions.width(), dimensions.height(), 0, textureFormat, GraphicsContext3D::UNSIGNED_BYTE, 0));
+ GLC(context, context->texImage2DResourceSafe(GraphicsContext3D::TEXTURE_2D, 0, textureFormat, dimensions.width(), dimensions.height(), 0, textureFormat, GraphicsContext3D::UNSIGNED_BYTE));
}
void VideoLayerChromium::updateTexture(GraphicsContext3D* context, unsigned textureId, const IntSize& dimensions, unsigned format, const void* data)
diff --git a/WebCore/platform/graphics/chromium/VideoLayerChromium.h b/WebCore/platform/graphics/chromium/VideoLayerChromium.h
index 05b6578..0992ab7 100644
--- a/WebCore/platform/graphics/chromium/VideoLayerChromium.h
+++ b/WebCore/platform/graphics/chromium/VideoLayerChromium.h
@@ -45,7 +45,7 @@ public:
static PassRefPtr<VideoLayerChromium> create(GraphicsLayerChromium* owner = 0,
VideoFrameProvider* = 0);
virtual ~VideoLayerChromium();
- virtual void updateContents();
+ virtual void updateContentsIfDirty();
virtual bool drawsContent() { return true; }
virtual void draw();
diff --git a/WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp b/WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp
index 2055ae6..5b34bb9 100644
--- a/WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp
+++ b/WebCore/platform/graphics/chromium/WebGLLayerChromium.cpp
@@ -50,8 +50,11 @@ WebGLLayerChromium::WebGLLayerChromium(GraphicsLayerChromium* owner)
{
}
-void WebGLLayerChromium::updateContents()
+void WebGLLayerChromium::updateContentsIfDirty()
{
+ if (!m_contentsDirty)
+ return;
+
GraphicsContext3D* rendererContext = layerRendererContext();
ASSERT(m_context);
if (m_textureChanged) {
diff --git a/WebCore/platform/graphics/chromium/WebGLLayerChromium.h b/WebCore/platform/graphics/chromium/WebGLLayerChromium.h
index 11b8db7..c67cc2c 100644
--- a/WebCore/platform/graphics/chromium/WebGLLayerChromium.h
+++ b/WebCore/platform/graphics/chromium/WebGLLayerChromium.h
@@ -45,7 +45,7 @@ class WebGLLayerChromium : public CanvasLayerChromium {
public:
static PassRefPtr<WebGLLayerChromium> create(GraphicsLayerChromium* owner = 0);
virtual bool drawsContent() { return m_context; }
- virtual void updateContents();
+ virtual void updateContentsIfDirty();
void setContext(const GraphicsContext3D* context);
diff --git a/WebCore/platform/graphics/efl/FontEfl.cpp b/WebCore/platform/graphics/efl/FontEfl.cpp
index 96d6a7b..d3ca183 100644
--- a/WebCore/platform/graphics/efl/FontEfl.cpp
+++ b/WebCore/platform/graphics/efl/FontEfl.cpp
@@ -40,6 +40,11 @@ void Font::drawComplexText(GraphicsContext*, const TextRun&, const FloatPoint&,
notImplemented();
}
+void Font::drawEmphasisMarksForComplexText(GraphicsContext* /* context */, const TextRun& /* run */, const AtomicString& /* mark */, const FloatPoint& /* point */, int /* from */, int /* to */) const
+{
+ notImplemented();
+}
+
bool Font::canReturnFallbackFontsForComplexText()
{
return false;
diff --git a/WebCore/platform/graphics/filters/FEBlend.cpp b/WebCore/platform/graphics/filters/FEBlend.cpp
index 89b44e0..f863487 100644
--- a/WebCore/platform/graphics/filters/FEBlend.cpp
+++ b/WebCore/platform/graphics/filters/FEBlend.cpp
@@ -88,30 +88,31 @@ static unsigned char lighten(unsigned char colorA, unsigned char colorB, unsigne
void FEBlend::apply()
{
+ if (hasResult())
+ return;
FilterEffect* in = inputEffect(0);
FilterEffect* in2 = inputEffect(1);
in->apply();
in2->apply();
- if (!in->resultImage() || !in2->resultImage())
+ if (!in->hasResult() || !in2->hasResult())
return;
if (m_mode <= FEBLEND_MODE_UNKNOWN || m_mode > FEBLEND_MODE_LIGHTEN)
return;
- if (!effectContext())
+ ImageData* resultImage = createPremultipliedImageResult();
+ if (!resultImage)
return;
IntRect effectADrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
- RefPtr<ImageData> srcImageDataA = in->resultImage()->getPremultipliedImageData(effectADrawingRect);
+ RefPtr<ImageData> srcImageDataA = in->asPremultipliedImage(effectADrawingRect);
ByteArray* srcPixelArrayA = srcImageDataA->data()->data();
IntRect effectBDrawingRect = requestedRegionOfInputImageData(in2->absolutePaintRect());
- RefPtr<ImageData> srcImageDataB = in2->resultImage()->getPremultipliedImageData(effectBDrawingRect);
+ RefPtr<ImageData> srcImageDataB = in2->asPremultipliedImage(effectBDrawingRect);
ByteArray* srcPixelArrayB = srcImageDataB->data()->data();
- IntRect imageRect(IntPoint(), resultImage()->size());
- RefPtr<ImageData> imageData = ImageData::create(imageRect.width(), imageRect.height());
- ByteArray* dstPixelArray = imageData->data()->data();
+ ByteArray* dstPixelArray = resultImage->data()->data();
// Keep synchronized with BlendModeType
static const BlendType callEffect[] = {unknown, normal, multiply, screen, darken, lighten};
@@ -131,8 +132,6 @@ void FEBlend::apply()
unsigned char alphaR = 255 - ((255 - alphaA) * (255 - alphaB)) / 255;
dstPixelArray->set(pixelOffset + 3, alphaR);
}
-
- resultImage()->putPremultipliedImageData(imageData.get(), imageRect, IntPoint());
}
void FEBlend::dump()
diff --git a/WebCore/platform/graphics/filters/FEColorMatrix.cpp b/WebCore/platform/graphics/filters/FEColorMatrix.cpp
index 1c99b1e..d316dfb 100644
--- a/WebCore/platform/graphics/filters/FEColorMatrix.cpp
+++ b/WebCore/platform/graphics/filters/FEColorMatrix.cpp
@@ -67,10 +67,10 @@ void FEColorMatrix::setValues(const Vector<float> &values)
inline void matrix(double& red, double& green, double& blue, double& alpha, const Vector<float>& values)
{
- double r = values[0] * red + values[1] * green + values[2] * blue + values[3] * alpha;
- double g = values[5] * red + values[6] * green + values[7] * blue + values[8] * alpha;
- double b = values[10] * red + values[11] * green + values[12] * blue + values[13] * alpha;
- double a = values[15] * red + values[16] * green + values[17] * blue + values[18] * alpha;
+ double r = values[0] * red + values[1] * green + values[2] * blue + values[3] * alpha + values[4] * 255;
+ double g = values[5] * red + values[6] * green + values[7] * blue + values[8] * alpha + values[9] * 255;
+ double b = values[10] * red + values[11] * green + values[12] * blue + values[13] * alpha + values[14] * 255;
+ double a = values[15] * red + values[16] * green + values[17] * blue + values[18] * alpha + values[19] * 255;
red = r;
green = g;
@@ -150,19 +150,21 @@ void effectType(ByteArray* pixelArray, const Vector<float>& values)
void FEColorMatrix::apply()
{
+ if (hasResult())
+ return;
FilterEffect* in = inputEffect(0);
in->apply();
- if (!in->resultImage())
+ if (!in->hasResult())
return;
- GraphicsContext* filterContext = effectContext();
- if (!filterContext)
+ ImageBuffer* resultImage = createImageBufferResult();
+ if (!resultImage)
return;
- filterContext->drawImageBuffer(in->resultImage(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in->absolutePaintRect()));
+ resultImage->context()->drawImageBuffer(in->asImageBuffer(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in->absolutePaintRect()));
- IntRect imageRect(IntPoint(), resultImage()->size());
- RefPtr<ImageData> imageData = resultImage()->getUnmultipliedImageData(imageRect);
+ IntRect imageRect(IntPoint(), absolutePaintRect().size());
+ RefPtr<ImageData> imageData = resultImage->getUnmultipliedImageData(imageRect);
ByteArray* pixelArray = imageData->data()->data();
switch (m_type) {
@@ -183,7 +185,7 @@ void FEColorMatrix::apply()
break;
}
- resultImage()->putUnmultipliedImageData(imageData.get(), imageRect, IntPoint());
+ resultImage->putUnmultipliedImageData(imageData.get(), imageRect, IntPoint());
}
void FEColorMatrix::dump()
diff --git a/WebCore/platform/graphics/filters/FEComponentTransfer.cpp b/WebCore/platform/graphics/filters/FEComponentTransfer.cpp
index cfab50b..f8f651c 100644
--- a/WebCore/platform/graphics/filters/FEComponentTransfer.cpp
+++ b/WebCore/platform/graphics/filters/FEComponentTransfer.cpp
@@ -149,12 +149,15 @@ static void gamma(unsigned char* values, const ComponentTransferFunction& transf
void FEComponentTransfer::apply()
{
+ if (hasResult())
+ return;
FilterEffect* in = inputEffect(0);
in->apply();
- if (!in->resultImage())
+ if (!in->hasResult())
return;
- if (!effectContext())
+ ImageData* imageData = createUnmultipliedImageResult();
+ if (!imageData)
return;
unsigned char rValues[256], gValues[256], bValues[256], aValues[256];
@@ -168,7 +171,7 @@ void FEComponentTransfer::apply()
(*callEffect[transferFunction[channel].type])(tables[channel], transferFunction[channel]);
IntRect drawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
- RefPtr<ImageData> imageData = in->resultImage()->getUnmultipliedImageData(drawingRect);
+ in->copyUnmultipliedImage(imageData, drawingRect);
ByteArray* pixelArray = imageData->data()->data();
unsigned pixelArrayLength = pixelArray->length();
@@ -178,8 +181,6 @@ void FEComponentTransfer::apply()
pixelArray->set(pixelOffset + channel, tables[channel][c]);
}
}
-
- resultImage()->putUnmultipliedImageData(imageData.get(), IntRect(IntPoint(), resultImage()->size()), IntPoint());
}
void FEComponentTransfer::dump()
diff --git a/WebCore/platform/graphics/filters/FEComposite.cpp b/WebCore/platform/graphics/filters/FEComposite.cpp
index d27321f..5ecd69b 100644
--- a/WebCore/platform/graphics/filters/FEComposite.cpp
+++ b/WebCore/platform/graphics/filters/FEComposite.cpp
@@ -97,23 +97,66 @@ void FEComposite::setK4(float k4)
m_k4 = k4;
}
-inline void arithmetic(const ByteArray* srcPixelArrayA, ByteArray* srcPixelArrayB,
+template <int b1, int b2, int b3, int b4>
+inline void computeArithmeticPixels(unsigned char* source, unsigned char* destination, int pixelArrayLength,
+ float k1, float k2, float k3, float k4)
+{
+ float scaledK4;
+ float scaledK1;
+ if (b1)
+ scaledK1 = k1 / 255.f;
+ if (b4)
+ scaledK4 = k4 * 255.f;
+
+ while (--pixelArrayLength >= 0) {
+ unsigned char i1 = *source;
+ unsigned char i2 = *destination;
+ float result = 0;
+ if (b1)
+ result += scaledK1 * i1 * i2;
+ if (b2)
+ result += k2 * i1;
+ if (b3)
+ result += k3 * i2;
+ if (b4)
+ result += scaledK4;
+
+ if (result <= 0)
+ *destination = 0;
+ else if (result >= 255)
+ *destination = 255;
+ else
+ *destination = result;
+ ++source;
+ ++destination;
+ }
+}
+
+inline void arithmetic(ByteArray* srcPixelArrayA, ByteArray* srcPixelArrayB,
float k1, float k2, float k3, float k4)
{
- float scaledK1 = k1 / 255.f;
- float scaledK4 = k4 * 255.f;
- unsigned pixelArrayLength = srcPixelArrayA->length();
- for (unsigned pixelOffset = 0; pixelOffset < pixelArrayLength; pixelOffset += 4) {
- for (unsigned channel = 0; channel < 4; ++channel) {
- unsigned char i1 = srcPixelArrayA->get(pixelOffset + channel);
- unsigned char i2 = srcPixelArrayB->get(pixelOffset + channel);
+ int pixelArrayLength = srcPixelArrayA->length();
+ ASSERT(pixelArrayLength == static_cast<int>(srcPixelArrayB->length()));
+ unsigned char* source = srcPixelArrayA->data();
+ unsigned char* destination = srcPixelArrayB->data();
- double result = scaledK1 * i1 * i2 + k2 * i1 + k3 * i2 + scaledK4;
- srcPixelArrayB->set(pixelOffset + channel, result);
+ if (!k4) {
+ if (!k1) {
+ computeArithmeticPixels<0, 1, 1, 0>(source, destination, pixelArrayLength, k1, k2, k3, k4);
+ return;
}
+
+ computeArithmeticPixels<1, 1, 1, 0>(source, destination, pixelArrayLength, k1, k2, k3, k4);
+ return;
+ }
+
+ if (!k1) {
+ computeArithmeticPixels<0, 1, 1, 1>(source, destination, pixelArrayLength, k1, k2, k3, k4);
+ return;
}
+ computeArithmeticPixels<1, 1, 1, 1>(source, destination, pixelArrayLength, k1, k2, k3, k4);
}
-
+
void FEComposite::determineAbsolutePaintRect()
{
switch (m_type) {
@@ -137,53 +180,58 @@ void FEComposite::determineAbsolutePaintRect()
void FEComposite::apply()
{
+ if (hasResult())
+ return;
FilterEffect* in = inputEffect(0);
FilterEffect* in2 = inputEffect(1);
in->apply();
in2->apply();
- if (!in->resultImage() || !in2->resultImage())
+ if (!in->hasResult() || !in2->hasResult())
return;
- GraphicsContext* filterContext = effectContext();
- if (!filterContext)
+ if (m_type == FECOMPOSITE_OPERATOR_ARITHMETIC) {
+ ImageData* resultImage = createPremultipliedImageResult();
+ if (!resultImage)
+ return;
+
+ IntRect effectADrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
+ RefPtr<ImageData> srcImageData = in->asPremultipliedImage(effectADrawingRect);
+
+ IntRect effectBDrawingRect = requestedRegionOfInputImageData(in2->absolutePaintRect());
+ in2->copyPremultipliedImage(resultImage, effectBDrawingRect);
+
+ arithmetic(srcImageData->data()->data(), resultImage->data()->data(), m_k1, m_k2, m_k3, m_k4);
+ return;
+ }
+
+ ImageBuffer* resultImage = createImageBufferResult();
+ if (!resultImage)
return;
+ GraphicsContext* filterContext = resultImage->context();
FloatRect srcRect = FloatRect(0, 0, -1, -1);
switch (m_type) {
case FECOMPOSITE_OPERATOR_OVER:
- filterContext->drawImageBuffer(in2->resultImage(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in2->absolutePaintRect()));
- filterContext->drawImageBuffer(in->resultImage(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in->absolutePaintRect()));
+ filterContext->drawImageBuffer(in2->asImageBuffer(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in2->absolutePaintRect()));
+ filterContext->drawImageBuffer(in->asImageBuffer(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in->absolutePaintRect()));
break;
case FECOMPOSITE_OPERATOR_IN:
filterContext->save();
- filterContext->clipToImageBuffer(in2->resultImage(), drawingRegionOfInputImage(in2->absolutePaintRect()));
- filterContext->drawImageBuffer(in->resultImage(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in->absolutePaintRect()));
+ filterContext->clipToImageBuffer(in2->asImageBuffer(), drawingRegionOfInputImage(in2->absolutePaintRect()));
+ filterContext->drawImageBuffer(in->asImageBuffer(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in->absolutePaintRect()));
filterContext->restore();
break;
case FECOMPOSITE_OPERATOR_OUT:
- filterContext->drawImageBuffer(in->resultImage(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in->absolutePaintRect()));
- filterContext->drawImageBuffer(in2->resultImage(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in2->absolutePaintRect()), srcRect, CompositeDestinationOut);
+ filterContext->drawImageBuffer(in->asImageBuffer(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in->absolutePaintRect()));
+ filterContext->drawImageBuffer(in2->asImageBuffer(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in2->absolutePaintRect()), srcRect, CompositeDestinationOut);
break;
case FECOMPOSITE_OPERATOR_ATOP:
- filterContext->drawImageBuffer(in2->resultImage(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in2->absolutePaintRect()));
- filterContext->drawImageBuffer(in->resultImage(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in->absolutePaintRect()), srcRect, CompositeSourceAtop);
+ filterContext->drawImageBuffer(in2->asImageBuffer(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in2->absolutePaintRect()));
+ filterContext->drawImageBuffer(in->asImageBuffer(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in->absolutePaintRect()), srcRect, CompositeSourceAtop);
break;
case FECOMPOSITE_OPERATOR_XOR:
- filterContext->drawImageBuffer(in2->resultImage(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in2->absolutePaintRect()));
- filterContext->drawImageBuffer(in->resultImage(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in->absolutePaintRect()), srcRect, CompositeXOR);
- break;
- case FECOMPOSITE_OPERATOR_ARITHMETIC: {
- IntRect effectADrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
- RefPtr<ImageData> srcImageData = in->resultImage()->getPremultipliedImageData(effectADrawingRect);
- ByteArray* srcPixelArrayA = srcImageData->data()->data();
-
- IntRect effectBDrawingRect = requestedRegionOfInputImageData(in2->absolutePaintRect());
- RefPtr<ImageData> imageData = in2->resultImage()->getPremultipliedImageData(effectBDrawingRect);
- ByteArray* srcPixelArrayB = imageData->data()->data();
-
- arithmetic(srcPixelArrayA, srcPixelArrayB, m_k1, m_k2, m_k3, m_k4);
- resultImage()->putPremultipliedImageData(imageData.get(), IntRect(IntPoint(), resultImage()->size()), IntPoint());
- }
+ filterContext->drawImageBuffer(in2->asImageBuffer(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in2->absolutePaintRect()));
+ filterContext->drawImageBuffer(in->asImageBuffer(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in->absolutePaintRect()), srcRect, CompositeXOR);
break;
default:
break;
diff --git a/WebCore/platform/graphics/filters/FEConvolveMatrix.cpp b/WebCore/platform/graphics/filters/FEConvolveMatrix.cpp
index 198d764..d1f9c7b 100644
--- a/WebCore/platform/graphics/filters/FEConvolveMatrix.cpp
+++ b/WebCore/platform/graphics/filters/FEConvolveMatrix.cpp
@@ -372,35 +372,40 @@ ALWAYS_INLINE void FEConvolveMatrix::setOuterPixels(PaintingData& paintingData,
void FEConvolveMatrix::apply()
{
+ if (hasResult())
+ return;
FilterEffect* in = inputEffect(0);
in->apply();
- if (!in->resultImage())
+ if (!in->hasResult())
return;
- if (!effectContext())
+ ImageData* resultImage;
+ if (m_preserveAlpha)
+ resultImage = createUnmultipliedImageResult();
+ else
+ resultImage = createPremultipliedImageResult();
+ if (!resultImage)
return;
- IntRect imageRect(IntPoint(), resultImage()->size());
IntRect effectDrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
RefPtr<CanvasPixelArray> srcPixelArray;
if (m_preserveAlpha)
- srcPixelArray = in->resultImage()->getUnmultipliedImageData(effectDrawingRect)->data();
+ srcPixelArray = in->asUnmultipliedImage(effectDrawingRect)->data();
else
- srcPixelArray = in->resultImage()->getPremultipliedImageData(effectDrawingRect)->data();
-
- RefPtr<ImageData> imageData = ImageData::create(imageRect.width(), imageRect.height());
+ srcPixelArray = in->asPremultipliedImage(effectDrawingRect)->data();
+ IntSize paintSize = absolutePaintRect().size();
PaintingData paintingData;
paintingData.srcPixelArray = srcPixelArray.get();
- paintingData.dstPixelArray = imageData->data();
- paintingData.width = imageRect.width();
- paintingData.height = imageRect.height();
+ paintingData.dstPixelArray = resultImage->data();
+ paintingData.width = paintSize.width();
+ paintingData.height = paintSize.height();
paintingData.bias = m_bias * 255;
// Drawing fully covered pixels
- int clipRight = imageRect.width() - m_kernelSize.width();
- int clipBottom = imageRect.height() - m_kernelSize.height();
+ int clipRight = paintSize.width() - m_kernelSize.width();
+ int clipBottom = paintSize.height() - m_kernelSize.height();
if (clipRight >= 0 && clipBottom >= 0) {
setInteriorPixels(paintingData, clipRight, clipBottom);
@@ -408,22 +413,17 @@ void FEConvolveMatrix::apply()
clipRight += m_targetOffset.x() + 1;
clipBottom += m_targetOffset.y() + 1;
if (m_targetOffset.y() > 0)
- setOuterPixels(paintingData, 0, 0, imageRect.width(), m_targetOffset.y());
- if (clipBottom < imageRect.height())
- setOuterPixels(paintingData, 0, clipBottom, imageRect.width(), imageRect.height());
+ setOuterPixels(paintingData, 0, 0, paintSize.width(), m_targetOffset.y());
+ if (clipBottom < paintSize.height())
+ setOuterPixels(paintingData, 0, clipBottom, paintSize.width(), paintSize.height());
if (m_targetOffset.x() > 0)
setOuterPixels(paintingData, 0, m_targetOffset.y(), m_targetOffset.x(), clipBottom);
- if (clipRight < imageRect.width())
- setOuterPixels(paintingData, clipRight, m_targetOffset.y(), imageRect.width(), clipBottom);
+ if (clipRight < paintSize.width())
+ setOuterPixels(paintingData, clipRight, m_targetOffset.y(), paintSize.width(), clipBottom);
} else {
// Rare situation, not optimizied for speed
- setOuterPixels(paintingData, 0, 0, imageRect.width(), imageRect.height());
+ setOuterPixels(paintingData, 0, 0, paintSize.width(), paintSize.height());
}
-
- if (m_preserveAlpha)
- resultImage()->putUnmultipliedImageData(imageData.get(), imageRect, IntPoint());
- else
- resultImage()->putPremultipliedImageData(imageData.get(), imageRect, IntPoint());
}
void FEConvolveMatrix::dump()
diff --git a/WebCore/platform/graphics/filters/FEDisplacementMap.cpp b/WebCore/platform/graphics/filters/FEDisplacementMap.cpp
index 55321e6..93239c4 100644
--- a/WebCore/platform/graphics/filters/FEDisplacementMap.cpp
+++ b/WebCore/platform/graphics/filters/FEDisplacementMap.cpp
@@ -78,57 +78,57 @@ void FEDisplacementMap::setScale(float scale)
void FEDisplacementMap::apply()
{
+ if (hasResult())
+ return;
FilterEffect* in = inputEffect(0);
FilterEffect* in2 = inputEffect(1);
in->apply();
in2->apply();
- if (!in->resultImage() || !in2->resultImage())
+ if (!in->hasResult() || !in2->hasResult())
return;
if (m_xChannelSelector == CHANNEL_UNKNOWN || m_yChannelSelector == CHANNEL_UNKNOWN)
return;
- if (!effectContext())
+ ImageData* resultImage = createPremultipliedImageResult();
+ if (!resultImage)
return;
IntRect effectADrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
- RefPtr<ImageData> srcImageDataA = in->resultImage()->getPremultipliedImageData(effectADrawingRect);
- ByteArray* srcPixelArrayA = srcImageDataA->data()->data() ;
+ RefPtr<ImageData> srcImageDataA = in->asPremultipliedImage(effectADrawingRect);
+ ByteArray* srcPixelArrayA = srcImageDataA->data()->data();
IntRect effectBDrawingRect = requestedRegionOfInputImageData(in2->absolutePaintRect());
- RefPtr<ImageData> srcImageDataB = in2->resultImage()->getUnmultipliedImageData(effectBDrawingRect);
+ RefPtr<ImageData> srcImageDataB = in2->asUnmultipliedImage(effectBDrawingRect);
ByteArray* srcPixelArrayB = srcImageDataB->data()->data();
- IntRect imageRect(IntPoint(), resultImage()->size());
- RefPtr<ImageData> imageData = ImageData::create(imageRect.width(), imageRect.height());
- ByteArray* dstPixelArray = imageData->data()->data();
+ ByteArray* dstPixelArray = resultImage->data()->data();
ASSERT(srcPixelArrayA->length() == srcPixelArrayB->length());
Filter* filter = this->filter();
+ IntSize paintSize = absolutePaintRect().size();
float scaleX = filter->applyHorizontalScale(m_scale / 255);
float scaleY = filter->applyVerticalScale(m_scale / 255);
float scaleAdjustmentX = filter->applyHorizontalScale(0.5f - 0.5f * m_scale);
float scaleAdjustmentY = filter->applyVerticalScale(0.5f - 0.5f * m_scale);
- int stride = imageRect.width() * 4;
- for (int y = 0; y < imageRect.height(); ++y) {
+ int stride = paintSize.width() * 4;
+ for (int y = 0; y < paintSize.height(); ++y) {
int line = y * stride;
- for (int x = 0; x < imageRect.width(); ++x) {
+ for (int x = 0; x < paintSize.width(); ++x) {
int dstIndex = line + x * 4;
int srcX = x + static_cast<int>(scaleX * srcPixelArrayB->get(dstIndex + m_xChannelSelector - 1) + scaleAdjustmentX);
int srcY = y + static_cast<int>(scaleY * srcPixelArrayB->get(dstIndex + m_yChannelSelector - 1) + scaleAdjustmentY);
for (unsigned channel = 0; channel < 4; ++channel) {
- if (srcX < 0 || srcX >= imageRect.width() || srcY < 0 || srcY >= imageRect.height())
+ if (srcX < 0 || srcX >= paintSize.width() || srcY < 0 || srcY >= paintSize.height())
dstPixelArray->set(dstIndex + channel, static_cast<unsigned char>(0));
else {
unsigned char pixelValue = srcPixelArrayA->get(srcY * stride + srcX * 4 + channel);
dstPixelArray->set(dstIndex + channel, pixelValue);
}
}
-
}
}
- resultImage()->putPremultipliedImageData(imageData.get(), imageRect, IntPoint());
}
void FEDisplacementMap::dump()
diff --git a/WebCore/platform/graphics/filters/FEFlood.cpp b/WebCore/platform/graphics/filters/FEFlood.cpp
index bc6721b..8bfdef8 100644
--- a/WebCore/platform/graphics/filters/FEFlood.cpp
+++ b/WebCore/platform/graphics/filters/FEFlood.cpp
@@ -64,12 +64,14 @@ void FEFlood::setFloodOpacity(float floodOpacity)
void FEFlood::apply()
{
- GraphicsContext* filterContext = effectContext();
- if (!filterContext)
+ if (hasResult())
+ return;
+ ImageBuffer* resultImage = createImageBufferResult();
+ if (!resultImage)
return;
Color color = colorWithOverrideAlpha(floodColor().rgb(), floodOpacity());
- filterContext->fillRect(FloatRect(FloatPoint(), absolutePaintRect().size()), color, ColorSpaceDeviceRGB);
+ resultImage->context()->fillRect(FloatRect(FloatPoint(), absolutePaintRect().size()), color, ColorSpaceDeviceRGB);
}
void FEFlood::dump()
diff --git a/WebCore/platform/graphics/filters/FEGaussianBlur.cpp b/WebCore/platform/graphics/filters/FEGaussianBlur.cpp
index 876e4b3..e1ffcb7 100644
--- a/WebCore/platform/graphics/filters/FEGaussianBlur.cpp
+++ b/WebCore/platform/graphics/filters/FEGaussianBlur.cpp
@@ -164,34 +164,35 @@ void FEGaussianBlur::determineAbsolutePaintRect()
void FEGaussianBlur::apply()
{
+ if (hasResult())
+ return;
FilterEffect* in = inputEffect(0);
in->apply();
- if (!in->resultImage())
+ if (!in->hasResult())
return;
- if (!effectContext())
+ ImageData* resultImage = createPremultipliedImageResult();
+ if (!resultImage)
return;
setIsAlphaImage(in->isAlphaImage());
IntRect effectDrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
- RefPtr<ImageData> srcImageData = in->resultImage()->getPremultipliedImageData(effectDrawingRect);
- IntRect imageRect(IntPoint(), resultImage()->size());
+ in->copyPremultipliedImage(resultImage, effectDrawingRect);
- if (!m_stdX && !m_stdY) {
- resultImage()->putPremultipliedImageData(srcImageData.get(), imageRect, IntPoint());
+ if (!m_stdX && !m_stdY)
return;
- }
unsigned kernelSizeX = 0;
unsigned kernelSizeY = 0;
calculateKernelSize(filter(), kernelSizeX, kernelSizeY, m_stdX, m_stdY);
- ByteArray* srcPixelArray = srcImageData->data()->data();
- RefPtr<ImageData> tmpImageData = ImageData::create(imageRect.width(), imageRect.height());
+ IntSize paintSize = absolutePaintRect().size();
+ ByteArray* srcPixelArray = resultImage->data()->data();
+ RefPtr<ImageData> tmpImageData = ImageData::create(paintSize.width(), paintSize.height());
ByteArray* tmpPixelArray = tmpImageData->data()->data();
- int stride = 4 * imageRect.width();
+ int stride = 4 * paintSize.width();
int dxLeft = 0;
int dxRight = 0;
int dyLeft = 0;
@@ -199,7 +200,7 @@ void FEGaussianBlur::apply()
for (int i = 0; i < 3; ++i) {
if (kernelSizeX) {
kernelPosition(i, kernelSizeX, dxLeft, dxRight);
- boxBlur(srcPixelArray, tmpPixelArray, kernelSizeX, dxLeft, dxRight, 4, stride, imageRect.width(), imageRect.height(), isAlphaImage());
+ boxBlur(srcPixelArray, tmpPixelArray, kernelSizeX, dxLeft, dxRight, 4, stride, paintSize.width(), paintSize.height(), isAlphaImage());
} else {
ByteArray* auxPixelArray = tmpPixelArray;
tmpPixelArray = srcPixelArray;
@@ -208,15 +209,13 @@ void FEGaussianBlur::apply()
if (kernelSizeY) {
kernelPosition(i, kernelSizeY, dyLeft, dyRight);
- boxBlur(tmpPixelArray, srcPixelArray, kernelSizeY, dyLeft, dyRight, stride, 4, imageRect.height(), imageRect.width(), isAlphaImage());
+ boxBlur(tmpPixelArray, srcPixelArray, kernelSizeY, dyLeft, dyRight, stride, 4, paintSize.height(), paintSize.width(), isAlphaImage());
} else {
ByteArray* auxPixelArray = tmpPixelArray;
tmpPixelArray = srcPixelArray;
srcPixelArray = auxPixelArray;
}
}
-
- resultImage()->putPremultipliedImageData(srcImageData.get(), imageRect, IntPoint());
}
void FEGaussianBlur::dump()
diff --git a/WebCore/platform/graphics/filters/FELighting.cpp b/WebCore/platform/graphics/filters/FELighting.cpp
index 812920c..4db40f1 100644
--- a/WebCore/platform/graphics/filters/FELighting.cpp
+++ b/WebCore/platform/graphics/filters/FELighting.cpp
@@ -331,19 +331,22 @@ bool FELighting::drawLighting(ByteArray* pixels, int width, int height)
void FELighting::apply()
{
+ if (hasResult())
+ return;
FilterEffect* in = inputEffect(0);
in->apply();
- if (!in->resultImage())
+ if (!in->hasResult())
return;
- if (!effectContext())
+ ImageData* resultImage = createUnmultipliedImageResult();
+ if (!resultImage)
return;
setIsAlphaImage(false);
IntRect effectDrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
- RefPtr<ImageData> srcImageData = in->resultImage()->getUnmultipliedImageData(effectDrawingRect);
- ByteArray* srcPixelArray = srcImageData->data()->data();
+ in->copyUnmultipliedImage(resultImage, effectDrawingRect);
+ ByteArray* srcPixelArray = resultImage->data()->data();
// FIXME: support kernelUnitLengths other than (1,1). The issue here is that the W3
// standard has no test case for them, and other browsers (like Firefox) has strange
@@ -351,8 +354,7 @@ void FELighting::apply()
// Anyway, feConvolveMatrix should also use the implementation
IntSize absolutePaintSize = absolutePaintRect().size();
- if (drawLighting(srcPixelArray, absolutePaintSize.width(), absolutePaintSize.height()))
- resultImage()->putUnmultipliedImageData(srcImageData.get(), IntRect(IntPoint(), absolutePaintSize), IntPoint());
+ drawLighting(srcPixelArray, absolutePaintSize.width(), absolutePaintSize.height());
}
} // namespace WebCore
diff --git a/WebCore/platform/graphics/filters/FEMerge.cpp b/WebCore/platform/graphics/filters/FEMerge.cpp
index ca53a86..4395321 100644
--- a/WebCore/platform/graphics/filters/FEMerge.cpp
+++ b/WebCore/platform/graphics/filters/FEMerge.cpp
@@ -41,22 +41,25 @@ PassRefPtr<FEMerge> FEMerge::create(Filter* filter)
void FEMerge::apply()
{
+ if (hasResult())
+ return;
unsigned size = numberOfEffectInputs();
ASSERT(size > 0);
for (unsigned i = 0; i < size; ++i) {
FilterEffect* in = inputEffect(i);
in->apply();
- if (!in->resultImage())
+ if (!in->hasResult())
return;
}
- GraphicsContext* filterContext = effectContext();
- if (!filterContext)
+ ImageBuffer* resultImage = createImageBufferResult();
+ if (!resultImage)
return;
+ GraphicsContext* filterContext = resultImage->context();
for (unsigned i = 0; i < size; ++i) {
FilterEffect* in = inputEffect(i);
- filterContext->drawImageBuffer(in->resultImage(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in->absolutePaintRect()));
+ filterContext->drawImageBuffer(in->asImageBuffer(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in->absolutePaintRect()));
}
}
diff --git a/WebCore/platform/graphics/filters/FEMerge.h b/WebCore/platform/graphics/filters/FEMerge.h
index 24d071e..dbee610 100644
--- a/WebCore/platform/graphics/filters/FEMerge.h
+++ b/WebCore/platform/graphics/filters/FEMerge.h
@@ -20,7 +20,7 @@
*/
#ifndef FEMerge_h
-#define EMerge_h
+#define FEMerge_h
#if ENABLE(FILTERS)
#include "FilterEffect.h"
diff --git a/WebCore/platform/graphics/filters/FEMorphology.cpp b/WebCore/platform/graphics/filters/FEMorphology.cpp
index dd7659a..b20adc5 100644
--- a/WebCore/platform/graphics/filters/FEMorphology.cpp
+++ b/WebCore/platform/graphics/filters/FEMorphology.cpp
@@ -91,12 +91,15 @@ void FEMorphology::setRadiusY(float radiusY)
void FEMorphology::apply()
{
+ if (hasResult())
+ return;
FilterEffect* in = inputEffect(0);
in->apply();
- if (!in->resultImage())
+ if (!in->hasResult())
return;
- if (!effectContext())
+ ImageData* resultImage = createPremultipliedImageResult();
+ if (!resultImage)
return;
setIsAlphaImage(in->isAlphaImage());
@@ -107,12 +110,10 @@ void FEMorphology::apply()
int radiusX = static_cast<int>(floorf(filter->applyHorizontalScale(m_radiusX)));
int radiusY = static_cast<int>(floorf(filter->applyVerticalScale(m_radiusY)));
- IntRect imageRect(IntPoint(), resultImage()->size());
IntRect effectDrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
- RefPtr<ImageData> srcImageData = in->resultImage()->getPremultipliedImageData(effectDrawingRect);
+ RefPtr<ImageData> srcImageData = in->asPremultipliedImage(effectDrawingRect);
ByteArray* srcPixelArray = srcImageData->data()->data();
- RefPtr<ImageData> imageData = ImageData::create(imageRect.width(), imageRect.height());
- ByteArray* dstPixelArray = imageData->data()->data();
+ ByteArray* dstPixelArray = resultImage->data()->data();
int effectWidth = effectDrawingRect.width() * 4;
@@ -162,7 +163,6 @@ void FEMorphology::apply()
}
}
}
- resultImage()->putPremultipliedImageData(imageData.get(), imageRect, IntPoint());
}
void FEMorphology::dump()
diff --git a/WebCore/platform/graphics/filters/FEOffset.cpp b/WebCore/platform/graphics/filters/FEOffset.cpp
index b640054..f1d5914 100644
--- a/WebCore/platform/graphics/filters/FEOffset.cpp
+++ b/WebCore/platform/graphics/filters/FEOffset.cpp
@@ -74,13 +74,15 @@ void FEOffset::determineAbsolutePaintRect()
void FEOffset::apply()
{
+ if (hasResult())
+ return;
FilterEffect* in = inputEffect(0);
in->apply();
- if (!in->resultImage())
+ if (!in->hasResult())
return;
- GraphicsContext* filterContext = effectContext();
- if (!filterContext)
+ ImageBuffer* resultImage = createImageBufferResult();
+ if (!resultImage)
return;
setIsAlphaImage(in->isAlphaImage());
@@ -88,7 +90,7 @@ void FEOffset::apply()
FloatRect drawingRegion = drawingRegionOfInputImage(in->absolutePaintRect());
Filter* filter = this->filter();
drawingRegion.move(filter->applyHorizontalScale(m_dx), filter->applyVerticalScale(m_dy));
- filterContext->drawImageBuffer(in->resultImage(), ColorSpaceDeviceRGB, drawingRegion);
+ resultImage->context()->drawImageBuffer(in->asImageBuffer(), ColorSpaceDeviceRGB, drawingRegion);
}
void FEOffset::dump()
diff --git a/WebCore/platform/graphics/filters/FETile.cpp b/WebCore/platform/graphics/filters/FETile.cpp
index 6b11401..e516c7e 100644
--- a/WebCore/platform/graphics/filters/FETile.cpp
+++ b/WebCore/platform/graphics/filters/FETile.cpp
@@ -45,13 +45,15 @@ void FETile::apply()
{
// FIXME: See bug 47315. This is a hack to work around a compile failure, but is incorrect behavior otherwise.
#if ENABLE(SVG)
+ if (hasResult())
+ return;
FilterEffect* in = inputEffect(0);
in->apply();
- if (!in->resultImage())
+ if (!in->hasResult())
return;
- GraphicsContext* filterContext = effectContext();
- if (!filterContext)
+ ImageBuffer* resultImage = createImageBufferResult();
+ if (!resultImage)
return;
setIsAlphaImage(in->isAlphaImage());
@@ -73,13 +75,14 @@ void FETile::apply()
GraphicsContext* tileImageContext = tileImage->context();
tileImageContext->translate(-inMaxEffectLocation.x(), -inMaxEffectLocation.y());
- tileImageContext->drawImageBuffer(in->resultImage(), ColorSpaceDeviceRGB, in->absolutePaintRect().location());
+ tileImageContext->drawImageBuffer(in->asImageBuffer(), ColorSpaceDeviceRGB, in->absolutePaintRect().location());
RefPtr<Pattern> pattern = Pattern::create(tileImage->copyImage(), true, true);
AffineTransform patternTransform;
patternTransform.translate(inMaxEffectLocation.x() - maxEffectLocation.x(), inMaxEffectLocation.y() - maxEffectLocation.y());
pattern->setPatternSpaceTransform(patternTransform);
+ GraphicsContext* filterContext = resultImage->context();
filterContext->setFillPattern(pattern);
filterContext->fillRect(FloatRect(FloatPoint(), absolutePaintRect().size()));
#endif
diff --git a/WebCore/platform/graphics/filters/FETurbulence.cpp b/WebCore/platform/graphics/filters/FETurbulence.cpp
index 8914db7..becf784 100644
--- a/WebCore/platform/graphics/filters/FETurbulence.cpp
+++ b/WebCore/platform/graphics/filters/FETurbulence.cpp
@@ -320,15 +320,16 @@ unsigned char FETurbulence::calculateTurbulenceValueForPoint(PaintingData& paint
void FETurbulence::apply()
{
- if (!effectContext())
+ if (hasResult())
+ return;
+ ImageData* resultImage = createUnmultipliedImageResult();
+ if (!resultImage)
return;
- IntRect imageRect(IntPoint(), resultImage()->size());
- if (!imageRect.size().width() || !imageRect.size().height())
+ if (absolutePaintRect().isEmpty())
return;
- RefPtr<ImageData> imageData = ImageData::create(imageRect.width(), imageRect.height());
- ByteArray* pixelArray = imageData->data()->data();
+ ByteArray* pixelArray = resultImage->data()->data();
PaintingData paintingData(m_seed, roundedIntSize(filterPrimitiveSubregion().size()));
initPaint(paintingData);
@@ -336,16 +337,15 @@ void FETurbulence::apply()
FloatPoint point;
point.setY(filterRegion.y());
int indexOfPixelChannel = 0;
- for (int y = 0; y < imageRect.height(); ++y) {
+ for (int y = 0; y < absolutePaintRect().height(); ++y) {
point.setY(point.y() + 1);
point.setX(filterRegion.x());
- for (int x = 0; x < imageRect.width(); ++x) {
+ for (int x = 0; x < absolutePaintRect().width(); ++x) {
point.setX(point.x() + 1);
for (paintingData.channel = 0; paintingData.channel < 4; ++paintingData.channel, ++indexOfPixelChannel)
pixelArray->set(indexOfPixelChannel, calculateTurbulenceValueForPoint(paintingData, filter()->mapAbsolutePointToLocalPoint(point)));
}
}
- resultImage()->putUnmultipliedImageData(imageData.get(), imageRect, IntPoint());
}
void FETurbulence::dump()
diff --git a/WebCore/platform/graphics/filters/FilterEffect.cpp b/WebCore/platform/graphics/filters/FilterEffect.cpp
index c228731..ebc6af0 100644
--- a/WebCore/platform/graphics/filters/FilterEffect.cpp
+++ b/WebCore/platform/graphics/filters/FilterEffect.cpp
@@ -23,6 +23,7 @@
#if ENABLE(FILTERS)
#include "FilterEffect.h"
+#include "ImageData.h"
namespace WebCore {
@@ -54,10 +55,10 @@ void FilterEffect::determineAbsolutePaintRect()
IntRect FilterEffect::requestedRegionOfInputImageData(const IntRect& effectRect) const
{
- ASSERT(m_effectBuffer);
+ ASSERT(hasResult());
IntPoint location = m_absolutePaintRect.location();
location.move(-effectRect.x(), -effectRect.y());
- return IntRect(location, m_effectBuffer->size());
+ return IntRect(location, m_absolutePaintRect.size());
}
IntRect FilterEffect::drawingRegionOfInputImage(const IntRect& srcRect) const
@@ -72,15 +73,170 @@ FilterEffect* FilterEffect::inputEffect(unsigned number) const
return m_inputEffects.at(number).get();
}
-GraphicsContext* FilterEffect::effectContext()
+ImageBuffer* FilterEffect::asImageBuffer()
{
+ if (!hasResult())
+ return 0;
+ if (m_imageBufferResult)
+ return m_imageBufferResult.get();
+ m_imageBufferResult = ImageBuffer::create(m_absolutePaintRect.size(), ColorSpaceLinearRGB);
+ IntRect destinationRect(IntPoint(), m_absolutePaintRect.size());
+ if (m_premultipliedImageResult)
+ m_imageBufferResult->putPremultipliedImageData(m_premultipliedImageResult.get(), destinationRect, IntPoint());
+ else
+ m_imageBufferResult->putUnmultipliedImageData(m_unmultipliedImageResult.get(), destinationRect, IntPoint());
+ return m_imageBufferResult.get();
+}
+
+PassRefPtr<ImageData> FilterEffect::asUnmultipliedImage(const IntRect& rect)
+{
+ RefPtr<ImageData> imageData = ImageData::create(rect.width(), rect.height());
+ copyUnmultipliedImage(imageData.get(), rect);
+ return imageData.release();
+}
+
+PassRefPtr<ImageData> FilterEffect::asPremultipliedImage(const IntRect& rect)
+{
+ RefPtr<ImageData> imageData = ImageData::create(rect.width(), rect.height());
+ copyPremultipliedImage(imageData.get(), rect);
+ return imageData.release();
+}
+
+inline void FilterEffect::copyImageBytes(ImageData* source, ImageData* destination, const IntRect& rect)
+{
+ // Copy the necessary lines.
+ ASSERT(IntSize(destination->width(), destination->height()) == rect.size());
+ if (rect.x() < 0 || rect.y() < 0 || rect.bottom() > m_absolutePaintRect.width() || rect.bottom() > m_absolutePaintRect.height())
+ memset(destination->data()->data()->data(), 0, destination->data()->length());
+
+ int xOrigin = rect.x();
+ int xDest = 0;
+ if (xOrigin < 0) {
+ xDest = -xOrigin;
+ xOrigin = 0;
+ }
+ int xEnd = rect.right();
+ if (xEnd > m_absolutePaintRect.width())
+ xEnd = m_absolutePaintRect.width();
+
+ int yOrigin = rect.y();
+ int yDest = 0;
+ if (yOrigin < 0) {
+ yDest = -yOrigin;
+ yOrigin = 0;
+ }
+ int yEnd = rect.bottom();
+ if (yEnd > m_absolutePaintRect.height())
+ yEnd = m_absolutePaintRect.height();
+
+ int size = (xEnd - xOrigin) * 4;
+ int destinationScanline = rect.width() * 4;
+ int sourceScanline = m_absolutePaintRect.width() * 4;
+ unsigned char *destinationPixel = destination->data()->data()->data() + ((yDest * rect.width()) + xDest) * 4;
+ unsigned char *sourcePixel = source->data()->data()->data() + ((yOrigin * m_absolutePaintRect.width()) + xOrigin) * 4;
+
+ while (yOrigin < yEnd) {
+ memcpy(destinationPixel, sourcePixel, size);
+ destinationPixel += destinationScanline;
+ sourcePixel += sourceScanline;
+ ++yOrigin;
+ }
+}
+
+void FilterEffect::copyUnmultipliedImage(ImageData* destination, const IntRect& rect)
+{
+ ASSERT(hasResult());
+
+ if (!m_unmultipliedImageResult) {
+ // We prefer a conversion from the image buffer.
+ if (m_imageBufferResult)
+ m_unmultipliedImageResult = m_imageBufferResult->getUnmultipliedImageData(IntRect(IntPoint(), m_absolutePaintRect.size()));
+ else {
+ m_unmultipliedImageResult = ImageData::create(m_absolutePaintRect.width(), m_absolutePaintRect.height());
+ unsigned char* sourceComponent = m_premultipliedImageResult->data()->data()->data();
+ unsigned char* destinationComponent = m_unmultipliedImageResult->data()->data()->data();
+ unsigned char* end = sourceComponent + (m_absolutePaintRect.width() * m_absolutePaintRect.height() * 4);
+ while (sourceComponent < end) {
+ int alpha = sourceComponent[3];
+ if (alpha) {
+ destinationComponent[0] = static_cast<int>(sourceComponent[0]) * 255 / alpha;
+ destinationComponent[1] = static_cast<int>(sourceComponent[1]) * 255 / alpha;
+ destinationComponent[2] = static_cast<int>(sourceComponent[2]) * 255 / alpha;
+ } else {
+ destinationComponent[0] = 0;
+ destinationComponent[1] = 0;
+ destinationComponent[2] = 0;
+ }
+ destinationComponent[3] = alpha;
+ sourceComponent += 4;
+ destinationComponent += 4;
+ }
+ }
+ }
+ copyImageBytes(m_unmultipliedImageResult.get(), destination, rect);
+}
+
+void FilterEffect::copyPremultipliedImage(ImageData* destination, const IntRect& rect)
+{
+ ASSERT(hasResult());
+
+ if (!m_premultipliedImageResult) {
+ // We prefer a conversion from the image buffer.
+ if (m_imageBufferResult)
+ m_premultipliedImageResult = m_imageBufferResult->getPremultipliedImageData(IntRect(IntPoint(), m_absolutePaintRect.size()));
+ else {
+ m_premultipliedImageResult = ImageData::create(m_absolutePaintRect.width(), m_absolutePaintRect.height());
+ unsigned char* sourceComponent = m_unmultipliedImageResult->data()->data()->data();
+ unsigned char* destinationComponent = m_premultipliedImageResult->data()->data()->data();
+ unsigned char* end = sourceComponent + (m_absolutePaintRect.width() * m_absolutePaintRect.height() * 4);
+ while (sourceComponent < end) {
+ int alpha = sourceComponent[3];
+ destinationComponent[0] = static_cast<int>(sourceComponent[0]) * alpha / 255;
+ destinationComponent[1] = static_cast<int>(sourceComponent[1]) * alpha / 255;
+ destinationComponent[2] = static_cast<int>(sourceComponent[2]) * alpha / 255;
+ destinationComponent[3] = alpha;
+ sourceComponent += 4;
+ destinationComponent += 4;
+ }
+ }
+ }
+ copyImageBytes(m_premultipliedImageResult.get(), destination, rect);
+}
+
+ImageBuffer* FilterEffect::createImageBufferResult()
+{
+ // Only one result type is allowed.
+ ASSERT(!hasResult());
+ determineAbsolutePaintRect();
+ if (m_absolutePaintRect.isEmpty())
+ return 0;
+ m_imageBufferResult = ImageBuffer::create(m_absolutePaintRect.size(), ColorSpaceLinearRGB);
+ if (!m_imageBufferResult)
+ return 0;
+ ASSERT(m_imageBufferResult->context());
+ return m_imageBufferResult.get();
+}
+
+ImageData* FilterEffect::createUnmultipliedImageResult()
+{
+ // Only one result type is allowed.
+ ASSERT(!hasResult());
determineAbsolutePaintRect();
if (m_absolutePaintRect.isEmpty())
return 0;
- m_effectBuffer = ImageBuffer::create(m_absolutePaintRect.size(), ColorSpaceLinearRGB);
- if (!m_effectBuffer)
+ m_unmultipliedImageResult = ImageData::create(m_absolutePaintRect.width(), m_absolutePaintRect.height());
+ return m_unmultipliedImageResult.get();
+}
+
+ImageData* FilterEffect::createPremultipliedImageResult()
+{
+ // Only one result type is allowed.
+ ASSERT(!hasResult());
+ determineAbsolutePaintRect();
+ if (m_absolutePaintRect.isEmpty())
return 0;
- return m_effectBuffer->context();
+ m_premultipliedImageResult = ImageData::create(m_absolutePaintRect.width(), m_absolutePaintRect.height());
+ return m_premultipliedImageResult.get();
}
TextStream& FilterEffect::externalRepresentation(TextStream& ts, int) const
diff --git a/WebCore/platform/graphics/filters/FilterEffect.h b/WebCore/platform/graphics/filters/FilterEffect.h
index f9674e2..81d5409 100644
--- a/WebCore/platform/graphics/filters/FilterEffect.h
+++ b/WebCore/platform/graphics/filters/FilterEffect.h
@@ -50,13 +50,12 @@ class FilterEffect : public RefCounted<FilterEffect> {
public:
virtual ~FilterEffect();
- // The result is bounded to the size of the filter primitive to save resources.
- ImageBuffer* resultImage() const { return m_effectBuffer.get(); }
- void setEffectBuffer(PassOwnPtr<ImageBuffer> effectBuffer) { m_effectBuffer = effectBuffer; }
-
- // Creates the ImageBuffer for the current filter primitive result in the size of the
- // repaintRect. Gives back the GraphicsContext of the own ImageBuffer.
- GraphicsContext* effectContext();
+ bool hasResult() const { return m_imageBufferResult || m_unmultipliedImageResult || m_premultipliedImageResult; }
+ ImageBuffer* asImageBuffer();
+ PassRefPtr<ImageData> asUnmultipliedImage(const IntRect&);
+ PassRefPtr<ImageData> asPremultipliedImage(const IntRect&);
+ void copyUnmultipliedImage(ImageData* destination, const IntRect&);
+ void copyPremultipliedImage(ImageData* destination, const IntRect&);
FilterEffectVector& inputEffects() { return m_inputEffects; }
FilterEffect* inputEffect(unsigned) const;
@@ -110,8 +109,14 @@ public:
protected:
FilterEffect(Filter*);
+ ImageBuffer* createImageBufferResult();
+ ImageData* createUnmultipliedImageResult();
+ ImageData* createPremultipliedImageResult();
+
private:
- OwnPtr<ImageBuffer> m_effectBuffer;
+ OwnPtr<ImageBuffer> m_imageBufferResult;
+ RefPtr<ImageData> m_unmultipliedImageResult;
+ RefPtr<ImageData> m_premultipliedImageResult;
FilterEffectVector m_inputEffects;
bool m_alphaImage;
@@ -124,6 +129,8 @@ private:
Filter* m_filter;
private:
+ inline void copyImageBytes(ImageData* source, ImageData* destination, const IntRect&);
+
// The following member variables are SVG specific and will move to RenderSVGResourceFilterPrimitive.
// See bug https://bugs.webkit.org/show_bug.cgi?id=45614.
diff --git a/WebCore/platform/graphics/filters/SourceAlpha.cpp b/WebCore/platform/graphics/filters/SourceAlpha.cpp
index a505b4b..2d2de00 100644
--- a/WebCore/platform/graphics/filters/SourceAlpha.cpp
+++ b/WebCore/platform/graphics/filters/SourceAlpha.cpp
@@ -52,14 +52,17 @@ void SourceAlpha::determineAbsolutePaintRect()
void SourceAlpha::apply()
{
- GraphicsContext* filterContext = effectContext();
+ if (hasResult())
+ return;
+ ImageBuffer* resultImage = createImageBufferResult();
Filter* filter = this->filter();
- if (!filterContext || !filter->sourceImage())
+ if (!resultImage || !filter->sourceImage())
return;
setIsAlphaImage(true);
FloatRect imageRect(FloatPoint(), absolutePaintRect().size());
+ GraphicsContext* filterContext = resultImage->context();
filterContext->save();
filterContext->clipToImageBuffer(filter->sourceImage(), imageRect);
filterContext->fillRect(imageRect, Color::black, ColorSpaceDeviceRGB);
diff --git a/WebCore/platform/graphics/filters/SourceGraphic.cpp b/WebCore/platform/graphics/filters/SourceGraphic.cpp
index 6aac367..04082ad 100644
--- a/WebCore/platform/graphics/filters/SourceGraphic.cpp
+++ b/WebCore/platform/graphics/filters/SourceGraphic.cpp
@@ -51,12 +51,14 @@ void SourceGraphic::determineAbsolutePaintRect()
void SourceGraphic::apply()
{
- GraphicsContext* filterContext = effectContext();
+ if (hasResult())
+ return;
+ ImageBuffer* resultImage = createImageBufferResult();
Filter* filter = this->filter();
- if (!filterContext || !filter->sourceImage())
+ if (!resultImage || !filter->sourceImage())
return;
- filterContext->drawImageBuffer(filter->sourceImage(), ColorSpaceDeviceRGB, IntPoint());
+ resultImage->context()->drawImageBuffer(filter->sourceImage(), ColorSpaceDeviceRGB, IntPoint());
}
void SourceGraphic::dump()
diff --git a/WebCore/platform/graphics/filters/SourceGraphic.h b/WebCore/platform/graphics/filters/SourceGraphic.h
index fa47f12..97d6882 100644
--- a/WebCore/platform/graphics/filters/SourceGraphic.h
+++ b/WebCore/platform/graphics/filters/SourceGraphic.h
@@ -19,7 +19,7 @@
*/
#ifndef SourceGraphic_h
-#define SourceGrahpic_h
+#define SourceGraphic_h
#if ENABLE(FILTERS)
#include "FilterEffect.h"
diff --git a/WebCore/platform/graphics/freetype/FontCacheFreeType.cpp b/WebCore/platform/graphics/freetype/FontCacheFreeType.cpp
index 61ee625..1430124 100644
--- a/WebCore/platform/graphics/freetype/FontCacheFreeType.cpp
+++ b/WebCore/platform/graphics/freetype/FontCacheFreeType.cpp
@@ -181,19 +181,26 @@ FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontD
FcChar8* fontConfigFamilyNameAfterMatching;
FcPatternGetString(resultPattern.get(), FC_FAMILY, 0, &fontConfigFamilyNameAfterMatching);
String familyNameAfterMatching = String::fromUTF8(reinterpret_cast<char*>(fontConfigFamilyNameAfterMatching));
- if (equalIgnoringCase(familyNameAfterConfiguration, familyNameAfterMatching))
- return new FontPlatformData(resultPattern.get(), fontDescription);
// If Fontconfig gave use a different font family than the one we requested, we should ignore it
// and allow WebCore to give us the next font on the CSS fallback list. The only exception is if
// this family name is a commonly used generic family.
- if (equalIgnoringCase(familyNameString, "sans") || equalIgnoringCase(familyNameString, "sans-serif")
- || equalIgnoringCase(familyNameString, "serif") || equalIgnoringCase(familyNameString, "monospace")
- || equalIgnoringCase(familyNameString, "fantasy") || equalIgnoringCase(familyNameString, "cursive"))
- return new FontPlatformData(resultPattern.get(), fontDescription);
+ if (!equalIgnoringCase(familyNameAfterConfiguration, familyNameAfterMatching)
+ && !(equalIgnoringCase(familyNameString, "sans") || equalIgnoringCase(familyNameString, "sans-serif")
+ || equalIgnoringCase(familyNameString, "serif") || equalIgnoringCase(familyNameString, "monospace")
+ || equalIgnoringCase(familyNameString, "fantasy") || equalIgnoringCase(familyNameString, "cursive")))
+ return 0;
- // Fontconfig did not return a good match.
- return 0;
+ // Verify that this font has an encoding compatible with Fontconfig. Fontconfig currently
+ // supports three encodings in FcFreeTypeCharIndex: Unicode, Symbol and AppleRoman.
+ // If this font doesn't have one of these three encodings, don't select it.
+ FontPlatformData* platformData = new FontPlatformData(resultPattern.get(), fontDescription);
+ if (!platformData->hasCompatibleCharmap()) {
+ delete platformData;
+ return 0;
+ }
+
+ return platformData;
}
}
diff --git a/WebCore/platform/graphics/freetype/FontPlatformData.h b/WebCore/platform/graphics/freetype/FontPlatformData.h
index 0793746..2841b14 100644
--- a/WebCore/platform/graphics/freetype/FontPlatformData.h
+++ b/WebCore/platform/graphics/freetype/FontPlatformData.h
@@ -68,6 +68,7 @@ public:
void setSize(float size) { m_size = size; }
bool syntheticBold() const { return m_syntheticBold; }
bool syntheticOblique() const { return m_syntheticOblique; }
+ bool hasCompatibleCharmap();
FontOrientation orientation() const { return Horizontal; } // FIXME: Implement.
diff --git a/WebCore/platform/graphics/freetype/FontPlatformDataFreeType.cpp b/WebCore/platform/graphics/freetype/FontPlatformDataFreeType.cpp
index c0756ee..7340e76 100644
--- a/WebCore/platform/graphics/freetype/FontPlatformDataFreeType.cpp
+++ b/WebCore/platform/graphics/freetype/FontPlatformDataFreeType.cpp
@@ -272,5 +272,17 @@ void FontPlatformData::initializeWithFontFace(cairo_font_face_t* fontFace)
cairo_font_options_destroy(options);
}
+bool FontPlatformData::hasCompatibleCharmap()
+{
+ if (!m_scaledFont)
+ return false;
+
+ FT_Face freeTypeFace = cairo_ft_scaled_font_lock_face(m_scaledFont);
+ bool hasCompatibleCharmap = !(FT_Select_Charmap(freeTypeFace, ft_encoding_unicode)
+ && FT_Select_Charmap(freeTypeFace, ft_encoding_symbol)
+ && FT_Select_Charmap(freeTypeFace, ft_encoding_apple_roman));
+ cairo_ft_scaled_font_unlock_face(m_scaledFont);
+ return hasCompatibleCharmap;
+}
}
diff --git a/WebCore/platform/graphics/freetype/SimpleFontDataFreeType.cpp b/WebCore/platform/graphics/freetype/SimpleFontDataFreeType.cpp
index cb096c3..97fd81a 100644
--- a/WebCore/platform/graphics/freetype/SimpleFontDataFreeType.cpp
+++ b/WebCore/platform/graphics/freetype/SimpleFontDataFreeType.cpp
@@ -79,16 +79,32 @@ void SimpleFontData::platformDestroy()
{
}
+SimpleFontData* SimpleFontData::scaledFontData(const FontDescription& fontDescription, float scaleFactor) const
+{
+ return new SimpleFontData(FontPlatformData(cairo_scaled_font_get_font_face(m_platformData.scaledFont()),
+ scaleFactor * fontDescription.computedSize(), m_platformData.syntheticBold(), m_platformData.syntheticOblique()),
+ isCustomFont(), false);
+}
+
SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const
{
+ if (!m_derivedFontData)
+ m_derivedFontData = DerivedFontData::create(isCustomFont());
// FIXME: I think we want to ask FontConfig for the right font again.
- if (!m_smallCapsFontData)
- m_smallCapsFontData = new SimpleFontData(
- FontPlatformData(cairo_scaled_font_get_font_face(m_platformData.scaledFont()),
- 0.70f * fontDescription.computedSize(), m_platformData.syntheticBold(), m_platformData.syntheticOblique()),
- isCustomFont(), false);
+ if (!m_derivedFontData->smallCaps)
+ m_derivedFontData->smallCaps = scaledFontData(fontDescription, .7);
+
+ return m_derivedFontData->smallCaps.get();
+}
+
+SimpleFontData* SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const
+{
+ if (!m_derivedFontData)
+ m_derivedFontData = DerivedFontData::create(isCustomFont());
+ if (!m_derivedFontData->emphasisMark)
+ m_derivedFontData->emphasisMark = scaledFontData(fontDescription, .5);
- return m_smallCapsFontData;
+ return m_derivedFontData->emphasisMark.get();
}
bool SimpleFontData::containsCharacters(const UChar* characters, int length) const
diff --git a/WebCore/platform/graphics/gpu/DrawingBuffer.cpp b/WebCore/platform/graphics/gpu/DrawingBuffer.cpp
index 8cb6d0c..d2415ca 100644
--- a/WebCore/platform/graphics/gpu/DrawingBuffer.cpp
+++ b/WebCore/platform/graphics/gpu/DrawingBuffer.cpp
@@ -41,7 +41,13 @@ namespace WebCore {
PassRefPtr<DrawingBuffer> DrawingBuffer::create(GraphicsContext3D* context, const IntSize& size)
{
RefPtr<DrawingBuffer> drawingBuffer = adoptRef(new DrawingBuffer(context, size));
- drawingBuffer->m_multisampleExtensionSupported = context->getExtensions()->supports("GL_ANGLE_framebuffer_blit") && context->getExtensions()->supports("GL_ANGLE_framebuffer_multisample");
+ Extensions3D* extensions = context->getExtensions();
+ bool multisampleSupported = extensions->supports("GL_ANGLE_framebuffer_blit") && extensions->supports("GL_ANGLE_framebuffer_multisample");
+ if (multisampleSupported) {
+ extensions->ensureEnabled("GL_ANGLE_framebuffer_blit");
+ extensions->ensureEnabled("GL_ANGLE_framebuffer_multisample");
+ }
+ drawingBuffer->m_multisampleExtensionSupported = multisampleSupported;
return (drawingBuffer->m_context) ? drawingBuffer.release() : 0;
}
@@ -113,13 +119,11 @@ void DrawingBuffer::reset(const IntSize& newSize)
// resize multisample FBO
if (multisample()) {
- int maxSampleCount;
+ int maxSampleCount = 0;
m_context->getIntegerv(Extensions3D::MAX_SAMPLES, &maxSampleCount);
int sampleCount = std::min(8, maxSampleCount);
- if (sampleCount > maxSampleCount)
- sampleCount = maxSampleCount;
-
+
m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_multisampleFBO);
m_context->bindRenderbuffer(GraphicsContext3D::RENDERBUFFER, m_multisampleColorBuffer);
@@ -145,7 +149,7 @@ void DrawingBuffer::reset(const IntSize& newSize)
m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_fbo);
m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_colorBuffer);
- m_context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, internalColorFormat, m_size.width(), m_size.height(), 0, colorFormat, GraphicsContext3D::UNSIGNED_BYTE, 0);
+ m_context->texImage2DResourceSafe(GraphicsContext3D::TEXTURE_2D, 0, internalColorFormat, m_size.width(), m_size.height(), 0, colorFormat, GraphicsContext3D::UNSIGNED_BYTE);
m_context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE, m_colorBuffer, 0);
m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, 0);
if (!multisample() && (attributes.stencil || attributes.depth)) {
@@ -166,57 +170,48 @@ void DrawingBuffer::reset(const IntSize& newSize)
if (multisample())
m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_multisampleFBO);
- // Initialize renderbuffers to 0.
- float clearColor[] = {0, 0, 0, 0}, clearDepth = 0;
- int clearStencil = 0;
- unsigned char colorMask[] = {true, true, true, true}, depthMask = true;
- unsigned int stencilMask = 0xffffffff;
- unsigned char isScissorEnabled = false;
- unsigned char isDitherEnabled = false;
- unsigned long clearMask = GraphicsContext3D::COLOR_BUFFER_BIT;
- m_context->getFloatv(GraphicsContext3D::COLOR_CLEAR_VALUE, clearColor);
- m_context->clearColor(0, 0, 0, 0);
- m_context->getBooleanv(GraphicsContext3D::COLOR_WRITEMASK, colorMask);
- m_context->colorMask(true, true, true, true);
- if (attributes.depth) {
- m_context->getFloatv(GraphicsContext3D::DEPTH_CLEAR_VALUE, &clearDepth);
- m_context->clearDepth(1);
- m_context->getBooleanv(GraphicsContext3D::DEPTH_WRITEMASK, &depthMask);
- m_context->depthMask(true);
- clearMask |= GraphicsContext3D::DEPTH_BUFFER_BIT;
- }
- if (attributes.stencil) {
- m_context->getIntegerv(GraphicsContext3D::STENCIL_CLEAR_VALUE, &clearStencil);
- m_context->clearStencil(0);
- m_context->getIntegerv(GraphicsContext3D::STENCIL_WRITEMASK, reinterpret_cast<int*>(&stencilMask));
- m_context->stencilMaskSeparate(GraphicsContext3D::FRONT, 0xffffffff);
- clearMask |= GraphicsContext3D::STENCIL_BUFFER_BIT;
- }
- isScissorEnabled = m_context->isEnabled(GraphicsContext3D::SCISSOR_TEST);
- m_context->disable(GraphicsContext3D::SCISSOR_TEST);
- isDitherEnabled = m_context->isEnabled(GraphicsContext3D::DITHER);
- m_context->disable(GraphicsContext3D::DITHER);
-
- m_context->clear(clearMask);
-
- m_context->clearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
- m_context->colorMask(colorMask[0], colorMask[1], colorMask[2], colorMask[3]);
- if (attributes.depth) {
- m_context->clearDepth(clearDepth);
- m_context->depthMask(depthMask);
- }
- if (attributes.stencil) {
- m_context->clearStencil(clearStencil);
- m_context->stencilMaskSeparate(GraphicsContext3D::FRONT, stencilMask);
+ if (!m_context->getExtensions()->supports("GL_CHROMIUM_resource_safe")) {
+ // Initialize renderbuffers (depth/stencil).
+ float clearDepth = 0;
+ int clearStencil = 0;
+ unsigned char depthMask = true;
+ unsigned int stencilMask = 0xffffffff;
+ unsigned char isScissorEnabled = false;
+ unsigned long clearMask = 0;
+ if (attributes.depth) {
+ m_context->getFloatv(GraphicsContext3D::DEPTH_CLEAR_VALUE, &clearDepth);
+ m_context->clearDepth(1);
+ m_context->getBooleanv(GraphicsContext3D::DEPTH_WRITEMASK, &depthMask);
+ m_context->depthMask(true);
+ clearMask |= GraphicsContext3D::DEPTH_BUFFER_BIT;
+ }
+ if (attributes.stencil) {
+ m_context->getIntegerv(GraphicsContext3D::STENCIL_CLEAR_VALUE, &clearStencil);
+ m_context->clearStencil(0);
+ m_context->getIntegerv(GraphicsContext3D::STENCIL_WRITEMASK, reinterpret_cast<int*>(&stencilMask));
+ m_context->stencilMaskSeparate(GraphicsContext3D::FRONT, 0xffffffff);
+ clearMask |= GraphicsContext3D::STENCIL_BUFFER_BIT;
+ }
+ if (clearMask) {
+ isScissorEnabled = m_context->isEnabled(GraphicsContext3D::SCISSOR_TEST);
+ m_context->disable(GraphicsContext3D::SCISSOR_TEST);
+
+ m_context->clear(clearMask);
+
+ if (attributes.depth) {
+ m_context->clearDepth(clearDepth);
+ m_context->depthMask(depthMask);
+ }
+ if (attributes.stencil) {
+ m_context->clearStencil(clearStencil);
+ m_context->stencilMaskSeparate(GraphicsContext3D::FRONT, stencilMask);
+ }
+ if (isScissorEnabled)
+ m_context->enable(GraphicsContext3D::SCISSOR_TEST);
+ else
+ m_context->disable(GraphicsContext3D::SCISSOR_TEST);
+ }
}
- if (isScissorEnabled)
- m_context->enable(GraphicsContext3D::SCISSOR_TEST);
- else
- m_context->disable(GraphicsContext3D::SCISSOR_TEST);
- if (isDitherEnabled)
- m_context->enable(GraphicsContext3D::DITHER);
- else
- m_context->disable(GraphicsContext3D::DITHER);
m_context->flush();
diff --git a/WebCore/platform/graphics/gpu/Shader.cpp b/WebCore/platform/graphics/gpu/Shader.cpp
index 8983adc..6978322 100644
--- a/WebCore/platform/graphics/gpu/Shader.cpp
+++ b/WebCore/platform/graphics/gpu/Shader.cpp
@@ -65,7 +65,7 @@ unsigned Shader::loadShader(GraphicsContext3D* context, unsigned type, const cha
String shaderSourceStr(shaderSource);
context->shaderSource(shader, shaderSourceStr);
context->compileShader(shader);
- int compileStatus;
+ int compileStatus = 0;
context->getShaderiv(shader, GraphicsContext3D::COMPILE_STATUS, &compileStatus);
if (!compileStatus) {
String infoLog = context->getShaderInfoLog(shader);
@@ -91,7 +91,7 @@ unsigned Shader::loadProgram(GraphicsContext3D* context, const char* vertexShade
context->attachShader(program, vertexShader);
context->attachShader(program, fragmentShader);
context->linkProgram(program);
- int linkStatus;
+ int linkStatus = 0;
context->getProgramiv(program, GraphicsContext3D::LINK_STATUS, &linkStatus);
if (!linkStatus)
context->deleteProgram(program);
diff --git a/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.cpp b/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.cpp
index a230384..a166d9c 100644
--- a/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.cpp
+++ b/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.cpp
@@ -68,11 +68,18 @@ PassRefPtr<SharedGraphicsContext3D> SharedGraphicsContext3D::create(HostWindow*
SharedGraphicsContext3D::SharedGraphicsContext3D(PassRefPtr<GraphicsContext3D> context, PassOwnPtr<SolidFillShader> solidFillShader, PassOwnPtr<TexShader> texShader)
: m_context(context)
+ , m_bgraSupported(false)
, m_quadVertices(0)
, m_solidFillShader(solidFillShader)
, m_texShader(texShader)
{
allContexts()->add(this);
+ Extensions3D* extensions = m_context->getExtensions();
+ m_bgraSupported = extensions->supports("GL_EXT_texture_format_BGRA8888") && extensions->supports("GL_EXT_read_format_bgra");
+ if (m_bgraSupported) {
+ extensions->ensureEnabled("GL_EXT_texture_format_BGRA8888");
+ extensions->ensureEnabled("GL_EXT_read_format_bgra");
+ }
}
SharedGraphicsContext3D::~SharedGraphicsContext3D()
@@ -165,6 +172,10 @@ void SharedGraphicsContext3D::texParameteri(unsigned target, unsigned pname, int
int SharedGraphicsContext3D::texImage2D(unsigned target, unsigned level, unsigned internalformat, unsigned width, unsigned height, unsigned border, unsigned format, unsigned type, void* pixels)
{
+ if (!pixels) {
+ m_context->texImage2DResourceSafe(target, level, internalformat, width, height, border, format, type);
+ return 0;
+ }
return m_context->texImage2D(target, level, internalformat, width, height, border, format, type, pixels);
}
@@ -180,8 +191,7 @@ void SharedGraphicsContext3D::readPixels(long x, long y, unsigned long width, un
bool SharedGraphicsContext3D::supportsBGRA()
{
- return m_context->getExtensions()->supports("GL_EXT_texture_format_BGRA8888")
- && m_context->getExtensions()->supports("GL_EXT_read_format_bgra");
+ return m_bgraSupported;
}
Texture* SharedGraphicsContext3D::createTexture(NativeImagePtr ptr, Texture::Format format, int width, int height)
diff --git a/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.h b/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.h
index 86c64b4..a1ae8f2 100644
--- a/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.h
+++ b/WebCore/platform/graphics/gpu/SharedGraphicsContext3D.h
@@ -124,6 +124,7 @@ private:
void removeTextureFor(NativeImagePtr);
RefPtr<GraphicsContext3D> m_context;
+ bool m_bgraSupported;
unsigned m_quadVertices;
diff --git a/WebCore/platform/graphics/gpu/Texture.cpp b/WebCore/platform/graphics/gpu/Texture.cpp
index 18c9ead..e1f8114 100644
--- a/WebCore/platform/graphics/gpu/Texture.cpp
+++ b/WebCore/platform/graphics/gpu/Texture.cpp
@@ -106,15 +106,15 @@ PassRefPtr<Texture> Texture::create(GraphicsContext3D* context, Format format, i
IntRect tileBoundsWithBorder = tiling.tileBoundsWithBorder(i);
- unsigned int glFormat = 0;
- unsigned int glType = 0;
- bool swizzle;
- convertFormat(context, format, &glFormat, &glType, &swizzle);
- context->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId);
- context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, glFormat,
- tileBoundsWithBorder.width(),
- tileBoundsWithBorder.height(),
- 0, glFormat, glType, 0);
+ unsigned int glFormat = 0;
+ unsigned int glType = 0;
+ bool swizzle;
+ convertFormat(context, format, &glFormat, &glType, &swizzle);
+ context->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId);
+ context->texImage2DResourceSafe(GraphicsContext3D::TEXTURE_2D, 0, glFormat,
+ tileBoundsWithBorder.width(),
+ tileBoundsWithBorder.height(),
+ 0, glFormat, glType);
}
return adoptRef(new Texture(context, textureIds.leakPtr(), format, width, height, maxTextureSize));
}
@@ -149,8 +149,11 @@ void Texture::load(void* pixels)
updateSubRect(pixels, IntRect(0, 0, m_tiles.totalSizeX(), m_tiles.totalSizeY()));
}
-void Texture::updateSubRect(void* pixels, const IntRect updateRect)
+void Texture::updateSubRect(void* pixels, const IntRect& updateRect)
{
+ IntRect updateRectSanitized(updateRect);
+ updateRectSanitized.intersect(IntRect(0, 0, m_tiles.totalSizeX(), m_tiles.totalSizeY()));
+
uint32_t* pixels32 = static_cast<uint32_t*>(pixels);
unsigned int glFormat = 0;
unsigned int glType = 0;
@@ -160,16 +163,16 @@ void Texture::updateSubRect(void* pixels, const IntRect updateRect)
ASSERT(glFormat == GraphicsContext3D::RGBA && glType == GraphicsContext3D::UNSIGNED_BYTE);
// FIXME: This could use PBO's to save doing an extra copy here.
}
- int tempBuffSize = // Temporary buffer size is the smaller of the max texture size or the updateRect
- min(m_tiles.maxTextureSize(), m_tiles.borderTexels() + updateRect.width()) *
- min(m_tiles.maxTextureSize(), m_tiles.borderTexels() + updateRect.height());
+ int tempBuffSize = // Temporary buffer size is the smaller of the max texture size or the updateRectSanitized
+ min(m_tiles.maxTextureSize(), m_tiles.borderTexels() + updateRectSanitized.width()) *
+ min(m_tiles.maxTextureSize(), m_tiles.borderTexels() + updateRectSanitized.height());
OwnArrayPtr<uint32_t> tempBuff(new uint32_t[tempBuffSize]);
for (int tile = 0; tile < m_tiles.numTiles(); tile++) {
// Intersect with tile
IntRect tileBoundsWithBorder = m_tiles.tileBoundsWithBorder(tile);
- IntRect updateRectIntersected = updateRect;
+ IntRect updateRectIntersected = updateRectSanitized;
updateRectIntersected.intersect(tileBoundsWithBorder);
IntRect dstRect = updateRectIntersected;
diff --git a/WebCore/platform/graphics/gpu/Texture.h b/WebCore/platform/graphics/gpu/Texture.h
index 92b6d0a..1f35006 100644
--- a/WebCore/platform/graphics/gpu/Texture.h
+++ b/WebCore/platform/graphics/gpu/Texture.h
@@ -50,7 +50,7 @@ public:
static PassRefPtr<Texture> create(GraphicsContext3D*, Format, int width, int height);
void bindTile(int tile);
void load(void* pixels);
- void updateSubRect(void* pixels, const IntRect);
+ void updateSubRect(void* pixels, const IntRect&);
Format format() const { return m_format; }
const TilingData& tiles() const { return m_tiles; }
private:
diff --git a/WebCore/platform/graphics/gstreamer/DataSourceGStreamer.cpp b/WebCore/platform/graphics/gstreamer/DataSourceGStreamer.cpp
deleted file mode 100644
index 5a94fd4..0000000
--- a/WebCore/platform/graphics/gstreamer/DataSourceGStreamer.cpp
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * Copyright (C) 2009 Igalia S.L
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "config.h"
-#include "DataSourceGStreamer.h"
-#if USE(GSTREAMER)
-
-#include <gio/gio.h>
-#include <glib.h>
-#include <gst/gst.h>
-#include <gst/pbutils/missing-plugins.h>
-
-static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE("src",
- GST_PAD_SRC,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS_ANY);
-
-GST_DEBUG_CATEGORY_STATIC(webkit_data_src_debug);
-#define GST_CAT_DEFAULT webkit_data_src_debug
-
-static void webkit_data_src_uri_handler_init(gpointer g_iface,
- gpointer iface_data);
-
-static void webkit_data_src_finalize(WebkitDataSrc* src);
-static GstStateChangeReturn webkit_data_src_change_state(GstElement* element,
- GstStateChange transition);
-
-static const GInterfaceInfo urihandler_info = {
- webkit_data_src_uri_handler_init,
- 0, 0
-};
-
-
-static void _do_init(GType datasrc_type)
-{
- GST_DEBUG_CATEGORY_INIT(webkit_data_src_debug, "webkit_data_src", 0, "datasrc element");
- g_type_add_interface_static(datasrc_type, GST_TYPE_URI_HANDLER,
- &urihandler_info);
-}
-
-GST_BOILERPLATE_FULL(WebkitDataSrc, webkit_data_src, GstBin, GST_TYPE_BIN, _do_init);
-
-static void webkit_data_src_base_init(gpointer klass)
-{
- GstElementClass* element_class = GST_ELEMENT_CLASS(klass);
-
- gst_element_class_add_pad_template(element_class,
- gst_static_pad_template_get(&src_template));
- gst_element_class_set_details_simple(element_class, (gchar*) "WebKit data source element",
- (gchar*) "Source",
- (gchar*) "Handles data: uris",
- (gchar*) "Philippe Normand <pnormand@igalia.com>");
-
-}
-
-static void webkit_data_src_class_init(WebkitDataSrcClass* klass)
-{
- GObjectClass* oklass = G_OBJECT_CLASS(klass);
- GstElementClass* eklass = GST_ELEMENT_CLASS(klass);
-
- oklass->finalize = (GObjectFinalizeFunc) webkit_data_src_finalize;
- eklass->change_state = webkit_data_src_change_state;
-}
-
-
-static gboolean webkit_data_src_reset(WebkitDataSrc* src)
-{
- GstPad* targetpad;
-
- if (src->kid) {
- gst_element_set_state(src->kid, GST_STATE_NULL);
- gst_bin_remove(GST_BIN(src), src->kid);
- }
-
- src->kid = gst_element_factory_make("giostreamsrc", "streamsrc");
- if (!src->kid) {
- GST_ERROR_OBJECT(src, "Failed to create giostreamsrc");
- return FALSE;
- }
-
- gst_bin_add(GST_BIN(src), src->kid);
-
- targetpad = gst_element_get_static_pad(src->kid, "src");
- gst_ghost_pad_set_target(GST_GHOST_PAD(src->pad), targetpad);
- gst_object_unref(targetpad);
-
- return TRUE;
-}
-
-static void webkit_data_src_init(WebkitDataSrc* src,
- WebkitDataSrcClass* g_class)
-{
- GstPadTemplate* pad_template = gst_static_pad_template_get(&src_template);
- src->pad = gst_ghost_pad_new_no_target_from_template("src",
- pad_template);
-
- gst_element_add_pad(GST_ELEMENT(src), src->pad);
-
- webkit_data_src_reset(src);
-}
-
-static void webkit_data_src_finalize(WebkitDataSrc* src)
-{
- g_free(src->uri);
-
- if (src->kid) {
- GST_DEBUG_OBJECT(src, "Removing giostreamsrc element");
- gst_element_set_state(src->kid, GST_STATE_NULL);
- gst_bin_remove(GST_BIN(src), src->kid);
- src->kid = 0;
- }
-
- GST_CALL_PARENT(G_OBJECT_CLASS, finalize, ((GObject* )(src)));
-}
-
-static GstStateChangeReturn webkit_data_src_change_state(GstElement* element, GstStateChange transition)
-{
- GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
- WebkitDataSrc* src = WEBKIT_DATA_SRC(element);
-
- switch (transition) {
- case GST_STATE_CHANGE_NULL_TO_READY:
- if (!src->kid) {
- gst_element_post_message(element,
- gst_missing_element_message_new(element, "giostreamsrc"));
- GST_ELEMENT_ERROR(src, CORE, MISSING_PLUGIN, (0), ("no giostreamsrc"));
- return GST_STATE_CHANGE_FAILURE;
- }
- break;
- default:
- break;
- }
-
- ret = GST_ELEMENT_CLASS(parent_class)->change_state(element, transition);
- if (G_UNLIKELY(ret == GST_STATE_CHANGE_FAILURE))
- return ret;
-
- // Downwards state change code should be here, after chaining up
- // to the parent class.
-
- return ret;
-}
-
-/*** GSTURIHANDLER INTERFACE *************************************************/
-
-static GstURIType webkit_data_src_uri_get_type(void)
-{
- return GST_URI_SRC;
-}
-
-static gchar** webkit_data_src_uri_get_protocols(void)
-{
- static gchar* protocols[] = {(gchar*) "data", 0 };
-
- return protocols;
-}
-
-static const gchar* webkit_data_src_uri_get_uri(GstURIHandler* handler)
-{
- WebkitDataSrc* src = WEBKIT_DATA_SRC(handler);
-
- return src->uri;
-}
-
-static gboolean webkit_data_src_uri_set_uri(GstURIHandler* handler, const gchar* uri)
-{
- WebkitDataSrc* src = WEBKIT_DATA_SRC(handler);
-
- // URI as defined in RFC2397:
- // "data:" [ mediatype ] [ ";base64" ] "," data
- // we parse URIs like this one:
- // data:audio/3gpp;base64,AA...
-
- gchar** scheme_and_remains = g_strsplit(uri, ":", 2);
- gchar** mime_type_and_options = g_strsplit(scheme_and_remains[1], ";", 0);
- gint options_size = g_strv_length(mime_type_and_options);
- gchar* data = 0;
- gchar* mime_type = 0;
- gint ret = FALSE;
-
- // we require uris with a specified mime-type and base64-encoded
- // data. It doesn't make much sense anyway to play plain/text data
- // with very few allowed characters (as per the RFC).
-
- if (GST_STATE(src) >= GST_STATE_PAUSED) {
- GST_ERROR_OBJECT(src, "Element already configured. Reset it and retry");
- } else if (!options_size)
- GST_ERROR_OBJECT(src, "A mime-type is needed in %s", uri);
- else {
- mime_type = mime_type_and_options[0];
- data = mime_type_and_options[options_size-1];
-
- guchar* decoded_data = 0;
- gsize decoded_size;
-
- if (!g_str_has_prefix(data, "base64"))
- GST_ERROR_OBJECT(src, "Data has to be base64-encoded in %s", uri);
- else {
- decoded_data = g_base64_decode(data+7, &decoded_size);
- GInputStream* stream = g_memory_input_stream_new_from_data(decoded_data,
- decoded_size,
- g_free);
- g_object_set(src->kid, "stream", stream, NULL);
- g_object_unref(stream);
-
- if (src->uri) {
- g_free(src->uri);
- src->uri = 0;
- }
-
- src->uri = g_strdup(uri);
- ret = TRUE;
- }
- }
-
- g_strfreev(scheme_and_remains);
- g_strfreev(mime_type_and_options);
- return ret;
-}
-
-static void webkit_data_src_uri_handler_init(gpointer g_iface, gpointer iface_data)
-{
- GstURIHandlerInterface* iface = (GstURIHandlerInterface *) g_iface;
-
- iface->get_type = webkit_data_src_uri_get_type;
- iface->get_protocols = webkit_data_src_uri_get_protocols;
- iface->get_uri = webkit_data_src_uri_get_uri;
- iface->set_uri = webkit_data_src_uri_set_uri;
-}
-
-#endif // USE(GSTREAMER)
diff --git a/WebCore/platform/graphics/gstreamer/DataSourceGStreamer.h b/WebCore/platform/graphics/gstreamer/DataSourceGStreamer.h
deleted file mode 100644
index d462ccc4..0000000
--- a/WebCore/platform/graphics/gstreamer/DataSourceGStreamer.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2009 Igalia S.L
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef DataSourceGStreamer_h
-#define DataSourceGStreamer_h
-
-#if USE(GSTREAMER)
-
-#include <glib-object.h>
-#include <gst/base/gstbasesrc.h>
-
-G_BEGIN_DECLS
-
-#define WEBKIT_TYPE_DATA_SRC (webkit_data_src_get_type ())
-#define WEBKIT_DATA_SRC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), WEBKIT_TYPE_DATA_SRC, WebkitDataSrc))
-#define WEBKIT_DATA_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), WEBKIT_TYPE_DATA_SRC, WebkitDataSrcClass))
-#define WEBKIT_IS_DATA_SRC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), WEBKIT_TYPE_DATA_SRC))
-#define WEBKIT_IS_DATA_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), WEBKIT_TYPE_DATA_SRC))
-
-typedef struct _WebkitDataSrc WebkitDataSrc;
-typedef struct _WebkitDataSrcClass WebkitDataSrcClass;
-
-
-struct _WebkitDataSrc {
- GstBin parent;
-
- /* explicit pointers to stuff used */
- GstElement* kid;
- GstPad* pad;
- gchar* uri;
-};
-
-struct _WebkitDataSrcClass {
- GstBinClass parent_class;
-};
-
-GType webkit_data_src_get_type(void);
-
-G_END_DECLS
-
-#endif // USE(GSTREAMER)
-#endif
diff --git a/WebCore/platform/graphics/gstreamer/GStreamerGWorld.cpp b/WebCore/platform/graphics/gstreamer/GStreamerGWorld.cpp
index b18bf84..e8c87ac 100644
--- a/WebCore/platform/graphics/gstreamer/GStreamerGWorld.cpp
+++ b/WebCore/platform/graphics/gstreamer/GStreamerGWorld.cpp
@@ -91,9 +91,16 @@ bool GStreamerGWorld::enterFullscreen()
g_object_set(valve, "drop-probability", 1.0, NULL);
- // Add and link a queue, ffmpegcolorspace and sink in the bin.
+ // Add and link a queue, ffmpegcolorspace, videoscale and sink in the bin.
gst_bin_add_many(GST_BIN(videoSink.get()), platformVideoSink, videoScale, colorspace, queue, NULL);
+#if GST_CHECK_VERSION(0, 10, 30)
+ // Faster elements linking, if possible.
+ gst_element_link_pads_full(queue, "src", colorspace, "sink", GST_PAD_LINK_CHECK_NOTHING);
+ gst_element_link_pads_full(colorspace, "src", videoScale, "sink", GST_PAD_LINK_CHECK_NOTHING);
+ gst_element_link_pads_full(videoScale, "src", platformVideoSink, "sink", GST_PAD_LINK_CHECK_NOTHING);
+#else
gst_element_link_many(queue, colorspace, videoScale, platformVideoSink, NULL);
+#endif
// Link a new src pad from tee to queue.
GstPad* srcPad = gst_element_get_request_pad(tee, "src%d");
diff --git a/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp b/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp
index 695d1f7..3cddd2e 100644
--- a/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp
+++ b/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp
@@ -27,7 +27,6 @@
#if USE(GSTREAMER)
#include "ColorSpace.h"
-#include "DataSourceGStreamer.h"
#include "Document.h"
#include "Frame.h"
#include "FrameView.h"
@@ -134,6 +133,13 @@ gboolean mediaPlayerPrivateMessageCallback(GstBus* bus, GstMessage* message, gpo
mp->didEnd();
break;
case GST_MESSAGE_STATE_CHANGED:
+ // Ignore state changes if load is delayed (preload=none). The
+ // player state will be updated once commitLoad() is called.
+ if (mp->loadDelayed()) {
+ LOG_VERBOSE(Media, "Media load has been delayed. Ignoring state changes for now");
+ break;
+ }
+
// Ignore state changes from internal elements. They are
// forwarded to playbin2 anyway.
if (GST_MESSAGE_SRC(message) == reinterpret_cast<GstObject*>(pipeline))
@@ -177,6 +183,13 @@ void mediaPlayerPrivateVolumeChangedCallback(GObject *element, GParamSpec *pspec
mp->volumeChanged();
}
+gboolean mediaPlayerPrivateVolumeChangeTimeoutCallback(MediaPlayerPrivateGStreamer* player)
+{
+ // This is the callback of the timeout source created in ::volumeChanged.
+ player->notifyPlayerOfVolumeChange();
+ return FALSE;
+}
+
void mediaPlayerPrivateMuteChangedCallback(GObject *element, GParamSpec *pspec, gpointer data)
{
// This is called when playbin receives the notify::mute signal.
@@ -184,6 +197,37 @@ void mediaPlayerPrivateMuteChangedCallback(GObject *element, GParamSpec *pspec,
mp->muteChanged();
}
+gboolean mediaPlayerPrivateMuteChangeTimeoutCallback(MediaPlayerPrivateGStreamer* player)
+{
+ // This is the callback of the timeout source created in ::muteChanged.
+ player->notifyPlayerOfMute();
+ return FALSE;
+}
+
+void mediaPlayerPrivateVideoTagsChangedCallback(GObject* element, gint streamId, MediaPlayerPrivateGStreamer* player)
+{
+ player->videoTagsChanged(streamId);
+}
+
+void mediaPlayerPrivateAudioTagsChangedCallback(GObject* element, gint streamId, MediaPlayerPrivateGStreamer* player)
+{
+ player->audioTagsChanged(streamId);
+}
+
+gboolean mediaPlayerPrivateAudioTagsChangeTimeoutCallback(MediaPlayerPrivateGStreamer* player)
+{
+ // This is the callback of the timeout source created in ::audioTagsChanged.
+ player->notifyPlayerOfAudioTags();
+ return FALSE;
+}
+
+gboolean mediaPlayerPrivateVideoTagsChangeTimeoutCallback(MediaPlayerPrivateGStreamer* player)
+{
+ // This is the callback of the timeout source created in ::videoTagsChanged.
+ player->notifyPlayerOfVideoTags();
+ return FALSE;
+}
+
static float playbackPosition(GstElement* playbin)
{
@@ -238,16 +282,12 @@ static bool doGstInit()
if (!gstInitialized) {
GOwnPtr<GError> error;
gstInitialized = gst_init_check(0, 0, &error.outPtr());
- if (!gstInitialized) {
+ if (!gstInitialized)
LOG_VERBOSE(Media, "Could not initialize GStreamer: %s",
error ? error->message : "unknown error occurred");
- } else {
- gst_element_register(0, "webkitmediasrc", GST_RANK_PRIMARY,
- WEBKIT_TYPE_DATA_SRC);
+ else
gst_element_register(0, "webkitwebsrc", GST_RANK_PRIMARY + 100,
WEBKIT_TYPE_WEB_SRC);
- }
-
}
return gstInitialized;
}
@@ -295,6 +335,12 @@ MediaPlayerPrivateGStreamer::MediaPlayerPrivateGStreamer(MediaPlayer* player)
, m_preload(MediaPlayer::Auto)
, m_delayingLoad(false)
, m_mediaDurationKnown(true)
+ , m_volumeTimerHandler(0)
+ , m_muteTimerHandler(0)
+ , m_hasVideo(false)
+ , m_hasAudio(false)
+ , m_audioTagsTimerHandler(0)
+ , m_videoTagsTimerHandler(0)
{
if (doGstInit())
createGSTPlayBin();
@@ -327,8 +373,22 @@ MediaPlayerPrivateGStreamer::~MediaPlayerPrivateGStreamer()
if (m_playBin) {
gst_element_set_state(m_playBin, GST_STATE_NULL);
gst_object_unref(GST_OBJECT(m_playBin));
+ m_playBin = 0;
}
+ m_player = 0;
+
+ if (m_muteTimerHandler)
+ g_source_remove(m_muteTimerHandler);
+
+ if (m_volumeTimerHandler)
+ g_source_remove(m_volumeTimerHandler);
+
+ if (m_videoTagsTimerHandler)
+ g_source_remove(m_videoTagsTimerHandler);
+
+ if (m_audioTagsTimerHandler)
+ g_source_remove(m_audioTagsTimerHandler);
}
void MediaPlayerPrivateGStreamer::load(const String& url)
@@ -340,27 +400,21 @@ void MediaPlayerPrivateGStreamer::load(const String& url)
if (m_preload == MediaPlayer::None) {
LOG_VERBOSE(Media, "Delaying load.");
m_delayingLoad = true;
- return;
}
- commitLoad();
-}
-
-void MediaPlayerPrivateGStreamer::commitLoad()
-{
// GStreamer needs to have the pipeline set to a paused state to
// start providing anything useful.
gst_element_set_state(m_playBin, GST_STATE_PAUSED);
+ if (!m_delayingLoad)
+ commitLoad();
+}
+
+void MediaPlayerPrivateGStreamer::commitLoad()
+{
+ ASSERT(!m_delayingLoad);
LOG_VERBOSE(Media, "Committing load.");
- if (m_networkState != MediaPlayer::Loading) {
- m_networkState = MediaPlayer::Loading;
- m_player->networkStateChanged();
- }
- if (m_readyState != MediaPlayer::HaveNothing) {
- m_readyState = MediaPlayer::HaveNothing;
- m_player->readyStateChanged();
- }
+ updateStates();
}
bool MediaPlayerPrivateGStreamer::changePipelineState(GstState newState)
@@ -472,21 +526,6 @@ void MediaPlayerPrivateGStreamer::seek(float time)
}
}
-void MediaPlayerPrivateGStreamer::startEndPointTimerIfNeeded()
-{
- notImplemented();
-}
-
-void MediaPlayerPrivateGStreamer::cancelSeek()
-{
- notImplemented();
-}
-
-void MediaPlayerPrivateGStreamer::endPointTimerFired(Timer<MediaPlayerPrivateGStreamer>*)
-{
- notImplemented();
-}
-
bool MediaPlayerPrivateGStreamer::paused() const
{
return m_paused;
@@ -560,20 +599,40 @@ IntSize MediaPlayerPrivateGStreamer::naturalSize() const
return IntSize(static_cast<int>(width), static_cast<int>(height));
}
-bool MediaPlayerPrivateGStreamer::hasVideo() const
+void MediaPlayerPrivateGStreamer::videoTagsChanged(gint streamId)
{
+ if (m_videoTagsTimerHandler)
+ g_source_remove(m_videoTagsTimerHandler);
+ m_videoTagsTimerHandler = g_timeout_add(0, reinterpret_cast<GSourceFunc>(mediaPlayerPrivateVideoTagsChangeTimeoutCallback), this);
+}
+
+void MediaPlayerPrivateGStreamer::notifyPlayerOfVideoTags()
+{
+ m_videoTagsTimerHandler = 0;
+
gint currentVideo = -1;
if (m_playBin)
g_object_get(m_playBin, "current-video", &currentVideo, NULL);
- return currentVideo > -1;
+ m_hasVideo = currentVideo > -1;
+ m_player->mediaPlayerClient()->mediaPlayerEngineUpdated(m_player);
+}
+
+void MediaPlayerPrivateGStreamer::audioTagsChanged(gint streamId)
+{
+ if (m_audioTagsTimerHandler)
+ g_source_remove(m_audioTagsTimerHandler);
+ m_audioTagsTimerHandler = g_timeout_add(0, reinterpret_cast<GSourceFunc>(mediaPlayerPrivateAudioTagsChangeTimeoutCallback), this);
}
-bool MediaPlayerPrivateGStreamer::hasAudio() const
+void MediaPlayerPrivateGStreamer::notifyPlayerOfAudioTags()
{
+ m_audioTagsTimerHandler = 0;
+
gint currentAudio = -1;
if (m_playBin)
g_object_get(m_playBin, "current-audio", &currentAudio, NULL);
- return currentAudio > -1;
+ m_hasAudio = currentAudio > -1;
+ m_player->mediaPlayerClient()->mediaPlayerEngineUpdated(m_player);
}
void MediaPlayerPrivateGStreamer::setVolume(float volume)
@@ -584,8 +643,12 @@ void MediaPlayerPrivateGStreamer::setVolume(float volume)
g_object_set(m_playBin, "volume", static_cast<double>(volume), NULL);
}
-void MediaPlayerPrivateGStreamer::volumeChangedTimerFired(Timer<MediaPlayerPrivateGStreamer>*)
+void MediaPlayerPrivateGStreamer::notifyPlayerOfVolumeChange()
{
+ m_volumeTimerHandler = 0;
+
+ if (!m_player || !m_playBin)
+ return;
double volume;
g_object_get(m_playBin, "volume", &volume, NULL);
m_player->volumeChanged(static_cast<float>(volume));
@@ -593,8 +656,9 @@ void MediaPlayerPrivateGStreamer::volumeChangedTimerFired(Timer<MediaPlayerPriva
void MediaPlayerPrivateGStreamer::volumeChanged()
{
- Timer<MediaPlayerPrivateGStreamer> volumeChangedTimer(this, &MediaPlayerPrivateGStreamer::volumeChangedTimerFired);
- volumeChangedTimer.startOneShot(0);
+ if (m_volumeTimerHandler)
+ g_source_remove(m_volumeTimerHandler);
+ m_volumeTimerHandler = g_timeout_add(0, reinterpret_cast<GSourceFunc>(mediaPlayerPrivateVolumeChangeTimeoutCallback), this);
}
void MediaPlayerPrivateGStreamer::setRate(float rate)
@@ -663,9 +727,40 @@ MediaPlayer::ReadyState MediaPlayerPrivateGStreamer::readyState() const
PassRefPtr<TimeRanges> MediaPlayerPrivateGStreamer::buffered() const
{
RefPtr<TimeRanges> timeRanges = TimeRanges::create();
+ if (m_errorOccured || m_isStreaming)
+ return timeRanges.release();
+
+#if GST_CHECK_VERSION(0, 10, 31)
+ float mediaDuration(duration());
+ if (!mediaDuration || isinf(mediaDuration))
+ return timeRanges.release();
+
+ GstQuery* query = gst_query_new_buffering(GST_FORMAT_PERCENT);
+
+ if (!gst_element_query(m_playBin, query)) {
+ gst_query_unref(query);
+ return timeRanges.release();
+ }
+
+ gint64 rangeStart = 0, rangeStop = 0;
+ for (guint index = 0; index < gst_query_get_n_buffering_ranges(query); index++) {
+ if (gst_query_parse_nth_buffering_range(query, index, &rangeStart, &rangeStop))
+ timeRanges->add(static_cast<float>((rangeStart * mediaDuration) / 100),
+ static_cast<float>((rangeStop * mediaDuration) / 100));
+ }
+
+ // Fallback to the more general maxTimeLoaded() if no range has
+ // been found.
+ if (!timeRanges->length())
+ if (float loaded = maxTimeLoaded())
+ timeRanges->add(0, loaded);
+
+ gst_query_unref(query);
+#else
float loaded = maxTimeLoaded();
if (!m_errorOccured && !m_isStreaming && loaded > 0)
timeRanges->add(0, loaded);
+#endif
return timeRanges.release();
}
@@ -1140,8 +1235,10 @@ void MediaPlayerPrivateGStreamer::durationChanged()
float previousDuration = m_mediaDuration;
cacheDuration();
-
- if (m_mediaDuration != previousDuration)
+ // Avoid emiting durationchanged in the case where the previous
+ // duration was 0 because that case is already handled by the
+ // HTMLMediaElement.
+ if (previousDuration && m_mediaDuration != previousDuration)
m_player->durationChanged();
}
@@ -1158,8 +1255,13 @@ void MediaPlayerPrivateGStreamer::setMuted(bool muted)
g_object_set(m_playBin, "mute", muted, NULL);
}
-void MediaPlayerPrivateGStreamer::muteChangedTimerFired(Timer<MediaPlayerPrivateGStreamer>*)
+void MediaPlayerPrivateGStreamer::notifyPlayerOfMute()
{
+ m_muteTimerHandler = 0;
+
+ if (!m_player || !m_playBin)
+ return;
+
gboolean muted;
g_object_get(m_playBin, "mute", &muted, NULL);
m_player->muteChanged(static_cast<bool>(muted));
@@ -1167,8 +1269,9 @@ void MediaPlayerPrivateGStreamer::muteChangedTimerFired(Timer<MediaPlayerPrivate
void MediaPlayerPrivateGStreamer::muteChanged()
{
- Timer<MediaPlayerPrivateGStreamer> muteChangedTimer(this, &MediaPlayerPrivateGStreamer::muteChangedTimerFired);
- muteChangedTimer.startOneShot(0);
+ if (m_muteTimerHandler)
+ g_source_remove(m_muteTimerHandler);
+ m_muteTimerHandler = g_timeout_add(0, reinterpret_cast<GSourceFunc>(mediaPlayerPrivateMuteChangeTimeoutCallback), this);
}
void MediaPlayerPrivateGStreamer::loadingFailed(MediaPlayer::NetworkState error)
@@ -1359,7 +1462,12 @@ bool MediaPlayerPrivateGStreamer::hasSingleSecurityOrigin() const
bool MediaPlayerPrivateGStreamer::supportsFullscreen() const
{
+#if defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD)
+ // See <rdar://problem/7389945>
+ return false;
+#else
return true;
+#endif
}
PlatformMedia MediaPlayerPrivateGStreamer::platformMedia() const
@@ -1401,9 +1509,13 @@ void MediaPlayerPrivateGStreamer::createGSTPlayBin()
g_signal_connect(bus, "message", G_CALLBACK(mediaPlayerPrivateMessageCallback), this);
gst_object_unref(bus);
+ g_object_set(m_playBin, "mute", m_player->muted(), "volume", m_player->volume(), NULL);
+
g_signal_connect(m_playBin, "notify::volume", G_CALLBACK(mediaPlayerPrivateVolumeChangedCallback), this);
g_signal_connect(m_playBin, "notify::source", G_CALLBACK(mediaPlayerPrivateSourceChangedCallback), this);
g_signal_connect(m_playBin, "notify::mute", G_CALLBACK(mediaPlayerPrivateMuteChangedCallback), this);
+ g_signal_connect(m_playBin, "video-tags-changed", G_CALLBACK(mediaPlayerPrivateVideoTagsChangedCallback), this);
+ g_signal_connect(m_playBin, "audio-tags-changed", G_CALLBACK(mediaPlayerPrivateAudioTagsChangedCallback), this);
m_webkitVideoSink = webkit_video_sink_new();
@@ -1437,16 +1549,32 @@ void MediaPlayerPrivateGStreamer::createGSTPlayBin()
if (g_object_class_find_property(G_OBJECT_GET_CLASS(m_fpsSink), "video-sink")) {
g_object_set(m_fpsSink, "video-sink", m_webkitVideoSink, NULL);
gst_bin_add(GST_BIN(m_videoSinkBin), m_fpsSink);
+#if GST_CHECK_VERSION(0, 10, 30)
+ // Faster elements linking, if possible.
+ gst_element_link_pads_full(queue, "src", m_fpsSink, "sink", GST_PAD_LINK_CHECK_NOTHING);
+#else
gst_element_link(queue, m_fpsSink);
+#endif
} else {
m_fpsSink = 0;
gst_bin_add(GST_BIN(m_videoSinkBin), m_webkitVideoSink);
+#if GST_CHECK_VERSION(0, 10, 30)
+ // Faster elements linking, if possible.
+ gst_element_link_pads_full(queue, "src", m_webkitVideoSink, "sink", GST_PAD_LINK_CHECK_NOTHING);
+#else
gst_element_link(queue, m_webkitVideoSink);
+#endif
LOG_VERBOSE(Media, "Can't display FPS statistics, you need gst-plugins-bad >= 0.10.18");
}
} else {
gst_bin_add(GST_BIN(m_videoSinkBin), m_webkitVideoSink);
+#if GST_CHECK_VERSION(0, 10, 30)
+ // Faster elements linking, if possible.
+ gst_element_link_pads_full(queue, "src", identity, "sink", GST_PAD_LINK_CHECK_NOTHING);
+ gst_element_link_pads_full(identity, "src", m_webkitVideoSink, "sink", GST_PAD_LINK_CHECK_NOTHING);
+#else
gst_element_link_many(queue, identity, m_webkitVideoSink, NULL);
+#endif
}
// Add a ghostpad to the bin so it can proxy to tee.
diff --git a/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h b/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h
index 800ca6d..11eb81b 100644
--- a/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h
+++ b/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h
@@ -43,11 +43,19 @@ class GraphicsContext;
class IntSize;
class IntRect;
class GStreamerGWorld;
+class MediaPlayerPrivateGStreamer;
gboolean mediaPlayerPrivateMessageCallback(GstBus* bus, GstMessage* message, gpointer data);
void mediaPlayerPrivateVolumeChangedCallback(GObject* element, GParamSpec* pspec, gpointer data);
void mediaPlayerPrivateMuteChangedCallback(GObject* element, GParamSpec* pspec, gpointer data);
void mediaPlayerPrivateSourceChangedCallback(GObject* element, GParamSpec* pspec, gpointer data);
+void mediaPlayerPrivateVideoTagsChangedCallback(GObject* element, gint, MediaPlayerPrivateGStreamer*);
+void mediaPlayerPrivateAudioTagsChangedCallback(GObject* element, gint, MediaPlayerPrivateGStreamer*);
+gboolean mediaPlayerPrivateAudioTagsChangeTimeoutCallback(MediaPlayerPrivateGStreamer* player);
+gboolean mediaPlayerPrivateVideoTagsChangeTimeoutCallback(MediaPlayerPrivateGStreamer* player);
+
+gboolean mediaPlayerPrivateVolumeChangeTimeoutCallback(MediaPlayerPrivateGStreamer*);
+gboolean mediaPlayerPrivateMuteChangeTimeoutCallback(MediaPlayerPrivateGStreamer*);
class MediaPlayerPrivateGStreamer : public MediaPlayerPrivateInterface {
friend gboolean mediaPlayerPrivateMessageCallback(GstBus* bus, GstMessage* message, gpointer data);
@@ -58,8 +66,8 @@ class MediaPlayerPrivateGStreamer : public MediaPlayerPrivateInterface {
static void registerMediaEngine(MediaEngineRegistrar);
IntSize naturalSize() const;
- bool hasVideo() const;
- bool hasAudio() const;
+ bool hasVideo() const { return m_hasVideo; }
+ bool hasAudio() const { return m_hasAudio; }
void load(const String &url);
void commitLoad();
@@ -81,13 +89,14 @@ class MediaPlayerPrivateGStreamer : public MediaPlayerPrivateInterface {
void setVolume(float);
void volumeChanged();
- void volumeChangedTimerFired(Timer<MediaPlayerPrivateGStreamer>*);
+ void notifyPlayerOfVolumeChange();
bool supportsMuting() const;
void setMuted(bool);
void muteChanged();
- void muteChangedTimerFired(Timer<MediaPlayerPrivateGStreamer>*);
+ void notifyPlayerOfMute();
+ bool loadDelayed() const { return m_delayingLoad; }
void setPreload(MediaPlayer::Preload);
void fillTimerFired(Timer<MediaPlayerPrivateGStreamer>*);
@@ -121,6 +130,11 @@ class MediaPlayerPrivateGStreamer : public MediaPlayerPrivateInterface {
GstElement* pipeline() const { return m_playBin; }
bool pipelineReset() const { return m_resetPipeline; }
+ void videoTagsChanged(gint);
+ void audioTagsChanged(gint);
+ void notifyPlayerOfVideoTags();
+ void notifyPlayerOfAudioTags();
+
private:
MediaPlayerPrivateGStreamer(MediaPlayer*);
~MediaPlayerPrivateGStreamer();
@@ -133,10 +147,7 @@ class MediaPlayerPrivateGStreamer : public MediaPlayerPrivateInterface {
void cacheDuration();
void updateStates();
- void cancelSeek();
- void endPointTimerFired(Timer<MediaPlayerPrivateGStreamer>*);
float maxTimeLoaded() const;
- void startEndPointTimerIfNeeded();
void createGSTPlayBin();
bool changePipelineState(GstState state);
@@ -176,6 +187,12 @@ class MediaPlayerPrivateGStreamer : public MediaPlayerPrivateInterface {
bool m_delayingLoad;
bool m_mediaDurationKnown;
RefPtr<GStreamerGWorld> m_gstGWorld;
+ guint m_volumeTimerHandler;
+ guint m_muteTimerHandler;
+ bool m_hasVideo;
+ bool m_hasAudio;
+ guint m_audioTagsTimerHandler;
+ guint m_videoTagsTimerHandler;
};
}
diff --git a/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp b/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp
index 635feff..e10e61f 100644
--- a/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp
+++ b/WebCore/platform/graphics/gstreamer/WebKitWebSourceGStreamer.cpp
@@ -110,6 +110,7 @@ static void webKitWebSrcFinalize(GObject* object);
static void webKitWebSrcSetProperty(GObject* object, guint propID, const GValue* value, GParamSpec* pspec);
static void webKitWebSrcGetProperty(GObject* object, guint propID, GValue* value, GParamSpec* pspec);
static GstStateChangeReturn webKitWebSrcChangeState(GstElement* element, GstStateChange transition);
+static gboolean webKitWebSrcQuery(GstPad* pad, GstQuery* query);
static void webKitWebSrcNeedDataCb(GstAppSrc* appsrc, guint length, gpointer userData);
static void webKitWebSrcEnoughDataCb(GstAppSrc* appsrc, gpointer userData);
@@ -221,6 +222,7 @@ static void webkit_web_src_init(WebKitWebSrc* src,
padTemplate);
gst_element_add_pad(GST_ELEMENT(src), priv->srcpad);
+ gst_pad_set_query_function(priv->srcpad, webKitWebSrcQuery);
priv->appsrc = GST_APP_SRC(gst_element_factory_make("appsrc", 0));
if (!priv->appsrc) {
@@ -476,6 +478,36 @@ static GstStateChangeReturn webKitWebSrcChangeState(GstElement* element, GstStat
return ret;
}
+static gboolean webKitWebSrcQuery(GstPad* pad, GstQuery* query)
+{
+ WebKitWebSrc* src = WEBKIT_WEB_SRC(gst_pad_get_parent(pad));
+ gboolean result = FALSE;
+
+ switch (GST_QUERY_TYPE(query)) {
+ case GST_QUERY_DURATION:
+ {
+ GstFormat format;
+
+ gst_query_parse_duration(query, &format, NULL);
+
+ GST_DEBUG_OBJECT(src, "duration query in format %s", gst_format_get_name(format));
+ if ((format == GST_FORMAT_BYTES) && (src->priv->size > 0)) {
+ gst_query_set_duration(query, format, src->priv->size);
+ result = TRUE;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+
+ if (!result)
+ result = gst_pad_query_default(pad, query);
+
+ gst_object_unref(src);
+ return result;
+}
+
// uri handler interface
static GstURIType webKitWebSrcUriGetType(void)
@@ -541,13 +573,7 @@ static gboolean webKitWebSrcNeedDataMainCb(WebKitWebSrc* src)
{
WebKitWebSrcPrivate* priv = src->priv;
-#if USE(NETWORK_SOUP)
- ResourceHandleInternal* d = priv->resourceHandle->getInternal();
- if (d->m_msg)
- soup_session_unpause_message(ResourceHandle::defaultSession(), d->m_msg);
-#endif
- // Ports not using libsoup need to call the unpause/schedule API of their
- // underlying network implementation here.
+ priv->resourceHandle->setDefersLoading(false);
GST_OBJECT_LOCK(src);
priv->paused = FALSE;
@@ -577,12 +603,7 @@ static gboolean webKitWebSrcEnoughDataMainCb(WebKitWebSrc* src)
{
WebKitWebSrcPrivate* priv = src->priv;
-#if USE(NETWORK_SOUP)
- ResourceHandleInternal* d = priv->resourceHandle->getInternal();
- soup_session_pause_message(ResourceHandle::defaultSession(), d->m_msg);
-#endif
- // Ports not using libsoup need to call the pause/unschedule API of their
- // underlying network implementation here.
+ priv->resourceHandle->setDefersLoading(true);
GST_OBJECT_LOCK(src);
priv->paused = TRUE;
diff --git a/WebCore/platform/graphics/gtk/FontGtk.cpp b/WebCore/platform/graphics/gtk/FontGtk.cpp
index 54e18c9..eabd913 100644
--- a/WebCore/platform/graphics/gtk/FontGtk.cpp
+++ b/WebCore/platform/graphics/gtk/FontGtk.cpp
@@ -36,6 +36,7 @@
#include "CairoUtilities.h"
#include "ContextShadow.h"
#include "GraphicsContext.h"
+#include "NotImplemented.h"
#include "SimpleFontData.h"
#include <cairo.h>
#include <gdk/gdk.h>
@@ -218,13 +219,13 @@ static void drawGlyphsShadow(GraphicsContext* graphicsContext, cairo_t* context,
ContextShadow* shadow = graphicsContext->contextShadow();
ASSERT(shadow);
- if (!(graphicsContext->textDrawingMode() & cTextFill) || shadow->m_type == ContextShadow::NoShadow)
+ if (!(graphicsContext->textDrawingMode() & TextModeFill) || shadow->m_type == ContextShadow::NoShadow)
return;
FloatPoint totalOffset(point + shadow->m_offset);
// Optimize non-blurry shadows, by just drawing text without the ContextShadow.
- if (shadow->m_type == ContextShadow::SolidShadow) {
+ if (!shadow->mustUseContextShadow(context)) {
cairo_save(context);
cairo_translate(context, totalOffset.x(), totalOffset.y());
@@ -300,7 +301,7 @@ void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const F
pango_cairo_show_layout_line(cr, layoutLine);
- if (context->textDrawingMode() & cTextStroke) {
+ if (context->textDrawingMode() & TextModeStroke) {
Color strokeColor = context->strokeColor();
strokeColor.getRGBA(red, green, blue, alpha);
cairo_set_source_rgba(cr, red, green, blue, alpha);
@@ -319,6 +320,11 @@ void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const F
cairo_restore(cr);
}
+void Font::drawEmphasisMarksForComplexText(GraphicsContext* /* context */, const TextRun& /* run */, const AtomicString& /* mark */, const FloatPoint& /* point */, int /* from */, int /* to */) const
+{
+ notImplemented();
+}
+
// We should create the layout with our actual context but we can't access it from here.
static PangoLayout* getDefaultPangoLayout(const TextRun& run)
{
diff --git a/WebCore/platform/graphics/gtk/ImageBufferGtk.cpp b/WebCore/platform/graphics/gtk/ImageBufferGtk.cpp
index 486a317..cf0470f 100644
--- a/WebCore/platform/graphics/gtk/ImageBufferGtk.cpp
+++ b/WebCore/platform/graphics/gtk/ImageBufferGtk.cpp
@@ -66,9 +66,8 @@ String ImageBuffer::toDataURL(const String& mimeType, const double* quality) con
Vector<char> out;
base64Encode(reinterpret_cast<const char*>(buffer.get()), bufferSize, out);
- out.append('\0');
- return makeString("data:", mimeType, ";base64,", out.data());
+ return makeString("data:", mimeType, ";base64,", out);
}
}
diff --git a/WebCore/platform/graphics/haiku/FontHaiku.cpp b/WebCore/platform/graphics/haiku/FontHaiku.cpp
index a991bfc..819fecb 100644
--- a/WebCore/platform/graphics/haiku/FontHaiku.cpp
+++ b/WebCore/platform/graphics/haiku/FontHaiku.cpp
@@ -93,6 +93,10 @@ void Font::drawComplexText(GraphicsContext* ctx, const TextRun& run, const Float
notImplemented();
}
+void Font::drawEmphasisMarksForComplexText(GraphicsContext* /* context */, const TextRun& /* run */, const AtomicString& /* mark */, const FloatPoint& /* point */, int /* from */, int /* to */) const
+{
+ notImplemented();
+}
float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
{
diff --git a/WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp b/WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp
index 05012e8..38c1fb7 100644
--- a/WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp
+++ b/WebCore/platform/graphics/haiku/GraphicsContextHaiku.cpp
@@ -62,16 +62,14 @@ GraphicsContextPlatformPrivate::~GraphicsContextPlatformPrivate()
{
}
-GraphicsContext::GraphicsContext(PlatformGraphicsContext* context)
- : m_common(createGraphicsContextPrivate())
- , m_data(new GraphicsContextPlatformPrivate(context))
+void GraphicsContext::platformInit(PlatformGraphicsContext* context)
{
+ m_data = new GraphicsContextPlatformPrivate(context);
setPaintingDisabled(!context);
}
-GraphicsContext::~GraphicsContext()
+void GraphicsContext::platformDestroy()
{
- destroyGraphicsContextPrivate(m_common);
delete m_data;
}
@@ -132,7 +130,7 @@ void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSp
m_data->m_view->StrokeArc(rect, startAngle, angleSpan, getHaikuStrokeStyle());
}
-void GraphicsContext::strokePath()
+void GraphicsContext::strokePath(const Path&)
{
notImplemented();
}
@@ -191,17 +189,7 @@ void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLef
// FillRect and FillArc calls are needed.
}
-void GraphicsContext::fillPath()
-{
- notImplemented();
-}
-
-void GraphicsContext::beginPath()
-{
- notImplemented();
-}
-
-void GraphicsContext::addPath(const Path& path)
+void GraphicsContext::fillPath(const Path&)
{
notImplemented();
}
@@ -355,7 +343,7 @@ void GraphicsContext::setAlpha(float opacity)
notImplemented();
}
-void GraphicsContext::setCompositeOperation(CompositeOperator op)
+void GraphicsContext::setPlatformCompositeOperation(CompositeOperator op)
{
if (paintingDisabled())
return;
@@ -370,7 +358,7 @@ void GraphicsContext::setCompositeOperation(CompositeOperator op)
mode = B_OP_OVER;
break;
default:
- printf("GraphicsContext::setCompositeOperation: Unsupported composite operation %s\n",
+ printf("GraphicsContext::setPlatformCompositeOperation: Unsupported composite operation %s\n",
compositeOperatorName(op).utf8().data());
}
m_data->m_view->SetDrawingMode(mode);
diff --git a/WebCore/platform/graphics/haiku/ImageBufferHaiku.cpp b/WebCore/platform/graphics/haiku/ImageBufferHaiku.cpp
index d1b06f3..cc12de7 100644
--- a/WebCore/platform/graphics/haiku/ImageBufferHaiku.cpp
+++ b/WebCore/platform/graphics/haiku/ImageBufferHaiku.cpp
@@ -66,7 +66,7 @@ ImageBufferData::~ImageBufferData()
m_bitmap.Unlock();
}
-ImageBuffer::ImageBuffer(const IntSize& size, ImageColorSpace imageColorSpace, bool& success)
+ImageBuffer::ImageBuffer(const IntSize& size, ImageColorSpace imageColorSpace, RenderingMode, bool& success)
: m_data(size)
, m_size(size)
{
@@ -368,7 +368,7 @@ String ImageBuffer::toDataURL(const String& mimeType, const double*) const
base64Encode(reinterpret_cast<const char*>(translatedStream.Buffer()),
translatedStream.BufferLength(), encodedBuffer);
- return makeString("data:", mimeType, ";base64,", encodedBuffer.data());
+ return makeString("data:", mimeType, ";base64,", encodedBuffer);
}
} // namespace WebCore
diff --git a/WebCore/platform/graphics/haiku/SimpleFontDataHaiku.cpp b/WebCore/platform/graphics/haiku/SimpleFontDataHaiku.cpp
index a960972..b1e7082 100644
--- a/WebCore/platform/graphics/haiku/SimpleFontDataHaiku.cpp
+++ b/WebCore/platform/graphics/haiku/SimpleFontDataHaiku.cpp
@@ -66,15 +66,32 @@ void SimpleFontData::platformDestroy()
{
}
+SimpleFontData* SimpleFontData::scaledFontData(const FontDescription& fontDescription, float scaleFactor) const
+{
+ FontDescription desc = FontDescription(fontDescription);
+ desc.setSpecifiedSize(scaleFactor * fontDescription.computedSize());
+ FontPlatformData fontPlatformData(desc, desc.family().family());
+ return new SimpleFontData(fontPlatformData, isCustomFont(), false);
+}
+
SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const
{
- if (!m_smallCapsFontData) {
- FontDescription desc = FontDescription(fontDescription);
- desc.setSpecifiedSize(0.70f * fontDescription.computedSize());
- FontPlatformData fontPlatformData(desc, desc.family().family());
- m_smallCapsFontData = new SimpleFontData(fontPlatformData, isCustomFont(), false);
- }
- return m_smallCapsFontData;
+ if (!m_derivedFontData)
+ m_derivedFontData = DerivedFontData::create(isCustomFont());
+ if (!m_derivedFontData->smallCaps)
+ m_derivedFontData->smallCaps = scaledFontData(fontDescription, .7);
+
+ return m_derivedFontData->smallCaps.get();
+}
+
+SimpleFontData* SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const
+{
+ if (!m_derivedFontData)
+ m_derivedFontData = DerivedFontData::create(isCustomFont());
+ if (!m_derivedFontData->emphasisMark)
+ m_derivedFontData->emphasisMark = scaledFontData(fontDescription, .5);
+
+ return m_derivedFontData->emphasisMark.get();
}
bool SimpleFontData::containsCharacters(const UChar* characters, int length) const
diff --git a/WebCore/platform/graphics/mac/ComplexTextController.cpp b/WebCore/platform/graphics/mac/ComplexTextController.cpp
index e6a7bef..206fd5f 100644
--- a/WebCore/platform/graphics/mac/ComplexTextController.cpp
+++ b/WebCore/platform/graphics/mac/ComplexTextController.cpp
@@ -56,10 +56,11 @@ static inline CGFloat ceilCGFloat(CGFloat f)
return static_cast<CGFloat>(ceil(f));
}
-ComplexTextController::ComplexTextController(const Font* font, const TextRun& run, bool mayUseNaturalWritingDirection, HashSet<const SimpleFontData*>* fallbackFonts)
+ComplexTextController::ComplexTextController(const Font* font, const TextRun& run, bool mayUseNaturalWritingDirection, HashSet<const SimpleFontData*>* fallbackFonts, bool forTextEmphasis)
: m_font(*font)
, m_run(run)
, m_mayUseNaturalWritingDirection(mayUseNaturalWritingDirection)
+ , m_forTextEmphasis(forTextEmphasis)
, m_currentCharacter(0)
, m_end(run.length())
, m_totalWidth(0)
@@ -240,7 +241,7 @@ void ComplexTextController::collectComplexTextRuns()
nextGlyphData = m_font.glyphDataForCharacter(U16_GET_SUPPLEMENTARY(curr[-1], curr[0]), false);
}
} else
- nextGlyphData = m_font.glyphDataForCharacter(*curr, false, forceSmallCaps);
+ nextGlyphData = m_font.glyphDataForCharacter(*curr, false, forceSmallCaps ? SmallCapsVariant : AutoVariant);
if (!isSurrogate && m_font.isSmallCaps()) {
nextIsSmallCaps = forceSmallCaps || (newC = u_toupper(c)) != c;
@@ -462,7 +463,7 @@ void ComplexTextController::adjustGlyphsAndAdvances()
if (ch == '\t' && m_run.allowTabs()) {
float tabWidth = m_font.tabWidth(*fontData);
advance.width = tabWidth - fmodf(m_run.xPos() + m_totalWidth + widthSinceLastRounding, tabWidth);
- } else if (ch == zeroWidthSpace || Font::treatAsZeroWidthSpace(ch) && !treatAsSpace) {
+ } else if (ch == zeroWidthSpace || (Font::treatAsZeroWidthSpace(ch) && !treatAsSpace)) {
advance.width = 0;
glyph = fontData->spaceGlyph();
}
@@ -518,7 +519,7 @@ void ComplexTextController::adjustGlyphsAndAdvances()
// Check to see if the next character is a "rounding hack character", if so, adjust the
// width so that the total run width will be on an integer boundary.
- if (m_run.applyWordRounding() && !lastGlyph && Font::isRoundingHackCharacter(nextCh) || m_run.applyRunRounding() && lastGlyph) {
+ if ((m_run.applyWordRounding() && !lastGlyph && Font::isRoundingHackCharacter(nextCh)) || (m_run.applyRunRounding() && lastGlyph)) {
CGFloat totalWidth = widthSinceLastRounding + advance.width;
widthSinceLastRounding = ceilCGFloat(totalWidth);
CGFloat extraWidth = widthSinceLastRounding - totalWidth;
@@ -536,6 +537,10 @@ void ComplexTextController::adjustGlyphsAndAdvances()
} else
widthSinceLastRounding += advance.width;
+ // FIXME: Combining marks should receive a text emphasis mark if they are combine with a space.
+ if (m_forTextEmphasis && (!Font::canReceiveTextEmphasis(ch) || (U_GET_GC_MASK(ch) & U_GC_M_MASK)))
+ glyph = 0;
+
advance.height *= -1;
m_adjustedAdvances.append(advance);
m_adjustedGlyphs.append(glyph);
diff --git a/WebCore/platform/graphics/mac/ComplexTextController.h b/WebCore/platform/graphics/mac/ComplexTextController.h
index 85407c7..9cf80a6 100644
--- a/WebCore/platform/graphics/mac/ComplexTextController.h
+++ b/WebCore/platform/graphics/mac/ComplexTextController.h
@@ -47,7 +47,7 @@ class TextRun;
// OS Versions >= 10.6, ATSUI is used otherwise.
class ComplexTextController {
public:
- ComplexTextController(const Font*, const TextRun&, bool mayUseNaturalWritingDirection = false, HashSet<const SimpleFontData*>* fallbackFonts = 0);
+ ComplexTextController(const Font*, const TextRun&, bool mayUseNaturalWritingDirection = false, HashSet<const SimpleFontData*>* fallbackFonts = 0, bool forTextEmphasis = false);
// Advance and emit glyphs up to the specified character.
void advance(unsigned to, GlyphBuffer* = 0);
@@ -156,6 +156,7 @@ private:
const Font& m_font;
const TextRun& m_run;
bool m_mayUseNaturalWritingDirection;
+ bool m_forTextEmphasis;
Vector<UChar, 256> m_smallCapsBuffer;
diff --git a/WebCore/platform/graphics/mac/FontComplexTextMac.cpp b/WebCore/platform/graphics/mac/FontComplexTextMac.cpp
index 05eae03..ca006d9 100644
--- a/WebCore/platform/graphics/mac/FontComplexTextMac.cpp
+++ b/WebCore/platform/graphics/mac/FontComplexTextMac.cpp
@@ -55,34 +55,55 @@ FloatRect Font::selectionRectForComplexText(const TextRun& run, const FloatPoint
return FloatRect(point.x() + floorf(beforeWidth), point.y(), roundf(afterWidth) - floorf(beforeWidth), h);
}
-void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const FloatPoint& point,
- int from, int to) const
+float Font::getGlyphsAndAdvancesForComplexText(const TextRun& run, int from, int to, GlyphBuffer& glyphBuffer, ForTextEmphasisOrNot forTextEmphasis) const
{
- // This glyph buffer holds our glyphs + advances + font data for each glyph.
- GlyphBuffer glyphBuffer;
+ float initialAdvance;
- float startX = point.x();
- ComplexTextController controller(this, run);
+ ComplexTextController controller(this, run, false, 0, forTextEmphasis);
controller.advance(from);
float beforeWidth = controller.runWidthSoFar();
controller.advance(to, &glyphBuffer);
-
- // We couldn't generate any glyphs for the run. Give up.
+
if (glyphBuffer.isEmpty())
- return;
-
+ return 0;
+
float afterWidth = controller.runWidthSoFar();
if (run.rtl()) {
- startX += controller.totalWidth() + controller.finalRoundingWidth() - afterWidth;
+ initialAdvance = controller.totalWidth() + controller.finalRoundingWidth() - afterWidth;
for (int i = 0, end = glyphBuffer.size() - 1; i < glyphBuffer.size() / 2; ++i, --end)
glyphBuffer.swap(i, end);
} else
- startX += beforeWidth;
+ initialAdvance = beforeWidth;
+
+ return initialAdvance;
+}
+
+void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const
+{
+ // This glyph buffer holds our glyphs + advances + font data for each glyph.
+ GlyphBuffer glyphBuffer;
+
+ float startX = point.x() + getGlyphsAndAdvancesForComplexText(run, from, to, glyphBuffer);
+
+ // We couldn't generate any glyphs for the run. Give up.
+ if (glyphBuffer.isEmpty())
+ return;
// Draw the glyph buffer now at the starting point returned in startX.
FloatPoint startPoint(startX, point.y());
- drawGlyphBuffer(context, glyphBuffer, run, startPoint);
+ drawGlyphBuffer(context, glyphBuffer, startPoint);
+}
+
+void Font::drawEmphasisMarksForComplexText(GraphicsContext* context, const TextRun& run, const AtomicString& mark, const FloatPoint& point, int from, int to) const
+{
+ GlyphBuffer glyphBuffer;
+ float initialAdvance = getGlyphsAndAdvancesForComplexText(run, from, to, glyphBuffer, ForTextEmphasis);
+
+ if (glyphBuffer.isEmpty())
+ return;
+
+ drawEmphasisMarks(context, glyphBuffer, mark, FloatPoint(point.x() + initialAdvance, point.y()));
}
float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
diff --git a/WebCore/platform/graphics/mac/FontMac.mm b/WebCore/platform/graphics/mac/FontMac.mm
index 8dc741b..8519667 100644
--- a/WebCore/platform/graphics/mac/FontMac.mm
+++ b/WebCore/platform/graphics/mac/FontMac.mm
@@ -91,22 +91,27 @@ static void showGlyphsWithAdvances(const SimpleFontData* font, CGContextRef cont
void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, const GlyphBuffer& glyphBuffer, int from, int numGlyphs, const FloatPoint& point) const
{
CGContextRef cgContext = context->platformContext();
- bool newShouldUseFontSmoothing = shouldUseSmoothing();
+ bool shouldSmoothFonts = true;
+ bool changeFontSmoothing = false;
+
switch(fontDescription().fontSmoothing()) {
case Antialiased: {
context->setShouldAntialias(true);
- newShouldUseFontSmoothing = false;
+ shouldSmoothFonts = false;
+ changeFontSmoothing = true;
break;
}
case SubpixelAntialiased: {
context->setShouldAntialias(true);
- newShouldUseFontSmoothing = true;
+ shouldSmoothFonts = true;
+ changeFontSmoothing = true;
break;
}
case NoSmoothing: {
context->setShouldAntialias(false);
- newShouldUseFontSmoothing = false;
+ shouldSmoothFonts = false;
+ changeFontSmoothing = true;
break;
}
case AutoSmoothing: {
@@ -116,11 +121,18 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons
default:
ASSERT_NOT_REACHED();
}
-
- bool originalShouldUseFontSmoothing = wkCGContextGetShouldSmoothFonts(cgContext);
- if (originalShouldUseFontSmoothing != newShouldUseFontSmoothing)
- CGContextSetShouldSmoothFonts(cgContext, newShouldUseFontSmoothing);
+ if (!shouldUseSmoothing()) {
+ shouldSmoothFonts = false;
+ changeFontSmoothing = true;
+ }
+
+ bool originalShouldUseFontSmoothing = false;
+ if (changeFontSmoothing) {
+ originalShouldUseFontSmoothing = wkCGContextGetShouldSmoothFonts(cgContext);
+ CGContextSetShouldSmoothFonts(cgContext, shouldSmoothFonts);
+ }
+
const FontPlatformData& platformData = font->platformData();
NSFont* drawFont;
if (!isPrinterFont()) {
@@ -157,20 +169,24 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons
FloatSize shadowOffset;
float shadowBlur;
Color shadowColor;
+ ColorSpace shadowColorSpace;
ColorSpace fillColorSpace = context->fillColorSpace();
- context->getShadow(shadowOffset, shadowBlur, shadowColor);
+ context->getShadow(shadowOffset, shadowBlur, shadowColor, shadowColorSpace);
- bool hasSimpleShadow = context->textDrawingMode() == cTextFill && shadowColor.isValid() && !shadowBlur && !platformData.isColorBitmapFont();
+ bool hasSimpleShadow = context->textDrawingMode() == TextModeFill && shadowColor.isValid() && !shadowBlur && !platformData.isColorBitmapFont() && (!context->shadowsIgnoreTransforms() || context->getCTM().isIdentityOrTranslationOrFlipped());
if (hasSimpleShadow) {
// Paint simple shadows ourselves instead of relying on CG shadows, to avoid losing subpixel antialiasing.
context->clearShadow();
Color fillColor = context->fillColor();
Color shadowFillColor(shadowColor.red(), shadowColor.green(), shadowColor.blue(), shadowColor.alpha() * fillColor.alpha() / 255);
- context->setFillColor(shadowFillColor, fillColorSpace);
- CGContextSetTextPosition(cgContext, point.x() + shadowOffset.width(), point.y() + shadowOffset.height());
+ context->setFillColor(shadowFillColor, shadowColorSpace);
+ 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, point.x() + shadowOffset.width() + font->syntheticBoldOffset(), point.y() + shadowOffset.height());
+ CGContextSetTextPosition(cgContext, shadowTextX + font->syntheticBoldOffset(), shadowTextY);
showGlyphsWithAdvances(font, cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs);
}
context->setFillColor(fillColor, fillColorSpace);
@@ -184,9 +200,9 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* font, cons
}
if (hasSimpleShadow)
- context->setShadow(shadowOffset, shadowBlur, shadowColor, fillColorSpace);
+ context->setShadow(shadowOffset, shadowBlur, shadowColor, shadowColorSpace);
- if (originalShouldUseFontSmoothing != newShouldUseFontSmoothing)
+ if (changeFontSmoothing)
CGContextSetShouldSmoothFonts(cgContext, originalShouldUseFontSmoothing);
}
diff --git a/WebCore/platform/graphics/mac/GlyphPageTreeNodeMac.cpp b/WebCore/platform/graphics/mac/GlyphPageTreeNodeMac.cpp
index 9524cd2..5388c24 100644
--- a/WebCore/platform/graphics/mac/GlyphPageTreeNodeMac.cpp
+++ b/WebCore/platform/graphics/mac/GlyphPageTreeNodeMac.cpp
@@ -28,6 +28,7 @@
#include "config.h"
#include "GlyphPageTreeNode.h"
+#include "Font.h"
#include "SimpleFontData.h"
#include "WebCoreSystemInterface.h"
@@ -35,12 +36,27 @@
namespace WebCore {
+#ifndef BUILDING_ON_TIGER
+static bool shouldUseCoreText(UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData)
+{
+ if (fontData->orientation() == Vertical && !fontData->isBrokenIdeographFont()) {
+ // Ideographs don't have a vertical variant.
+ for (unsigned i = 0; i < bufferLength; ++i) {
+ if (!Font::isCJKIdeograph(buffer[i]))
+ return true;
+ }
+ }
+
+ return false;
+}
+#endif
+
bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData)
{
bool haveGlyphs = false;
#ifndef BUILDING_ON_TIGER
- if (fontData->orientation() == Horizontal || fontData->isBrokenIdeographFont()) {
+ if (!shouldUseCoreText(buffer, bufferLength, fontData)) {
Vector<CGGlyph, 512> glyphs(bufferLength);
wkGetGlyphsForCharacters(fontData->platformData().cgFont(), buffer, glyphs.data(), bufferLength);
for (unsigned i = 0; i < length; ++i) {
diff --git a/WebCore/platform/graphics/mac/GraphicsContextMac.mm b/WebCore/platform/graphics/mac/GraphicsContextMac.mm
index c149d70..6a4fa03 100644
--- a/WebCore/platform/graphics/mac/GraphicsContextMac.mm
+++ b/WebCore/platform/graphics/mac/GraphicsContextMac.mm
@@ -87,8 +87,8 @@ void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int width, int
drawFocusRingToContext(platformContext(), focusRingPath.get(), colorRef, radius);
}
-#ifdef BUILDING_ON_TIGER // Post-Tiger's setCompositeOperation() is defined in GraphicsContextCG.cpp.
-void GraphicsContext::setCompositeOperation(CompositeOperator op)
+#ifdef BUILDING_ON_TIGER // Post-Tiger's setPlatformCompositeOperation() is defined in GraphicsContextCG.cpp.
+void GraphicsContext::setPlatformCompositeOperation(CompositeOperator op)
{
if (paintingDisabled())
return;
diff --git a/WebCore/platform/graphics/mac/GraphicsLayerMac.mm b/WebCore/platform/graphics/mac/GraphicsLayerMac.mm
deleted file mode 100644
index f9b16a0..0000000
--- a/WebCore/platform/graphics/mac/GraphicsLayerMac.mm
+++ /dev/null
@@ -1,2514 +0,0 @@
-/*
- * Copyright (C) 2009 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 COMPUTER, 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.
- */
-
-#import "config.h"
-
-#if USE(ACCELERATED_COMPOSITING)
-
-#import "GraphicsLayerMac.h"
-
-#import "Animation.h"
-#import "BlockExceptions.h"
-#import "FloatConversion.h"
-#import "FloatRect.h"
-#import "Image.h"
-#import "PlatformString.h"
-#import <QuartzCore/QuartzCore.h>
-#import "RotateTransformOperation.h"
-#import "ScaleTransformOperation.h"
-#import "SystemTime.h"
-#import "TranslateTransformOperation.h"
-#import "WebLayer.h"
-#import "WebTiledLayer.h"
-#import <limits.h>
-#import <objc/objc-auto.h>
-#import <wtf/CurrentTime.h>
-#import <wtf/UnusedParam.h>
-#import <wtf/RetainPtr.h>
-#import <wtf/text/StringConcatenate.h>
-
-using namespace std;
-
-#define HAVE_MODERN_QUARTZCORE (!defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD))
-
-namespace WebCore {
-
-static NSString * const WebKitAnimationBeginTimeSetKey = @"WebKitAnimationBeginTimeSet";
-
-// The threshold width or height above which a tiled layer will be used. This should be
-// large enough to avoid tiled layers for most GraphicsLayers, but less than the OpenGL
-// texture size limit on all supported hardware.
-static const int cMaxPixelDimension = 2000;
-
-// The width and height of a single tile in a tiled layer. Should be large enough to
-// avoid lots of small tiles (and therefore lots of drawing callbacks), but small enough
-// to keep the overall tile cost low.
-static const int cTiledLayerTileSize = 512;
-
-// If we send a duration of 0 to CA, then it will use the default duration
-// of 250ms. So send a very small value instead.
-static const float cAnimationAlmostZeroDuration = 1e-3f;
-
-// CACurrentMediaTime() is a time since boot. These methods convert between that and
-// WebCore time, which is system time (UTC).
-static CFTimeInterval currentTimeToMediaTime(double t)
-{
- return CACurrentMediaTime() + t - WTF::currentTime();
-}
-
-static double mediaTimeToCurrentTime(CFTimeInterval t)
-{
- return WTF::currentTime() + t - CACurrentMediaTime();
-}
-
-} // namespace WebCore
-
-@interface CALayer(Private)
-- (void)setContentsChanged;
-@end
-
-@interface WebAnimationDelegate : NSObject {
- WebCore::GraphicsLayerMac* m_graphicsLayer;
-}
-
-- (void)animationDidStart:(CAAnimation *)anim;
-- (WebCore::GraphicsLayerMac*)graphicsLayer;
-- (void)setLayer:(WebCore::GraphicsLayerMac*)graphicsLayer;
-
-@end
-
-@implementation WebAnimationDelegate
-
-- (void)animationDidStart:(CAAnimation *)animation
-{
- if (m_graphicsLayer)
- m_graphicsLayer->animationDidStart(animation);
-}
-
-- (WebCore::GraphicsLayerMac*)graphicsLayer
-{
- return m_graphicsLayer;
-}
-
-- (void)setLayer:(WebCore::GraphicsLayerMac*)graphicsLayer
-{
- m_graphicsLayer = graphicsLayer;
-}
-
-@end
-
-namespace WebCore {
-
-static inline void copyTransform(CATransform3D& toT3D, const TransformationMatrix& t)
-{
- toT3D.m11 = narrowPrecisionToFloat(t.m11());
- toT3D.m12 = narrowPrecisionToFloat(t.m12());
- toT3D.m13 = narrowPrecisionToFloat(t.m13());
- toT3D.m14 = narrowPrecisionToFloat(t.m14());
- toT3D.m21 = narrowPrecisionToFloat(t.m21());
- toT3D.m22 = narrowPrecisionToFloat(t.m22());
- toT3D.m23 = narrowPrecisionToFloat(t.m23());
- toT3D.m24 = narrowPrecisionToFloat(t.m24());
- toT3D.m31 = narrowPrecisionToFloat(t.m31());
- toT3D.m32 = narrowPrecisionToFloat(t.m32());
- toT3D.m33 = narrowPrecisionToFloat(t.m33());
- toT3D.m34 = narrowPrecisionToFloat(t.m34());
- toT3D.m41 = narrowPrecisionToFloat(t.m41());
- toT3D.m42 = narrowPrecisionToFloat(t.m42());
- toT3D.m43 = narrowPrecisionToFloat(t.m43());
- toT3D.m44 = narrowPrecisionToFloat(t.m44());
-}
-
-static NSValue* getTransformFunctionValue(const TransformOperation* transformOp, TransformOperation::OperationType transformType, const IntSize& size)
-{
- switch (transformType) {
- case TransformOperation::ROTATE:
- case TransformOperation::ROTATE_X:
- case TransformOperation::ROTATE_Y:
- return [NSNumber numberWithDouble:transformOp ? deg2rad(static_cast<const RotateTransformOperation*>(transformOp)->angle()) : 0];
- case TransformOperation::SCALE_X:
- return [NSNumber numberWithDouble:transformOp ? static_cast<const ScaleTransformOperation*>(transformOp)->x() : 1];
- case TransformOperation::SCALE_Y:
- return [NSNumber numberWithDouble:transformOp ? static_cast<const ScaleTransformOperation*>(transformOp)->y() : 1];
- case TransformOperation::SCALE_Z:
- return [NSNumber numberWithDouble:transformOp ? static_cast<const ScaleTransformOperation*>(transformOp)->z() : 1];
- case TransformOperation::TRANSLATE_X:
- return [NSNumber numberWithDouble:transformOp ? static_cast<const TranslateTransformOperation*>(transformOp)->x(size) : 0];
- case TransformOperation::TRANSLATE_Y:
- return [NSNumber numberWithDouble:transformOp ? static_cast<const TranslateTransformOperation*>(transformOp)->y(size) : 0];
- case TransformOperation::TRANSLATE_Z:
- return [NSNumber numberWithDouble:transformOp ? static_cast<const TranslateTransformOperation*>(transformOp)->z(size) : 0];
- case TransformOperation::SCALE:
- case TransformOperation::SCALE_3D:
- return [NSArray arrayWithObjects:
- [NSNumber numberWithDouble:transformOp ? static_cast<const ScaleTransformOperation*>(transformOp)->x() : 1],
- [NSNumber numberWithDouble:transformOp ? static_cast<const ScaleTransformOperation*>(transformOp)->y() : 1],
- [NSNumber numberWithDouble:transformOp ? static_cast<const ScaleTransformOperation*>(transformOp)->z() : 1],
- nil];
- case TransformOperation::TRANSLATE:
- case TransformOperation::TRANSLATE_3D:
- return [NSArray arrayWithObjects:
- [NSNumber numberWithDouble:transformOp ? static_cast<const TranslateTransformOperation*>(transformOp)->x(size) : 0],
- [NSNumber numberWithDouble:transformOp ? static_cast<const TranslateTransformOperation*>(transformOp)->y(size) : 0],
- [NSNumber numberWithDouble:transformOp ? static_cast<const TranslateTransformOperation*>(transformOp)->z(size) : 0],
- nil];
- case TransformOperation::SKEW_X:
- case TransformOperation::SKEW_Y:
- case TransformOperation::SKEW:
- case TransformOperation::MATRIX:
- case TransformOperation::ROTATE_3D:
- case TransformOperation::MATRIX_3D:
- case TransformOperation::PERSPECTIVE:
- case TransformOperation::IDENTITY:
- case TransformOperation::NONE: {
- TransformationMatrix transform;
- if (transformOp)
- transformOp->apply(transform, size);
- CATransform3D caTransform;
- copyTransform(caTransform, transform);
- return [NSValue valueWithCATransform3D:caTransform];
- }
- }
-
- return 0;
-}
-
-#if HAVE_MODERN_QUARTZCORE
-static NSString *getValueFunctionNameForTransformOperation(TransformOperation::OperationType transformType)
-{
- // Use literal strings to avoid link-time dependency on those symbols.
- switch (transformType) {
- case TransformOperation::ROTATE_X:
- return @"rotateX"; // kCAValueFunctionRotateX;
- case TransformOperation::ROTATE_Y:
- return @"rotateY"; // kCAValueFunctionRotateY;
- case TransformOperation::ROTATE:
- return @"rotateZ"; // kCAValueFunctionRotateZ;
- case TransformOperation::SCALE_X:
- return @"scaleX"; // kCAValueFunctionScaleX;
- case TransformOperation::SCALE_Y:
- return @"scaleY"; // kCAValueFunctionScaleY;
- case TransformOperation::SCALE_Z:
- return @"scaleZ"; // kCAValueFunctionScaleZ;
- case TransformOperation::TRANSLATE_X:
- return @"translateX"; // kCAValueFunctionTranslateX;
- case TransformOperation::TRANSLATE_Y:
- return @"translateY"; // kCAValueFunctionTranslateY;
- case TransformOperation::TRANSLATE_Z:
- return @"translateZ"; // kCAValueFunctionTranslateZ;
- case TransformOperation::SCALE:
- case TransformOperation::SCALE_3D:
- return @"scale"; // kCAValueFunctionScale;
- case TransformOperation::TRANSLATE:
- case TransformOperation::TRANSLATE_3D:
- return @"translate"; // kCAValueFunctionTranslate;
- default:
- return nil;
- }
-}
-#endif
-
-static String propertyIdToString(AnimatedPropertyID property)
-{
- switch (property) {
- case AnimatedPropertyWebkitTransform:
- return "transform";
- case AnimatedPropertyOpacity:
- return "opacity";
- case AnimatedPropertyBackgroundColor:
- return "backgroundColor";
- case AnimatedPropertyInvalid:
- ASSERT_NOT_REACHED();
- }
- ASSERT_NOT_REACHED();
- return "";
-}
-
-static String animationIdentifier(const String& animationName, AnimatedPropertyID property, int index)
-{
- return makeString(animationName, '_', String::number(property), '_', String::number(index));
-}
-
-static CAMediaTimingFunction* getCAMediaTimingFunction(const TimingFunction* timingFunction)
-{
- // By this point, timing functions can only be linear or cubic, not steps.
- ASSERT(!timingFunction->isStepsTimingFunction());
- if (timingFunction->isCubicBezierTimingFunction()) {
- const CubicBezierTimingFunction* ctf = static_cast<const CubicBezierTimingFunction*>(timingFunction);
- return [CAMediaTimingFunction functionWithControlPoints:static_cast<float>(ctf->x1()) :static_cast<float>(ctf->y1())
- :static_cast<float>(ctf->x2()) :static_cast<float>(ctf->y2())];
- } else
- return [CAMediaTimingFunction functionWithName:@"linear"];
-}
-
-static void setLayerBorderColor(PlatformLayer* layer, const Color& color)
-{
- [layer setBorderColor:cachedCGColor(color, ColorSpaceDeviceRGB)];
-}
-
-static void clearBorderColor(PlatformLayer* layer)
-{
- [layer setBorderColor:nil];
-}
-
-static void setLayerBackgroundColor(PlatformLayer* layer, const Color& color)
-{
- [layer setBackgroundColor:cachedCGColor(color, ColorSpaceDeviceRGB)];
-}
-
-static void clearLayerBackgroundColor(PlatformLayer* layer)
-{
- [layer setBackgroundColor:0];
-}
-
-static void safeSetSublayers(CALayer* layer, NSArray* sublayers)
-{
- // Workaround for <rdar://problem/7390716>: -[CALayer setSublayers:] crashes if sublayers is an empty array, or nil, under GC.
- if (objc_collectingEnabled() && ![sublayers count]) {
- while ([[layer sublayers] count])
- [[[layer sublayers] objectAtIndex:0] removeFromSuperlayer];
- return;
- }
-
- [layer setSublayers:sublayers];
-}
-
-static bool caValueFunctionSupported()
-{
- static bool sHaveValueFunction = [CAPropertyAnimation instancesRespondToSelector:@selector(setValueFunction:)];
- return sHaveValueFunction;
-}
-
-static bool forceSoftwareAnimation()
-{
- static bool forceSoftwareAnimation = [[NSUserDefaults standardUserDefaults] boolForKey:@"WebCoreForceSoftwareAnimation"];
- return forceSoftwareAnimation;
-}
-
-static NSDictionary* nullActionsDictionary()
-{
- NSNull* nullValue = [NSNull null];
- NSDictionary* actions = [NSDictionary dictionaryWithObjectsAndKeys:
- nullValue, @"anchorPoint",
- nullValue, @"bounds",
- nullValue, @"contents",
- nullValue, @"contentsRect",
- nullValue, @"opacity",
- nullValue, @"position",
- nullValue, @"shadowColor",
- nullValue, @"sublayerTransform",
- nullValue, @"sublayers",
- nullValue, @"transform",
- nullValue, @"zPosition",
- nil];
- return actions;
-}
-
-static bool animationHasStepsTimingFunction(const KeyframeValueList& valueList, const Animation* anim)
-{
- if (anim->timingFunction()->isStepsTimingFunction())
- return true;
-
- for (unsigned i = 0; i < valueList.size(); ++i) {
- const TimingFunction* timingFunction = valueList.at(i)->timingFunction();
- if (timingFunction && timingFunction->isStepsTimingFunction())
- return true;
- }
-
- return false;
-}
-
-PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client)
-{
- return new GraphicsLayerMac(client);
-}
-
-GraphicsLayerMac::GraphicsLayerMac(GraphicsLayerClient* client)
- : GraphicsLayer(client)
- , m_contentsLayerPurpose(NoContentsLayer)
- , m_contentsLayerHasBackgroundColor(false)
- , m_uncommittedChanges(NoChange)
-{
- BEGIN_BLOCK_OBJC_EXCEPTIONS
- m_layer.adoptNS([[WebLayer alloc] init]);
- [m_layer.get() setLayerOwner:this];
-
-#if !HAVE_MODERN_QUARTZCORE
- setContentsOrientation(defaultContentsOrientation());
-#endif
-
- updateDebugIndicators();
-
- m_animationDelegate.adoptNS([[WebAnimationDelegate alloc] init]);
- [m_animationDelegate.get() setLayer:this];
-
- END_BLOCK_OBJC_EXCEPTIONS
-}
-
-GraphicsLayerMac::~GraphicsLayerMac()
-{
- // We release our references to the CALayers here, but do not actively unparent them,
- // since that will cause a commit and break our batched commit model. The layers will
- // get released when the rootmost modified GraphicsLayerMac rebuilds its child layers.
-
- BEGIN_BLOCK_OBJC_EXCEPTIONS
-
- // Clean up the WK layer.
- if (m_layer) {
- WebLayer* layer = m_layer.get();
- [layer setLayerOwner:nil];
- }
-
- if (m_contentsLayer) {
- if ([m_contentsLayer.get() respondsToSelector:@selector(setLayerOwner:)])
- [(id)m_contentsLayer.get() setLayerOwner:nil];
- }
-
- // animationDidStart: can fire after this, so we need to clear out the layer on the delegate.
- [m_animationDelegate.get() setLayer:0];
-
- // Release the clone layers inside the exception-handling block.
- removeCloneLayers();
-
- END_BLOCK_OBJC_EXCEPTIONS
-}
-
-void GraphicsLayerMac::setName(const String& name)
-{
- String longName = String::format("CALayer(%p) GraphicsLayer(%p) ", m_layer.get(), this) + name;
- GraphicsLayer::setName(longName);
- noteLayerPropertyChanged(NameChanged);
-}
-
-NativeLayer GraphicsLayerMac::nativeLayer() const
-{
- return m_layer.get();
-}
-
-bool GraphicsLayerMac::setChildren(const Vector<GraphicsLayer*>& children)
-{
- bool childrenChanged = GraphicsLayer::setChildren(children);
- if (childrenChanged)
- noteSublayersChanged();
-
- return childrenChanged;
-}
-
-void GraphicsLayerMac::addChild(GraphicsLayer* childLayer)
-{
- GraphicsLayer::addChild(childLayer);
- noteSublayersChanged();
-}
-
-void GraphicsLayerMac::addChildAtIndex(GraphicsLayer* childLayer, int index)
-{
- GraphicsLayer::addChildAtIndex(childLayer, index);
- noteSublayersChanged();
-}
-
-void GraphicsLayerMac::addChildBelow(GraphicsLayer* childLayer, GraphicsLayer* sibling)
-{
- GraphicsLayer::addChildBelow(childLayer, sibling);
- noteSublayersChanged();
-}
-
-void GraphicsLayerMac::addChildAbove(GraphicsLayer* childLayer, GraphicsLayer* sibling)
-{
- GraphicsLayer::addChildAbove(childLayer, sibling);
- noteSublayersChanged();
-}
-
-bool GraphicsLayerMac::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild)
-{
- if (GraphicsLayer::replaceChild(oldChild, newChild)) {
- noteSublayersChanged();
- return true;
- }
- return false;
-}
-
-void GraphicsLayerMac::removeFromParent()
-{
- if (m_parent)
- static_cast<GraphicsLayerMac*>(m_parent)->noteSublayersChanged();
- GraphicsLayer::removeFromParent();
-}
-
-void GraphicsLayerMac::setMaskLayer(GraphicsLayer* layer)
-{
- if (layer == m_maskLayer)
- return;
-
- GraphicsLayer::setMaskLayer(layer);
- noteLayerPropertyChanged(MaskLayerChanged);
-
- propagateLayerChangeToReplicas();
-
- if (m_replicatedLayer)
- static_cast<GraphicsLayerMac*>(m_replicatedLayer)->propagateLayerChangeToReplicas();
-}
-
-void GraphicsLayerMac::setReplicatedLayer(GraphicsLayer* layer)
-{
- if (layer == m_replicatedLayer)
- return;
-
- GraphicsLayer::setReplicatedLayer(layer);
- noteLayerPropertyChanged(ReplicatedLayerChanged);
-}
-
-void GraphicsLayerMac::setReplicatedByLayer(GraphicsLayer* layer)
-{
- if (layer == m_replicaLayer)
- return;
-
- GraphicsLayer::setReplicatedByLayer(layer);
- noteSublayersChanged();
- noteLayerPropertyChanged(ReplicatedLayerChanged);
-}
-
-void GraphicsLayerMac::setPosition(const FloatPoint& point)
-{
- if (point == m_position)
- return;
-
- GraphicsLayer::setPosition(point);
- noteLayerPropertyChanged(PositionChanged);
-}
-
-void GraphicsLayerMac::setAnchorPoint(const FloatPoint3D& point)
-{
- if (point == m_anchorPoint)
- return;
-
- GraphicsLayer::setAnchorPoint(point);
- noteLayerPropertyChanged(AnchorPointChanged);
-}
-
-void GraphicsLayerMac::setSize(const FloatSize& size)
-{
- if (size == m_size)
- return;
-
- GraphicsLayer::setSize(size);
- noteLayerPropertyChanged(SizeChanged);
-}
-
-void GraphicsLayerMac::setTransform(const TransformationMatrix& t)
-{
- if (t == m_transform)
- return;
-
- GraphicsLayer::setTransform(t);
- noteLayerPropertyChanged(TransformChanged);
-}
-
-void GraphicsLayerMac::setChildrenTransform(const TransformationMatrix& t)
-{
- if (t == m_childrenTransform)
- return;
-
- GraphicsLayer::setChildrenTransform(t);
- noteLayerPropertyChanged(ChildrenTransformChanged);
-}
-
-void GraphicsLayerMac::moveOrCopyLayerAnimation(MoveOrCopy operation, const String& animationIdentifier, CALayer *fromLayer, CALayer *toLayer)
-{
- NSString *animationID = animationIdentifier;
- CAAnimation *anim = [fromLayer animationForKey:animationID];
- if (!anim)
- return;
-
- switch (operation) {
- case Move:
- [anim retain];
- [fromLayer removeAnimationForKey:animationID];
- [toLayer addAnimation:anim forKey:animationID];
- [anim release];
- break;
-
- case Copy:
- [toLayer addAnimation:anim forKey:animationID];
- break;
- }
-}
-
-void GraphicsLayerMac::moveOrCopyAnimationsForProperty(MoveOrCopy operation, AnimatedPropertyID property, CALayer *fromLayer, CALayer *toLayer)
-{
- // Look for running animations affecting this property.
- AnimationsMap::const_iterator end = m_runningAnimations.end();
- for (AnimationsMap::const_iterator it = m_runningAnimations.begin(); it != end; ++it) {
- const Vector<LayerPropertyAnimation>& propertyAnimations = it->second;
- size_t numAnimations = propertyAnimations.size();
- for (size_t i = 0; i < numAnimations; ++i) {
- const LayerPropertyAnimation& currAnimation = propertyAnimations[i];
- if (currAnimation.m_property == property)
- moveOrCopyLayerAnimation(operation, animationIdentifier(currAnimation.m_name, currAnimation.m_property, currAnimation.m_index), fromLayer, toLayer);
- }
- }
-}
-
-void GraphicsLayerMac::setPreserves3D(bool preserves3D)
-{
- if (preserves3D == m_preserves3D)
- return;
-
- GraphicsLayer::setPreserves3D(preserves3D);
- noteLayerPropertyChanged(Preserves3DChanged);
-}
-
-void GraphicsLayerMac::setMasksToBounds(bool masksToBounds)
-{
- if (masksToBounds == m_masksToBounds)
- return;
-
- GraphicsLayer::setMasksToBounds(masksToBounds);
- noteLayerPropertyChanged(MasksToBoundsChanged);
-}
-
-void GraphicsLayerMac::setDrawsContent(bool drawsContent)
-{
- if (drawsContent == m_drawsContent)
- return;
-
- GraphicsLayer::setDrawsContent(drawsContent);
- noteLayerPropertyChanged(DrawsContentChanged);
-}
-
-void GraphicsLayerMac::setBackgroundColor(const Color& color)
-{
- if (m_backgroundColorSet && m_backgroundColor == color)
- return;
-
- GraphicsLayer::setBackgroundColor(color);
-
- m_contentsLayerHasBackgroundColor = true;
- noteLayerPropertyChanged(BackgroundColorChanged);
-}
-
-void GraphicsLayerMac::clearBackgroundColor()
-{
- if (!m_backgroundColorSet)
- return;
-
- GraphicsLayer::clearBackgroundColor();
- m_contentsLayerHasBackgroundColor = false;
- noteLayerPropertyChanged(BackgroundColorChanged);
-}
-
-void GraphicsLayerMac::setContentsOpaque(bool opaque)
-{
- if (m_contentsOpaque == opaque)
- return;
-
- GraphicsLayer::setContentsOpaque(opaque);
- noteLayerPropertyChanged(ContentsOpaqueChanged);
-}
-
-void GraphicsLayerMac::setBackfaceVisibility(bool visible)
-{
- if (m_backfaceVisibility == visible)
- return;
-
- GraphicsLayer::setBackfaceVisibility(visible);
- noteLayerPropertyChanged(BackfaceVisibilityChanged);
-}
-
-void GraphicsLayerMac::setOpacity(float opacity)
-{
- float clampedOpacity = max(0.0f, min(opacity, 1.0f));
-
- if (clampedOpacity == m_opacity)
- return;
-
- GraphicsLayer::setOpacity(clampedOpacity);
- noteLayerPropertyChanged(OpacityChanged);
-}
-
-void GraphicsLayerMac::setNeedsDisplay()
-{
- FloatRect hugeRect(-numeric_limits<float>::max() / 2, -numeric_limits<float>::max() / 2,
- numeric_limits<float>::max(), numeric_limits<float>::max());
-
- setNeedsDisplayInRect(hugeRect);
-}
-
-void GraphicsLayerMac::setNeedsDisplayInRect(const FloatRect& rect)
-{
- if (!drawsContent())
- return;
-
- const size_t maxDirtyRects = 32;
-
- for (size_t i = 0; i < m_dirtyRects.size(); ++i) {
- if (m_dirtyRects[i].contains(rect))
- return;
- }
-
- if (m_dirtyRects.size() < maxDirtyRects)
- m_dirtyRects.append(rect);
- else
- m_dirtyRects[0].unite(rect);
-
- noteLayerPropertyChanged(DirtyRectsChanged);
-}
-
-void GraphicsLayerMac::setContentsNeedsDisplay()
-{
- noteLayerPropertyChanged(ContentsNeedsDisplay);
-}
-
-void GraphicsLayerMac::setContentsRect(const IntRect& rect)
-{
- if (rect == m_contentsRect)
- return;
-
- GraphicsLayer::setContentsRect(rect);
- noteLayerPropertyChanged(ContentsRectChanged);
-}
-
-bool GraphicsLayerMac::addAnimation(const KeyframeValueList& valueList, const IntSize& boxSize, const Animation* anim, const String& animationName, double timeOffset)
-{
- ASSERT(!animationName.isEmpty());
-
- if (forceSoftwareAnimation() || !anim || anim->isEmptyOrZeroDuration() || valueList.size() < 2)
- return false;
-
-#if !HAVE_MODERN_QUARTZCORE
- // Older versions of QuartzCore do not handle opacity in transform layers properly, so we will
- // always do software animation in that case.
- if (valueList.property() == AnimatedPropertyOpacity)
- return false;
-#endif
-
- // CoreAnimation does not handle the steps() timing function. Fall back
- // to software animation in that case.
- if (animationHasStepsTimingFunction(valueList, anim))
- return false;
-
- bool createdAnimations = false;
- if (valueList.property() == AnimatedPropertyWebkitTransform)
- createdAnimations = createTransformAnimationsFromKeyframes(valueList, anim, animationName, timeOffset, boxSize);
- else
- createdAnimations = createAnimationFromKeyframes(valueList, anim, animationName, timeOffset);
-
- if (createdAnimations)
- noteLayerPropertyChanged(AnimationChanged);
-
- return createdAnimations;
-}
-
-void GraphicsLayerMac::pauseAnimation(const String& animationName, double timeOffset)
-{
- if (!animationIsRunning(animationName))
- return;
-
- AnimationsToProcessMap::iterator it = m_animationsToProcess.find(animationName);
- if (it != m_animationsToProcess.end()) {
- AnimationProcessingAction& processingInfo = it->second;
- // If an animation is scheduled to be removed, don't change the remove to a pause.
- if (processingInfo.action != Remove)
- processingInfo.action = Pause;
- } else
- m_animationsToProcess.add(animationName, AnimationProcessingAction(Pause, timeOffset));
-
- noteLayerPropertyChanged(AnimationChanged);
-}
-
-void GraphicsLayerMac::removeAnimation(const String& animationName)
-{
- if (!animationIsRunning(animationName))
- return;
-
- m_animationsToProcess.add(animationName, AnimationProcessingAction(Remove));
- noteLayerPropertyChanged(AnimationChanged);
-}
-
-void GraphicsLayerMac::animationDidStart(CAAnimation* caAnimation)
-{
- bool hadNonZeroBeginTime = [[caAnimation valueForKey:WebKitAnimationBeginTimeSetKey] boolValue];
-
- double startTime;
- if (hadNonZeroBeginTime) {
- // We don't know what time CA used to commit the animation, so just use the current time
- // (even though this will be slightly off).
- startTime = WebCore::mediaTimeToCurrentTime(CACurrentMediaTime());
- } else
- startTime = WebCore::mediaTimeToCurrentTime([caAnimation beginTime]);
-
- if (m_client)
- m_client->notifyAnimationStarted(this, startTime);
-}
-
-void GraphicsLayerMac::setContentsToImage(Image* image)
-{
- if (image) {
- CGImageRef newImage = image->nativeImageForCurrentFrame();
- if (!newImage)
- return;
-
- // Check to see if the image changed; we have to do this because the call to
- // CGImageCreateCopyWithColorSpace() below can create a new image every time.
- if (m_uncorrectedContentsImage && m_uncorrectedContentsImage.get() == newImage)
- return;
-
- m_uncorrectedContentsImage = newImage;
- m_pendingContentsImage = newImage;
- CGColorSpaceRef colorSpace = CGImageGetColorSpace(m_pendingContentsImage.get());
-
- static CGColorSpaceRef deviceRGB = CGColorSpaceCreateDeviceRGB();
- if (colorSpace && CFEqual(colorSpace, deviceRGB)) {
- // CoreGraphics renders images tagged with DeviceRGB using the color space of the main display. When we hand such
- // images to CA we need to tag them similarly so CA rendering matches CG rendering.
- static CGColorSpaceRef genericRGB = CGDisplayCopyColorSpace(kCGDirectMainDisplay);
- m_pendingContentsImage.adoptCF(CGImageCreateCopyWithColorSpace(m_pendingContentsImage.get(), genericRGB));
- }
- m_contentsLayerPurpose = ContentsLayerForImage;
- if (!m_contentsLayer)
- noteSublayersChanged();
- } else {
- m_uncorrectedContentsImage = 0;
- m_pendingContentsImage = 0;
- m_contentsLayerPurpose = NoContentsLayer;
- if (m_contentsLayer)
- noteSublayersChanged();
- }
-
- noteLayerPropertyChanged(ContentsImageChanged);
-}
-
-void GraphicsLayerMac::setContentsToMedia(PlatformLayer* mediaLayer)
-{
- if (mediaLayer == m_contentsLayer)
- return;
-
- m_contentsLayer = mediaLayer;
- m_contentsLayerPurpose = mediaLayer ? ContentsLayerForMedia : NoContentsLayer;
-
- noteSublayersChanged();
- noteLayerPropertyChanged(ContentsMediaLayerChanged);
-}
-
-void GraphicsLayerMac::didDisplay(PlatformLayer* layer)
-{
- CALayer* sourceLayer;
- LayerMap* layerCloneMap;
-
- if (layer == m_layer) {
- sourceLayer = m_layer.get();
- layerCloneMap = m_layerClones.get();
- } else if (layer == m_contentsLayer) {
- sourceLayer = m_contentsLayer.get();
- layerCloneMap = m_contentsLayerClones.get();
- } else
- return;
-
- if (layerCloneMap) {
- LayerMap::const_iterator end = layerCloneMap->end();
- for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
- CALayer *currClone = it->second.get();
- if (!currClone)
- continue;
-
- if ([currClone contents] != [sourceLayer contents])
- [currClone setContents:[sourceLayer contents]];
- else
- [currClone setContentsChanged];
- }
- }
-}
-
-void GraphicsLayerMac::syncCompositingState()
-{
- recursiveCommitChanges();
-}
-
-void GraphicsLayerMac::syncCompositingStateForThisLayerOnly()
-{
- commitLayerChangesBeforeSublayers();
- commitLayerChangesAfterSublayers();
-}
-
-void GraphicsLayerMac::recursiveCommitChanges()
-{
- commitLayerChangesBeforeSublayers();
-
- if (m_maskLayer)
- static_cast<GraphicsLayerMac*>(m_maskLayer)->commitLayerChangesBeforeSublayers();
-
- const Vector<GraphicsLayer*>& childLayers = children();
- size_t numChildren = childLayers.size();
- for (size_t i = 0; i < numChildren; ++i) {
- GraphicsLayerMac* curChild = static_cast<GraphicsLayerMac*>(childLayers[i]);
- curChild->recursiveCommitChanges();
- }
-
- if (m_replicaLayer)
- static_cast<GraphicsLayerMac*>(m_replicaLayer)->recursiveCommitChanges();
-
- if (m_maskLayer)
- static_cast<GraphicsLayerMac*>(m_maskLayer)->commitLayerChangesAfterSublayers();
-
- commitLayerChangesAfterSublayers();
-}
-
-void GraphicsLayerMac::commitLayerChangesBeforeSublayers()
-{
- if (!m_uncommittedChanges)
- return;
-
- BEGIN_BLOCK_OBJC_EXCEPTIONS
-
- // Need to handle Preserves3DChanged first, because it affects which layers subsequent properties are applied to
- if (m_uncommittedChanges & (Preserves3DChanged | ReplicatedLayerChanged))
- updateStructuralLayer();
-
- if (m_uncommittedChanges & NameChanged)
- updateLayerNames();
-
- if (m_uncommittedChanges & ContentsImageChanged) // Needs to happen before ChildrenChanged
- updateContentsImage();
-
- if (m_uncommittedChanges & ContentsMediaLayerChanged) // Needs to happen before ChildrenChanged
- updateContentsMediaLayer();
-
- if (m_uncommittedChanges & ContentsCanvasLayerChanged) // Needs to happen before ChildrenChanged
- updateContentsCanvasLayer();
-
- if (m_uncommittedChanges & BackgroundColorChanged) // Needs to happen before ChildrenChanged, and after updating image or video
- updateLayerBackgroundColor();
-
- if (m_uncommittedChanges & ChildrenChanged)
- updateSublayerList();
-
- if (m_uncommittedChanges & PositionChanged)
- updateLayerPosition();
-
- if (m_uncommittedChanges & AnchorPointChanged)
- updateAnchorPoint();
-
- if (m_uncommittedChanges & SizeChanged)
- updateLayerSize();
-
- if (m_uncommittedChanges & TransformChanged)
- updateTransform();
-
- if (m_uncommittedChanges & ChildrenTransformChanged)
- updateChildrenTransform();
-
- if (m_uncommittedChanges & MasksToBoundsChanged)
- updateMasksToBounds();
-
- if (m_uncommittedChanges & DrawsContentChanged)
- updateLayerDrawsContent();
-
- if (m_uncommittedChanges & ContentsOpaqueChanged)
- updateContentsOpaque();
-
- if (m_uncommittedChanges & BackfaceVisibilityChanged)
- updateBackfaceVisibility();
-
- if (m_uncommittedChanges & OpacityChanged)
- updateOpacityOnLayer();
-
- if (m_uncommittedChanges & AnimationChanged)
- updateLayerAnimations();
-
- if (m_uncommittedChanges & DirtyRectsChanged)
- repaintLayerDirtyRects();
-
- if (m_uncommittedChanges & ContentsRectChanged)
- updateContentsRect();
-
- if (m_uncommittedChanges & MaskLayerChanged)
- updateMaskLayer();
-
- if (m_uncommittedChanges & ContentsNeedsDisplay)
- updateContentsNeedsDisplay();
-
- END_BLOCK_OBJC_EXCEPTIONS
-}
-
-void GraphicsLayerMac::commitLayerChangesAfterSublayers()
-{
- if (!m_uncommittedChanges)
- return;
-
- BEGIN_BLOCK_OBJC_EXCEPTIONS
-
- if (m_uncommittedChanges & ReplicatedLayerChanged)
- updateReplicatedLayers();
-
- m_uncommittedChanges = NoChange;
- END_BLOCK_OBJC_EXCEPTIONS
-}
-
-void GraphicsLayerMac::updateLayerNames()
-{
- switch (structuralLayerPurpose()) {
- case StructuralLayerForPreserves3D:
- [m_structuralLayer.get() setName:("Transform layer " + name())];
- break;
- case StructuralLayerForReplicaFlattening:
- [m_structuralLayer.get() setName:("Replica flattening layer " + name())];
- break;
- case NoStructuralLayer:
- break;
- }
- [m_layer.get() setName:name()];
-}
-
-void GraphicsLayerMac::updateSublayerList()
-{
- NSMutableArray* newSublayers = nil;
-
- const Vector<GraphicsLayer*>& childLayers = children();
-
- if (m_structuralLayer || m_contentsLayer || childLayers.size() > 0) {
- newSublayers = [[NSMutableArray alloc] init];
-
- if (m_structuralLayer) {
- // Add the replica layer first.
- if (m_replicaLayer)
- [newSublayers addObject:static_cast<GraphicsLayerMac*>(m_replicaLayer)->primaryLayer()];
- // Add the primary layer. Even if we have negative z-order children, the primary layer always comes behind.
- [newSublayers addObject:m_layer.get()];
- } else if (m_contentsLayer) {
- // FIXME: add the contents layer in the correct order with negative z-order children.
- // This does not cause visible rendering issues because currently contents layers are only used
- // for replaced elements that don't have children.
- [newSublayers addObject:m_contentsLayer.get()];
- }
-
- size_t numChildren = childLayers.size();
- for (size_t i = 0; i < numChildren; ++i) {
- GraphicsLayerMac* curChild = static_cast<GraphicsLayerMac*>(childLayers[i]);
- CALayer *childLayer = curChild->layerForSuperlayer();
- [newSublayers addObject:childLayer];
- }
-
- [newSublayers makeObjectsPerformSelector:@selector(removeFromSuperlayer)];
- }
-
- if (m_structuralLayer) {
- safeSetSublayers(m_structuralLayer.get(), newSublayers);
-
- if (m_contentsLayer) {
- // If we have a transform layer, then the contents layer is parented in the
- // primary layer (which is itself a child of the transform layer).
- safeSetSublayers(m_layer.get(), nil);
- [m_layer.get() addSublayer:m_contentsLayer.get()];
- }
- } else
- safeSetSublayers(m_layer.get(), newSublayers);
-
- [newSublayers release];
-}
-
-void GraphicsLayerMac::updateLayerPosition()
-{
- FloatSize usedSize = m_usingTiledLayer ? constrainedSize() : m_size;
-
- // Position is offset on the layer by the layer anchor point.
- CGPoint posPoint = CGPointMake(m_position.x() + m_anchorPoint.x() * usedSize.width(),
- m_position.y() + m_anchorPoint.y() * usedSize.height());
-
- [primaryLayer() setPosition:posPoint];
-
- if (LayerMap* layerCloneMap = primaryLayerClones()) {
- LayerMap::const_iterator end = layerCloneMap->end();
- for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
- CGPoint clonePosition = posPoint;
- if (m_replicaLayer && isReplicatedRootClone(it->first)) {
- // Maintain the special-case position for the root of a clone subtree,
- // which we set up in replicatedLayerRoot().
- clonePosition = positionForCloneRootLayer();
- }
- CALayer *currLayer = it->second.get();
- [currLayer setPosition:clonePosition];
- }
- }
-}
-
-void GraphicsLayerMac::updateLayerSize()
-{
- CGRect rect = CGRectMake(0, 0, m_size.width(), m_size.height());
- if (m_structuralLayer) {
- [m_structuralLayer.get() setBounds:rect];
-
- if (LayerMap* layerCloneMap = m_structuralLayerClones.get()) {
- LayerMap::const_iterator end = layerCloneMap->end();
- for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it)
- [it->second.get() setBounds:rect];
- }
-
- // The anchor of the contents layer is always at 0.5, 0.5, so the position is center-relative.
- CGPoint centerPoint = CGPointMake(m_size.width() / 2.0f, m_size.height() / 2.0f);
- [m_layer.get() setPosition:centerPoint];
-
- if (LayerMap* layerCloneMap = m_layerClones.get()) {
- LayerMap::const_iterator end = layerCloneMap->end();
- for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it)
- [it->second.get() setPosition:centerPoint];
- }
- }
-
- bool needTiledLayer = requiresTiledLayer(m_size);
- if (needTiledLayer != m_usingTiledLayer)
- swapFromOrToTiledLayer(needTiledLayer);
-
- if (m_usingTiledLayer) {
- FloatSize sizeToUse = constrainedSize();
- rect = CGRectMake(0, 0, sizeToUse.width(), sizeToUse.height());
- }
-
- [m_layer.get() setBounds:rect];
- if (LayerMap* layerCloneMap = m_layerClones.get()) {
- LayerMap::const_iterator end = layerCloneMap->end();
- for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it)
- [it->second.get() setBounds:rect];
- }
-
- // Contents transform may depend on height.
- updateContentsTransform();
-
- // Note that we don't resize m_contentsLayer. It's up the caller to do that.
-
- // if we've changed the bounds, we need to recalculate the position
- // of the layer, taking anchor point into account.
- updateLayerPosition();
-}
-
-void GraphicsLayerMac::updateAnchorPoint()
-{
- [primaryLayer() setAnchorPoint:FloatPoint(m_anchorPoint.x(), m_anchorPoint.y())];
-#if HAVE_MODERN_QUARTZCORE
- [primaryLayer() setAnchorPointZ:m_anchorPoint.z()];
-#endif
-
- if (LayerMap* layerCloneMap = primaryLayerClones()) {
- LayerMap::const_iterator end = layerCloneMap->end();
- for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
- CALayer *currLayer = it->second.get();
- [currLayer setAnchorPoint:FloatPoint(m_anchorPoint.x(), m_anchorPoint.y())];
-#if HAVE_MODERN_QUARTZCORE
- [currLayer setAnchorPointZ:m_anchorPoint.z()];
-#endif
- }
- }
-
- updateLayerPosition();
-}
-
-void GraphicsLayerMac::updateTransform()
-{
- CATransform3D transform;
- copyTransform(transform, m_transform);
- [primaryLayer() setTransform:transform];
-
- if (LayerMap* layerCloneMap = primaryLayerClones()) {
- LayerMap::const_iterator end = layerCloneMap->end();
- for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
- CALayer *currLayer = it->second.get();
- if (m_replicaLayer && isReplicatedRootClone(it->first)) {
- // Maintain the special-case transform for the root of a clone subtree,
- // which we set up in replicatedLayerRoot().
- [currLayer setTransform:CATransform3DIdentity];
- } else
- [currLayer setTransform:transform];
- }
- }
-}
-
-void GraphicsLayerMac::updateChildrenTransform()
-{
- CATransform3D transform;
- copyTransform(transform, m_childrenTransform);
- [primaryLayer() setSublayerTransform:transform];
-
- if (LayerMap* layerCloneMap = primaryLayerClones()) {
- LayerMap::const_iterator end = layerCloneMap->end();
- for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
- CALayer *currLayer = it->second.get();
- [currLayer setSublayerTransform:transform];
- }
- }
-}
-
-void GraphicsLayerMac::updateMasksToBounds()
-{
- [m_layer.get() setMasksToBounds:m_masksToBounds];
-
- if (LayerMap* layerCloneMap = m_layerClones.get()) {
- LayerMap::const_iterator end = layerCloneMap->end();
- for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
- CALayer *currLayer = it->second.get();
- [currLayer setMasksToBounds:m_masksToBounds];
- }
- }
-
- updateDebugIndicators();
-}
-
-void GraphicsLayerMac::updateContentsOpaque()
-{
- [m_layer.get() setOpaque:m_contentsOpaque];
-
- if (LayerMap* layerCloneMap = m_layerClones.get()) {
- LayerMap::const_iterator end = layerCloneMap->end();
- for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
- CALayer *currLayer = it->second.get();
- [currLayer setOpaque:m_contentsOpaque];
- }
- }
-}
-
-void GraphicsLayerMac::updateBackfaceVisibility()
-{
- if (m_structuralLayer && structuralLayerPurpose() == StructuralLayerForReplicaFlattening) {
- [m_structuralLayer.get() setDoubleSided:m_backfaceVisibility];
-
- if (LayerMap* layerCloneMap = m_structuralLayerClones.get()) {
- LayerMap::const_iterator end = layerCloneMap->end();
- for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
- CALayer *currLayer = it->second.get();
- [currLayer setDoubleSided:m_backfaceVisibility];
- }
- }
- }
-
- [m_layer.get() setDoubleSided:m_backfaceVisibility];
-
- if (LayerMap* layerCloneMap = m_layerClones.get()) {
- LayerMap::const_iterator end = layerCloneMap->end();
- for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
- CALayer *currLayer = it->second.get();
- [currLayer setDoubleSided:m_backfaceVisibility];
- }
- }
-}
-
-void GraphicsLayerMac::updateStructuralLayer()
-{
- ensureStructuralLayer(structuralLayerPurpose());
-}
-
-void GraphicsLayerMac::ensureStructuralLayer(StructuralLayerPurpose purpose)
-{
- if (purpose == NoStructuralLayer) {
- if (m_structuralLayer) {
- // Replace the transformLayer in the parent with this layer.
- [m_layer.get() removeFromSuperlayer];
- [[m_structuralLayer.get() superlayer] replaceSublayer:m_structuralLayer.get() with:m_layer.get()];
-
- moveOrCopyAnimationsForProperty(Move, AnimatedPropertyWebkitTransform, m_structuralLayer.get(), m_layer.get());
- moveOrCopyAnimationsForProperty(Move, AnimatedPropertyOpacity, m_structuralLayer.get(), m_layer.get());
-
- // Release the structural layer.
- m_structuralLayer = 0;
-
- // Update the properties of m_layer now that we no longer have a structural layer.
- updateLayerPosition();
- updateLayerSize();
- updateAnchorPoint();
- updateTransform();
- updateChildrenTransform();
-
- updateSublayerList();
- updateOpacityOnLayer();
- }
- return;
- }
-
- bool structuralLayerChanged = false;
-
- if (purpose == StructuralLayerForPreserves3D) {
- Class transformLayerClass = NSClassFromString(@"CATransformLayer");
- if (!transformLayerClass)
- return;
-
- if (m_structuralLayer && ![m_structuralLayer.get() isKindOfClass:transformLayerClass])
- m_structuralLayer = 0;
-
- if (!m_structuralLayer) {
- m_structuralLayer.adoptNS([[transformLayerClass alloc] init]);
- structuralLayerChanged = true;
- }
- } else {
- if (m_structuralLayer && ![m_structuralLayer.get() isMemberOfClass:[CALayer self]])
- m_structuralLayer = 0;
-
- if (!m_structuralLayer) {
- m_structuralLayer.adoptNS([[CALayer alloc] init]);
- structuralLayerChanged = true;
- }
- }
-
- if (!structuralLayerChanged)
- return;
-
- // Turn off default animations.
- [m_structuralLayer.get() setStyle:[NSDictionary dictionaryWithObject:nullActionsDictionary() forKey:@"actions"]];
-
- updateLayerNames();
-
- // Update the properties of the structural layer.
- updateLayerPosition();
- updateLayerSize();
- updateAnchorPoint();
- updateTransform();
- updateChildrenTransform();
- updateBackfaceVisibility();
-
- // Set properties of m_layer to their default values, since these are expressed on on the structural layer.
- CGPoint point = CGPointMake(m_size.width() / 2.0f, m_size.height() / 2.0f);
- [m_layer.get() setPosition:point];
- [m_layer.get() setAnchorPoint:CGPointMake(0.5f, 0.5f)];
- [m_layer.get() setTransform:CATransform3DIdentity];
- [m_layer.get() setOpacity:1];
-
- // Move this layer to be a child of the transform layer.
- [[m_layer.get() superlayer] replaceSublayer:m_layer.get() with:m_structuralLayer.get()];
- [m_structuralLayer.get() addSublayer:m_layer.get()];
-
- moveOrCopyAnimationsForProperty(Move, AnimatedPropertyWebkitTransform, m_layer.get(), m_structuralLayer.get());
- moveOrCopyAnimationsForProperty(Move, AnimatedPropertyOpacity, m_layer.get(), m_structuralLayer.get());
-
- updateSublayerList();
- updateOpacityOnLayer();
-}
-
-GraphicsLayerMac::StructuralLayerPurpose GraphicsLayerMac::structuralLayerPurpose() const
-{
- if (preserves3D())
- return StructuralLayerForPreserves3D;
-
- if (isReplicated())
- return StructuralLayerForReplicaFlattening;
-
- return NoStructuralLayer;
-}
-
-void GraphicsLayerMac::updateLayerDrawsContent()
-{
- bool needTiledLayer = requiresTiledLayer(m_size);
- if (needTiledLayer != m_usingTiledLayer)
- swapFromOrToTiledLayer(needTiledLayer);
-
- if (m_drawsContent)
- [m_layer.get() setNeedsDisplay];
- else
- [m_layer.get() setContents:nil];
-
- updateDebugIndicators();
-}
-
-void GraphicsLayerMac::updateLayerBackgroundColor()
-{
- if (!m_contentsLayer)
- return;
-
- // We never create the contents layer just for background color yet.
- if (m_backgroundColorSet)
- setLayerBackgroundColor(m_contentsLayer.get(), m_backgroundColor);
- else
- clearLayerBackgroundColor(m_contentsLayer.get());
-}
-
-void GraphicsLayerMac::updateContentsImage()
-{
- if (m_pendingContentsImage) {
- if (!m_contentsLayer.get()) {
- WebLayer* imageLayer = [WebLayer layer];
-#ifndef NDEBUG
- [imageLayer setName:@"Image Layer"];
-#endif
- setupContentsLayer(imageLayer);
- m_contentsLayer.adoptNS([imageLayer retain]);
- // m_contentsLayer will be parented by updateSublayerList
- }
-
- // FIXME: maybe only do trilinear if the image is being scaled down,
- // but then what if the layer size changes?
-#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
- [m_contentsLayer.get() setMinificationFilter:kCAFilterTrilinear];
-#endif
- [m_contentsLayer.get() setContents:(id)m_pendingContentsImage.get()];
- m_pendingContentsImage = 0;
-
- if (m_contentsLayerClones) {
- LayerMap::const_iterator end = m_contentsLayerClones->end();
- for (LayerMap::const_iterator it = m_contentsLayerClones->begin(); it != end; ++it)
- [it->second.get() setContents:[m_contentsLayer.get() contents]];
- }
-
- updateContentsRect();
- } else {
- // No image.
- // m_contentsLayer will be removed via updateSublayerList.
- m_contentsLayer = 0;
- }
-}
-
-void GraphicsLayerMac::updateContentsMediaLayer()
-{
- // Video layer was set as m_contentsLayer, and will get parented in updateSublayerList().
- if (m_contentsLayer) {
- setupContentsLayer(m_contentsLayer.get());
- updateContentsRect();
- }
-}
-
-void GraphicsLayerMac::updateContentsCanvasLayer()
-{
- // CanvasLayer was set as m_contentsLayer, and will get parented in updateSublayerList().
- if (m_contentsLayer) {
- setupContentsLayer(m_contentsLayer.get());
- [m_contentsLayer.get() setNeedsDisplay];
- updateContentsRect();
- }
-}
-
-void GraphicsLayerMac::updateContentsRect()
-{
- if (!m_contentsLayer)
- return;
-
- CGPoint point = CGPointMake(m_contentsRect.x(),
- m_contentsRect.y());
- CGRect rect = CGRectMake(0.0f,
- 0.0f,
- m_contentsRect.width(),
- m_contentsRect.height());
-
- [m_contentsLayer.get() setPosition:point];
- [m_contentsLayer.get() setBounds:rect];
-
- if (m_contentsLayerClones) {
- LayerMap::const_iterator end = m_contentsLayerClones->end();
- for (LayerMap::const_iterator it = m_contentsLayerClones->begin(); it != end; ++it) {
- CALayer *currLayer = it->second.get();
- [currLayer setPosition:point];
- [currLayer setBounds:rect];
- }
- }
-}
-
-void GraphicsLayerMac::updateMaskLayer()
-{
- CALayer *maskCALayer = m_maskLayer ? m_maskLayer->platformLayer() : 0;
- [m_layer.get() setMask:maskCALayer];
-
- LayerMap* maskLayerCloneMap = m_maskLayer ? static_cast<GraphicsLayerMac*>(m_maskLayer)->primaryLayerClones() : 0;
-
- if (LayerMap* layerCloneMap = m_layerClones.get()) {
- LayerMap::const_iterator end = layerCloneMap->end();
- for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
- CALayer *currLayer = it->second.get();
-
- CALayer *maskClone = maskLayerCloneMap ? maskLayerCloneMap->get(it->first).get() : 0;
- [currLayer setMask:maskClone];
- }
- }
-}
-
-void GraphicsLayerMac::updateReplicatedLayers()
-{
- // Clone the descendants of the replicated layer, and parent under us.
- ReplicaState replicaState(ReplicaState::ReplicaBranch);
-
- CALayer *replicaRoot = replicatedLayerRoot(replicaState);
- if (!replicaRoot)
- return;
-
- if (m_structuralLayer)
- [m_structuralLayer.get() insertSublayer:replicaRoot atIndex:0];
- else
- [m_layer.get() insertSublayer:replicaRoot atIndex:0];
-}
-
-// For now, this assumes that layers only ever have one replica, so replicaIndices contains only 0 and 1.
-GraphicsLayerMac::CloneID GraphicsLayerMac::ReplicaState::cloneID() const
-{
- size_t depth = m_replicaBranches.size();
-
- const size_t bitsPerUChar = sizeof(UChar) * 8;
- size_t vectorSize = (depth + bitsPerUChar - 1) / bitsPerUChar;
-
- Vector<UChar> result(vectorSize);
- result.fill(0);
-
- // Create a string from the bit sequence which we can use to identify the clone.
- // Note that the string may contain embedded nulls, but that's OK.
- for (size_t i = 0; i < depth; ++i) {
- UChar& currChar = result[i / bitsPerUChar];
- currChar = (currChar << 1) | m_replicaBranches[i];
- }
-
- return String::adopt(result);
-}
-
-CALayer *GraphicsLayerMac::replicatedLayerRoot(ReplicaState& replicaState)
-{
- // Limit replica nesting, to avoid 2^N explosion of replica layers.
- if (!m_replicatedLayer || replicaState.replicaDepth() == ReplicaState::maxReplicaDepth)
- return nil;
-
- GraphicsLayerMac* replicatedLayer = static_cast<GraphicsLayerMac*>(m_replicatedLayer);
-
- CALayer *clonedLayerRoot = replicatedLayer->fetchCloneLayers(this, replicaState, RootCloneLevel);
- FloatPoint cloneRootPosition = replicatedLayer->positionForCloneRootLayer();
-
- // Replica root has no offset or transform
- [clonedLayerRoot setPosition:cloneRootPosition];
- [clonedLayerRoot setTransform:CATransform3DIdentity];
-
- return clonedLayerRoot;
-}
-
-void GraphicsLayerMac::updateLayerAnimations()
-{
- if (m_animationsToProcess.size()) {
- AnimationsToProcessMap::const_iterator end = m_animationsToProcess.end();
- for (AnimationsToProcessMap::const_iterator it = m_animationsToProcess.begin(); it != end; ++it) {
- const String& currAnimationName = it->first;
- AnimationsMap::iterator animationIt = m_runningAnimations.find(currAnimationName);
- if (animationIt == m_runningAnimations.end())
- continue;
-
- const AnimationProcessingAction& processingInfo = it->second;
- const Vector<LayerPropertyAnimation>& animations = animationIt->second;
- for (size_t i = 0; i < animations.size(); ++i) {
- const LayerPropertyAnimation& currAnimation = animations[i];
- switch (processingInfo.action) {
- case Remove:
- removeCAAnimationFromLayer(currAnimation.m_property, currAnimationName, currAnimation.m_index);
- break;
- case Pause:
- pauseCAAnimationOnLayer(currAnimation.m_property, currAnimationName, currAnimation.m_index, processingInfo.timeOffset);
- break;
- }
- }
-
- if (processingInfo.action == Remove)
- m_runningAnimations.remove(currAnimationName);
- }
-
- m_animationsToProcess.clear();
- }
-
- size_t numAnimations;
- if ((numAnimations = m_uncomittedAnimations.size())) {
- for (size_t i = 0; i < numAnimations; ++i) {
- const LayerPropertyAnimation& pendingAnimation = m_uncomittedAnimations[i];
- setCAAnimationOnLayer(pendingAnimation.m_animation.get(), pendingAnimation.m_property, pendingAnimation.m_name, pendingAnimation.m_index, pendingAnimation.m_timeOffset);
-
- AnimationsMap::iterator it = m_runningAnimations.find(pendingAnimation.m_name);
- if (it == m_runningAnimations.end()) {
- Vector<LayerPropertyAnimation> animations;
- animations.append(pendingAnimation);
- m_runningAnimations.add(pendingAnimation.m_name, animations);
- } else {
- Vector<LayerPropertyAnimation>& animations = it->second;
- animations.append(pendingAnimation);
- }
- }
-
- m_uncomittedAnimations.clear();
- }
-}
-
-void GraphicsLayerMac::setCAAnimationOnLayer(CAPropertyAnimation* caAnim, AnimatedPropertyID property, const String& animationName, int index, double timeOffset)
-{
- PlatformLayer* layer = animatedLayer(property);
-
- if (timeOffset) {
- [caAnim setBeginTime:CACurrentMediaTime() - timeOffset];
- [caAnim setValue:[NSNumber numberWithBool:YES] forKey:WebKitAnimationBeginTimeSetKey];
- }
-
- NSString *animationID = animationIdentifier(animationName, property, index);
-
- [layer removeAnimationForKey:animationID];
- [layer addAnimation:caAnim forKey:animationID];
-
- if (LayerMap* layerCloneMap = animatedLayerClones(property)) {
- LayerMap::const_iterator end = layerCloneMap->end();
- for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
- // Skip immediate replicas, since they move with the original.
- if (m_replicaLayer && isReplicatedRootClone(it->first))
- continue;
- CALayer *currLayer = it->second.get();
- [currLayer removeAnimationForKey:animationID];
- [currLayer addAnimation:caAnim forKey:animationID];
- }
- }
-}
-
-// Workaround for <rdar://problem/7311367>
-static void bug7311367Workaround(CALayer* transformLayer, const TransformationMatrix& transform)
-{
- if (!transformLayer)
- return;
-
- CATransform3D caTransform;
- copyTransform(caTransform, transform);
- caTransform.m41 += 1;
- [transformLayer setTransform:caTransform];
-
- caTransform.m41 -= 1;
- [transformLayer setTransform:caTransform];
-}
-
-bool GraphicsLayerMac::removeCAAnimationFromLayer(AnimatedPropertyID property, const String& animationName, int index)
-{
- PlatformLayer* layer = animatedLayer(property);
-
- NSString *animationID = animationIdentifier(animationName, property, index);
-
- if (![layer animationForKey:animationID])
- return false;
-
- [layer removeAnimationForKey:animationID];
- bug7311367Workaround(m_structuralLayer.get(), m_transform);
-
- if (LayerMap* layerCloneMap = animatedLayerClones(property)) {
- LayerMap::const_iterator end = layerCloneMap->end();
- for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
- // Skip immediate replicas, since they move with the original.
- if (m_replicaLayer && isReplicatedRootClone(it->first))
- continue;
-
- CALayer *currLayer = it->second.get();
- [currLayer removeAnimationForKey:animationID];
- }
- }
- return true;
-}
-
-static void copyAnimationProperties(CAPropertyAnimation* from, CAPropertyAnimation* to)
-{
- [to setBeginTime:[from beginTime]];
- [to setDuration:[from duration]];
- [to setRepeatCount:[from repeatCount]];
- [to setAutoreverses:[from autoreverses]];
- [to setFillMode:[from fillMode]];
- [to setRemovedOnCompletion:[from isRemovedOnCompletion]];
- [to setAdditive:[from isAdditive]];
- [to setTimingFunction:[from timingFunction]];
-
-#if HAVE_MODERN_QUARTZCORE
- [to setValueFunction:[from valueFunction]];
-#endif
-
- if (id object = [from valueForKey:WebKitAnimationBeginTimeSetKey])
- [to setValue:object forKey:WebKitAnimationBeginTimeSetKey];
-}
-
-void GraphicsLayerMac::pauseCAAnimationOnLayer(AnimatedPropertyID property, const String& animationName, int index, double timeOffset)
-{
- PlatformLayer* layer = animatedLayer(property);
-
- NSString *animationID = animationIdentifier(animationName, property, index);
-
- CAAnimation *caAnim = [layer animationForKey:animationID];
- if (!caAnim)
- return;
-
- // Animations on the layer are immutable, so we have to clone and modify.
- CAPropertyAnimation* pausedAnim = nil;
- if ([caAnim isKindOfClass:[CAKeyframeAnimation class]]) {
- CAKeyframeAnimation* existingKeyframeAnim = static_cast<CAKeyframeAnimation*>(caAnim);
- CAKeyframeAnimation* newAnim = [CAKeyframeAnimation animationWithKeyPath:[existingKeyframeAnim keyPath]];
- copyAnimationProperties(existingKeyframeAnim, newAnim);
- [newAnim setValues:[existingKeyframeAnim values]];
- [newAnim setKeyTimes:[existingKeyframeAnim keyTimes]];
- [newAnim setTimingFunctions:[existingKeyframeAnim timingFunctions]];
- pausedAnim = newAnim;
- } else if ([caAnim isKindOfClass:[CABasicAnimation class]]) {
- CABasicAnimation* existingPropertyAnim = static_cast<CABasicAnimation*>(caAnim);
- CABasicAnimation* newAnim = [CABasicAnimation animationWithKeyPath:[existingPropertyAnim keyPath]];
- copyAnimationProperties(existingPropertyAnim, newAnim);
- [newAnim setFromValue:[existingPropertyAnim fromValue]];
- [newAnim setToValue:[existingPropertyAnim toValue]];
- pausedAnim = newAnim;
- }
-
- // pausedAnim has the beginTime of caAnim already.
- [pausedAnim setSpeed:0];
- [pausedAnim setTimeOffset:timeOffset];
-
- [layer addAnimation:pausedAnim forKey:animationID]; // This will replace the running animation.
-
- // Pause the animations on the clones too.
- if (LayerMap* layerCloneMap = animatedLayerClones(property)) {
- LayerMap::const_iterator end = layerCloneMap->end();
- for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
- // Skip immediate replicas, since they move with the original.
- if (m_replicaLayer && isReplicatedRootClone(it->first))
- continue;
- CALayer *currLayer = it->second.get();
- [currLayer addAnimation:pausedAnim forKey:animationID];
- }
- }
-}
-
-void GraphicsLayerMac::setContentsToCanvas(PlatformLayer* canvasLayer)
-{
- if (canvasLayer == m_contentsLayer)
- return;
-
- m_contentsLayer = canvasLayer;
- if (m_contentsLayer && [m_contentsLayer.get() respondsToSelector:@selector(setLayerOwner:)])
- [(id)m_contentsLayer.get() setLayerOwner:this];
-
- m_contentsLayerPurpose = canvasLayer ? ContentsLayerForCanvas : NoContentsLayer;
-
- noteSublayersChanged();
- noteLayerPropertyChanged(ContentsCanvasLayerChanged);
-}
-
-void GraphicsLayerMac::repaintLayerDirtyRects()
-{
- if (!m_dirtyRects.size())
- return;
-
- for (size_t i = 0; i < m_dirtyRects.size(); ++i)
- [m_layer.get() setNeedsDisplayInRect:m_dirtyRects[i]];
-
- m_dirtyRects.clear();
-}
-
-void GraphicsLayerMac::updateContentsNeedsDisplay()
-{
- if (m_contentsLayer)
- [m_contentsLayer.get() setNeedsDisplay];
-}
-
-bool GraphicsLayerMac::createAnimationFromKeyframes(const KeyframeValueList& valueList, const Animation* animation, const String& animationName, double timeOffset)
-{
- ASSERT(valueList.property() != AnimatedPropertyWebkitTransform);
-
- BEGIN_BLOCK_OBJC_EXCEPTIONS;
-
- bool isKeyframe = valueList.size() > 2;
- bool valuesOK;
-
- bool additive = false;
- int animationIndex = 0;
-
- CAPropertyAnimation* caAnimation;
- if (isKeyframe) {
- CAKeyframeAnimation* keyframeAnim = createKeyframeAnimation(animation, valueList.property(), additive);
- valuesOK = setAnimationKeyframes(valueList, animation, keyframeAnim);
- caAnimation = keyframeAnim;
- } else {
- CABasicAnimation* basicAnim = createBasicAnimation(animation, valueList.property(), additive);
- valuesOK = setAnimationEndpoints(valueList, animation, basicAnim);
- caAnimation = basicAnim;
- }
-
- if (!valuesOK)
- return false;
-
- m_uncomittedAnimations.append(LayerPropertyAnimation(caAnimation, animationName, valueList.property(), animationIndex, timeOffset));
-
- END_BLOCK_OBJC_EXCEPTIONS;
-
- return true;
-}
-
-bool GraphicsLayerMac::createTransformAnimationsFromKeyframes(const KeyframeValueList& valueList, const Animation* animation, const String& animationName, double timeOffset, const IntSize& boxSize)
-{
- ASSERT(valueList.property() == AnimatedPropertyWebkitTransform);
-
- TransformOperationList functionList;
- bool listsMatch, hasBigRotation;
- fetchTransformOperationList(valueList, functionList, listsMatch, hasBigRotation);
-
- // We need to fall back to software animation if we don't have setValueFunction:, and
- // we would need to animate each incoming transform function separately. This is the
- // case if we have a rotation >= 180 or we have more than one transform function.
- if ((hasBigRotation || functionList.size() > 1) && !caValueFunctionSupported())
- return false;
-
- bool validMatrices = true;
-
- BEGIN_BLOCK_OBJC_EXCEPTIONS;
-
- // If functionLists don't match we do a matrix animation, otherwise we do a component hardware animation.
- // Also, we can't do component animation unless we have valueFunction, so we need to do matrix animation
- // if that's not true as well.
- bool isMatrixAnimation = !listsMatch || !caValueFunctionSupported();
-
- size_t numAnimations = isMatrixAnimation ? 1 : functionList.size();
- bool isKeyframe = valueList.size() > 2;
-
- // Iterate through the transform functions, sending an animation for each one.
- for (size_t animationIndex = 0; animationIndex < numAnimations; ++animationIndex) {
- TransformOperation::OperationType transformOp = isMatrixAnimation ? TransformOperation::MATRIX_3D : functionList[animationIndex];
- CAPropertyAnimation* caAnimation;
-
-#if defined(BUILDING_ON_LEOPARD) || defined(BUILDING_ON_SNOW_LEOPARD)
- // CA applies animations in reverse order (<rdar://problem/7095638>) so we need the last one we add (per property)
- // to be non-additive.
- bool additive = animationIndex < (numAnimations - 1);
-#else
- bool additive = animationIndex > 0;
-#endif
- if (isKeyframe) {
- CAKeyframeAnimation* keyframeAnim = createKeyframeAnimation(animation, valueList.property(), additive);
- validMatrices = setTransformAnimationKeyframes(valueList, animation, keyframeAnim, animationIndex, transformOp, isMatrixAnimation, boxSize);
- caAnimation = keyframeAnim;
- } else {
- CABasicAnimation* basicAnim = createBasicAnimation(animation, valueList.property(), additive);
- validMatrices = setTransformAnimationEndpoints(valueList, animation, basicAnim, animationIndex, transformOp, isMatrixAnimation, boxSize);
- caAnimation = basicAnim;
- }
-
- if (!validMatrices)
- break;
-
- m_uncomittedAnimations.append(LayerPropertyAnimation(caAnimation, animationName, valueList.property(), animationIndex, timeOffset));
- }
-
- END_BLOCK_OBJC_EXCEPTIONS;
-
- return validMatrices;
-}
-
-CABasicAnimation* GraphicsLayerMac::createBasicAnimation(const Animation* anim, AnimatedPropertyID property, bool additive)
-{
- CABasicAnimation* basicAnim = [CABasicAnimation animationWithKeyPath:propertyIdToString(property)];
- setupAnimation(basicAnim, anim, additive);
- return basicAnim;
-}
-
-CAKeyframeAnimation* GraphicsLayerMac::createKeyframeAnimation(const Animation* anim, AnimatedPropertyID property, bool additive)
-{
- CAKeyframeAnimation* keyframeAnim = [CAKeyframeAnimation animationWithKeyPath:propertyIdToString(property)];
- setupAnimation(keyframeAnim, anim, additive);
- return keyframeAnim;
-}
-
-void GraphicsLayerMac::setupAnimation(CAPropertyAnimation* propertyAnim, const Animation* anim, bool additive)
-{
- double duration = anim->duration();
- if (duration <= 0)
- duration = cAnimationAlmostZeroDuration;
-
- float repeatCount = anim->iterationCount();
- if (repeatCount == Animation::IterationCountInfinite)
- repeatCount = FLT_MAX;
- else if (anim->direction() == Animation::AnimationDirectionAlternate)
- repeatCount /= 2;
-
- NSString *fillMode = 0;
- switch (anim->fillMode()) {
- case AnimationFillModeNone:
- fillMode = kCAFillModeForwards; // Use "forwards" rather than "removed" because the style system will remove the animation when it is finished. This avoids a flash.
- break;
- case AnimationFillModeBackwards:
- fillMode = kCAFillModeBoth; // Use "both" rather than "backwards" because the style system will remove the animation when it is finished. This avoids a flash.
- break;
- case AnimationFillModeForwards:
- fillMode = kCAFillModeForwards;
- break;
- case AnimationFillModeBoth:
- fillMode = kCAFillModeBoth;
- break;
- }
-
- [propertyAnim setDuration:duration];
- [propertyAnim setRepeatCount:repeatCount];
- [propertyAnim setAutoreverses:anim->direction()];
- [propertyAnim setRemovedOnCompletion:NO];
- [propertyAnim setAdditive:additive];
- [propertyAnim setFillMode:fillMode];
-
- [propertyAnim setDelegate:m_animationDelegate.get()];
-}
-
-CAMediaTimingFunction* GraphicsLayerMac::timingFunctionForAnimationValue(const AnimationValue* animValue, const Animation* anim)
-{
- const TimingFunction* tf = 0;
- if (animValue->timingFunction())
- tf = animValue->timingFunction();
- else if (anim->isTimingFunctionSet())
- tf = anim->timingFunction().get();
-
- return getCAMediaTimingFunction(tf ? tf : CubicBezierTimingFunction::create().get());
-}
-
-bool GraphicsLayerMac::setAnimationEndpoints(const KeyframeValueList& valueList, const Animation* anim, CABasicAnimation* basicAnim)
-{
- id fromValue = nil;
- id toValue = nil;
-
- switch (valueList.property()) {
- case AnimatedPropertyOpacity: {
- const FloatAnimationValue* startVal = static_cast<const FloatAnimationValue*>(valueList.at(0));
- const FloatAnimationValue* endVal = static_cast<const FloatAnimationValue*>(valueList.at(1));
- fromValue = [NSNumber numberWithFloat:startVal->value()];
- toValue = [NSNumber numberWithFloat:endVal->value()];
- break;
- }
- default:
- ASSERT_NOT_REACHED(); // we don't animate color yet
- break;
- }
-
- // This codepath is used for 2-keyframe animations, so we still need to look in the start
- // for a timing function.
- CAMediaTimingFunction* timingFunction = timingFunctionForAnimationValue(valueList.at(0), anim);
- [basicAnim setTimingFunction:timingFunction];
-
- [basicAnim setFromValue:fromValue];
- [basicAnim setToValue:toValue];
-
- return true;
-}
-
-bool GraphicsLayerMac::setAnimationKeyframes(const KeyframeValueList& valueList, const Animation* anim, CAKeyframeAnimation* keyframeAnim)
-{
- RetainPtr<NSMutableArray> keyTimes(AdoptNS, [[NSMutableArray alloc] init]);
- RetainPtr<NSMutableArray> values(AdoptNS, [[NSMutableArray alloc] init]);
- RetainPtr<NSMutableArray> timingFunctions(AdoptNS, [[NSMutableArray alloc] init]);
-
- for (unsigned i = 0; i < valueList.size(); ++i) {
- const AnimationValue* curValue = valueList.at(i);
- [keyTimes.get() addObject:[NSNumber numberWithFloat:curValue->keyTime()]];
-
- switch (valueList.property()) {
- case AnimatedPropertyOpacity: {
- const FloatAnimationValue* floatValue = static_cast<const FloatAnimationValue*>(curValue);
- [values.get() addObject:[NSNumber numberWithFloat:floatValue->value()]];
- break;
- }
- default:
- ASSERT_NOT_REACHED(); // we don't animate color yet
- break;
- }
-
- CAMediaTimingFunction* timingFunction = timingFunctionForAnimationValue(curValue, anim);
- [timingFunctions.get() addObject:timingFunction];
- }
-
- // We toss the last tfArray value because it has to one shorter than the others.
- [timingFunctions.get() removeLastObject];
-
- [keyframeAnim setKeyTimes:keyTimes.get()];
- [keyframeAnim setValues:values.get()];
- [keyframeAnim setTimingFunctions:timingFunctions.get()];
-
- return true;
-}
-
-bool GraphicsLayerMac::setTransformAnimationEndpoints(const KeyframeValueList& valueList, const Animation* anim, CABasicAnimation* basicAnim, int functionIndex, TransformOperation::OperationType transformOp, bool isMatrixAnimation, const IntSize& boxSize)
-{
- id fromValue;
- id toValue;
-
- ASSERT(valueList.size() == 2);
- const TransformAnimationValue* startValue = static_cast<const TransformAnimationValue*>(valueList.at(0));
- const TransformAnimationValue* endValue = static_cast<const TransformAnimationValue*>(valueList.at(1));
-
- if (isMatrixAnimation) {
- TransformationMatrix fromTransform, toTransform;
- startValue->value()->apply(boxSize, fromTransform);
- endValue->value()->apply(boxSize, toTransform);
-
- // If any matrix is singular, CA won't animate it correctly. So fall back to software animation
- if (!fromTransform.isInvertible() || !toTransform.isInvertible())
- return false;
-
- CATransform3D caTransform;
- copyTransform(caTransform, fromTransform);
- fromValue = [NSValue valueWithCATransform3D:caTransform];
-
- copyTransform(caTransform, toTransform);
- toValue = [NSValue valueWithCATransform3D:caTransform];
- } else {
- fromValue = getTransformFunctionValue(startValue->value()->at(functionIndex), transformOp, boxSize);
- toValue = getTransformFunctionValue(endValue->value()->at(functionIndex), transformOp, boxSize);
- }
-
- // This codepath is used for 2-keyframe animations, so we still need to look in the start
- // for a timing function.
- CAMediaTimingFunction* timingFunction = timingFunctionForAnimationValue(valueList.at(0), anim);
- [basicAnim setTimingFunction:timingFunction];
-
- [basicAnim setFromValue:fromValue];
- [basicAnim setToValue:toValue];
-
-#if HAVE_MODERN_QUARTZCORE
- if (NSString *valueFunctionName = getValueFunctionNameForTransformOperation(transformOp))
- [basicAnim setValueFunction:[CAValueFunction functionWithName:valueFunctionName]];
-#endif
-
- return true;
-}
-
-bool GraphicsLayerMac::setTransformAnimationKeyframes(const KeyframeValueList& valueList, const Animation* animation, CAKeyframeAnimation* keyframeAnim, int functionIndex, TransformOperation::OperationType transformOpType, bool isMatrixAnimation, const IntSize& boxSize)
-{
- RetainPtr<NSMutableArray> keyTimes(AdoptNS, [[NSMutableArray alloc] init]);
- RetainPtr<NSMutableArray> values(AdoptNS, [[NSMutableArray alloc] init]);
- RetainPtr<NSMutableArray> timingFunctions(AdoptNS, [[NSMutableArray alloc] init]);
-
- for (unsigned i = 0; i < valueList.size(); ++i) {
- const TransformAnimationValue* curValue = static_cast<const TransformAnimationValue*>(valueList.at(i));
- [keyTimes.get() addObject:[NSNumber numberWithFloat:curValue->keyTime()]];
-
- if (isMatrixAnimation) {
- TransformationMatrix transform;
- curValue->value()->apply(boxSize, transform);
-
- // If any matrix is singular, CA won't animate it correctly. So fall back to software animation
- if (!transform.isInvertible())
- return false;
-
- CATransform3D caTransform;
- copyTransform(caTransform, transform);
- [values.get() addObject:[NSValue valueWithCATransform3D:caTransform]];
- } else {
- const TransformOperation* transformOp = curValue->value()->at(functionIndex);
- [values.get() addObject:getTransformFunctionValue(transformOp, transformOpType, boxSize)];
- }
-
- CAMediaTimingFunction* timingFunction = timingFunctionForAnimationValue(curValue, animation);
- [timingFunctions.get() addObject:timingFunction];
- }
-
- // We toss the last tfArray value because it has to one shorter than the others.
- [timingFunctions.get() removeLastObject];
-
- [keyframeAnim setKeyTimes:keyTimes.get()];
- [keyframeAnim setValues:values.get()];
- [keyframeAnim setTimingFunctions:timingFunctions.get()];
-
-#if HAVE_MODERN_QUARTZCORE
- if (NSString *valueFunctionName = getValueFunctionNameForTransformOperation(transformOpType))
- [keyframeAnim setValueFunction:[CAValueFunction functionWithName:valueFunctionName]];
-#endif
- return true;
-}
-
-void GraphicsLayerMac::suspendAnimations(double time)
-{
- double t = currentTimeToMediaTime(time ? time : currentTime());
- [primaryLayer() setSpeed:0];
- [primaryLayer() setTimeOffset:t];
-
- // Suspend the animations on the clones too.
- if (LayerMap* layerCloneMap = primaryLayerClones()) {
- LayerMap::const_iterator end = layerCloneMap->end();
- for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
- CALayer *currLayer = it->second.get();
- [currLayer setSpeed:0];
- [currLayer setTimeOffset:t];
- }
- }
-}
-
-void GraphicsLayerMac::resumeAnimations()
-{
- [primaryLayer() setSpeed:1];
- [primaryLayer() setTimeOffset:0];
-
- // Resume the animations on the clones too.
- if (LayerMap* layerCloneMap = primaryLayerClones()) {
- LayerMap::const_iterator end = layerCloneMap->end();
- for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
- CALayer *currLayer = it->second.get();
- [currLayer setSpeed:1];
- [currLayer setTimeOffset:0];
- }
- }
-}
-
-CALayer* GraphicsLayerMac::hostLayerForSublayers() const
-{
- return m_structuralLayer.get() ? m_structuralLayer.get() : m_layer.get();
-}
-
-CALayer* GraphicsLayerMac::layerForSuperlayer() const
-{
- return m_structuralLayer ? m_structuralLayer.get() : m_layer.get();
-}
-
-CALayer* GraphicsLayerMac::animatedLayer(AnimatedPropertyID property) const
-{
- return (property == AnimatedPropertyBackgroundColor) ? m_contentsLayer.get() : primaryLayer();
-}
-
-GraphicsLayerMac::LayerMap* GraphicsLayerMac::animatedLayerClones(AnimatedPropertyID property) const
-{
- return (property == AnimatedPropertyBackgroundColor) ? m_contentsLayerClones.get() : primaryLayerClones();
-}
-
-PlatformLayer* GraphicsLayerMac::platformLayer() const
-{
- return primaryLayer();
-}
-
-void GraphicsLayerMac::setDebugBackgroundColor(const Color& color)
-{
- BEGIN_BLOCK_OBJC_EXCEPTIONS
-
- if (color.isValid())
- setLayerBackgroundColor(m_layer.get(), color);
- else
- clearLayerBackgroundColor(m_layer.get());
-
- END_BLOCK_OBJC_EXCEPTIONS
-}
-
-void GraphicsLayerMac::setDebugBorder(const Color& color, float borderWidth)
-{
- BEGIN_BLOCK_OBJC_EXCEPTIONS
-
- if (color.isValid()) {
- setLayerBorderColor(m_layer.get(), color);
- [m_layer.get() setBorderWidth:borderWidth];
- } else {
- clearBorderColor(m_layer.get());
- [m_layer.get() setBorderWidth:0];
- }
-
- END_BLOCK_OBJC_EXCEPTIONS
-}
-
-FloatSize GraphicsLayerMac::constrainedSize() const
-{
- float tileColumns = ceilf(m_size.width() / cTiledLayerTileSize);
- float tileRows = ceilf(m_size.height() / cTiledLayerTileSize);
- double numTiles = tileColumns * tileRows;
-
- FloatSize constrainedSize = m_size;
- const unsigned cMaxTileCount = 512;
- while (numTiles > cMaxTileCount) {
- // Constrain the wider dimension.
- if (constrainedSize.width() >= constrainedSize.height()) {
- tileColumns = max(floorf(cMaxTileCount / tileRows), 1.0f);
- constrainedSize.setWidth(tileColumns * cTiledLayerTileSize);
- } else {
- tileRows = max(floorf(cMaxTileCount / tileColumns), 1.0f);
- constrainedSize.setHeight(tileRows * cTiledLayerTileSize);
- }
- numTiles = tileColumns * tileRows;
- }
-
- return constrainedSize;
-}
-
-bool GraphicsLayerMac::requiresTiledLayer(const FloatSize& size) const
-{
- if (!m_drawsContent)
- return false;
-
- // FIXME: catch zero-size height or width here (or earlier)?
- return size.width() > cMaxPixelDimension || size.height() > cMaxPixelDimension;
-}
-
-void GraphicsLayerMac::swapFromOrToTiledLayer(bool useTiledLayer)
-{
- if (useTiledLayer == m_usingTiledLayer)
- return;
-
- CGSize tileSize = CGSizeMake(cTiledLayerTileSize, cTiledLayerTileSize);
-
- RetainPtr<CALayer> oldLayer = m_layer.get();
-
- Class layerClass = useTiledLayer ? [WebTiledLayer self] : [WebLayer self];
- m_layer.adoptNS([[layerClass alloc] init]);
-
- m_usingTiledLayer = useTiledLayer;
-
- if (useTiledLayer) {
- WebTiledLayer* tiledLayer = (WebTiledLayer*)m_layer.get();
- [tiledLayer setTileSize:tileSize];
- [tiledLayer setLevelsOfDetail:1];
- [tiledLayer setLevelsOfDetailBias:0];
- [tiledLayer setContentsGravity:@"bottomLeft"];
-
-#if !HAVE_MODERN_QUARTZCORE
- // Tiled layer has issues with flipped coordinates.
- setContentsOrientation(CompositingCoordinatesTopDown);
-#endif
- } else {
-#if !HAVE_MODERN_QUARTZCORE
- setContentsOrientation(defaultContentsOrientation());
-#endif
- }
-
- [m_layer.get() setLayerOwner:this];
- safeSetSublayers(m_layer.get(), [oldLayer.get() sublayers]);
-
- [[oldLayer.get() superlayer] replaceSublayer:oldLayer.get() with:m_layer.get()];
-
- updateContentsTransform();
-
- updateLayerPosition();
- updateLayerSize();
- updateAnchorPoint();
- updateTransform();
- updateChildrenTransform();
- updateMasksToBounds();
- updateContentsOpaque();
- updateBackfaceVisibility();
- updateLayerBackgroundColor();
-
- updateOpacityOnLayer();
-
-#ifndef NDEBUG
- String name = String::format("CALayer(%p) GraphicsLayer(%p) ", m_layer.get(), this) + m_name;
- [m_layer.get() setName:name];
-#endif
-
- // move over animations
- moveOrCopyAnimationsForProperty(Move, AnimatedPropertyWebkitTransform, oldLayer.get(), m_layer.get());
- moveOrCopyAnimationsForProperty(Move, AnimatedPropertyOpacity, oldLayer.get(), m_layer.get());
- moveOrCopyAnimationsForProperty(Move, AnimatedPropertyBackgroundColor, oldLayer.get(), m_layer.get());
-
- // need to tell new layer to draw itself
- setNeedsDisplay();
-
- updateDebugIndicators();
-}
-
-GraphicsLayer::CompositingCoordinatesOrientation GraphicsLayerMac::defaultContentsOrientation() const
-{
-#if !HAVE_MODERN_QUARTZCORE
- // Older QuartzCore does not support -geometryFlipped, so we manually flip the root
- // layer geometry, and then flip the contents of each layer back so that the CTM for CG
- // is unflipped, allowing it to do the correct font auto-hinting.
- return CompositingCoordinatesBottomUp;
-#else
- return CompositingCoordinatesTopDown;
-#endif
-}
-
-void GraphicsLayerMac::updateContentsTransform()
-{
-#if !HAVE_MODERN_QUARTZCORE
- if (contentsOrientation() == CompositingCoordinatesBottomUp) {
- CGAffineTransform contentsTransform = CGAffineTransformMakeScale(1, -1);
- contentsTransform = CGAffineTransformTranslate(contentsTransform, 0, -[m_layer.get() bounds].size.height);
- [m_layer.get() setContentsTransform:contentsTransform];
- }
-#endif
-}
-
-void GraphicsLayerMac::setupContentsLayer(CALayer* contentsLayer)
-{
- // Turn off implicit animations on the inner layer.
- [contentsLayer setStyle:[NSDictionary dictionaryWithObject:nullActionsDictionary() forKey:@"actions"]];
- [contentsLayer setMasksToBounds:YES];
-
- if (defaultContentsOrientation() == CompositingCoordinatesBottomUp) {
- CATransform3D flipper = {
- 1.0f, 0.0f, 0.0f, 0.0f,
- 0.0f, -1.0f, 0.0f, 0.0f,
- 0.0f, 0.0f, 1.0f, 0.0f,
- 0.0f, 0.0f, 0.0f, 1.0f};
- [contentsLayer setTransform:flipper];
- [contentsLayer setAnchorPoint:CGPointMake(0.0f, 1.0f)];
- } else
- [contentsLayer setAnchorPoint:CGPointZero];
-
- if (showDebugBorders()) {
- setLayerBorderColor(contentsLayer, Color(0, 0, 128, 180));
- [contentsLayer setBorderWidth:1.0f];
- }
-}
-
-CALayer *GraphicsLayerMac::findOrMakeClone(CloneID cloneID, CALayer *sourceLayer, LayerMap* clones, CloneLevel cloneLevel)
-{
- if (!sourceLayer)
- return 0;
-
- CALayer *resultLayer;
-
- // Add with a dummy value to get an iterator for the insertion position, and a boolean that tells
- // us whether there's an item there. This technique avoids two hash lookups.
- RetainPtr<CALayer> dummy;
- pair<LayerMap::iterator, bool> addResult = clones->add(cloneID, dummy);
- if (!addResult.second) {
- // Value was not added, so it exists already.
- resultLayer = addResult.first->second.get();
- } else {
- resultLayer = cloneLayer(sourceLayer, cloneLevel);
-#ifndef NDEBUG
- [resultLayer setName:[NSString stringWithFormat:@"Clone %d of layer %@", cloneID[0U], sourceLayer]];
-#endif
- addResult.first->second = resultLayer;
- }
-
- return resultLayer;
-}
-
-void GraphicsLayerMac::ensureCloneLayers(CloneID cloneID, CALayer *& primaryLayer, CALayer *& structuralLayer, CALayer *& contentsLayer, CloneLevel cloneLevel)
-{
- structuralLayer = nil;
- contentsLayer = nil;
-
- if (!m_layerClones)
- m_layerClones = new LayerMap;
-
- if (!m_structuralLayerClones && m_structuralLayer)
- m_structuralLayerClones = new LayerMap;
-
- if (!m_contentsLayerClones && m_contentsLayer)
- m_contentsLayerClones = new LayerMap;
-
- primaryLayer = findOrMakeClone(cloneID, m_layer.get(), m_layerClones.get(), cloneLevel);
- structuralLayer = findOrMakeClone(cloneID, m_structuralLayer.get(), m_structuralLayerClones.get(), cloneLevel);
- contentsLayer = findOrMakeClone(cloneID, m_contentsLayer.get(), m_contentsLayerClones.get(), cloneLevel);
-}
-
-void GraphicsLayerMac::removeCloneLayers()
-{
- m_layerClones = 0;
- m_structuralLayerClones = 0;
- m_contentsLayerClones = 0;
-}
-
-FloatPoint GraphicsLayerMac::positionForCloneRootLayer() const
-{
- // This can get called during a sync when we've just removed the m_replicaLayer.
- if (!m_replicaLayer)
- return FloatPoint();
-
- FloatPoint replicaPosition = m_replicaLayer->replicatedLayerPosition();
- return FloatPoint(replicaPosition.x() + m_anchorPoint.x() * m_size.width(),
- replicaPosition.y() + m_anchorPoint.y() * m_size.height());
-}
-
-void GraphicsLayerMac::propagateLayerChangeToReplicas()
-{
- for (GraphicsLayer* currLayer = this; currLayer; currLayer = currLayer->parent()) {
- GraphicsLayerMac* currLayerCA = static_cast<GraphicsLayerMac*>(currLayer);
- if (!currLayerCA->hasCloneLayers())
- break;
-
- if (currLayerCA->replicaLayer())
- static_cast<GraphicsLayerMac*>(currLayerCA->replicaLayer())->noteLayerPropertyChanged(ReplicatedLayerChanged);
- }
-}
-
-CALayer *GraphicsLayerMac::fetchCloneLayers(GraphicsLayer* replicaRoot, ReplicaState& replicaState, CloneLevel cloneLevel)
-{
- CALayer *primaryLayer;
- CALayer *structuralLayer;
- CALayer *contentsLayer;
- ensureCloneLayers(replicaState.cloneID(), primaryLayer, structuralLayer, contentsLayer, cloneLevel);
-
- if (m_maskLayer) {
- CALayer *maskClone = static_cast<GraphicsLayerMac*>(m_maskLayer)->fetchCloneLayers(replicaRoot, replicaState, IntermediateCloneLevel);
- [primaryLayer setMask:maskClone];
- }
-
- if (m_replicatedLayer) {
- // We are a replica being asked for clones of our layers.
- CALayer *replicaRoot = replicatedLayerRoot(replicaState);
- if (!replicaRoot)
- return nil;
-
- if (structuralLayer) {
- [structuralLayer insertSublayer:replicaRoot atIndex:0];
- return structuralLayer;
- }
-
- [primaryLayer insertSublayer:replicaRoot atIndex:0];
- return primaryLayer;
- }
-
- const Vector<GraphicsLayer*>& childLayers = children();
- NSMutableArray* clonalSublayers = nil;
-
- CALayer *replicaLayer = nil;
- if (m_replicaLayer && m_replicaLayer != replicaRoot) {
- // We have nested replicas. Ask the replica layer for a clone of its contents.
- replicaState.setBranchType(ReplicaState::ReplicaBranch);
- replicaLayer = static_cast<GraphicsLayerMac*>(m_replicaLayer)->fetchCloneLayers(replicaRoot, replicaState, RootCloneLevel);
- replicaState.setBranchType(ReplicaState::ChildBranch);
- }
-
- if (replicaLayer || structuralLayer || contentsLayer || childLayers.size() > 0) {
- clonalSublayers = [[NSMutableArray alloc] init];
-
- if (structuralLayer) {
- // Replicas render behind the actual layer content.
- if (replicaLayer)
- [clonalSublayers addObject:replicaLayer];
-
- // Add the primary layer next. Even if we have negative z-order children, the primary layer always comes behind.
- [clonalSublayers addObject:primaryLayer];
- } else if (contentsLayer) {
- // FIXME: add the contents layer in the correct order with negative z-order children.
- // This does not cause visible rendering issues because currently contents layers are only used
- // for replaced elements that don't have children.
- [clonalSublayers addObject:contentsLayer];
- }
-
- replicaState.push(ReplicaState::ChildBranch);
-
- size_t numChildren = childLayers.size();
- for (size_t i = 0; i < numChildren; ++i) {
- GraphicsLayerMac* curChild = static_cast<GraphicsLayerMac*>(childLayers[i]);
-
- CALayer *childLayer = curChild->fetchCloneLayers(replicaRoot, replicaState, IntermediateCloneLevel);
- if (childLayer)
- [clonalSublayers addObject:childLayer];
- }
-
- replicaState.pop();
-
- [clonalSublayers makeObjectsPerformSelector:@selector(removeFromSuperlayer)];
- }
-
- CALayer *result;
- if (structuralLayer) {
- [structuralLayer setSublayers:clonalSublayers];
-
- if (contentsLayer) {
- // If we have a transform layer, then the contents layer is parented in the
- // primary layer (which is itself a child of the transform layer).
- [primaryLayer setSublayers:nil];
- [primaryLayer addSublayer:contentsLayer];
- }
-
- result = structuralLayer;
- } else {
- [primaryLayer setSublayers:clonalSublayers];
- result = primaryLayer;
- }
-
- [clonalSublayers release];
- return result;
-}
-
-CALayer *GraphicsLayerMac::cloneLayer(CALayer *layer, CloneLevel cloneLevel)
-{
- static Class transformLayerClass = NSClassFromString(@"CATransformLayer");
- CALayer *newLayer = nil;
- if ([layer isKindOfClass:transformLayerClass])
- newLayer = [transformLayerClass layer];
- else
- newLayer = [CALayer layer];
-
- [newLayer setStyle:[NSDictionary dictionaryWithObject:nullActionsDictionary() forKey:@"actions"]];
-
- [newLayer setPosition:[layer position]];
- [newLayer setBounds:[layer bounds]];
- [newLayer setAnchorPoint:[layer anchorPoint]];
-#if HAVE_MODERN_QUARTZCORE
- [newLayer setAnchorPointZ:[layer anchorPointZ]];
-#endif
- [newLayer setTransform:[layer transform]];
- [newLayer setSublayerTransform:[layer sublayerTransform]];
- [newLayer setContents:[layer contents]];
- [newLayer setMasksToBounds:[layer masksToBounds]];
- [newLayer setDoubleSided:[layer isDoubleSided]];
- [newLayer setOpaque:[layer isOpaque]];
- [newLayer setBackgroundColor:[layer backgroundColor]];
-
- if (cloneLevel == IntermediateCloneLevel) {
- [newLayer setOpacity:[layer opacity]];
- moveOrCopyAnimationsForProperty(Copy, AnimatedPropertyWebkitTransform, layer, newLayer);
- moveOrCopyAnimationsForProperty(Copy, AnimatedPropertyOpacity, layer, newLayer);
- }
-
- if (showDebugBorders()) {
- setLayerBorderColor(newLayer, Color(255, 122, 251));
- [newLayer setBorderWidth:2];
- }
-
- return newLayer;
-}
-
-void GraphicsLayerMac::setOpacityInternal(float accumulatedOpacity)
-{
- LayerMap* layerCloneMap = 0;
-
- if (preserves3D()) {
- [m_layer.get() setOpacity:accumulatedOpacity];
- layerCloneMap = m_layerClones.get();
- } else {
- [primaryLayer() setOpacity:accumulatedOpacity];
- layerCloneMap = primaryLayerClones();
- }
-
- if (layerCloneMap) {
- LayerMap::const_iterator end = layerCloneMap->end();
- for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
- if (m_replicaLayer && isReplicatedRootClone(it->first))
- continue;
- CALayer *currLayer = it->second.get();
- [currLayer setOpacity:m_opacity];
- }
- }
-}
-
-void GraphicsLayerMac::updateOpacityOnLayer()
-{
-#if !HAVE_MODERN_QUARTZCORE
- // Distribute opacity either to our own layer or to our children. We pass in the
- // contribution from our parent(s).
- distributeOpacity(parent() ? parent()->accumulatedOpacity() : 1);
-#else
- [primaryLayer() setOpacity:m_opacity];
-
- if (LayerMap* layerCloneMap = primaryLayerClones()) {
- LayerMap::const_iterator end = layerCloneMap->end();
- for (LayerMap::const_iterator it = layerCloneMap->begin(); it != end; ++it) {
- if (m_replicaLayer && isReplicatedRootClone(it->first))
- continue;
-
- CALayer *currLayer = it->second.get();
- [currLayer setOpacity:m_opacity];
- }
-
- }
-#endif
-}
-
-void GraphicsLayerMac::noteSublayersChanged()
-{
- noteLayerPropertyChanged(ChildrenChanged);
- propagateLayerChangeToReplicas();
-}
-
-void GraphicsLayerMac::noteLayerPropertyChanged(LayerChangeFlags flags)
-{
- if (!m_uncommittedChanges && m_client)
- m_client->notifySyncRequired(this);
-
- m_uncommittedChanges |= flags;
-}
-
-} // namespace WebCore
-
-#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm
index 1538e07..2361f6a 100644
--- a/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm
+++ b/WebCore/platform/graphics/mac/MediaPlayerPrivateQTKit.mm
@@ -255,7 +255,7 @@ void MediaPlayerPrivateQTKit::createQTMovie(const String& url)
#endif
nil];
-#if defined(BUILDING_ON_SNOW_LEOPARD)
+#if !defined(BUILDING_ON_LEOPARD)
CFDictionaryRef proxySettings = CFNetworkCopySystemProxySettings();
CFArrayRef proxiesForURL = CFNetworkCopyProxiesForURL((CFURLRef)cocoaURL, proxySettings);
BOOL willUseProxy = YES;
@@ -623,7 +623,7 @@ void MediaPlayerPrivateQTKit::resumeLoad()
{
m_delayingLoad = false;
- if (m_movieURL)
+ if (!m_movieURL.isNull())
loadInternal(m_movieURL);
}
diff --git a/WebCore/platform/graphics/mac/SimpleFontDataMac.mm b/WebCore/platform/graphics/mac/SimpleFontDataMac.mm
index e1d3f43..92585c6 100644
--- a/WebCore/platform/graphics/mac/SimpleFontDataMac.mm
+++ b/WebCore/platform/graphics/mac/SimpleFontDataMac.mm
@@ -357,9 +357,13 @@ void SimpleFontData::platformCharWidthInit()
void SimpleFontData::platformDestroy()
{
- if (m_smallCapsFontData && !isCustomFont()) {
- fontCache()->releaseFontData(m_smallCapsFontData);
- m_smallCapsFontData = 0;
+ if (!isCustomFont() && m_derivedFontData) {
+ // These come from the cache.
+ if (m_derivedFontData->smallCaps)
+ fontCache()->releaseFontData(m_derivedFontData->smallCaps.leakPtr());
+
+ if (m_derivedFontData->emphasisMark)
+ fontCache()->releaseFontData(m_derivedFontData->emphasisMark.leakPtr());
}
#ifdef BUILDING_ON_TIGER
@@ -373,41 +377,60 @@ void SimpleFontData::platformDestroy()
#endif
}
-SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const
+SimpleFontData* SimpleFontData::scaledFontData(const FontDescription& fontDescription, float scaleFactor) const
{
- if (!m_smallCapsFontData) {
- if (isCustomFont()) {
- FontPlatformData smallCapsFontData(m_platformData);
- smallCapsFontData.m_size = smallCapsFontData.m_size * smallCapsFontSizeMultiplier;
- m_smallCapsFontData = new SimpleFontData(smallCapsFontData, true, false);
- } else {
- BEGIN_BLOCK_OBJC_EXCEPTIONS;
- float size = m_platformData.size() * smallCapsFontSizeMultiplier;
- FontPlatformData smallCapsFont([[NSFontManager sharedFontManager] convertFont:m_platformData.font() toSize:size], size);
-
- // AppKit resets the type information (screen/printer) when you convert a font to a different size.
- // We have to fix up the font that we're handed back.
- smallCapsFont.setFont(fontDescription.usePrinterFont() ? [smallCapsFont.font() printerFont] : [smallCapsFont.font() screenFont]);
-
- if (smallCapsFont.font()) {
- NSFontManager *fontManager = [NSFontManager sharedFontManager];
- NSFontTraitMask fontTraits = [fontManager traitsOfFont:m_platformData.font()];
-
- if (m_platformData.m_syntheticBold)
- fontTraits |= NSBoldFontMask;
- if (m_platformData.m_syntheticOblique)
- fontTraits |= NSItalicFontMask;
-
- NSFontTraitMask smallCapsFontTraits = [fontManager traitsOfFont:smallCapsFont.font()];
- smallCapsFont.m_syntheticBold = (fontTraits & NSBoldFontMask) && !(smallCapsFontTraits & NSBoldFontMask);
- smallCapsFont.m_syntheticOblique = (fontTraits & NSItalicFontMask) && !(smallCapsFontTraits & NSItalicFontMask);
-
- m_smallCapsFontData = fontCache()->getCachedFontData(&smallCapsFont);
- }
- END_BLOCK_OBJC_EXCEPTIONS;
- }
+ if (isCustomFont()) {
+ FontPlatformData scaledFontData(m_platformData);
+ scaledFontData.m_size = scaledFontData.m_size * scaleFactor;
+ return new SimpleFontData(scaledFontData, true, false);
+ }
+
+ BEGIN_BLOCK_OBJC_EXCEPTIONS;
+ float size = m_platformData.size() * scaleFactor;
+ FontPlatformData scaledFontData([[NSFontManager sharedFontManager] convertFont:m_platformData.font() toSize:size], size);
+
+ // AppKit resets the type information (screen/printer) when you convert a font to a different size.
+ // We have to fix up the font that we're handed back.
+ scaledFontData.setFont(fontDescription.usePrinterFont() ? [scaledFontData.font() printerFont] : [scaledFontData.font() screenFont]);
+
+ if (scaledFontData.font()) {
+ NSFontManager *fontManager = [NSFontManager sharedFontManager];
+ NSFontTraitMask fontTraits = [fontManager traitsOfFont:m_platformData.font()];
+
+ if (m_platformData.m_syntheticBold)
+ fontTraits |= NSBoldFontMask;
+ if (m_platformData.m_syntheticOblique)
+ fontTraits |= NSItalicFontMask;
+
+ NSFontTraitMask scaledFontTraits = [fontManager traitsOfFont:scaledFontData.font()];
+ scaledFontData.m_syntheticBold = (fontTraits & NSBoldFontMask) && !(scaledFontTraits & NSBoldFontMask);
+ scaledFontData.m_syntheticOblique = (fontTraits & NSItalicFontMask) && !(scaledFontTraits & NSItalicFontMask);
+
+ return fontCache()->getCachedFontData(&scaledFontData);
}
- return m_smallCapsFontData;
+ END_BLOCK_OBJC_EXCEPTIONS;
+
+ return 0;
+}
+
+SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const
+{
+ if (!m_derivedFontData)
+ m_derivedFontData = DerivedFontData::create(isCustomFont());
+ if (!m_derivedFontData->smallCaps)
+ m_derivedFontData->smallCaps = scaledFontData(fontDescription, smallCapsFontSizeMultiplier);
+
+ return m_derivedFontData->smallCaps.get();
+}
+
+SimpleFontData* SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const
+{
+ if (!m_derivedFontData)
+ m_derivedFontData = DerivedFontData::create(isCustomFont());
+ if (!m_derivedFontData->emphasisMark)
+ m_derivedFontData->emphasisMark = scaledFontData(fontDescription, .5f);
+
+ return m_derivedFontData->emphasisMark.get();
}
bool SimpleFontData::containsCharacters(const UChar* characters, int length) const
diff --git a/WebCore/platform/graphics/mac/WebLayer.h b/WebCore/platform/graphics/mac/WebLayer.h
index 3a91f04..62d69fc 100644
--- a/WebCore/platform/graphics/mac/WebLayer.h
+++ b/WebCore/platform/graphics/mac/WebLayer.h
@@ -34,14 +34,6 @@ namespace WebCore {
class GraphicsLayer;
}
-// Category implemented by WebLayer and WebTiledLayer.
-@interface CALayer(WebLayerAdditions)
-
-- (void)setLayerOwner:(WebCore::GraphicsLayer*)layer;
-- (WebCore::GraphicsLayer*)layerOwner;
-
-@end
-
#if defined(BUILDING_ON_LEOPARD)
@interface CALayer(WebLayerInternal)
- (CGAffineTransform)contentsTransform;
@@ -51,7 +43,6 @@ namespace WebCore {
@interface WebLayer : CALayer
{
- WebCore::GraphicsLayer* m_layerOwner;
}
@end
diff --git a/WebCore/platform/graphics/mac/WebLayer.mm b/WebCore/platform/graphics/mac/WebLayer.mm
index 9bb8212..128e63b 100644
--- a/WebCore/platform/graphics/mac/WebLayer.mm
+++ b/WebCore/platform/graphics/mac/WebLayer.mm
@@ -30,7 +30,8 @@
#import "WebLayer.h"
#import "GraphicsContext.h"
-#import "GraphicsLayer.h"
+#import "GraphicsLayerCA.h"
+#import "PlatformCALayer.h"
#import <objc/objc-runtime.h>
#import <QuartzCore/QuartzCore.h>
#import <wtf/UnusedParam.h>
@@ -62,6 +63,11 @@ void drawLayerContents(CGContextRef context, CALayer *layer, WebCore::GraphicsLa
GraphicsContext graphicsContext(context);
+ if (!layerContents->contentsOpaque()) {
+ // Turn off font smoothing to improve the appearance of text rendered onto a transparent background.
+ graphicsContext.setShouldSmoothFonts(false);
+ }
+
// It's important to get the clip from the context, because it may be significantly
// smaller than the layer bounds (e.g. tiled layers)
CGRect clipBounds = CGContextGetClipBoundingBox(context);
@@ -146,58 +152,39 @@ void setLayerNeedsDisplayInRect(CALayer *layer, WebCore::GraphicsLayer* layerCon
return nil;
}
-// Implement this so presentationLayer can get our custom attributes
-- (id)initWithLayer:(id)layer
-{
- if ((self = [super initWithLayer:layer]))
- m_layerOwner = [(WebLayer*)layer layerOwner];
-
- return self;
-}
-
- (void)setNeedsDisplay
{
- if (m_layerOwner && m_layerOwner->client() && m_layerOwner->drawsContent())
+ PlatformCALayer* layer = PlatformCALayer::platformCALayer(self);
+ if (layer && layer->owner() && layer->owner()->client() && layer->owner()->drawsContent())
[super setNeedsDisplay];
}
- (void)setNeedsDisplayInRect:(CGRect)dirtyRect
{
- setLayerNeedsDisplayInRect(self, m_layerOwner, dirtyRect);
+ PlatformCALayer* layer = PlatformCALayer::platformCALayer(self);
+ if (layer)
+ setLayerNeedsDisplayInRect(self, layer->owner(), dirtyRect);
}
- (void)display
{
[super display];
- if (m_layerOwner)
- m_layerOwner->didDisplay(self);
+ PlatformCALayer* layer = PlatformCALayer::platformCALayer(self);
+ if (layer && layer->owner())
+ layer->owner()->didDisplay(self);
}
- (void)drawInContext:(CGContextRef)context
{
- drawLayerContents(context, self, m_layerOwner);
+ PlatformCALayer* layer = PlatformCALayer::platformCALayer(self);
+ if (layer)
+ drawLayerContents(context, self, layer->owner());
}
@end // implementation WebLayer
#pragma mark -
-@implementation WebLayer(WebLayerAdditions)
-
-- (void)setLayerOwner:(GraphicsLayer*)aLayer
-{
- m_layerOwner = aLayer;
-}
-
-- (GraphicsLayer*)layerOwner
-{
- return m_layerOwner;
-}
-
-@end
-
-#pragma mark -
-
#ifndef NDEBUG
@implementation CALayer(ExtendedDescription)
diff --git a/WebCore/platform/graphics/mac/WebTiledLayer.h b/WebCore/platform/graphics/mac/WebTiledLayer.h
index 1c9144d..6f559e3 100644
--- a/WebCore/platform/graphics/mac/WebTiledLayer.h
+++ b/WebCore/platform/graphics/mac/WebTiledLayer.h
@@ -32,7 +32,6 @@
@interface WebTiledLayer : CATiledLayer
{
- WebCore::GraphicsLayer* m_layerOwner;
}
// implements WebLayerAdditions
diff --git a/WebCore/platform/graphics/mac/WebTiledLayer.mm b/WebCore/platform/graphics/mac/WebTiledLayer.mm
index 72128ad..bf35431 100644
--- a/WebCore/platform/graphics/mac/WebTiledLayer.mm
+++ b/WebCore/platform/graphics/mac/WebTiledLayer.mm
@@ -30,7 +30,8 @@
#import "WebTiledLayer.h"
#import "GraphicsContext.h"
-#import "GraphicsLayer.h"
+#import "GraphicsLayerCA.h"
+#import "PlatformCALayer.h"
#import <wtf/UnusedParam.h>
using namespace WebCore;
@@ -56,54 +57,35 @@ using namespace WebCore;
return nil;
}
-// Implement this so presentationLayer can get our custom attributes
-- (id)initWithLayer:(id)layer
-{
- if ((self = [super initWithLayer:layer]))
- m_layerOwner = [(WebLayer*)layer layerOwner];
-
- return self;
-}
-
- (void)setNeedsDisplay
{
- if (m_layerOwner && m_layerOwner->client() && m_layerOwner->drawsContent())
+ PlatformCALayer* layer = PlatformCALayer::platformCALayer(self);
+ if (layer && layer->owner() && layer->owner()->client() && layer->owner()->drawsContent())
[super setNeedsDisplay];
}
- (void)setNeedsDisplayInRect:(CGRect)dirtyRect
{
- setLayerNeedsDisplayInRect(self, m_layerOwner, dirtyRect);
+ PlatformCALayer* layer = PlatformCALayer::platformCALayer(self);
+ if (layer)
+ setLayerNeedsDisplayInRect(self, layer->owner(), dirtyRect);
}
- (void)display
{
[super display];
- if (m_layerOwner)
- m_layerOwner->didDisplay(self);
+ PlatformCALayer* layer = PlatformCALayer::platformCALayer(self);
+ if (layer && layer->owner())
+ layer->owner()->didDisplay(self);
}
- (void)drawInContext:(CGContextRef)context
{
- drawLayerContents(context, self, m_layerOwner);
+ PlatformCALayer* layer = PlatformCALayer::platformCALayer(self);
+ if (layer)
+ drawLayerContents(context, self, layer->owner());
}
@end // implementation WebTiledLayer
-#pragma mark -
-
-@implementation WebTiledLayer(LayerMacAdditions)
-
-- (void)setLayerOwner:(GraphicsLayer*)aLayer
-{
- m_layerOwner = aLayer;
-}
-
-- (GraphicsLayer*)layerOwner
-{
- return m_layerOwner;
-}
-
-@end
-
#endif // USE(ACCELERATED_COMPOSITING)
diff --git a/WebCore/platform/graphics/opengl/Extensions3DOpenGL.cpp b/WebCore/platform/graphics/opengl/Extensions3DOpenGL.cpp
index a6fa5d9..4215d12 100644
--- a/WebCore/platform/graphics/opengl/Extensions3DOpenGL.cpp
+++ b/WebCore/platform/graphics/opengl/Extensions3DOpenGL.cpp
@@ -76,10 +76,20 @@ bool Extensions3DOpenGL::supports(const String& name)
return m_availableExtensions.contains("GL_EXT_framebuffer_blit");
if (name == "GL_ANGLE_framebuffer_multisample")
return m_availableExtensions.contains("GL_EXT_framebuffer_multisample");
-
+
+ // If GL_ARB_texture_float is available then we report GL_OES_texture_float and
+ // GL_OES_texture_half_float as available.
+ if (name == "GL_OES_texture_float" || name == "GL_OES_texture_half_float")
+ return m_availableExtensions.contains("GL_ARB_texture_float");
+
return m_availableExtensions.contains(name);
}
+void Extensions3DOpenGL::ensureEnabled(const String& name)
+{
+ ASSERT_UNUSED(name, supports(name));
+}
+
int Extensions3DOpenGL::getGraphicsResetStatusARB()
{
return GraphicsContext3D::NO_ERROR;
diff --git a/WebCore/platform/graphics/opengl/Extensions3DOpenGL.h b/WebCore/platform/graphics/opengl/Extensions3DOpenGL.h
index 0fbe022..59f8180 100644
--- a/WebCore/platform/graphics/opengl/Extensions3DOpenGL.h
+++ b/WebCore/platform/graphics/opengl/Extensions3DOpenGL.h
@@ -40,6 +40,7 @@ public:
// Extensions3D methods.
virtual bool supports(const String&);
+ virtual void ensureEnabled(const String&);
virtual int getGraphicsResetStatusARB();
virtual void blitFramebuffer(long srcX0, long srcY0, long srcX1, long srcY1, long dstX0, long dstY0, long dstX1, long dstY1, unsigned long mask, unsigned long filter);
virtual void renderbufferStorageMultisample(unsigned long target, unsigned long samples, unsigned long internalformat, unsigned long width, unsigned long height);
diff --git a/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp b/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp
index d295abb..aa3b60e 100644
--- a/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp
+++ b/WebCore/platform/graphics/opengl/GraphicsContext3DOpenGL.cpp
@@ -125,7 +125,10 @@ void GraphicsContext3D::paintRenderingResultsToCanvas(CanvasRenderingContext* co
void GraphicsContext3D::reshape(int width, int height)
{
- if (width == m_currentWidth && height == m_currentHeight || !m_contextObj)
+ if (!m_contextObj)
+ return;
+
+ if (width == m_currentWidth && height == m_currentHeight)
return;
m_currentWidth = width;
@@ -1324,9 +1327,20 @@ long GraphicsContext3D::getVertexAttribOffset(unsigned long index, unsigned long
int GraphicsContext3D::texImage2D(unsigned target, unsigned level, unsigned internalformat, unsigned width, unsigned height, unsigned border, unsigned format, unsigned type, void* pixels)
{
+ if (width && height && !pixels) {
+ synthesizeGLError(INVALID_VALUE);
+ return 1;
+ }
makeContextCurrent();
+ unsigned openGLInternalFormat = internalformat;
+ if (type == GL_FLOAT) {
+ if (format == GL_RGBA)
+ openGLInternalFormat = GL_RGBA32F_ARB;
+ else if (format == GL_RGB)
+ openGLInternalFormat = GL_RGB32F_ARB;
+ }
- ::glTexImage2D(target, level, internalformat, width, height, border, format, type, pixels);
+ ::glTexImage2D(target, level, openGLInternalFormat, width, height, border, format, type, pixels);
return 0;
}
diff --git a/WebCore/platform/graphics/openvg/GraphicsContextOpenVG.cpp b/WebCore/platform/graphics/openvg/GraphicsContextOpenVG.cpp
index 0d16d4d..633ca75 100644
--- a/WebCore/platform/graphics/openvg/GraphicsContextOpenVG.cpp
+++ b/WebCore/platform/graphics/openvg/GraphicsContextOpenVG.cpp
@@ -21,7 +21,6 @@
#include "GraphicsContext.h"
#include "AffineTransform.h"
-#include "GraphicsContextPrivate.h"
#include "KURL.h"
#include "NotImplemented.h"
#include "PainterOpenVG.h"
@@ -49,16 +48,14 @@ public:
}
};
-GraphicsContext::GraphicsContext(SurfaceOpenVG* surface)
- : m_common(createGraphicsContextPrivate())
- , m_data(surface ? new GraphicsContextPlatformPrivate(surface) : 0)
+void GraphicsContext::platformInit(SurfaceOpenVG* surface)
{
+ m_data = surface ? new GraphicsContextPlatformPrivate(surface) : 0;
setPaintingDisabled(!surface);
}
-GraphicsContext::~GraphicsContext()
+void GraphicsContext::platformDestroy()
{
- destroyGraphicsContextPrivate(m_common);
delete m_data;
}
@@ -139,28 +136,20 @@ void GraphicsContext::drawConvexPolygon(size_t numPoints, const FloatPoint* poin
UNUSED_PARAM(shouldAntialias); // FIXME
}
-void GraphicsContext::fillPath()
+void GraphicsContext::fillPath(const Path& path)
{
if (paintingDisabled())
return;
- m_data->drawPath(VG_FILL_PATH, m_common->state.fillRule);
+ m_data->drawPath(path, VG_FILL_PATH, m_state.fillRule);
}
-void GraphicsContext::strokePath()
+void GraphicsContext::strokePath(const Path& path)
{
if (paintingDisabled())
return;
- m_data->drawPath(VG_STROKE_PATH, m_common->state.fillRule);
-}
-
-void GraphicsContext::drawPath()
-{
- if (paintingDisabled())
- return;
-
- m_data->drawPath(VG_FILL_PATH | VG_STROKE_PATH, m_common->state.fillRule);
+ m_data->drawPath(path, VG_STROKE_PATH, m_state.fillRule);
}
void GraphicsContext::fillRect(const FloatRect& rect)
@@ -197,22 +186,6 @@ void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLef
UNUSED_PARAM(colorSpace); // FIXME
}
-void GraphicsContext::beginPath()
-{
- if (paintingDisabled())
- return;
-
- m_data->beginPath();
-}
-
-void GraphicsContext::addPath(const Path& path)
-{
- if (paintingDisabled())
- return;
-
- m_data->addPath(path);
-}
-
void GraphicsContext::clip(const FloatRect& rect)
{
if (paintingDisabled())
@@ -221,12 +194,12 @@ void GraphicsContext::clip(const FloatRect& rect)
m_data->intersectClipRect(rect);
}
-void GraphicsContext::clipPath(WindRule clipRule)
+void GraphicsContext::clipPath(const Path& path, WindRule clipRule)
{
if (paintingDisabled())
return;
- m_data->clipPath(*(m_data->currentPath()), PainterOpenVG::IntersectClip, clipRule);
+ m_data->clipPath(path, PainterOpenVG::IntersectClip, clipRule);
}
void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int width, int offset, const Color& color)
@@ -391,7 +364,7 @@ void GraphicsContext::setAlpha(float opacity)
m_data->setOpacity(opacity);
}
-void GraphicsContext::setCompositeOperation(CompositeOperator op)
+void GraphicsContext::setPlatformCompositeOperation(CompositeOperator op)
{
if (paintingDisabled())
return;
@@ -404,7 +377,7 @@ void GraphicsContext::clip(const Path& path)
if (paintingDisabled())
return;
- m_data->clipPath(path, PainterOpenVG::IntersectClip, m_common->state.fillRule);
+ m_data->clipPath(path, PainterOpenVG::IntersectClip, m_state.fillRule);
}
void GraphicsContext::canvasClip(const Path& path)
@@ -417,7 +390,7 @@ void GraphicsContext::clipOut(const Path& path)
if (paintingDisabled())
return;
- m_data->clipPath(path, PainterOpenVG::SubtractClip, m_common->state.fillRule);
+ m_data->clipPath(path, PainterOpenVG::SubtractClip, m_state.fillRule);
}
void GraphicsContext::scale(const FloatSize& scaleFactors)
@@ -451,7 +424,7 @@ void GraphicsContext::clipOut(const IntRect& rect)
Path path;
path.addRect(rect);
- m_data->clipPath(path, PainterOpenVG::SubtractClip, m_common->state.fillRule);
+ m_data->clipPath(path, PainterOpenVG::SubtractClip, m_state.fillRule);
}
void GraphicsContext::clipToImageBuffer(const FloatRect& rect, const ImageBuffer* imageBuffer)
@@ -474,7 +447,7 @@ void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness
path.addEllipse(FloatRect(rect.x() + thickness, rect.y() + thickness,
rect.width() - (thickness * 2), rect.height() - (thickness * 2)));
- m_data->clipPath(path, PainterOpenVG::IntersectClip, m_common->state.fillRule);
+ m_data->clipPath(path, PainterOpenVG::IntersectClip, m_state.fillRule);
}
void GraphicsContext::concatCTM(const AffineTransform& transformation)
diff --git a/WebCore/platform/graphics/openvg/PainterOpenVG.cpp b/WebCore/platform/graphics/openvg/PainterOpenVG.cpp
index b2f2302..54937a4 100644
--- a/WebCore/platform/graphics/openvg/PainterOpenVG.cpp
+++ b/WebCore/platform/graphics/openvg/PainterOpenVG.cpp
@@ -123,7 +123,7 @@ struct PlatformPainterState {
DashArray strokeDashArray;
float strokeDashOffset;
- int textDrawingMode;
+ TextDrawingModeFlags textDrawingMode;
bool antialiasingEnabled;
PlatformPainterState()
@@ -141,7 +141,7 @@ struct PlatformPainterState {
, strokeLineJoin(MiterJoin)
, strokeMiterLimit(4.0)
, strokeDashOffset(0.0)
- , textDrawingMode(cTextFill)
+ , textDrawingMode(TextModeFill)
, antialiasingEnabled(true)
{
}
@@ -399,14 +399,12 @@ struct PlatformPainterState {
PainterOpenVG::PainterOpenVG()
: m_state(0)
, m_surface(0)
- , m_currentPath(0)
{
}
PainterOpenVG::PainterOpenVG(SurfaceOpenVG* surface)
: m_state(0)
, m_surface(0)
- , m_currentPath(0)
{
ASSERT(surface);
begin(surface);
@@ -415,7 +413,6 @@ PainterOpenVG::PainterOpenVG(SurfaceOpenVG* surface)
PainterOpenVG::~PainterOpenVG()
{
end();
- delete m_currentPath;
}
void PainterOpenVG::begin(SurfaceOpenVG* surface)
@@ -656,13 +653,13 @@ void PainterOpenVG::setFillColor(const Color& color)
setVGSolidColor(VG_FILL_PATH, color);
}
-int PainterOpenVG::textDrawingMode() const
+TextDrawingModeFlags PainterOpenVG::textDrawingMode() const
{
ASSERT(m_state);
return m_state->textDrawingMode;
}
-void PainterOpenVG::setTextDrawingMode(int mode)
+void PainterOpenVG::setTextDrawingMode(TextDrawingModeFlags mode)
{
ASSERT(m_state);
m_state->textDrawingMode = mode;
@@ -717,26 +714,7 @@ void PainterOpenVG::translate(float dx, float dy)
setTransformation(transformation);
}
-void PainterOpenVG::beginPath()
-{
- delete m_currentPath;
- m_currentPath = new Path();
-}
-
-void PainterOpenVG::addPath(const Path& path)
-{
- m_currentPath->platformPath()->makeCompatibleContextCurrent();
-
- vgAppendPath(m_currentPath->platformPath()->vgPath(), path.platformPath()->vgPath());
- ASSERT_VG_NO_ERROR();
-}
-
-Path* PainterOpenVG::currentPath() const
-{
- return m_currentPath;
-}
-
-void PainterOpenVG::drawPath(VGbitfield specifiedPaintModes, WindRule fillRule)
+void PainterOpenVG::drawPath(const Path& path, VGbitfield specifiedPaintModes, WindRule fillRule)
{
ASSERT(m_state);
@@ -754,7 +732,7 @@ void PainterOpenVG::drawPath(VGbitfield specifiedPaintModes, WindRule fillRule)
m_surface->makeCurrent();
vgSeti(VG_FILL_RULE, toVGFillRule(fillRule));
- vgDrawPath(m_currentPath->platformPath()->vgPath(), paintModes);
+ vgDrawPath(path.platformPath()->vgPath(), paintModes);
ASSERT_VG_NO_ERROR();
}
@@ -1136,11 +1114,11 @@ void PainterOpenVG::drawText(VGFont vgFont, Vector<VGuint>& characters, VGfloat*
VGbitfield paintModes = 0;
- if (m_state->textDrawingMode & cTextClip)
+ if (m_state->textDrawingMode & TextModeClip)
return; // unsupported for every port except CG at the time of writing
- if (m_state->textDrawingMode & cTextFill && !m_state->fillDisabled())
+ if (m_state->textDrawingMode & TextModeFill && !m_state->fillDisabled())
paintModes |= VG_FILL_PATH;
- if (m_state->textDrawingMode & cTextStroke && !m_state->strokeDisabled())
+ if (m_state->textDrawingMode & TextModeStroke && !m_state->strokeDisabled())
paintModes |= VG_STROKE_PATH;
m_surface->makeCurrent();
diff --git a/WebCore/platform/graphics/openvg/PainterOpenVG.h b/WebCore/platform/graphics/openvg/PainterOpenVG.h
index e4c6688..24fd8a0 100644
--- a/WebCore/platform/graphics/openvg/PainterOpenVG.h
+++ b/WebCore/platform/graphics/openvg/PainterOpenVG.h
@@ -111,10 +111,7 @@ public:
void rotate(float radians);
void translate(float dx, float dy);
- void beginPath();
- void addPath(const Path&);
- Path* currentPath() const;
- void drawPath(VGbitfield paintModes = (VG_STROKE_PATH | VG_FILL_PATH), WindRule fillRule = RULE_NONZERO);
+ void drawPath(const Path&, VGbitfield paintModes = (VG_STROKE_PATH | VG_FILL_PATH), WindRule fillRule = RULE_NONZERO);
void intersectClipRect(const FloatRect&);
void clipPath(const Path&, PainterOpenVG::ClipOperation, WindRule clipRule = RULE_NONZERO);
@@ -137,7 +134,6 @@ private:
Vector<PlatformPainterState*> m_stateStack;
PlatformPainterState* m_state;
SurfaceOpenVG* m_surface;
- Path* m_currentPath;
};
}
diff --git a/WebCore/platform/graphics/pango/SimpleFontDataPango.cpp b/WebCore/platform/graphics/pango/SimpleFontDataPango.cpp
index bdfe237..d0bf836 100644
--- a/WebCore/platform/graphics/pango/SimpleFontDataPango.cpp
+++ b/WebCore/platform/graphics/pango/SimpleFontDataPango.cpp
@@ -76,19 +76,34 @@ void SimpleFontData::platformCharWidthInit()
void SimpleFontData::platformDestroy()
{
- delete m_smallCapsFontData;
- m_smallCapsFontData = 0;
+}
+
+SimpleFontData* SimpleFontData::scaledFontData(const FontDescription& fontDescription, float scaleFactor) const
+{
+ FontDescription desc = FontDescription(fontDescription);
+ desc.setSpecifiedSize(scaleFactor * fontDescription.computedSize());
+ FontPlatformData platformData(desc, desc.family().family());
+ return new SimpleFontData(platformData);
}
SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const
{
- if (!m_smallCapsFontData) {
- FontDescription desc = FontDescription(fontDescription);
- desc.setSpecifiedSize(0.70f * fontDescription.computedSize());
- FontPlatformData platformData(desc, desc.family().family());
- m_smallCapsFontData = new SimpleFontData(platformData);
- }
- return m_smallCapsFontData;
+ if (!m_derivedFontData)
+ m_derivedFontData = DerivedFontData::create(isCustomFont());
+ if (!m_derivedFontData->smallCaps)
+ m_derivedFontData->smallCaps = scaledFontData(fontDescription, .7);
+
+ return m_derivedFontData->smallCaps.get();
+}
+
+SimpleFontData* SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const
+{
+ if (!m_derivedFontData)
+ m_derivedFontData = DerivedFontData::create(isCustomFont());
+ if (!m_derivedFontData->emphasisMark)
+ m_derivedFontData->emphasisMark = scaledFontData(fontDescription, .5);
+
+ return m_derivedFontData->emphasisMark.get();
}
bool SimpleFontData::containsCharacters(const UChar* characters, int length) const
diff --git a/WebCore/platform/graphics/qt/ContextShadowQt.cpp b/WebCore/platform/graphics/qt/ContextShadowQt.cpp
index f7c70f6..cb53b24 100644
--- a/WebCore/platform/graphics/qt/ContextShadowQt.cpp
+++ b/WebCore/platform/graphics/qt/ContextShadowQt.cpp
@@ -100,10 +100,20 @@ void ShadowBuffer::timerEvent(QTimerEvent* event)
QObject::timerEvent(event);
}
+TransformationMatrix ContextShadow::getTransformationMatrixFromContext(PlatformContext context)
+{
+ const QTransform& transform = context->transform();
+ return TransformationMatrix(transform.m11(), transform.m12(), transform.m21(),
+ transform.m22(), transform.dx(), transform.dy());
+}
+
Q_GLOBAL_STATIC(ShadowBuffer, scratchShadowBuffer)
PlatformContext ContextShadow::beginShadowLayer(PlatformContext p, const FloatRect& layerArea)
{
+ // Set m_blurDistance.
+ adjustBlurDistance(p);
+
QRect clipRect;
if (p->hasClipping())
#if QT_VERSION >= QT_VERSION_CHECK(4, 8, 0)
@@ -114,25 +124,22 @@ PlatformContext ContextShadow::beginShadowLayer(PlatformContext p, const FloatRe
else
clipRect = p->transform().inverted().mapRect(p->window());
- m_unscaledLayerRect = layerArea;
- calculateLayerBoundingRect(layerArea, IntRect(clipRect.x(), clipRect.y(), clipRect.width(), clipRect.height()));
+ // Set m_layerOrigin, m_layerContextTranslation, m_sourceRect.
+ IntRect clip(clipRect.x(), clipRect.y(), clipRect.width(), clipRect.height());
+ IntRect layerRect = calculateLayerBoundingRect(p, layerArea, clip);
// Don't paint if we are totally outside the clip region.
- if (m_layerRect.isEmpty())
+ if (layerRect.isEmpty())
return 0;
ShadowBuffer* shadowBuffer = scratchShadowBuffer();
- QImage* shadowImage = shadowBuffer->scratchImage(m_layerRect.size());
+ QImage* shadowImage = shadowBuffer->scratchImage(layerRect.size());
m_layerImage = QImage(*shadowImage);
m_layerContext = new QPainter;
m_layerContext->begin(&m_layerImage);
m_layerContext->setFont(p->font());
- m_layerContext->translate(m_offset.width(), m_offset.height());
-
- // The origin is now the top left corner of the scratch image.
- m_layerContext->translate(-m_layerRect.x(), -m_layerRect.y());
-
+ m_layerContext->translate(m_layerContextTranslation);
return m_layerContext;
}
@@ -155,13 +162,7 @@ void ContextShadow::endShadowLayer(PlatformContext p)
p.end();
}
- const QTransform transform = p->transform();
- if (transform.isScaling()) {
- qreal x = m_unscaledLayerRect.x() + m_offset.width() / transform.m11() - m_blurDistance;
- qreal y = m_unscaledLayerRect.y() + m_offset.height() / transform.m22() - m_blurDistance;
- p->drawImage(QPointF(x, y), m_layerImage);
- } else
- p->drawImage(m_layerRect.topLeft(), m_layerImage);
+ p->drawImage(m_layerOrigin, m_layerImage, m_sourceRect);
scratchShadowBuffer()->schedulePurge();
}
diff --git a/WebCore/platform/graphics/qt/Extensions3DQt.cpp b/WebCore/platform/graphics/qt/Extensions3DQt.cpp
index 6a34671..cd28f0e 100644
--- a/WebCore/platform/graphics/qt/Extensions3DQt.cpp
+++ b/WebCore/platform/graphics/qt/Extensions3DQt.cpp
@@ -46,6 +46,11 @@ bool Extensions3DQt::supports(const String&)
return false;
}
+void Extensions3DQt::ensureEnabled(const String& name)
+{
+ ASSERT(supports(name));
+}
+
int Extensions3DQt::getGraphicsResetStatusARB()
{
return GraphicsContext3D::NO_ERROR;
diff --git a/WebCore/platform/graphics/qt/Extensions3DQt.h b/WebCore/platform/graphics/qt/Extensions3DQt.h
index 29209ba..ae4b375 100644
--- a/WebCore/platform/graphics/qt/Extensions3DQt.h
+++ b/WebCore/platform/graphics/qt/Extensions3DQt.h
@@ -36,6 +36,7 @@ public:
// Extensions3D methods.
virtual bool supports(const String&);
+ virtual void ensureEnabled(const String&);
virtual int getGraphicsResetStatusARB();
private:
diff --git a/WebCore/platform/graphics/qt/FontPlatformData.h b/WebCore/platform/graphics/qt/FontPlatformData.h
index 2201f18..1c57e29 100644
--- a/WebCore/platform/graphics/qt/FontPlatformData.h
+++ b/WebCore/platform/graphics/qt/FontPlatformData.h
@@ -36,7 +36,7 @@ class FontPlatformDataPrivate : public Noncopyable {
public:
FontPlatformDataPrivate()
: refCount(1)
- , size(font.pointSizeF())
+ , size(font.pixelSize())
, bold(font.bold())
, oblique(false)
{}
@@ -49,7 +49,7 @@ public:
FontPlatformDataPrivate(const QFont& font)
: refCount(1)
, font(font)
- , size(font.pointSizeF())
+ , size(font.pixelSize())
, bold(font.bold())
, oblique(false)
{}
@@ -150,8 +150,12 @@ public:
int pixelSize() const
{
Q_ASSERT(m_data != reinterpret_cast<FontPlatformDataPrivate*>(-1));
- if (m_data)
+ if (m_data) {
+ // WebKit allows font size zero but QFont does not.
+ if (!m_data->size)
+ return m_data->size;
return m_data->font.pixelSize();
+ }
return 0;
}
diff --git a/WebCore/platform/graphics/qt/FontPlatformDataQt.cpp b/WebCore/platform/graphics/qt/FontPlatformDataQt.cpp
index 35e9e0c..4c9eb32 100644
--- a/WebCore/platform/graphics/qt/FontPlatformDataQt.cpp
+++ b/WebCore/platform/graphics/qt/FontPlatformDataQt.cpp
@@ -50,8 +50,9 @@ FontPlatformData::FontPlatformData(const FontDescription& description, const Ato
: m_data(new FontPlatformDataPrivate())
{
QFont& font = m_data->font;
+ int requestedSize = qRound(description.computedPixelSize());
font.setFamily(familyName);
- font.setPixelSize(qRound(description.computedSize()));
+ font.setPixelSize(qRound(requestedSize));
font.setItalic(description.italic());
font.setWeight(toQFontWeight(description.weight()));
font.setWordSpacing(wordSpacing);
@@ -63,7 +64,10 @@ FontPlatformData::FontPlatformData(const FontDescription& description, const Ato
#endif
m_data->bold = font.bold();
- m_data->size = font.pointSizeF();
+ // WebKit allows font size zero but QFont does not. We will return
+ // m_data->size if a font size of zero is requested and pixelSize()
+ // otherwise.
+ m_data->size = (!requestedSize) ? requestedSize : font.pixelSize();
}
FontPlatformData::~FontPlatformData()
diff --git a/WebCore/platform/graphics/qt/FontQt.cpp b/WebCore/platform/graphics/qt/FontQt.cpp
index 89dfd00..131ae93 100644
--- a/WebCore/platform/graphics/qt/FontQt.cpp
+++ b/WebCore/platform/graphics/qt/FontQt.cpp
@@ -29,6 +29,7 @@
#include "FontSelector.h"
#include "Gradient.h"
#include "GraphicsContext.h"
+#include "NotImplemented.h"
#include "Pattern.h"
#include <QBrush>
@@ -79,7 +80,7 @@ static void drawTextCommon(GraphicsContext* ctx, const TextRun& run, const Float
QPainter *p = ctx->platformContext();
QPen textFillPen;
- if (ctx->textDrawingMode() & cTextFill) {
+ if (ctx->textDrawingMode() & TextModeFill) {
if (ctx->fillGradient()) {
QBrush brush(*ctx->fillGradient()->platformGradient());
brush.setTransform(ctx->fillGradient()->gradientSpaceTransform());
@@ -92,7 +93,7 @@ static void drawTextCommon(GraphicsContext* ctx, const TextRun& run, const Float
}
QPen textStrokePen;
- if (ctx->textDrawingMode() & cTextStroke) {
+ if (ctx->textDrawingMode() & TextModeStroke) {
if (ctx->strokeGradient()) {
QBrush brush(*ctx->strokeGradient()->platformGradient());
brush.setTransform(ctx->strokeGradient()->gradientSpaceTransform());
@@ -145,7 +146,7 @@ static void drawTextCommon(GraphicsContext* ctx, const TextRun& run, const Float
if (ctxShadow->m_type != ContextShadow::NoShadow) {
ContextShadow* ctxShadow = ctx->contextShadow();
- if (ctxShadow->m_type != ContextShadow::BlurShadow) {
+ if (!ctxShadow->mustUseContextShadow(p)) {
p->save();
p->setPen(ctxShadow->m_color);
p->translate(ctxShadow->offset());
@@ -179,17 +180,17 @@ static void drawTextCommon(GraphicsContext* ctx, const TextRun& run, const Float
int flags = run.rtl() ? Qt::TextForceRightToLeft : Qt::TextForceLeftToRight;
#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
// See QWebPagePrivate::QWebPagePrivate() where the default path is set to Complex for Qt 4.6 and earlier.
- if (!isComplexText && !(ctx->textDrawingMode() & cTextStroke))
+ if (!isComplexText && !(ctx->textDrawingMode() & TextModeStroke))
flags |= Qt::TextBypassShaping;
#endif
QPainterPath textStrokePath;
- if (ctx->textDrawingMode() & cTextStroke)
+ if (ctx->textDrawingMode() & TextModeStroke)
textStrokePath.addText(pt, font, string);
ContextShadow* ctxShadow = ctx->contextShadow();
if (ctxShadow->m_type != ContextShadow::NoShadow) {
- if (ctx->textDrawingMode() & cTextFill) {
+ if (ctx->textDrawingMode() & TextModeFill) {
if (ctxShadow->m_type != ContextShadow::BlurShadow) {
p->save();
p->setPen(ctxShadow->m_color);
@@ -212,7 +213,7 @@ static void drawTextCommon(GraphicsContext* ctx, const TextRun& run, const Float
ctxShadow->endShadowLayer(p);
}
}
- } else if (ctx->textDrawingMode() & cTextStroke) {
+ } else if (ctx->textDrawingMode() & TextModeStroke) {
if (ctxShadow->m_type != ContextShadow::BlurShadow) {
p->translate(ctxShadow->offset());
p->strokePath(textStrokePath, QPen(ctxShadow->m_color));
@@ -235,10 +236,10 @@ static void drawTextCommon(GraphicsContext* ctx, const TextRun& run, const Float
}
}
- if (ctx->textDrawingMode() & cTextStroke)
+ if (ctx->textDrawingMode() & TextModeStroke)
p->strokePath(textStrokePath, textStrokePen);
- if (ctx->textDrawingMode() & cTextFill) {
+ if (ctx->textDrawingMode() & TextModeFill) {
QPen previousPen = p->pen();
p->setPen(textFillPen);
p->drawText(pt, string, flags, run.padding());
@@ -260,8 +261,39 @@ void Font::drawComplexText(GraphicsContext* ctx, const TextRun& run, const Float
drawTextCommon(ctx, run, point, from, to, font(), /* isComplexText = */true);
}
+int Font::emphasisMarkAscent(const AtomicString&) const
+{
+ notImplemented();
+ return 0;
+}
+
+int Font::emphasisMarkDescent(const AtomicString&) const
+{
+ notImplemented();
+ return 0;
+}
+
+int Font::emphasisMarkHeight(const AtomicString&) const
+{
+ notImplemented();
+ return 0;
+}
+
+void Font::drawEmphasisMarksForSimpleText(GraphicsContext* /* context */, const TextRun& /* run */, const AtomicString& /* mark */, const FloatPoint& /* point */, int /* from */, int /* to */) const
+{
+ notImplemented();
+}
+
+void Font::drawEmphasisMarksForComplexText(GraphicsContext* /* context */, const TextRun& /* run */, const AtomicString& /* mark */, const FloatPoint& /* point */, int /* from */, int /* to */) const
+{
+ notImplemented();
+}
+
float Font::floatWidthForSimpleText(const TextRun& run, GlyphBuffer* glyphBuffer, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
{
+ if (!primaryFont()->platformData().size())
+ return 0;
+
#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
if (!run.length())
return 0;
@@ -278,12 +310,15 @@ float Font::floatWidthForSimpleText(const TextRun& run, GlyphBuffer* glyphBuffer
return w + run.padding();
#else
Q_ASSERT(false);
- return 0.0f;
+ return 0;
#endif
}
float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>*, GlyphOverflow*) const
{
+ if (!primaryFont()->platformData().size())
+ return 0;
+
if (!run.length())
return 0;
diff --git a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
index b399f4e..9dd38aa 100644
--- a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
+++ b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
@@ -46,16 +46,13 @@
#include "ContextShadow.h"
#include "FloatConversion.h"
#include "Font.h"
-#include "GraphicsContextPrivate.h"
#include "ImageBuffer.h"
#include "NotImplemented.h"
#include "Path.h"
#include "Pattern.h"
-#include "Pen.h"
#include "TransparencyLayer.h"
#include <QBrush>
-#include <QDebug>
#include <QGradient>
#include <QPaintDevice>
#include <QPaintEngine>
@@ -200,9 +197,7 @@ public:
QBrush solidColor;
InterpolationQuality imageInterpolationQuality;
-
- // Only used by SVG for now.
- QPainterPath currentPath;
+ bool initialSmoothPixmapTransformHint;
ContextShadow shadow;
QStack<ContextShadow> shadowStack;
@@ -212,13 +207,6 @@ public:
return shadow.m_type != ContextShadow::NoShadow;
}
- inline void clearCurrentPath()
- {
- if (!currentPath.elementCount())
- return;
- currentPath = QPainterPath();
- }
-
QRectF clipBoundingRect() const
{
#if QT_VERSION >= QT_VERSION_CHECK(4, 8, 0)
@@ -235,12 +223,12 @@ private:
bool platformContextIsOwned;
};
-
GraphicsContextPlatformPrivate::GraphicsContextPlatformPrivate(QPainter* p, const QColor& initialSolidColor)
: antiAliasingForRectsAndLines(false)
, layerCount(0)
, solidColor(initialSolidColor)
, imageInterpolationQuality(InterpolationDefault)
+ , initialSmoothPixmapTransformHint(false)
, painter(p)
, platformContextIsOwned(false)
{
@@ -250,7 +238,10 @@ GraphicsContextPlatformPrivate::GraphicsContextPlatformPrivate(QPainter* p, cons
// Use the default the QPainter was constructed with.
antiAliasingForRectsAndLines = painter->testRenderHint(QPainter::Antialiasing);
- painter->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, true);
+ // Used for default image interpolation quality.
+ initialSmoothPixmapTransformHint = painter->testRenderHint(QPainter::SmoothPixmapTransform);
+
+ painter->setRenderHint(QPainter::Antialiasing, true);
}
GraphicsContextPlatformPrivate::~GraphicsContextPlatformPrivate()
@@ -258,16 +249,16 @@ GraphicsContextPlatformPrivate::~GraphicsContextPlatformPrivate()
if (!platformContextIsOwned)
return;
- painter->end();
QPaintDevice* device = painter->device();
+ painter->end();
delete painter;
delete device;
}
-GraphicsContext::GraphicsContext(PlatformGraphicsContext* painter)
- : m_common(createGraphicsContextPrivate())
- , m_data(new GraphicsContextPlatformPrivate(painter, fillColor()))
+void GraphicsContext::platformInit(PlatformGraphicsContext* painter)
{
+ m_data = new GraphicsContextPlatformPrivate(painter, fillColor());
+
setPaintingDisabled(!painter);
if (!painter)
@@ -282,12 +273,11 @@ GraphicsContext::GraphicsContext(PlatformGraphicsContext* painter)
painter->setPen(pen);
}
-GraphicsContext::~GraphicsContext()
+void GraphicsContext::platformDestroy()
{
while (!m_data->layers.isEmpty())
endTransparencyLayer();
- destroyGraphicsContextPrivate(m_common);
delete m_data;
}
@@ -319,11 +309,6 @@ void GraphicsContext::restorePlatformState()
m_data->p()->restore();
- if (!m_data->currentPath.isEmpty() && m_common->state.pathTransform.isInvertible()) {
- QTransform matrix = m_common->state.pathTransform;
- m_data->currentPath = m_data->currentPath * matrix;
- }
-
if (m_data->shadowStack.isEmpty())
m_data->shadow = ContextShadow();
else
@@ -514,93 +499,88 @@ void GraphicsContext::clipConvexPolygon(size_t numPoints, const FloatPoint* poin
p->setRenderHint(QPainter::Antialiasing, painterWasAntialiased);
}
-void GraphicsContext::fillPath()
+void GraphicsContext::fillPath(const Path& path)
{
if (paintingDisabled())
return;
QPainter* p = m_data->p();
- QPainterPath& path = m_data->currentPath; // Avoid detaching the QPainterPath
- path.setFillRule(toQtFillRule(fillRule()));
+ QPainterPath platformPath = path.platformPath();
+ platformPath.setFillRule(toQtFillRule(fillRule()));
if (m_data->hasShadow()) {
ContextShadow* shadow = contextShadow();
- if (shadow->m_type != ContextShadow::BlurShadow
- && !m_common->state.fillPattern && !m_common->state.fillGradient)
+ if (shadow->mustUseContextShadow(p) || m_state.fillPattern || m_state.fillGradient)
{
- p->translate(m_data->shadow.offset());
- p->fillPath(path, QColor(m_data->shadow.m_color));
- p->translate(-m_data->shadow.offset());
- } else {
- QPainter* shadowPainter = shadow->beginShadowLayer(p, path.controlPointRect());
+ QPainter* shadowPainter = shadow->beginShadowLayer(p, platformPath.controlPointRect());
if (shadowPainter) {
shadowPainter->setCompositionMode(QPainter::CompositionMode_Source);
- shadowPainter->fillPath(path, QColor(m_data->shadow.m_color));
+ shadowPainter->fillPath(platformPath, QColor(m_data->shadow.m_color));
shadow->endShadowLayer(p);
}
+ } else {
+ QPointF offset = shadow->offset();
+ p->translate(offset);
+ p->fillPath(platformPath, QColor(shadow->m_color));
+ p->translate(-offset);
}
-
}
- if (m_common->state.fillPattern) {
+ if (m_state.fillPattern) {
AffineTransform affine;
- p->fillPath(path, QBrush(m_common->state.fillPattern->createPlatformPattern(affine)));
- } else if (m_common->state.fillGradient) {
- QBrush brush(*m_common->state.fillGradient->platformGradient());
- brush.setTransform(m_common->state.fillGradient->gradientSpaceTransform());
- p->fillPath(path, brush);
+ p->fillPath(platformPath, QBrush(m_state.fillPattern->createPlatformPattern(affine)));
+ } else if (m_state.fillGradient) {
+ QBrush brush(*m_state.fillGradient->platformGradient());
+ brush.setTransform(m_state.fillGradient->gradientSpaceTransform());
+ p->fillPath(platformPath, brush);
} else
- p->fillPath(path, p->brush());
-
- m_data->clearCurrentPath();
+ p->fillPath(platformPath, p->brush());
}
-void GraphicsContext::strokePath()
+void GraphicsContext::strokePath(const Path& path)
{
if (paintingDisabled())
return;
QPainter* p = m_data->p();
QPen pen(p->pen());
- QPainterPath& path = m_data->currentPath; // Avoid detaching the QPainterPath
- path.setFillRule(toQtFillRule(fillRule()));
+ QPainterPath platformPath = path.platformPath();
+ platformPath.setFillRule(toQtFillRule(fillRule()));
if (m_data->hasShadow()) {
ContextShadow* shadow = contextShadow();
-
- if (shadow->m_type != ContextShadow::BlurShadow
- && !m_common->state.strokePattern && !m_common->state.strokeGradient)
+ if (shadow->mustUseContextShadow(p) || m_state.strokePattern || m_state.strokeGradient)
{
- QPen shadowPen(pen);
- shadowPen.setColor(m_data->shadow.m_color);
- p->translate(m_data->shadow.offset());
- p->strokePath(path, shadowPen);
- p->translate(-m_data->shadow.offset());
- } else {
- FloatRect boundingRect = path.controlPointRect();
+ FloatRect boundingRect = platformPath.controlPointRect();
boundingRect.inflate(pen.miterLimit() + pen.widthF());
QPainter* shadowPainter = shadow->beginShadowLayer(p, boundingRect);
if (shadowPainter) {
shadowPainter->setOpacity(static_cast<qreal>(m_data->shadow.m_color.alpha()) / 255);
- shadowPainter->strokePath(path, pen);
+ shadowPainter->strokePath(platformPath, pen);
shadow->endShadowLayer(p);
}
+ } else {
+ QPen shadowPen(pen);
+ shadowPen.setColor(m_data->shadow.m_color);
+ QPointF offset = shadow->offset();
+ p->translate(offset);
+ p->strokePath(platformPath, shadowPen);
+ p->translate(-offset);
}
}
- if (m_common->state.strokePattern) {
+ if (m_state.strokePattern) {
AffineTransform affine;
- pen.setBrush(QBrush(m_common->state.strokePattern->createPlatformPattern(affine)));
+ pen.setBrush(QBrush(m_state.strokePattern->createPlatformPattern(affine)));
p->setPen(pen);
- p->strokePath(path, pen);
- } else if (m_common->state.strokeGradient) {
- QBrush brush(*m_common->state.strokeGradient->platformGradient());
- brush.setTransform(m_common->state.strokeGradient->gradientSpaceTransform());
+ p->strokePath(platformPath, pen);
+ } else if (m_state.strokeGradient) {
+ QBrush brush(*m_state.strokeGradient->platformGradient());
+ brush.setTransform(m_state.strokeGradient->gradientSpaceTransform());
pen.setBrush(brush);
p->setPen(pen);
- p->strokePath(path, pen);
+ p->strokePath(platformPath, pen);
} else
- p->strokePath(path, pen);
- m_data->clearCurrentPath();
+ p->strokePath(platformPath, pen);
}
static inline void drawRepeatPattern(QPainter* p, QPixmap* image, const FloatRect& rect, const bool repeatX, const bool repeatY)
@@ -679,21 +659,21 @@ void GraphicsContext::fillRect(const FloatRect& rect)
QRectF normalizedRect = rect.normalized();
ContextShadow* shadow = contextShadow();
- if (m_common->state.fillPattern) {
+ if (m_state.fillPattern) {
AffineTransform affine;
- QBrush brush(m_common->state.fillPattern->createPlatformPattern(affine));
- QPixmap* image = m_common->state.fillPattern->tileImage()->nativeImageForCurrentFrame();
+ QBrush brush(m_state.fillPattern->createPlatformPattern(affine));
+ QPixmap* image = m_state.fillPattern->tileImage()->nativeImageForCurrentFrame();
QPainter* shadowPainter = m_data->hasShadow() ? shadow->beginShadowLayer(p, normalizedRect) : 0;
if (shadowPainter) {
- drawRepeatPattern(shadowPainter, image, normalizedRect, m_common->state.fillPattern->repeatX(), m_common->state.fillPattern->repeatY());
+ drawRepeatPattern(shadowPainter, image, normalizedRect, m_state.fillPattern->repeatX(), m_state.fillPattern->repeatY());
shadowPainter->setCompositionMode(QPainter::CompositionMode_SourceIn);
shadowPainter->fillRect(normalizedRect, shadow->m_color);
shadow->endShadowLayer(p);
}
- drawRepeatPattern(p, image, normalizedRect, m_common->state.fillPattern->repeatX(), m_common->state.fillPattern->repeatY());
- } else if (m_common->state.fillGradient) {
- QBrush brush(*m_common->state.fillGradient->platformGradient());
- brush.setTransform(m_common->state.fillGradient->gradientSpaceTransform());
+ drawRepeatPattern(p, image, normalizedRect, m_state.fillPattern->repeatX(), m_state.fillPattern->repeatY());
+ } else if (m_state.fillGradient) {
+ QBrush brush(*m_state.fillGradient->platformGradient());
+ brush.setTransform(m_state.fillGradient->gradientSpaceTransform());
QPainter* shadowPainter = m_data->hasShadow() ? shadow->beginShadowLayer(p, normalizedRect) : 0;
if (shadowPainter) {
shadowPainter->fillRect(normalizedRect, brush);
@@ -704,7 +684,7 @@ void GraphicsContext::fillRect(const FloatRect& rect)
p->fillRect(normalizedRect, brush);
} else {
if (m_data->hasShadow()) {
- if (shadow->m_type == ContextShadow::BlurShadow) {
+ if (shadow->mustUseContextShadow(p)) {
QPainter* shadowPainter = shadow->beginShadowLayer(p, normalizedRect);
if (shadowPainter) {
shadowPainter->setOpacity(static_cast<qreal>(shadow->m_color.alpha()) / 255);
@@ -712,17 +692,11 @@ void GraphicsContext::fillRect(const FloatRect& rect)
shadow->endShadowLayer(p);
}
} else {
- // Solid rectangle fill with no blur shadow can be done faster
- // without using the shadow layer at all.
+ // Solid rectangle fill with no blur shadow or transformations applied can be done
+ // faster without using the shadow layer at all.
QColor shadowColor = shadow->m_color;
shadowColor.setAlphaF(shadowColor.alphaF() * p->brush().color().alphaF());
- const QTransform transform = p->transform();
- if (transform.isScaling()) {
- p->fillRect(normalizedRect.translated(static_cast<qreal>(shadow->offset().x()) / transform.m11(),
- static_cast<qreal>(shadow->offset().y() / transform.m22())),
- shadowColor);
- } else
- p->fillRect(normalizedRect.translated(shadow->offset()), shadowColor);
+ p->fillRect(normalizedRect.translated(shadow->offset()), shadowColor);
}
}
@@ -742,18 +716,15 @@ void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorS
if (m_data->hasShadow()) {
ContextShadow* shadow = contextShadow();
-
- if (shadow->m_type != ContextShadow::BlurShadow) {
- // We do not need any layer for simple shadow.
- p->fillRect(normalizedRect.translated(shadow->offset()), shadow->m_color);
- } else {
+ if (shadow->mustUseContextShadow(p)) {
QPainter* shadowPainter = shadow->beginShadowLayer(p, normalizedRect);
if (shadowPainter) {
shadowPainter->setCompositionMode(QPainter::CompositionMode_Source);
shadowPainter->fillRect(normalizedRect, shadow->m_color);
shadow->endShadowLayer(p);
}
- }
+ } else
+ p->fillRect(normalizedRect.translated(shadow->offset()), shadow->m_color);
}
p->fillRect(normalizedRect, m_data->solidColor);
@@ -769,48 +740,27 @@ void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLef
QPainter* p = m_data->p();
if (m_data->hasShadow()) {
ContextShadow* shadow = contextShadow();
-
- if (shadow->m_type != ContextShadow::BlurShadow) {
- // We do not need any layer for simple shadow.
- p->translate(m_data->shadow.offset());
- p->fillPath(path.platformPath(), QColor(m_data->shadow.m_color));
- p->translate(-m_data->shadow.offset());
- } else {
+ if (shadow->mustUseContextShadow(p)) {
QPainter* shadowPainter = shadow->beginShadowLayer(p, rect);
if (shadowPainter) {
shadowPainter->setCompositionMode(QPainter::CompositionMode_Source);
shadowPainter->fillPath(path.platformPath(), QColor(m_data->shadow.m_color));
shadow->endShadowLayer(p);
}
+ } else {
+ p->translate(m_data->shadow.offset());
+ p->fillPath(path.platformPath(), QColor(m_data->shadow.m_color));
+ p->translate(-m_data->shadow.offset());
}
}
p->fillPath(path.platformPath(), QColor(color));
}
-void GraphicsContext::beginPath()
-{
- m_data->clearCurrentPath();
-}
-
-void GraphicsContext::addPath(const Path& path)
-{
- if (!m_data->currentPath.elementCount()) {
- m_data->currentPath = path.platformPath();
- return;
- }
- m_data->currentPath.addPath(path.platformPath());
-}
-
bool GraphicsContext::inTransparencyLayer() const
{
return m_data->layerCount;
}
-PlatformPath* GraphicsContext::currentPath()
-{
- return &m_data->currentPath;
-}
-
ContextShadow* GraphicsContext::contextShadow()
{
return &m_data->shadow;
@@ -824,47 +774,54 @@ void GraphicsContext::clip(const FloatRect& rect)
m_data->p()->setClipRect(rect, Qt::IntersectClip);
}
-void GraphicsContext::clipPath(WindRule clipRule)
+void GraphicsContext::clipPath(const Path& path, WindRule clipRule)
{
if (paintingDisabled())
return;
QPainter* p = m_data->p();
- QPainterPath newPath = m_data->currentPath;
- newPath.setFillRule(clipRule == RULE_EVENODD ? Qt::OddEvenFill : Qt::WindingFill);
- p->setClipPath(newPath, Qt::IntersectClip);
+ QPainterPath platformPath = path.platformPath();
+ platformPath.setFillRule(clipRule == RULE_EVENODD ? Qt::OddEvenFill : Qt::WindingFill);
+ p->setClipPath(platformPath, Qt::IntersectClip);
}
-void GraphicsContext::drawFocusRing(const Path& path, int width, int offset, const Color& color)
+void drawFocusRingForPath(QPainter* p, const QPainterPath& path, int width, const Color& color, bool antiAliasing)
{
- // FIXME: Use 'width' and 'offset' for something? http://webkit.org/b/49909
-
- if (paintingDisabled() || !color.isValid())
- return;
-
- QPainter* p = m_data->p();
const bool antiAlias = p->testRenderHint(QPainter::Antialiasing);
- p->setRenderHint(QPainter::Antialiasing, m_data->antiAliasingForRectsAndLines);
+ p->setRenderHint(QPainter::Antialiasing, antiAliasing);
+ const QPen oldPen = p->pen();
const QBrush oldBrush = p->brush();
QPen nPen = p->pen();
- nPen.setColor(color);
+ nPen.setColor(QColor(color.red(), color.green(), color.blue(), 127));
+ nPen.setWidth(width);
p->setBrush(Qt::NoBrush);
- nPen.setStyle(Qt::DotLine);
+ nPen.setStyle(Qt::SolidLine);
- p->strokePath(path.platformPath(), nPen);
+ p->strokePath(path, nPen);
p->setBrush(oldBrush);
+ p->setPen(oldPen);
p->setRenderHint(QPainter::Antialiasing, antiAlias);
}
+void GraphicsContext::drawFocusRing(const Path& path, int width, int offset, const Color& color)
+{
+ // FIXME: Use 'offset' for something? http://webkit.org/b/49909
+
+ if (paintingDisabled() || !color.isValid())
+ return;
+
+ drawFocusRingForPath(m_data->p(), path.platformPath(), width, color, m_data->antiAliasingForRectsAndLines);
+}
+
/**
* Focus ring handling for form controls is not handled here. Qt style in
* RenderTheme handles drawing focus on widgets which
* need it. It is still handled here for links.
*/
-void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int /* width */, int /* offset */, const Color& color)
+void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int width, int offset, const Color& color)
{
if (paintingDisabled() || !color.isValid())
return;
@@ -874,34 +831,18 @@ void GraphicsContext::drawFocusRing(const Vector<IntRect>& rects, int /* width *
if (!rects.size())
return;
- QPainter* p = m_data->p();
- const bool antiAlias = p->testRenderHint(QPainter::Antialiasing);
- p->setRenderHint(QPainter::Antialiasing, m_data->antiAliasingForRectsAndLines);
-
- const QPen oldPen = p->pen();
- const QBrush oldBrush = p->brush();
-
- QPen nPen = p->pen();
- nPen.setColor(color);
- p->setBrush(Qt::NoBrush);
- nPen.setStyle(Qt::DotLine);
- p->setPen(nPen);
-#if 0
- // FIXME How do we do a bounding outline with Qt?
+ int radius = (width - 1) / 2;
QPainterPath path;
- for (int i = 0; i < rectCount; ++i)
- path.addRect(QRectF(rects[i]));
- QPainterPathStroker stroker;
- QPainterPath newPath = stroker.createStroke(path);
- p->strokePath(newPath, nPen);
-#else
- for (unsigned i = 0; i < rectCount; ++i)
- p->drawRect(QRectF(rects[i]));
-#endif
- p->setPen(oldPen);
- p->setBrush(oldBrush);
+ for (unsigned i = 0; i < rectCount; ++i) {
+ QRect rect = QRect((rects[i])).adjusted(-offset - radius, -offset - radius, offset + radius, offset + radius);
+ // This is not the most efficient way to add a rect to a path, but if we don't create the tmpPath,
+ // we will end up with ugly lines in between rows of text on anchors with multiple lines.
+ QPainterPath tmpPath;
+ tmpPath.addRoundedRect(rect, radius, radius);
+ path = path.united(tmpPath);
+ }
- p->setRenderHint(QPainter::Antialiasing, antiAlias);
+ drawFocusRingForPath(m_data->p(), path, width, color, m_data->antiAliasingForRectsAndLines);
}
void GraphicsContext::drawLineForText(const IntPoint& origin, int width, bool)
@@ -974,14 +915,15 @@ void GraphicsContext::setPlatformShadow(const FloatSize& size, float blur, const
// Qt doesn't support shadows natively, they are drawn manually in the draw*
// functions
- if (m_common->state.shadowsIgnoreTransforms) {
+ if (m_state.shadowsIgnoreTransforms) {
// Meaning that this graphics context is associated with a CanvasRenderingContext
// We flip the height since CG and HTML5 Canvas have opposite Y axis
- m_common->state.shadowOffset = FloatSize(size.width(), -size.height());
+ m_state.shadowOffset = FloatSize(size.width(), -size.height());
m_data->shadow = ContextShadow(color, blur, FloatSize(size.width(), -size.height()));
- } else {
+ } else
m_data->shadow = ContextShadow(color, blur, FloatSize(size.width(), size.height()));
- }
+
+ m_data->shadow.setShadowsIgnoreTransforms(m_state.shadowsIgnoreTransforms);
}
void GraphicsContext::clearPlatformShadow()
@@ -991,7 +933,8 @@ void GraphicsContext::clearPlatformShadow()
void GraphicsContext::pushTransparencyLayerInternal(const QRect &rect, qreal opacity, QPixmap& alphaMask)
{
- m_data->layers.push(new TransparencyLayer(m_data->p(), m_data->p()->transform().mapRect(rect), 1.0, alphaMask));
+ QPainter* p = m_data->p();
+ m_data->layers.push(new TransparencyLayer(p, p->transform().mapRect(rect), 1.0, alphaMask));
}
void GraphicsContext::beginTransparencyLayer(float opacity)
@@ -1014,7 +957,7 @@ void GraphicsContext::beginTransparencyLayer(float opacity)
h = int(qBound(qreal(0), deviceClip.height(), (qreal)h) + 2);
QPixmap emptyAlphaMask;
- m_data->layers.push(new TransparencyLayer(m_data->p(), QRect(x, y, w, h), opacity, emptyAlphaMask));
+ m_data->layers.push(new TransparencyLayer(p, QRect(x, y, w, h), opacity, emptyAlphaMask));
++m_data->layerCount;
}
@@ -1056,17 +999,23 @@ void GraphicsContext::clearRect(const FloatRect& rect)
p->setCompositionMode(currentCompositionMode);
}
-void GraphicsContext::strokeRect(const FloatRect& rect, float width)
+void GraphicsContext::strokeRect(const FloatRect& rect, float lineWidth)
{
if (paintingDisabled())
return;
- QPainterPath path;
+ Path path;
path.addRect(rect);
- setStrokeThickness(width);
- m_data->currentPath = path;
- strokePath();
+ float previousStrokeThickness = strokeThickness();
+
+ if (lineWidth != previousStrokeThickness)
+ setStrokeThickness(lineWidth);
+
+ strokePath(path);
+
+ if (lineWidth != previousStrokeThickness)
+ setStrokeThickness(previousStrokeThickness);
}
void GraphicsContext::setLineCap(LineCap lc)
@@ -1132,24 +1081,20 @@ void GraphicsContext::setAlpha(float opacity)
p->setOpacity(opacity);
}
-void GraphicsContext::setCompositeOperation(CompositeOperator op)
+void GraphicsContext::setPlatformCompositeOperation(CompositeOperator op)
{
if (paintingDisabled())
return;
- if (m_data->p()->paintEngine()->hasFeature(QPaintEngine::PorterDuff))
- m_data->p()->setCompositionMode(toQtCompositionMode(op));
-}
+ QPainter* painter = m_data->p();
-void GraphicsContext::clip(const Path& path)
-{
- if (paintingDisabled())
+ if (!painter->paintEngine()->hasFeature(QPaintEngine::PorterDuff))
return;
- m_data->p()->setClipPath(path.platformPath(), Qt::IntersectClip);
+ painter->setCompositionMode(toQtCompositionMode(op));
}
-void GraphicsContext::canvasClip(const Path& path)
+void GraphicsContext::clip(const Path& path)
{
if (paintingDisabled())
return;
@@ -1159,6 +1104,11 @@ void GraphicsContext::canvasClip(const Path& path)
m_data->p()->setClipPath(clipPath, Qt::IntersectClip);
}
+void GraphicsContext::canvasClip(const Path& path)
+{
+ clip(path);
+}
+
void GraphicsContext::clipOut(const Path& path)
{
if (paintingDisabled())
@@ -1186,12 +1136,6 @@ void GraphicsContext::translate(float x, float y)
return;
m_data->p()->translate(x, y);
-
- if (!m_data->currentPath.isEmpty()) {
- QTransform matrix;
- m_data->currentPath = m_data->currentPath * matrix.translate(-x, -y);
- m_common->state.pathTransform.translate(x, y);
- }
}
void GraphicsContext::rotate(float radians)
@@ -1200,12 +1144,6 @@ void GraphicsContext::rotate(float radians)
return;
m_data->p()->rotate(180 / M_PI*radians);
-
- if (!m_data->currentPath.isEmpty()) {
- QTransform matrix;
- m_data->currentPath = m_data->currentPath * matrix.rotate(-180 / M_PI*radians);
- m_common->state.pathTransform.rotate(radians);
- }
}
void GraphicsContext::scale(const FloatSize& s)
@@ -1214,12 +1152,6 @@ void GraphicsContext::scale(const FloatSize& s)
return;
m_data->p()->scale(s.width(), s.height());
-
- if (!m_data->currentPath.isEmpty()) {
- QTransform matrix;
- m_data->currentPath = m_data->currentPath * matrix.scale(1 / s.width(), 1 / s.height());
- m_common->state.pathTransform.scaleNonUniform(s.width(), s.height());
- }
}
void GraphicsContext::clipOut(const IntRect& rect)
@@ -1276,15 +1208,6 @@ void GraphicsContext::concatCTM(const AffineTransform& transform)
return;
m_data->p()->setWorldTransform(transform, true);
-
- // Transformations to the context shouldn't transform the currentPath.
- // We have to undo every change made to the context from the currentPath
- // to avoid wrong drawings.
- if (!m_data->currentPath.isEmpty() && transform.isInvertible()) {
- QTransform matrix = transform.inverse();
- m_data->currentPath = m_data->currentPath * matrix;
- m_common->state.pathTransform.multiply(transform.toTransformationMatrix());
- }
}
void GraphicsContext::setURLForRect(const KURL&, const IntRect&)
@@ -1437,13 +1360,16 @@ void GraphicsContext::setImageInterpolationQuality(InterpolationQuality quality)
m_data->p()->setRenderHint(QPainter::SmoothPixmapTransform, false);
break;
- case InterpolationDefault:
case InterpolationMedium:
case InterpolationHigh:
- default:
// use the filter
m_data->p()->setRenderHint(QPainter::SmoothPixmapTransform, true);
break;
+
+ case InterpolationDefault:
+ default:
+ m_data->p()->setRenderHint(QPainter::SmoothPixmapTransform, m_data->initialSmoothPixmapTransformHint);
+ break;
};
}
diff --git a/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp b/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp
index 49387a2..f31844a 100644
--- a/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp
+++ b/WebCore/platform/graphics/qt/GraphicsLayerQt.cpp
@@ -686,7 +686,7 @@ void GraphicsLayerQtImpl::flushChanges(bool recursive, bool forceUpdateTransform
// try to snatch that ownership.
if (!m_layer->parent() && !parentItem())
setParentItem(0);
- else if (m_layer && m_layer->parent() && m_layer->parent()->nativeLayer() != parentItem())
+ else if (m_layer && m_layer->parent() && m_layer->parent()->platformLayer() != parentItem())
setParentItem(m_layer->parent()->platformLayer());
}
@@ -1318,13 +1318,6 @@ void GraphicsLayerQt::syncCompositingStateForThisLayerOnly()
}
/* \reimp (GraphicsLayer.h)
- */
-NativeLayer GraphicsLayerQt::nativeLayer() const
-{
- return m_impl.get();
-}
-
-/* \reimp (GraphicsLayer.h)
*/
PlatformLayer* GraphicsLayerQt::platformLayer() const
{
diff --git a/WebCore/platform/graphics/qt/GraphicsLayerQt.h b/WebCore/platform/graphics/qt/GraphicsLayerQt.h
index ed535eb..b1692d2 100644
--- a/WebCore/platform/graphics/qt/GraphicsLayerQt.h
+++ b/WebCore/platform/graphics/qt/GraphicsLayerQt.h
@@ -38,7 +38,6 @@ public:
virtual ~GraphicsLayerQt();
// reimps from GraphicsLayer.h
- virtual NativeLayer nativeLayer() const;
virtual PlatformLayer* platformLayer() const;
virtual void setNeedsDisplay();
virtual void setNeedsDisplayInRect(const FloatRect&);
diff --git a/WebCore/platform/graphics/qt/ImageBufferQt.cpp b/WebCore/platform/graphics/qt/ImageBufferQt.cpp
index de23297..1652b5b 100644
--- a/WebCore/platform/graphics/qt/ImageBufferQt.cpp
+++ b/WebCore/platform/graphics/qt/ImageBufferQt.cpp
@@ -80,7 +80,7 @@ ImageBufferData::ImageBufferData(const IntSize& size)
m_image = StillImage::createForRendering(&m_pixmap);
}
-ImageBuffer::ImageBuffer(const IntSize& size, ColorSpace, bool& success)
+ImageBuffer::ImageBuffer(const IntSize& size, ColorSpace, RenderingMode, bool& success)
: m_data(size)
, m_size(size)
{
diff --git a/WebCore/platform/graphics/qt/ImageDecoderQt.cpp b/WebCore/platform/graphics/qt/ImageDecoderQt.cpp
index 2dd239f..2bbb9ce 100644
--- a/WebCore/platform/graphics/qt/ImageDecoderQt.cpp
+++ b/WebCore/platform/graphics/qt/ImageDecoderQt.cpp
@@ -37,17 +37,17 @@
namespace WebCore {
-ImageDecoder* ImageDecoder::create(const SharedBuffer& data, bool premultiplyAlpha, bool ignoreGammaAndColorProfile)
+ImageDecoder* ImageDecoder::create(const SharedBuffer& data, ImageSource::AlphaOption alphaOption, ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption)
{
// We need at least 4 bytes to figure out what kind of image we're dealing with.
if (data.size() < 4)
return 0;
- return new ImageDecoderQt(premultiplyAlpha, ignoreGammaAndColorProfile);
+ return new ImageDecoderQt(alphaOption, gammaAndColorProfileOption);
}
-ImageDecoderQt::ImageDecoderQt(bool premultiplyAlpha, bool ignoreGammaAndColorProfile)
- : ImageDecoder(premultiplyAlpha, ignoreGammaAndColorProfile)
+ImageDecoderQt::ImageDecoderQt(ImageSource::AlphaOption alphaOption, ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption)
+ : ImageDecoder(alphaOption, gammaAndColorProfileOption)
, m_repetitionCount(cAnimationNone)
{
}
diff --git a/WebCore/platform/graphics/qt/ImageDecoderQt.h b/WebCore/platform/graphics/qt/ImageDecoderQt.h
index 914c020..23fb79a 100644
--- a/WebCore/platform/graphics/qt/ImageDecoderQt.h
+++ b/WebCore/platform/graphics/qt/ImageDecoderQt.h
@@ -41,7 +41,7 @@ namespace WebCore {
class ImageDecoderQt : public ImageDecoder
{
public:
- ImageDecoderQt(bool premultiplyAlpha, bool ignoreGammaAndColorProfile);
+ ImageDecoderQt(ImageSource::AlphaOption, ImageSource::GammaAndColorProfileOption);
~ImageDecoderQt();
virtual void setData(SharedBuffer* data, bool allDataReceived);
diff --git a/WebCore/platform/graphics/qt/ImageQt.cpp b/WebCore/platform/graphics/qt/ImageQt.cpp
index 3611308..f713d37 100644
--- a/WebCore/platform/graphics/qt/ImageQt.cpp
+++ b/WebCore/platform/graphics/qt/ImageQt.cpp
@@ -114,7 +114,7 @@ void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const
if (tr.x() || tr.y() || tr.width() != pixmap.width() || tr.height() != pixmap.height())
pixmap = pixmap.copy(tr);
- ctxt->save();
+ CompositeOperator previousOperator = ctxt->compositeOperation();
ctxt->setCompositeOperation(op);
QPainter* p = ctxt->platformContext();
@@ -130,7 +130,7 @@ void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const
b.setTransform(transform);
p->fillRect(dr, b);
- ctxt->restore();
+ ctxt->setCompositeOperation(previousOperator);
if (imageObserver())
imageObserver()->didDraw(this);
diff --git a/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp b/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp
index 962c931..dd4b6e6 100644
--- a/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp
+++ b/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp
@@ -25,6 +25,7 @@
#include "GraphicsContext.h"
#include "HTMLMediaElement.h"
#include "HTMLVideoElement.h"
+#include "QtNAMThreadSafeProxy.h"
#include "NetworkingContext.h"
#include "NotImplemented.h"
#include "RenderVideo.h"
@@ -209,8 +210,8 @@ void MediaPlayerPrivateQt::commitLoad(const String& url)
if (document && manager) {
// Set the cookies
- QNetworkCookieJar* jar = manager->cookieJar();
- QList<QNetworkCookie> cookies = jar->cookiesForUrl(rUrl);
+ QtNAMThreadSafeProxy managerProxy(manager);
+ QList<QNetworkCookie> cookies = managerProxy.cookiesForUrl(rUrl);
// Don't set the header if there are no cookies.
// This prevents a warning from being emitted.
diff --git a/WebCore/platform/graphics/qt/SimpleFontDataQt.cpp b/WebCore/platform/graphics/qt/SimpleFontDataQt.cpp
index f093d7d..47ddf02 100644
--- a/WebCore/platform/graphics/qt/SimpleFontDataQt.cpp
+++ b/WebCore/platform/graphics/qt/SimpleFontDataQt.cpp
@@ -40,6 +40,18 @@ bool SimpleFontData::containsCharacters(const UChar*, int) const
void SimpleFontData::platformInit()
{
+ if (!m_platformData.size()) {
+ m_ascent = 0;
+ m_descent = 0;
+ m_lineGap = 0;
+ m_lineSpacing = 0;
+ m_avgCharWidth = 0;
+ m_maxCharWidth = 0;
+ m_xHeight = 0;
+ m_unitsPerEm = 0;
+ return;
+ }
+
QFontMetrics fm(m_platformData.font());
m_ascent = fm.ascent();
@@ -52,6 +64,8 @@ void SimpleFontData::platformInit()
void SimpleFontData::platformGlyphInit()
{
+ if (!m_platformData.size())
+ return;
m_spaceGlyph = 0;
m_adjustedSpaceWidth = m_spaceWidth;
determinePitch();
@@ -61,6 +75,8 @@ void SimpleFontData::platformGlyphInit()
void SimpleFontData::platformCharWidthInit()
{
+ if (!m_platformData.size())
+ return;
QFontMetrics fm(m_platformData.font());
m_avgCharWidth = fm.averageCharWidth();
m_maxCharWidth = fm.maxWidth();
diff --git a/WebCore/platform/graphics/qt/StillImageQt.cpp b/WebCore/platform/graphics/qt/StillImageQt.cpp
index 3038356..51c9499 100644
--- a/WebCore/platform/graphics/qt/StillImageQt.cpp
+++ b/WebCore/platform/graphics/qt/StillImageQt.cpp
@@ -28,6 +28,7 @@
#include "config.h"
#include "StillImageQt.h"
+#include "ContextShadow.h"
#include "GraphicsContext.h"
#include "IntSize.h"
@@ -67,34 +68,26 @@ void StillImage::draw(GraphicsContext* ctxt, const FloatRect& dst,
if (m_pixmap->isNull())
return;
-
FloatRect normalizedSrc = src.normalized();
FloatRect normalizedDst = dst.normalized();
- QPainter* painter = ctxt->platformContext();
- QPainter::CompositionMode oldCompositionMode = painter->compositionMode();
-
+ CompositeOperator previousOperator = ctxt->compositeOperation();
ctxt->setCompositeOperation(op);
- FloatSize shadowOffset;
- float shadowBlur;
- Color shadowColor;
- if (ctxt->getShadow(shadowOffset, shadowBlur, shadowColor)) {
- FloatRect shadowImageRect(normalizedDst);
- shadowImageRect.move(shadowOffset.width(), shadowOffset.height());
-
- QImage shadowImage(QSize(static_cast<int>(normalizedSrc.width()), static_cast<int>(normalizedSrc.height())), QImage::Format_ARGB32_Premultiplied);
- QPainter p(&shadowImage);
- p.setCompositionMode(QPainter::CompositionMode_Source);
- p.fillRect(shadowImage.rect(), shadowColor);
- p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
- p.drawPixmap(QRect(0, 0, normalizedDst.width(), normalizedDst.height()), *m_pixmap, normalizedSrc);
- p.end();
- painter->drawImage(shadowImageRect, shadowImage, normalizedSrc);
+ QPainter* painter = ctxt->platformContext();
+
+ ContextShadow* shadow = ctxt->contextShadow();
+ if (shadow->m_type != ContextShadow::NoShadow) {
+ QPainter* shadowPainter = shadow->beginShadowLayer(painter, normalizedDst);
+ if (shadowPainter) {
+ shadowPainter->setOpacity(static_cast<qreal>(shadow->m_color.alpha()) / 255);
+ shadowPainter->drawPixmap(normalizedDst, *m_pixmap, normalizedSrc);
+ shadow->endShadowLayer(painter);
+ }
}
painter->drawPixmap(normalizedDst, *m_pixmap, normalizedSrc);
- painter->setCompositionMode(oldCompositionMode);
+ ctxt->setCompositeOperation(previousOperator);
}
}
diff --git a/WebCore/platform/graphics/qt/TransparencyLayer.h b/WebCore/platform/graphics/qt/TransparencyLayer.h
index 6bdfb39..5b2f8b2 100644
--- a/WebCore/platform/graphics/qt/TransparencyLayer.h
+++ b/WebCore/platform/graphics/qt/TransparencyLayer.h
@@ -52,7 +52,7 @@ struct TransparencyLayer : FastAllocBase {
offset = rect.topLeft();
pixmap.fill(Qt::transparent);
painter.begin(&pixmap);
- painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
+ painter.setRenderHints(p->renderHints());
painter.translate(-offset);
painter.setPen(p->pen());
painter.setBrush(p->brush());
diff --git a/WebCore/platform/graphics/skia/FontCustomPlatformData.cpp b/WebCore/platform/graphics/skia/FontCustomPlatformData.cpp
index 2ea568b..161fee9 100644
--- a/WebCore/platform/graphics/skia/FontCustomPlatformData.cpp
+++ b/WebCore/platform/graphics/skia/FontCustomPlatformData.cpp
@@ -65,7 +65,7 @@ FontCustomPlatformData::~FontCustomPlatformData()
#endif
}
-FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation, FontRenderingMode mode)
+FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation orientation, FontRenderingMode mode)
{
#if OS(WINDOWS)
ASSERT(m_fontReference);
@@ -102,7 +102,7 @@ FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, b
return FontPlatformData(hfont, size);
#elif OS(LINUX) || OS(FREEBSD) || PLATFORM(BREWMP)
ASSERT(m_fontReference);
- return FontPlatformData(m_fontReference, "", size, bold && !m_fontReference->isBold(), italic && !m_fontReference->isItalic());
+ return FontPlatformData(m_fontReference, "", size, bold && !m_fontReference->isBold(), italic && !m_fontReference->isItalic(), orientation);
#else
notImplemented();
return FontPlatformData();
diff --git a/WebCore/platform/graphics/skia/GlyphPageTreeNodeSkia.cpp b/WebCore/platform/graphics/skia/GlyphPageTreeNodeSkia.cpp
index 6024d43..66e6839 100644
--- a/WebCore/platform/graphics/skia/GlyphPageTreeNodeSkia.cpp
+++ b/WebCore/platform/graphics/skia/GlyphPageTreeNodeSkia.cpp
@@ -32,6 +32,7 @@
#include "GlyphPageTreeNode.h"
#include "Font.h"
+#include "HarfbuzzSkia.h"
#include "SimpleFontData.h"
#include "SkTemplates.h"
@@ -40,6 +41,36 @@
namespace WebCore {
+static int substituteWithVerticalGlyphs(const SimpleFontData* fontData, uint16_t* glyphs, unsigned bufferLength)
+{
+ HB_FaceRec_* hbFace = fontData->platformData().harfbuzzFace();
+ if (!hbFace->gsub) {
+ // if there is no GSUB table, treat it as not covered
+ return 0Xffff;
+ }
+
+ HB_Buffer buffer;
+ hb_buffer_new(&buffer);
+ for (unsigned i = 0; i < bufferLength; ++i)
+ hb_buffer_add_glyph(buffer, glyphs[i], 0, i);
+
+ HB_UShort scriptIndex;
+ HB_UShort featureIndex;
+
+ HB_GSUB_Select_Script(hbFace->gsub, HB_MAKE_TAG('D', 'F', 'L', 'T'), &scriptIndex);
+ HB_GSUB_Select_Feature(hbFace->gsub, HB_MAKE_TAG('v', 'e', 'r', 't'), scriptIndex, 0xffff, &featureIndex);
+ HB_GSUB_Add_Feature(hbFace->gsub, featureIndex, 1);
+ HB_GSUB_Select_Feature(hbFace->gsub, HB_MAKE_TAG('v', 'r', 't', '2'), scriptIndex, 0xffff, &featureIndex);
+ HB_GSUB_Add_Feature(hbFace->gsub, featureIndex, 1);
+
+ int error = HB_GSUB_Apply_String(hbFace->gsub, buffer);
+ if (!error) {
+ for (unsigned i = 0; i < bufferLength; ++i)
+ glyphs[i] = static_cast<Glyph>(buffer->out_string[i].gindex);
+ }
+ return error;
+}
+
bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData)
{
if (SkUTF16_IsHighSurrogate(buffer[bufferLength-1])) {
@@ -60,6 +91,18 @@ bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned b
return false;
}
+ if ((fontData->orientation() == Vertical) && (!fontData->isBrokenIdeographFont())) {
+ bool lookVariants = false;
+ for (unsigned i = 0; i < bufferLength; ++i) {
+ if (!Font::isCJKIdeograph(buffer[i])) {
+ lookVariants = true;
+ continue;
+ }
+ }
+ if (lookVariants)
+ substituteWithVerticalGlyphs(fontData, glyphs, bufferLength);
+ }
+
unsigned allGlyphs = 0; // track if any of the glyphIDs are non-zero
for (unsigned i = 0; i < length; i++) {
setGlyphDataForIndex(offset + i, glyphs[i], glyphs[i] ? fontData : NULL);
diff --git a/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp b/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp
index cbe6775..8b7ac86 100644
--- a/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp
+++ b/WebCore/platform/graphics/skia/GraphicsContext3DSkia.cpp
@@ -53,7 +53,8 @@ bool GraphicsContext3D::getImageData(Image* image,
NativeImageSkia* skiaImage = 0;
AlphaOp neededAlphaOp = AlphaDoNothing;
if (image->data()) {
- ImageSource decoder(false, ignoreGammaAndColorProfile);
+ ImageSource decoder(ImageSource::AlphaNotPremultiplied,
+ ignoreGammaAndColorProfile ? ImageSource::GammaAndColorProfileIgnored : ImageSource::GammaAndColorProfileApplied);
decoder.setData(image->data(), true);
if (!decoder.frameCount() || !decoder.frameIsCompleteAtIndex(0))
return false;
diff --git a/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp b/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp
index 7c0bcd1..1b217ee 100644
--- a/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp
+++ b/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp
@@ -37,7 +37,6 @@
#include "GLES2Canvas.h"
#include "Gradient.h"
#include "GraphicsContextPlatformPrivate.h"
-#include "GraphicsContextPrivate.h"
#include "ImageBuffer.h"
#include "IntRect.h"
#include "NativeImageSkia.h"
@@ -219,17 +218,15 @@ void addCornerArc(SkPath* path, const SkRect& rect, const IntSize& size, int sta
// This may be called with a NULL pointer to create a graphics context that has
// no painting.
-GraphicsContext::GraphicsContext(PlatformGraphicsContext* gc)
- : m_common(createGraphicsContextPrivate())
- , m_data(new GraphicsContextPlatformPrivate(gc))
+void GraphicsContext::platformInit(PlatformGraphicsContext* gc)
{
+ m_data = new GraphicsContextPlatformPrivate(gc);
setPaintingDisabled(!gc || !platformContext()->canvas());
}
-GraphicsContext::~GraphicsContext()
+void GraphicsContext::platformDestroy()
{
delete m_data;
- this->destroyGraphicsContextPrivate(m_common);
}
PlatformGraphicsContext* GraphicsContext::platformContext() const
@@ -420,11 +417,15 @@ void GraphicsContext::clipOut(const Path& p)
platformContext()->canvas()->clipPath(path, SkRegion::kDifference_Op);
}
-void GraphicsContext::clipPath(WindRule clipRule)
+void GraphicsContext::clipPath(const Path& pathToClip, WindRule clipRule)
{
if (paintingDisabled())
return;
+ // FIXME: Be smarter about this.
+ beginPath();
+ addPath(pathToClip);
+
SkPath path = platformContext()->currentPathInLocalCoordinates();
if (!isPathSkiaSafe(getCTM(), path))
return;
@@ -723,18 +724,22 @@ void GraphicsContext::drawRect(const IntRect& rect)
platformContext()->drawRect(r);
}
-void GraphicsContext::fillPath()
+void GraphicsContext::fillPath(const Path& pathToFill)
{
if (paintingDisabled())
return;
+ // FIXME: Be smarter about this.
+ beginPath();
+ addPath(pathToFill);
+
SkPath path = platformContext()->currentPathInLocalCoordinates();
if (!isPathSkiaSafe(getCTM(), path))
return;
platformContext()->prepareForSoftwareDraw();
- const GraphicsContextState& state = m_common->state;
+ const GraphicsContextState& state = m_state;
path.setFillType(state.fillRule == RULE_EVENODD ?
SkPath::kEvenOdd_FillType : SkPath::kWinding_FillType);
@@ -921,7 +926,7 @@ void GraphicsContext::setAlpha(float alpha)
platformContext()->setAlpha(alpha);
}
-void GraphicsContext::setCompositeOperation(CompositeOperator op)
+void GraphicsContext::setPlatformCompositeOperation(CompositeOperator op)
{
if (paintingDisabled())
return;
@@ -1061,13 +1066,15 @@ void GraphicsContext::setPlatformShadow(const FloatSize& size,
double height = size.height();
double blur = blurFloat;
- // TODO(tc): This still does not address the issue that shadows
- // within canvas elements should ignore transforms.
- if (m_common->state.shadowsIgnoreTransforms) {
+ SkBlurDrawLooper::BlurFlags blurFlags = SkBlurDrawLooper::kNone_BlurFlag;
+
+ if (m_state.shadowsIgnoreTransforms) {
// Currently only the GraphicsContext associated with the
// CanvasRenderingContext for HTMLCanvasElement have shadows ignore
// Transforms. So with this flag set, we know this state is associated
// with a CanvasRenderingContext.
+ blurFlags = SkBlurDrawLooper::kIgnoreTransform_BlurFlag;
+
// CG uses natural orientation for Y axis, but the HTML5 canvas spec
// does not.
// So we now flip the height since it was flipped in
@@ -1083,7 +1090,7 @@ void GraphicsContext::setPlatformShadow(const FloatSize& size,
// TODO(tc): Should we have a max value for the blur? CG clamps at 1000.0
// for perf reasons.
- SkDrawLooper* dl = new SkBlurDrawLooper(blur / 2, width, height, c);
+ SkDrawLooper* dl = new SkBlurDrawLooper(blur / 2, width, height, c, blurFlags);
platformContext()->setDrawLooper(dl);
dl->unref();
}
@@ -1128,7 +1135,7 @@ void GraphicsContext::setPlatformStrokePattern(Pattern* pattern)
platformContext()->setStrokeShader(pattern->platformPattern(getCTM()));
}
-void GraphicsContext::setPlatformTextDrawingMode(int mode)
+void GraphicsContext::setPlatformTextDrawingMode(TextDrawingModeFlags mode)
{
if (paintingDisabled())
return;
@@ -1177,11 +1184,15 @@ void GraphicsContext::strokeArc(const IntRect& r, int startAngle, int angleSpan)
platformContext()->canvas()->drawPath(path, paint);
}
-void GraphicsContext::strokePath()
+void GraphicsContext::strokePath(const Path& pathToStroke)
{
if (paintingDisabled())
return;
+ // FIXME: Be smarter about this.
+ beginPath();
+ addPath(pathToStroke);
+
SkPath path = platformContext()->currentPathInLocalCoordinates();
if (!isPathSkiaSafe(getCTM(), path))
return;
diff --git a/WebCore/platform/graphics/skia/ImageBufferSkia.cpp b/WebCore/platform/graphics/skia/ImageBufferSkia.cpp
index adb732b..468ccda 100644
--- a/WebCore/platform/graphics/skia/ImageBufferSkia.cpp
+++ b/WebCore/platform/graphics/skia/ImageBufferSkia.cpp
@@ -40,6 +40,8 @@
#include "GLES2Canvas.h"
#include "GraphicsContext.h"
#include "ImageData.h"
+#include "JPEGImageEncoder.h"
+#include "MIMETypeRegistry.h"
#include "PNGImageEncoder.h"
#include "PlatformContextSkia.h"
#include "SkColorPriv.h"
@@ -60,7 +62,7 @@ ImageBufferData::ImageBufferData(const IntSize& size)
{
}
-ImageBuffer::ImageBuffer(const IntSize& size, ColorSpace, bool& success)
+ImageBuffer::ImageBuffer(const IntSize& size, ColorSpace, RenderingMode, bool& success)
: m_data(size)
, m_size(size)
{
@@ -244,14 +246,6 @@ PassRefPtr<ImageData> ImageBuffer::getPremultipliedImageData(const IntRect& rect
return getImageData<Premultiplied>(rect, *context()->platformContext()->bitmap(), m_size);
}
-// This function does the equivalent of (a * b + 254) / 255, without an integer divide.
-// Valid for a, b in the range [0..255].
-unsigned mulDiv255Ceil(unsigned a, unsigned b)
-{
- unsigned value = a * b + 255;
- return (value + (value >> 8)) >> 8;
-}
-
template <Multiply multiplied>
void putImageData(ImageData*& source, const IntRect& sourceRect, const IntPoint& destPoint,
const SkBitmap& bitmap, const IntSize& size)
@@ -295,9 +289,9 @@ void putImageData(ImageData*& source, const IntRect& sourceRect, const IntPoint&
const unsigned char* srcPixel = &srcRow[x * 4];
if (multiplied == Unmultiplied) {
unsigned char alpha = srcPixel[3];
- unsigned char r = mulDiv255Ceil(srcPixel[0], alpha);
- unsigned char g = mulDiv255Ceil(srcPixel[1], alpha);
- unsigned char b = mulDiv255Ceil(srcPixel[2], alpha);
+ unsigned char r = SkMulDiv255Ceiling(srcPixel[0], alpha);
+ unsigned char g = SkMulDiv255Ceiling(srcPixel[1], alpha);
+ unsigned char b = SkMulDiv255Ceiling(srcPixel[2], alpha);
destRow[x] = SkPackARGB32(alpha, r, g, b);
} else
destRow[x] = SkPackARGB32(srcPixel[3], srcPixel[0],
@@ -318,20 +312,27 @@ void ImageBuffer::putPremultipliedImageData(ImageData* source, const IntRect& so
putImageData<Premultiplied>(source, sourceRect, destPoint, *context()->platformContext()->bitmap(), m_size);
}
-String ImageBuffer::toDataURL(const String&, const double*) const
+String ImageBuffer::toDataURL(const String& mimeType, const double* quality) const
{
- // Encode the image into a vector.
- Vector<unsigned char> pngEncodedData;
- PNGImageEncoder::encode(*context()->platformContext()->bitmap(), &pngEncodedData);
-
- // Convert it into base64.
- Vector<char> base64EncodedData;
- base64Encode(*reinterpret_cast<Vector<char>*>(&pngEncodedData), base64EncodedData);
- // Append with a \0 so that it's a valid string.
- base64EncodedData.append('\0');
-
- // And the resulting string.
- return makeString("data:image/png;base64,", base64EncodedData.data());
+ ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType));
+
+ Vector<unsigned char> encodedImage;
+ if (mimeType == "image/jpeg") {
+ int compressionQuality = JPEGImageEncoder::DefaultCompressionQuality;
+ if (quality && *quality >= 0.0 && *quality <= 1.0)
+ compressionQuality = static_cast<int>(*quality * 100 + 0.5);
+ if (!JPEGImageEncoder::encode(*context()->platformContext()->bitmap(), compressionQuality, &encodedImage))
+ return "data:,";
+ } else {
+ if (!PNGImageEncoder::encode(*context()->platformContext()->bitmap(), &encodedImage))
+ return "data:,";
+ ASSERT(mimeType == "image/png");
+ }
+
+ Vector<char> base64Data;
+ base64Encode(*reinterpret_cast<Vector<char>*>(&encodedImage), base64Data);
+
+ return makeString("data:", mimeType, ";base64,", base64Data);
}
} // namespace WebCore
diff --git a/WebCore/platform/graphics/skia/ImageSkia.cpp b/WebCore/platform/graphics/skia/ImageSkia.cpp
index ae2653a..c7fa6f4 100644
--- a/WebCore/platform/graphics/skia/ImageSkia.cpp
+++ b/WebCore/platform/graphics/skia/ImageSkia.cpp
@@ -143,7 +143,9 @@ static ResamplingMode computeResamplingMode(PlatformContextSkia* platformContext
// Everything else gets resampled.
// If the platform context permits high quality interpolation, use it.
- if (platformContext->interpolationQuality() == InterpolationHigh)
+ // High quality interpolation only enabled for scaling and translation.
+ if (platformContext->interpolationQuality() == InterpolationHigh
+ && !(platformContext->canvas()->getTotalMatrix().getType() & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask)))
return RESAMPLE_AWESOME;
return RESAMPLE_LINEAR;
@@ -178,17 +180,32 @@ static void drawResampledBitmap(SkCanvas& canvas, SkPaint& paint, const NativeIm
SkIRect resizedImageRect = // Represents the size of the resized image.
{ 0, 0, destRectRounded.width(), destRectRounded.height() };
- if (srcIsFull && bitmap.hasResizedBitmap(destRectRounded.width(), destRectRounded.height())) {
+ // Apply forward transform to destRect to estimate required size of
+ // re-sampled bitmap, and use only in calls required to resize, or that
+ // check for the required size.
+ SkRect destRectTransformed;
+ canvas.getTotalMatrix().mapRect(&destRectTransformed, destRect);
+ SkIRect destRectTransformedRounded;
+ destRectTransformed.round(&destRectTransformedRounded);
+
+ if (srcIsFull && bitmap.hasResizedBitmap(destRectTransformedRounded.width(), destRectTransformedRounded.height())) {
// Yay, this bitmap frame already has a resized version.
- SkBitmap resampled = bitmap.resizedBitmap(destRectRounded.width(), destRectRounded.height());
+ SkBitmap resampled = bitmap.resizedBitmap(destRectTransformedRounded.width(), destRectTransformedRounded.height());
canvas.drawBitmapRect(resampled, 0, destRect, &paint);
return;
}
// Compute the visible portion of our rect.
+ // We also need to compute the transformed portion of the
+ // visible portion for use below.
SkRect destBitmapSubsetSk;
ClipRectToCanvas(canvas, destRect, &destBitmapSubsetSk);
+ SkRect destBitmapSubsetTransformed;
+ canvas.getTotalMatrix().mapRect(&destBitmapSubsetTransformed, destBitmapSubsetSk);
destBitmapSubsetSk.offset(-destRect.fLeft, -destRect.fTop);
+ SkIRect destBitmapSubsetTransformedRounded;
+ destBitmapSubsetTransformed.round(&destBitmapSubsetTransformedRounded);
+ destBitmapSubsetTransformedRounded.offset(-destRectTransformedRounded.fLeft, -destRectTransformedRounded.fTop);
// The matrix inverting, etc. could have introduced rounding error which
// causes the bounds to be outside of the resized bitmap. We round outward
@@ -207,27 +224,33 @@ static void drawResampledBitmap(SkCanvas& canvas, SkPaint& paint, const NativeIm
destBitmapSubsetSkI.height())) {
// We're supposed to resize the entire image and cache it, even though
// we don't need all of it.
- SkBitmap resampled = bitmap.resizedBitmap(destRectRounded.width(),
- destRectRounded.height());
+ SkBitmap resampled = bitmap.resizedBitmap(destRectTransformedRounded.width(),
+ destRectTransformedRounded.height());
canvas.drawBitmapRect(resampled, 0, destRect, &paint);
} else {
// We should only resize the exposed part of the bitmap to do the
// minimal possible work.
// Resample the needed part of the image.
- SkBitmap resampled = skia::ImageOperations::Resize(subset,
- skia::ImageOperations::RESIZE_LANCZOS3,
- destRectRounded.width(), destRectRounded.height(),
- destBitmapSubsetSkI);
-
- // Compute where the new bitmap should be drawn. Since our new bitmap
- // may be smaller than the original, we have to shift it over by the
- // same amount that we cut off the top and left.
- destBitmapSubsetSkI.offset(destRect.fLeft, destRect.fTop);
- SkRect offsetDestRect;
- offsetDestRect.set(destBitmapSubsetSkI);
-
- canvas.drawBitmapRect(resampled, 0, offsetDestRect, &paint);
+ // Transforms above plus rounding may cause destBitmapSubsetTransformedRounded
+ // to go outside the image, so need to clip to avoid problems.
+ if (destBitmapSubsetTransformedRounded.intersect(0, 0,
+ destRectTransformedRounded.width(), destRectTransformedRounded.height())) {
+
+ SkBitmap resampled = skia::ImageOperations::Resize(subset,
+ skia::ImageOperations::RESIZE_LANCZOS3,
+ destRectTransformedRounded.width(), destRectTransformedRounded.height(),
+ destBitmapSubsetTransformedRounded);
+
+ // Compute where the new bitmap should be drawn. Since our new bitmap
+ // may be smaller than the original, we have to shift it over by the
+ // same amount that we cut off the top and left.
+ destBitmapSubsetSkI.offset(destRect.fLeft, destRect.fTop);
+ SkRect offsetDestRect;
+ offsetDestRect.set(destBitmapSubsetSkI);
+
+ canvas.drawBitmapRect(resampled, 0, offsetDestRect, &paint);
+ }
}
}
diff --git a/WebCore/platform/graphics/skia/PlatformContextSkia.cpp b/WebCore/platform/graphics/skia/PlatformContextSkia.cpp
index d610c2a..d3c0e00 100644
--- a/WebCore/platform/graphics/skia/PlatformContextSkia.cpp
+++ b/WebCore/platform/graphics/skia/PlatformContextSkia.cpp
@@ -94,8 +94,8 @@ struct PlatformContextSkia::State {
SkPaint::Join m_lineJoin;
SkDashPathEffect* m_dash;
- // Text. (See cTextFill & friends in GraphicsContext.h.)
- int m_textDrawingMode;
+ // Text. (See TextModeFill & friends in GraphicsContext.h.)
+ TextDrawingModeFlags m_textDrawingMode;
// Helper function for applying the state's alpha value to the given input
// color to produce a new output color.
@@ -137,7 +137,7 @@ PlatformContextSkia::State::State()
, m_lineCap(SkPaint::kDefault_Cap)
, m_lineJoin(SkPaint::kDefault_Join)
, m_dash(0)
- , m_textDrawingMode(cTextFill)
+ , m_textDrawingMode(TextModeFill)
, m_interpolationQuality(InterpolationHigh)
, m_canvasClipApplied(false)
{
@@ -299,6 +299,9 @@ void PlatformContextSkia::clipPathAntiAliased(const SkPath& clipPath)
if (!haveLayerOutstanding) {
SkRect bounds = clipPath.getBounds();
canvas()->saveLayerAlpha(&bounds, 255, static_cast<SkCanvas::SaveFlags>(SkCanvas::kHasAlphaLayer_SaveFlag | SkCanvas::kFullColorLayer_SaveFlag | SkCanvas::kClipToLayer_SaveFlag));
+ // Guards state modification during clipped operations.
+ // The state is popped in applyAntiAliasedClipPaths().
+ canvas()->save();
}
}
@@ -494,6 +497,9 @@ void PlatformContextSkia::setStrokeThickness(float thickness)
void PlatformContextSkia::setStrokeShader(SkShader* strokeShader)
{
+ if (strokeShader)
+ m_state->m_strokeColor = Color::black;
+
if (strokeShader != m_state->m_strokeShader) {
SkSafeUnref(m_state->m_strokeShader);
m_state->m_strokeShader = strokeShader;
@@ -501,7 +507,7 @@ void PlatformContextSkia::setStrokeShader(SkShader* strokeShader)
}
}
-int PlatformContextSkia::getTextDrawingMode() const
+TextDrawingModeFlags PlatformContextSkia::getTextDrawingMode() const
{
return m_state->m_textDrawingMode;
}
@@ -521,11 +527,11 @@ int PlatformContextSkia::getNormalizedAlpha() const
return alpha;
}
-void PlatformContextSkia::setTextDrawingMode(int mode)
+void PlatformContextSkia::setTextDrawingMode(TextDrawingModeFlags mode)
{
- // cTextClip is never used, so we assert that it isn't set:
+ // TextModeClip is never used, so we assert that it isn't set:
// https://bugs.webkit.org/show_bug.cgi?id=21898
- ASSERT(!(mode & cTextClip));
+ ASSERT(!(mode & TextModeClip));
m_state->m_textDrawingMode = mode;
}
@@ -578,6 +584,9 @@ void PlatformContextSkia::setFillRule(SkPath::FillType fr)
void PlatformContextSkia::setFillShader(SkShader* fillShader)
{
+ if (fillShader)
+ m_state->m_fillColor = Color::black;
+
if (fillShader != m_state->m_fillShader) {
SkSafeUnref(m_state->m_fillShader);
m_state->m_fillShader = fillShader;
@@ -675,6 +684,8 @@ void PlatformContextSkia::applyAntiAliasedClipPaths(WTF::Vector<SkPath>& paths)
// When we call restore on the SkCanvas, the layer's bitmap is composed
// into the layer below and we end up with correct, anti-aliased clipping.
+ m_canvas->restore();
+
SkPaint paint;
paint.setXfermodeMode(SkXfermode::kClear_Mode);
paint.setAntiAlias(true);
diff --git a/WebCore/platform/graphics/skia/PlatformContextSkia.h b/WebCore/platform/graphics/skia/PlatformContextSkia.h
index 110085d..11b311a 100644
--- a/WebCore/platform/graphics/skia/PlatformContextSkia.h
+++ b/WebCore/platform/graphics/skia/PlatformContextSkia.h
@@ -125,14 +125,14 @@ public:
void setStrokeColor(SkColor);
void setStrokeThickness(float thickness);
void setStrokeShader(SkShader*);
- void setTextDrawingMode(int mode);
+ void setTextDrawingMode(TextDrawingModeFlags mode);
void setUseAntialiasing(bool enable);
void setDashPathEffect(SkDashPathEffect*);
SkDrawLooper* getDrawLooper() const;
StrokeStyle getStrokeStyle() const;
float getStrokeThickness() const;
- int getTextDrawingMode() const;
+ TextDrawingModeFlags getTextDrawingMode() const;
float getAlpha() const;
int getNormalizedAlpha() const;
diff --git a/WebCore/platform/graphics/skia/SkiaFontWin.cpp b/WebCore/platform/graphics/skia/SkiaFontWin.cpp
index 6acfd35..5046c50 100644
--- a/WebCore/platform/graphics/skia/SkiaFontWin.cpp
+++ b/WebCore/platform/graphics/skia/SkiaFontWin.cpp
@@ -225,8 +225,9 @@ bool windowsCanHandleDrawTextShadow(GraphicsContext *context)
FloatSize shadowOffset;
float shadowBlur;
Color shadowColor;
+ ColorSpace shadowColorSpace;
- bool hasShadow = context->getShadow(shadowOffset, shadowBlur, shadowColor);
+ bool hasShadow = context->getShadow(shadowOffset, shadowBlur, shadowColor, shadowColorSpace);
return (hasShadow && (shadowBlur == 0) && (shadowColor.alpha() == 255) && (context->fillColor().alpha() == 255));
}
@@ -242,7 +243,7 @@ bool windowsCanHandleTextDrawing(GraphicsContext* context)
return false;
// Check for stroke effects.
- if (context->platformContext()->getTextDrawingMode() != cTextFill)
+ if (context->platformContext()->getTextDrawingMode() != TextModeFill)
return false;
// Check for gradients.
@@ -307,7 +308,7 @@ bool paintSkiaText(GraphicsContext* context,
HGDIOBJ oldFont = SelectObject(dc, hfont);
PlatformContextSkia* platformContext = context->platformContext();
- int textMode = platformContext->getTextDrawingMode();
+ TextDrawingModeFlags textMode = platformContext->getTextDrawingMode();
// Filling (if necessary). This is the common case.
SkPaint paint;
@@ -315,7 +316,7 @@ bool paintSkiaText(GraphicsContext* context,
paint.setFlags(SkPaint::kAntiAlias_Flag);
bool didFill = false;
- if ((textMode & cTextFill) && SkColorGetA(paint.getColor())) {
+ if ((textMode & TextModeFill) && SkColorGetA(paint.getColor())) {
if (!skiaDrawText(hfont, dc, platformContext->canvas(), *origin, &paint,
&glyphs[0], &advances[0], &offsets[0], numGlyphs))
return false;
@@ -323,7 +324,7 @@ bool paintSkiaText(GraphicsContext* context,
}
// Stroking on top (if necessary).
- if ((textMode & cTextStroke)
+ if ((textMode & TextModeStroke)
&& platformContext->getStrokeStyle() != NoStroke
&& platformContext->getStrokeThickness() > 0) {
diff --git a/WebCore/platform/graphics/skia/SkiaUtils.cpp b/WebCore/platform/graphics/skia/SkiaUtils.cpp
index b16a344..da83793 100644
--- a/WebCore/platform/graphics/skia/SkiaUtils.cpp
+++ b/WebCore/platform/graphics/skia/SkiaUtils.cpp
@@ -108,7 +108,7 @@ SkXfermode::Mode WebCoreCompositeToSkiaComposite(CompositeOperator op)
return (SkXfermode::Mode)table[i].m_xfermodeMode;
}
- SkDEBUGF(("GraphicsContext::setCompositeOperation uknown CompositeOperator %d\n", op));
+ SkDEBUGF(("GraphicsContext::setPlatformCompositeOperation unknown CompositeOperator %d\n", op));
return SkXfermode::kSrcOver_Mode; // fall-back
}
diff --git a/WebCore/platform/graphics/texmap/TextureMapper.h b/WebCore/platform/graphics/texmap/TextureMapper.h
index 250125b..589fda1 100644
--- a/WebCore/platform/graphics/texmap/TextureMapper.h
+++ b/WebCore/platform/graphics/texmap/TextureMapper.h
@@ -110,22 +110,22 @@ public:
virtual PassRefPtr<BitmapTexture> createTexture() = 0;
void setImageInterpolationQuality(InterpolationQuality quality) { m_interpolationQuality = quality; }
- void setTextDrawingMode(int mode) { m_textDrawingMode = mode; }
+ void setTextDrawingMode(TextDrawingModeFlags mode) { m_textDrawingMode = mode; }
InterpolationQuality imageInterpolationQuality() const { return m_interpolationQuality; }
- int textDrawingMode() const { return m_textDrawingMode; }
+ TextDrawingModeFlags textDrawingMode() const { return m_textDrawingMode; }
void setViewportSize(const IntSize&);
protected:
TextureMapper()
: m_interpolationQuality(InterpolationDefault)
- , m_textDrawingMode(cTextFill)
+ , m_textDrawingMode(TextModeFill)
{}
private:
InterpolationQuality m_interpolationQuality;
- int m_textDrawingMode;
+ TextDrawingModeFlags m_textDrawingMode;
};
};
diff --git a/WebCore/platform/graphics/transforms/TransformationMatrix.h b/WebCore/platform/graphics/transforms/TransformationMatrix.h
index 96b4baa..f13bcc1 100644
--- a/WebCore/platform/graphics/transforms/TransformationMatrix.h
+++ b/WebCore/platform/graphics/transforms/TransformationMatrix.h
@@ -32,6 +32,9 @@
#include <string.h> //for memcpy
#include <wtf/FastAllocBase.h>
+#if PLATFORM(CA)
+#include <QuartzCore/CATransform3D.h>
+#endif
#if PLATFORM(CG)
#include <CoreGraphics/CGAffineTransform.h>
#elif PLATFORM(CAIRO)
@@ -309,7 +312,12 @@ public:
return result;
}
+#if PLATFORM(CA)
+ TransformationMatrix(const CATransform3D&);
+ operator CATransform3D() const;
+#endif
#if PLATFORM(CG)
+ TransformationMatrix(const CGAffineTransform&);
operator CGAffineTransform() const;
#elif PLATFORM(CAIRO)
operator cairo_matrix_t() const;
diff --git a/WebCore/platform/graphics/win/FontCGWin.cpp b/WebCore/platform/graphics/win/FontCGWin.cpp
index 2f1fb41..8012722 100644
--- a/WebCore/platform/graphics/win/FontCGWin.cpp
+++ b/WebCore/platform/graphics/win/FontCGWin.cpp
@@ -133,8 +133,8 @@ static void drawGDIGlyphs(GraphicsContext* graphicsContext, const SimpleFontData
Color fillColor = graphicsContext->fillColor();
bool drawIntoBitmap = false;
- int drawingMode = graphicsContext->textDrawingMode();
- if (drawingMode == cTextFill) {
+ TextDrawingModeFlags drawingMode = graphicsContext->textDrawingMode();
+ if (drawingMode == TextModeFill) {
if (!fillColor.alpha())
return;
@@ -143,7 +143,9 @@ static void drawGDIGlyphs(GraphicsContext* graphicsContext, const SimpleFontData
FloatSize offset;
float blur;
Color color;
- graphicsContext->getShadow(offset, blur, color);
+ ColorSpace shadowColorSpace;
+
+ graphicsContext->getShadow(offset, blur, color, shadowColorSpace);
drawIntoBitmap = offset.width() || offset.height() || blur;
}
}
@@ -205,7 +207,7 @@ static void drawGDIGlyphs(GraphicsContext* graphicsContext, const SimpleFontData
ModifyWorldTransform(hdc, &xform, MWT_LEFTMULTIPLY);
}
- if (drawingMode == cTextFill) {
+ if (drawingMode == TextModeFill) {
XFORM xform;
xform.eM11 = 1.0;
xform.eM12 = 0;
@@ -247,7 +249,7 @@ static void drawGDIGlyphs(GraphicsContext* graphicsContext, const SimpleFontData
CGContextSaveGState(cgContext);
CGContextConcatCTM(cgContext, initialGlyphTransform);
- if (drawingMode & cTextFill) {
+ if (drawingMode & TextModeFill) {
CGContextAddPath(cgContext, glyphPath.get());
CGContextFillPath(cgContext);
if (font->syntheticBoldOffset()) {
@@ -257,7 +259,7 @@ static void drawGDIGlyphs(GraphicsContext* graphicsContext, const SimpleFontData
CGContextTranslateCTM(cgContext, -font->syntheticBoldOffset(), 0);
}
}
- if (drawingMode & cTextStroke) {
+ if (drawingMode & TextModeStroke) {
CGContextAddPath(cgContext, glyphPath.get());
CGContextStrokePath(cgContext);
if (font->syntheticBoldOffset()) {
@@ -352,16 +354,20 @@ void Font::drawGlyphs(GraphicsContext* graphicsContext, const SimpleFontData* fo
FloatSize shadowOffset;
float shadowBlur;
Color shadowColor;
- graphicsContext->getShadow(shadowOffset, shadowBlur, shadowColor);
+ ColorSpace shadowColorSpace;
+ graphicsContext->getShadow(shadowOffset, shadowBlur, shadowColor, shadowColorSpace);
- bool hasSimpleShadow = graphicsContext->textDrawingMode() == cTextFill && shadowColor.isValid() && !shadowBlur;
+ bool hasSimpleShadow = graphicsContext->textDrawingMode() == TextModeFill && shadowColor.isValid() && !shadowBlur && (!graphicsContext->shadowsIgnoreTransforms() || graphicsContext->getCTM().isIdentityOrTranslationOrFlipped());
if (hasSimpleShadow) {
// Paint simple shadows ourselves instead of relying on CG shadows, to avoid losing subpixel antialiasing.
graphicsContext->clearShadow();
Color fillColor = graphicsContext->fillColor();
Color shadowFillColor(shadowColor.red(), shadowColor.green(), shadowColor.blue(), shadowColor.alpha() * fillColor.alpha() / 255);
graphicsContext->setFillColor(shadowFillColor, ColorSpaceDeviceRGB);
- CGContextSetTextPosition(cgContext, point.x() + translation.width() + shadowOffset.width(), point.y() + translation.height() + shadowOffset.height());
+ float shadowTextX = point.x() + translation.width() + 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() + translation.height() + shadowOffset.height() * (graphicsContext->shadowsIgnoreTransforms() ? -1 : 1);
+ CGContextSetTextPosition(cgContext, shadowTextX, shadowTextY);
CGContextShowGlyphsWithAdvances(cgContext, glyphBuffer.glyphs(from), glyphBuffer.advances(from), numGlyphs);
if (font->syntheticBoldOffset()) {
CGContextSetTextPosition(cgContext, point.x() + translation.width() + shadowOffset.width() + font->syntheticBoldOffset(), point.y() + translation.height() + shadowOffset.height());
diff --git a/WebCore/platform/graphics/win/FontWin.cpp b/WebCore/platform/graphics/win/FontWin.cpp
index 97971dc..2170954 100644
--- a/WebCore/platform/graphics/win/FontWin.cpp
+++ b/WebCore/platform/graphics/win/FontWin.cpp
@@ -30,6 +30,7 @@
#include "GlyphBuffer.h"
#include "GraphicsContext.h"
#include "IntRect.h"
+#include "Logging.h"
#include "SimpleFontData.h"
#include "UniscribeController.h"
#include <wtf/MathExtras.h>
@@ -62,33 +63,57 @@ FloatRect Font::selectionRectForComplexText(const TextRun& run, const FloatPoint
return FloatRect(point.x() + floorf(beforeWidth), point.y(), roundf(afterWidth) - floorf(beforeWidth), h);
}
-void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const FloatPoint& point,
- int from, int to) const
+float Font::getGlyphsAndAdvancesForComplexText(const TextRun& run, int from, int to, GlyphBuffer& glyphBuffer, ForTextEmphasisOrNot forTextEmphasis) const
{
- // This glyph buffer holds our glyphs + advances + font data for each glyph.
- GlyphBuffer glyphBuffer;
+ if (forTextEmphasis) {
+ // FIXME: Add forTextEmphasis paremeter to UniscribeController and use it.
+ LOG_ERROR("Not implemented for text emphasis.");
+ return 0;
+ }
- float startX = point.x();
UniscribeController controller(this, run);
controller.advance(from);
float beforeWidth = controller.runWidthSoFar();
controller.advance(to, &glyphBuffer);
-
- // We couldn't generate any glyphs for the run. Give up.
+
if (glyphBuffer.isEmpty())
- return;
-
+ return 0;
+
float afterWidth = controller.runWidthSoFar();
if (run.rtl()) {
controller.advance(run.length());
- startX += controller.runWidthSoFar() - afterWidth;
- } else
- startX += beforeWidth;
+ return controller.runWidthSoFar() - afterWidth;
+ }
+ return beforeWidth;
+}
+
+void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const FloatPoint& point,
+ int from, int to) const
+{
+ // This glyph buffer holds our glyphs + advances + font data for each glyph.
+ GlyphBuffer glyphBuffer;
+
+ float startX = point.x() + getGlyphsAndAdvancesForComplexText(run, from, to, glyphBuffer);
+
+ // We couldn't generate any glyphs for the run. Give up.
+ if (glyphBuffer.isEmpty())
+ return;
// Draw the glyph buffer now at the starting point returned in startX.
FloatPoint startPoint(startX, point.y());
- drawGlyphBuffer(context, glyphBuffer, run, startPoint);
+ drawGlyphBuffer(context, glyphBuffer, startPoint);
+}
+
+void Font::drawEmphasisMarksForComplexText(GraphicsContext* context, const TextRun& run, const AtomicString& mark, const FloatPoint& point, int from, int to) const
+{
+ GlyphBuffer glyphBuffer;
+ float initialAdvance = getGlyphsAndAdvancesForComplexText(run, from, to, glyphBuffer, ForTextEmphasis);
+
+ if (glyphBuffer.isEmpty())
+ return;
+
+ drawEmphasisMarks(context, glyphBuffer, mark, FloatPoint(point.x() + initialAdvance, point.y()));
}
float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
diff --git a/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp b/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp
index 1ad6bc1..b42e51c 100644
--- a/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp
+++ b/WebCore/platform/graphics/win/GraphicsContextCGWin.cpp
@@ -62,9 +62,14 @@ static CGContextRef CGContextWithHDC(HDC hdc, bool hasAlpha)
}
GraphicsContext::GraphicsContext(HDC hdc, bool hasAlpha)
- : m_common(createGraphicsContextPrivate())
- , m_data(new GraphicsContextPlatformPrivate(CGContextWithHDC(hdc, hasAlpha)))
+ : m_updatingControlTints(false)
{
+ platformInit(hdc, hasAlpha);
+}
+
+void GraphicsContext::platformInit(HDC hdc, bool hasAlpha)
+{
+ m_data = new GraphicsContextPlatformPrivate(CGContextWithHDC(hdc, hasAlpha));
CGContextRelease(m_data->m_cgContext.get());
m_data->m_hdc = hdc;
setPaintingDisabled(!m_data->m_cgContext);
diff --git a/WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp b/WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp
index a989c24..b2c702f 100644
--- a/WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp
+++ b/WebCore/platform/graphics/win/GraphicsContextCairoWin.cpp
@@ -65,9 +65,15 @@ static cairo_t* createCairoContextWithHDC(HDC hdc, bool hasAlpha)
}
GraphicsContext::GraphicsContext(HDC dc, bool hasAlpha)
- : m_common(createGraphicsContextPrivate())
- , m_data(new GraphicsContextPlatformPrivate)
+ : m_updatingControlTints(false)
{
+ platformInit(dc, hasAlpha);
+}
+
+void GraphicsContext::platformInit(HDC dc, bool hasAlpha)
+{
+ m_data = new GraphicsContextPlatformPrivate;
+
if (dc) {
m_data->cr = createCairoContextWithHDC(dc, hasAlpha);
m_data->m_hdc = dc;
diff --git a/WebCore/platform/graphics/win/GraphicsLayerCACF.cpp b/WebCore/platform/graphics/win/GraphicsLayerCACF.cpp
index f7674db..984fd3f 100644
--- a/WebCore/platform/graphics/win/GraphicsLayerCACF.cpp
+++ b/WebCore/platform/graphics/win/GraphicsLayerCACF.cpp
@@ -153,11 +153,6 @@ void GraphicsLayerCACF::setName(const String& name)
m_layer->setName(longName);
}
-NativeLayer GraphicsLayerCACF::nativeLayer() const
-{
- return m_layer.get();
-}
-
bool GraphicsLayerCACF::setChildren(const Vector<GraphicsLayer*>& children)
{
bool childrenChanged = GraphicsLayer::setChildren(children);
diff --git a/WebCore/platform/graphics/win/GraphicsLayerCACF.h b/WebCore/platform/graphics/win/GraphicsLayerCACF.h
index c18a6e9..23f36b2 100644
--- a/WebCore/platform/graphics/win/GraphicsLayerCACF.h
+++ b/WebCore/platform/graphics/win/GraphicsLayerCACF.h
@@ -44,9 +44,6 @@ public:
virtual void setName(const String& inName);
- // for hosting this GraphicsLayer in a native layer hierarchy
- virtual NativeLayer nativeLayer() const;
-
virtual bool setChildren(const Vector<GraphicsLayer*>&);
virtual void addChild(GraphicsLayer *layer);
virtual void addChildAtIndex(GraphicsLayer *layer, int index);
diff --git a/WebCore/platform/graphics/win/SimpleFontDataWin.cpp b/WebCore/platform/graphics/win/SimpleFontDataWin.cpp
index 6d1d777..60afe6a 100644
--- a/WebCore/platform/graphics/win/SimpleFontDataWin.cpp
+++ b/WebCore/platform/graphics/win/SimpleFontDataWin.cpp
@@ -110,24 +110,40 @@ void SimpleFontData::platformDestroy()
delete m_scriptFontProperties;
}
-SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const
+SimpleFontData* SimpleFontData::scaledFontData(const FontDescription& fontDescription, float scaleFactor) const
{
- if (!m_smallCapsFontData) {
- float smallCapsHeight = cSmallCapsFontSizeMultiplier * m_platformData.size();
+ float scaledSize = scaleFactor * m_platformData.size();
if (isCustomFont()) {
- FontPlatformData smallCapsFontData(m_platformData);
- smallCapsFontData.setSize(smallCapsHeight);
- m_smallCapsFontData = new SimpleFontData(smallCapsFontData, true, false);
- } else {
- LOGFONT winfont;
- GetObject(m_platformData.hfont(), sizeof(LOGFONT), &winfont);
- winfont.lfHeight = -lroundf(smallCapsHeight * (m_platformData.useGDI() ? 1 : 32));
- HFONT hfont = CreateFontIndirect(&winfont);
- m_smallCapsFontData = new SimpleFontData(FontPlatformData(hfont, smallCapsHeight, m_platformData.syntheticBold(), m_platformData.syntheticOblique(), m_platformData.useGDI()),
- isCustomFont(), false);
+ FontPlatformData scaledFont(m_platformData);
+ scaledFont.setSize(scaledSize);
+ return new SimpleFontData(scaledFont, true, false);
}
- }
- return m_smallCapsFontData;
+
+ LOGFONT winfont;
+ GetObject(m_platformData.hfont(), sizeof(LOGFONT), &winfont);
+ winfont.lfHeight = -lroundf(scaledSize * (m_platformData.useGDI() ? 1 : 32));
+ HFONT hfont = CreateFontIndirect(&winfont);
+ return new SimpleFontData(FontPlatformData(hfont, scaledSize, m_platformData.syntheticBold(), m_platformData.syntheticOblique(), m_platformData.useGDI()), isCustomFont(), false);
+}
+
+SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const
+{
+ if (!m_derivedFontData)
+ m_derivedFontData = DerivedFontData::create(isCustomFont());
+ if (!m_derivedFontData->smallCaps)
+ m_derivedFontData->smallCaps = scaledFontData(fontDescription, cSmallCapsFontSizeMultiplier);
+
+ return m_derivedFontData->smallCaps.get();
+}
+
+SimpleFontData* SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const
+{
+ if (!m_derivedFontData)
+ m_derivedFontData = DerivedFontData::create(isCustomFont());
+ if (!m_derivedFontData->emphasisMark)
+ m_derivedFontData->emphasisMark = scaledFontData(fontDescription, .5);
+
+ return m_derivedFontData->emphasisMark.get();
}
bool SimpleFontData::containsCharacters(const UChar* characters, int length) const
diff --git a/WebCore/platform/graphics/win/UniscribeController.cpp b/WebCore/platform/graphics/win/UniscribeController.cpp
index d0acac2..ab32150 100644
--- a/WebCore/platform/graphics/win/UniscribeController.cpp
+++ b/WebCore/platform/graphics/win/UniscribeController.cpp
@@ -145,7 +145,7 @@ void UniscribeController::advance(unsigned offset, GlyphBuffer* glyphBuffer)
UChar c = *curr;
bool forceSmallCaps = isSmallCaps && (U_GET_GC_MASK(c) & U_GC_M_MASK);
- nextFontData = m_font.glyphDataForCharacter(*curr, false, forceSmallCaps).fontData;
+ nextFontData = m_font.glyphDataForCharacter(*curr, false, forceSmallCaps ? SmallCapsVariant : AutoVariant).fontData;
if (m_font.isSmallCaps()) {
nextIsSmallCaps = forceSmallCaps || (newC = u_toupper(c)) != c;
if (nextIsSmallCaps)
diff --git a/WebCore/platform/graphics/win/cairo/FontPlatformData.h b/WebCore/platform/graphics/win/cairo/FontPlatformData.h
index 05f9eab..d8f538a 100644
--- a/WebCore/platform/graphics/win/cairo/FontPlatformData.h
+++ b/WebCore/platform/graphics/win/cairo/FontPlatformData.h
@@ -3,6 +3,7 @@
* Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com
* Copyright (C) 2007 Holger Hans Peter Freyther
* Copyright (C) 2007 Pioneer Research Center USA, Inc.
+ * Copyright (C) 2010 Brent Fulgham <bfulgham@webkit.org>
* All rights reserved.
*
* This library is free software; you can redistribute it and/or
@@ -25,7 +26,7 @@
#ifndef FontPlatformDataCairoWin_h
#define FontPlatformDataCairoWin_h
-#include "FontDescription.h"
+#include "FontOrientation.h"
#include "GlyphBuffer.h"
#include "RefCountedGDIHandle.h"
#include "StringImpl.h"
@@ -37,6 +38,8 @@ typedef struct HFONT__* HFONT;
namespace WebCore {
+class FontDescription;
+
class FontPlatformData {
public:
FontPlatformData(WTF::HashTableDeletedValueType)
@@ -73,6 +76,9 @@ public:
void setSize(float size) { m_size = size; }
bool syntheticBold() const { return m_syntheticBold; }
bool syntheticOblique() const { return m_syntheticOblique; }
+
+ FontOrientation orientation() const { return Horizontal; } // FIXME: Implement.
+
cairo_scaled_font_t* scaledFont() const { return m_scaledFont; }
unsigned hash() const
diff --git a/WebCore/platform/graphics/wince/FontWinCE.cpp b/WebCore/platform/graphics/wince/FontWinCE.cpp
index e2ff067..d636517 100644
--- a/WebCore/platform/graphics/wince/FontWinCE.cpp
+++ b/WebCore/platform/graphics/wince/FontWinCE.cpp
@@ -235,6 +235,11 @@ void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const F
}
}
+void Font::drawEmphasisMarksForComplexText(GraphicsContext* /* context */, const TextRun& /* run */, const AtomicString& /* mark */, const FloatPoint& /* point */, int /* from */, int /* to */) const
+{
+ notImplemented();
+}
+
float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
{
TextRunComponents components;
diff --git a/WebCore/platform/graphics/wince/GraphicsContextWinCE.cpp b/WebCore/platform/graphics/wince/GraphicsContextWinCE.cpp
index 0802826..1ea1a64 100644
--- a/WebCore/platform/graphics/wince/GraphicsContextWinCE.cpp
+++ b/WebCore/platform/graphics/wince/GraphicsContextWinCE.cpp
@@ -28,7 +28,6 @@
#include "GDIExtras.h"
#include "GlyphBuffer.h"
#include "Gradient.h"
-#include "GraphicsContextPrivate.h"
#include "NotImplemented.h"
#include "Path.h"
#include "PlatformPathWinCE.h"
@@ -173,7 +172,6 @@ public:
AffineTransform m_transform;
float m_opacity;
- Vector<Path> m_paths;
};
enum AlphaPaintType {
@@ -581,15 +579,13 @@ private:
};
-GraphicsContext::GraphicsContext(PlatformGraphicsContext* dc)
-: m_common(createGraphicsContextPrivate())
-, m_data(new GraphicsContextPlatformPrivate(dc))
+void GraphicsContext::platformInit(PlatformGraphicsContext* dc)
{
+ m_data = new GraphicsContextPlatformPrivate(dc);
}
-GraphicsContext::~GraphicsContext()
+void GraphicsContext::platformDestroy()
{
- destroyGraphicsContextPrivate(m_common);
delete m_data;
}
@@ -1177,21 +1173,11 @@ void GraphicsContext::setAlpha(float alpha)
m_data->m_opacity = alpha;
}
-void GraphicsContext::setCompositeOperation(CompositeOperator op)
+void GraphicsContext::setPlatformCompositeOperation(CompositeOperator op)
{
notImplemented();
}
-void GraphicsContext::beginPath()
-{
- m_data->m_paths.clear();
-}
-
-void GraphicsContext::addPath(const Path& path)
-{
- m_data->m_paths.append(path);
-}
-
void GraphicsContext::clip(const Path& path)
{
notImplemented();
@@ -1220,8 +1206,9 @@ void GraphicsContext::fillRoundedRect(const IntRect& fillRect, const IntSize& to
FloatSize shadowOffset;
float shadowBlur = 0;
Color shadowColor;
+ ColorSpace shadowColorSpace;
- getShadow(shadowOffset, shadowBlur, shadowColor);
+ getShadow(shadowOffset, shadowBlur, shadowColor, shadowColorSpace);
IntRect dstRect = fillRect;
@@ -1325,10 +1312,10 @@ Color gradientAverageColor(const Gradient* gradient)
, (stop.alpha + lastStop.alpha) * 0.5f);
}
-void GraphicsContext::fillPath()
+void GraphicsContext::fillPath(const Path& path)
{
- Color c = m_common->state.fillGradient
- ? gradientAverageColor(m_common->state.fillGradient.get())
+ Color c = m_state.fillGradient
+ ? gradientAverageColor(m_state.fillGradient.get())
: fillColor();
if (!c.alpha() || !m_data->m_opacity)
@@ -1341,33 +1328,30 @@ void GraphicsContext::fillPath()
OwnPtr<HBRUSH> brush = createBrush(c);
if (m_data->m_opacity < 1.0f || m_data->hasAlpha()) {
- for (Vector<Path>::const_iterator i = m_data->m_paths.begin(); i != m_data->m_paths.end(); ++i) {
- IntRect trRect = enclosingIntRect(m_data->mapRect(i->boundingRect()));
- trRect.inflate(1);
- TransparentLayerDC transparentDC(m_data, trRect);
- HDC dc = transparentDC.hdc();
- if (!dc)
- continue;
-
- AffineTransform tr = m_data->m_transform;
- tr.translate(transparentDC.toShift().width(), transparentDC.toShift().height());
-
- SelectObject(dc, GetStockObject(NULL_PEN));
- HGDIOBJ oldBrush = SelectObject(dc, brush.get());
- i->platformPath()->fillPath(dc, &tr);
- SelectObject(dc, oldBrush);
- }
+ IntRect trRect = enclosingIntRect(m_data->mapRect(path.boundingRect()));
+ trRect.inflate(1);
+ TransparentLayerDC transparentDC(m_data, trRect);
+ HDC dc = transparentDC.hdc();
+ if (!dc)
+ return;
+
+ AffineTransform tr = m_data->m_transform;
+ tr.translate(transparentDC.toShift().width(), transparentDC.toShift().height());
+
+ SelectObject(dc, GetStockObject(NULL_PEN));
+ HGDIOBJ oldBrush = SelectObject(dc, brush.get());
+ path.platformPath()->fillPath(dc, &tr);
+ SelectObject(dc, oldBrush);
} else {
SelectObject(m_data->m_dc, GetStockObject(NULL_PEN));
HGDIOBJ oldBrush = SelectObject(m_data->m_dc, brush.get());
- for (Vector<Path>::const_iterator i = m_data->m_paths.begin(); i != m_data->m_paths.end(); ++i)
- i->platformPath()->fillPath(m_data->m_dc, &m_data->m_transform);
+ path.platformPath()->fillPath(m_data->m_dc, &m_data->m_transform);
SelectObject(m_data->m_dc, oldBrush);
}
}
-void GraphicsContext::strokePath()
+void GraphicsContext::strokePath(const Path& path)
{
if (!m_data->m_opacity)
return;
@@ -1379,27 +1363,24 @@ void GraphicsContext::strokePath()
OwnPtr<HPEN> pen = createPen(strokeColor(), strokeThickness(), strokeStyle());
if (m_data->m_opacity < 1.0f || m_data->hasAlpha()) {
- for (Vector<Path>::const_iterator i = m_data->m_paths.begin(); i != m_data->m_paths.end(); ++i) {
- IntRect trRect = enclosingIntRect(m_data->mapRect(i->boundingRect()));
- trRect.inflate(1);
- TransparentLayerDC transparentDC(m_data, trRect);
- HDC dc = transparentDC.hdc();
- if (!dc)
- continue;
-
- AffineTransform tr = m_data->m_transform;
- tr.translate(transparentDC.toShift().width(), transparentDC.toShift().height());
-
- SelectObject(dc, GetStockObject(NULL_BRUSH));
- HGDIOBJ oldPen = SelectObject(dc, pen.get());
- i->platformPath()->strokePath(dc, &tr);
- SelectObject(dc, oldPen);
- }
+ IntRect trRect = enclosingIntRect(m_data->mapRect(path.boundingRect()));
+ trRect.inflate(1);
+ TransparentLayerDC transparentDC(m_data, trRect);
+ HDC dc = transparentDC.hdc();
+ if (!dc)
+ return;
+
+ AffineTransform tr = m_data->m_transform;
+ tr.translate(transparentDC.toShift().width(), transparentDC.toShift().height());
+
+ SelectObject(dc, GetStockObject(NULL_BRUSH));
+ HGDIOBJ oldPen = SelectObject(dc, pen.get());
+ path.platformPath()->strokePath(dc, &tr);
+ SelectObject(dc, oldPen);
} else {
SelectObject(m_data->m_dc, GetStockObject(NULL_BRUSH));
HGDIOBJ oldPen = SelectObject(m_data->m_dc, pen.get());
- for (Vector<Path>::const_iterator i = m_data->m_paths.begin(); i != m_data->m_paths.end(); ++i)
- i->platformPath()->strokePath(m_data->m_dc, &m_data->m_transform);
+ path.platformPath()->strokePath(m_data->m_dc, &m_data->m_transform);
SelectObject(m_data->m_dc, oldPen);
}
}
@@ -1504,8 +1485,8 @@ void GraphicsContext::fillRect(const FloatRect& rect)
{
savePlatformState();
- if (m_common->state.fillGradient)
- fillRect(rect, m_common->state.fillGradient.get());
+ if (m_state.fillGradient)
+ fillRect(rect, m_state.fillGradient.get());
else
fillRect(rect, fillColor(), ColorSpaceDeviceRGB);
@@ -1643,8 +1624,9 @@ void GraphicsContext::drawText(const SimpleFontData* fontData, const GlyphBuffer
FloatSize shadowOffset;
float shadowBlur = 0;
Color shadowColor;
- bool hasShadow = textDrawingMode() == cTextFill
- && getShadow(shadowOffset, shadowBlur, shadowColor)
+ ColorSpace shadowColorSpace;
+ bool hasShadow = textDrawingMode() == TextModeFill
+ && getShadow(shadowOffset, shadowBlur, shadowColor, shadowColorSpace)
&& shadowColor.alpha();
COLORREF shadowRGBColor;
FloatPoint trShadowPoint;
@@ -1900,7 +1882,7 @@ void GraphicsContext::setLineDash(const DashArray&, float)
notImplemented();
}
-void GraphicsContext::clipPath(WindRule)
+void GraphicsContext::clipPath(const Path&, WindRule)
{
notImplemented();
}
diff --git a/WebCore/platform/graphics/wince/ImageBufferWinCE.cpp b/WebCore/platform/graphics/wince/ImageBufferWinCE.cpp
index ec8517b..e6edb41 100644
--- a/WebCore/platform/graphics/wince/ImageBufferWinCE.cpp
+++ b/WebCore/platform/graphics/wince/ImageBufferWinCE.cpp
@@ -72,7 +72,7 @@ ImageBufferData::ImageBufferData(const IntSize& size)
m_bitmap->setHasAlpha(true);
}
-ImageBuffer::ImageBuffer(const IntSize& size, ColorSpace colorSpace, bool& success)
+ImageBuffer::ImageBuffer(const IntSize& size, ColorSpace colorSpace, RenderingMode, bool& success)
: m_data(size)
, m_size(size)
{
diff --git a/WebCore/platform/graphics/wince/SimpleFontDataWinCE.cpp b/WebCore/platform/graphics/wince/SimpleFontDataWinCE.cpp
index c8c5474..27a021e 100644
--- a/WebCore/platform/graphics/wince/SimpleFontDataWinCE.cpp
+++ b/WebCore/platform/graphics/wince/SimpleFontDataWinCE.cpp
@@ -60,22 +60,36 @@ void SimpleFontData::platformInit()
void SimpleFontData::platformDestroy()
{
- delete m_smallCapsFontData;
- m_smallCapsFontData = 0;
+}
+
+SimpleFontData* SimpleFontData::scaledFontData(const FontDescription& fontDescription, float scaleFactor) const
+{
+ FontDescription fontDesc(fontDescription);
+ fontDesc.setComputedSize(lroundf(scaleFactor * fontDesc.computedSize()));
+ fontDesc.setSpecifiedSize(lroundf(scaleFactor * fontDesc.specifiedSize()));
+ fontDesc.setKeywordSize(lroundf(scaleFactor * fontDesc.keywordSize()));
+ FontPlatformData* result = fontCache()->getCachedFontPlatformData(fontDesc, m_platformData.family());
+ return result ? new SimpleFontData(*result) : 0;
}
SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const
{
- if (!m_smallCapsFontData) {
- FontDescription fontDesc(fontDescription);
- fontDesc.setComputedSize(lroundf(0.70f * fontDesc.computedSize()));
- fontDesc.setSpecifiedSize(lroundf(0.70f * fontDesc.specifiedSize()));
- fontDesc.setKeywordSize(lroundf(0.70f * fontDesc.keywordSize()));
- FontPlatformData* result = fontCache()->getCachedFontPlatformData(fontDesc, m_platformData.family());
- if (result)
- m_smallCapsFontData = new SimpleFontData(*result);
- }
- return m_smallCapsFontData;
+ if (!m_derivedFontData)
+ m_derivedFontData = DerivedFontData::create(isCustomFont());
+ if (!m_derivedFontData->smallCaps)
+ m_derivedFontData->smallCaps = scaledFontData(fontDescription, .7);
+
+ return m_derivedFontData->smallCaps.get();
+}
+
+SimpleFontData* SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const
+{
+ if (!m_derivedFontData)
+ m_derivedFontData = DerivedFontData::create(isCustomFont());
+ if (!m_derivedFontData->emphasisMark)
+ m_derivedFontData->emphasisMark = scaledFontData(fontDescription, .5);
+
+ return m_derivedFontData->emphasisMark.get();
}
DWORD getKnownFontCodePages(const wchar_t* family);
diff --git a/WebCore/platform/graphics/wx/FontWx.cpp b/WebCore/platform/graphics/wx/FontWx.cpp
index cc45ab0..c01e249 100644
--- a/WebCore/platform/graphics/wx/FontWx.cpp
+++ b/WebCore/platform/graphics/wx/FontWx.cpp
@@ -98,6 +98,14 @@ FloatRect Font::selectionRectForComplexText(const TextRun& run, const FloatPoint
#endif
}
+float Font::getGlyphsAndAdvancesForComplexText(const TextRun& /* run */, int /* from */, int /* to */, GlyphBuffer& /* glyphBuffer */, ForTextEmphasisOrNot /* forTextEmphasis */) const
+{
+ // FIXME: Implement this by moving most of the drawComplexText() implementation in here. Set up the
+ // ComplexTextController according to forTextEmphasis.
+ notImplemented();
+ return 0;
+}
+
void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const
{
#if OS(WINDOWS) || OS(DARWIN)
@@ -130,12 +138,22 @@ void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const F
// Draw the glyph buffer now at the starting point returned in startX.
FloatPoint startPoint(startX, point.y());
- drawGlyphBuffer(context, glyphBuffer, run, startPoint);
+ drawGlyphBuffer(context, glyphBuffer, startPoint);
#else
notImplemented();
#endif
}
+void Font::drawEmphasisMarksForComplexText(GraphicsContext* context, const TextRun& run, const AtomicString& mark, const FloatPoint& point, int from, int to) const
+{
+ GlyphBuffer glyphBuffer;
+ float initialAdvance = getGlyphsAndAdvancesForComplexText(run, from, to, glyphBuffer, ForTextEmphasis);
+
+ if (glyphBuffer.isEmpty())
+ return;
+
+ drawEmphasisMarks(context, glyphBuffer, mark, FloatPoint(point.x() + initialAdvance, point.y()));
+}
float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow*) const
{
diff --git a/WebCore/platform/graphics/wx/GraphicsContextWx.cpp b/WebCore/platform/graphics/wx/GraphicsContextWx.cpp
index 5007ffe..cee6aee 100644
--- a/WebCore/platform/graphics/wx/GraphicsContextWx.cpp
+++ b/WebCore/platform/graphics/wx/GraphicsContextWx.cpp
@@ -91,7 +91,6 @@ public:
#if USE(WXGC)
wxGCDC* context;
- wxGraphicsPath currentPath;
#else
wxWindowDC* context;
#endif
@@ -113,11 +112,11 @@ GraphicsContextPlatformPrivate::~GraphicsContextPlatformPrivate()
}
-GraphicsContext::GraphicsContext(PlatformGraphicsContext* context)
- : m_common(createGraphicsContextPrivate())
- , m_data(new GraphicsContextPlatformPrivate)
-{
+void GraphicsContext::platformInit(PlatformGraphicsContext* context)
+{
+ m_data = new GraphicsContextPlatformPrivate;
setPaintingDisabled(!context);
+
if (context) {
// Make sure the context starts in sync with our state.
setPlatformFillColor(fillColor(), ColorSpaceDeviceRGB);
@@ -125,17 +124,13 @@ GraphicsContext::GraphicsContext(PlatformGraphicsContext* context)
}
#if USE(WXGC)
m_data->context = (wxGCDC*)context;
- wxGraphicsContext* gc = m_data->context->GetGraphicsContext();
- if (gc)
- m_data->currentPath = gc->CreatePath();
#else
m_data->context = (wxWindowDC*)context;
#endif
}
-GraphicsContext::~GraphicsContext()
+void GraphicsContext::platformDestroy()
{
- destroyGraphicsContextPrivate(m_common);
delete m_data;
}
@@ -337,7 +332,7 @@ void GraphicsContext::clipOut(const IntRect&)
notImplemented();
}
-void GraphicsContext::clipPath(WindRule)
+void GraphicsContext::clipPath(const Path&, WindRule)
{
notImplemented();
}
@@ -447,7 +442,7 @@ void GraphicsContext::setURLForRect(const KURL&, const IntRect&)
notImplemented();
}
-void GraphicsContext::setCompositeOperation(CompositeOperator op)
+void GraphicsContext::setPlatformCompositeOperation(CompositeOperator op)
{
if (m_data->context)
{
@@ -459,23 +454,6 @@ void GraphicsContext::setCompositeOperation(CompositeOperator op)
}
}
-void GraphicsContext::beginPath()
-{
-#if USE(WXGC)
- wxGraphicsContext* gc = m_data->context->GetGraphicsContext();
- if (gc)
- m_data->currentPath = gc->CreatePath();
-#endif
-}
-
-void GraphicsContext::addPath(const Path& path)
-{
-#if USE(WXGC)
- if (path.platformPath())
- m_data->currentPath.AddPath(*path.platformPath());
-#endif
-}
-
void GraphicsContext::setPlatformStrokeColor(const Color& color, ColorSpace colorSpace)
{
if (paintingDisabled())
@@ -533,30 +511,24 @@ InterpolationQuality GraphicsContext::imageInterpolationQuality() const
return InterpolationDefault;
}
-void GraphicsContext::fillPath()
+void GraphicsContext::fillPath(const Path& path)
{
#if USE(WXGC)
wxGraphicsContext* gc = m_data->context->GetGraphicsContext();
if (gc)
- gc->FillPath(m_data->currentPath);
+ gc->FillPath(path.platformPath());
#endif
}
-void GraphicsContext::strokePath()
+void GraphicsContext::strokePath(const Path& path)
{
#if USE(WXGC)
wxGraphicsContext* gc = m_data->context->GetGraphicsContext();
if (gc)
- gc->StrokePath(m_data->currentPath);
+ gc->StrokePath(path.platformPath());
#endif
}
-void GraphicsContext::drawPath()
-{
- fillPath();
- strokePath();
-}
-
void GraphicsContext::fillRect(const FloatRect& rect)
{
if (paintingDisabled())
diff --git a/WebCore/platform/graphics/wx/ImageBufferWx.cpp b/WebCore/platform/graphics/wx/ImageBufferWx.cpp
index 2522cbd..74c9c39 100644
--- a/WebCore/platform/graphics/wx/ImageBufferWx.cpp
+++ b/WebCore/platform/graphics/wx/ImageBufferWx.cpp
@@ -37,7 +37,7 @@ ImageBufferData::ImageBufferData(const IntSize&)
{
}
-ImageBuffer::ImageBuffer(const IntSize&, ImageColorSpace imageColorSpace, bool& success) :
+ImageBuffer::ImageBuffer(const IntSize&, ColorSpace imageColorSpace, RenderingMode, bool& success) :
m_data(IntSize())
{
notImplemented();
diff --git a/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp b/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp
index 96129f9..0e24bfc 100644
--- a/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp
+++ b/WebCore/platform/graphics/wx/SimpleFontDataWx.cpp
@@ -90,15 +90,32 @@ void SimpleFontData::platformDestroy()
#endif
}
+SimpleFontData* SimpleFontData::scaledFontData(const FontDescription& fontDescription, float scaleFactor) const
+{
+ FontDescription desc = FontDescription(fontDescription);
+ desc.setSpecifiedSize(scaleFactor * fontDescription.computedSize());
+ FontPlatformData platformData(desc, desc.family().family());
+ return new SimpleFontData(platformData, isCustomFont(), false);
+}
+
SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const
{
- if (!m_smallCapsFontData){
- FontDescription desc = FontDescription(fontDescription);
- desc.setSpecifiedSize(0.70f * fontDescription.computedSize());
- FontPlatformData platformData(desc, desc.family().family());
- m_smallCapsFontData = new SimpleFontData(platformData, isCustomFont(), false);
- }
- return m_smallCapsFontData;
+ if (!m_derivedFontData)
+ m_derivedFontData = DerivedFontData::create(isCustomFont());
+ if (!m_derivedFontData->smallCaps)
+ m_derivedFontData->smallCaps = scaledFontData(fontDescription, .7);
+
+ return m_derivedFontData->smallCaps.get();
+}
+
+SimpleFontData* SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const
+{
+ if (!m_derivedFontData)
+ m_derivedFontData = DerivedFontData::create(isCustomFont());
+ if (!m_derivedFontData->emphasisMark)
+ m_derivedFontData->emphasisMark = scaledFontData(fontDescription, .5);
+
+ return m_derivedFontData->emphasisMark.get();
}
bool SimpleFontData::containsCharacters(const UChar* characters, int length) const
diff --git a/WebCore/platform/gtk/ContextMenuGtk.cpp b/WebCore/platform/gtk/ContextMenuGtk.cpp
index 210cfa6..423959a 100644
--- a/WebCore/platform/gtk/ContextMenuGtk.cpp
+++ b/WebCore/platform/gtk/ContextMenuGtk.cpp
@@ -19,23 +19,11 @@
#include "config.h"
#include "ContextMenu.h"
-#include "ContextMenuController.h"
-
#include <gtk/gtk.h>
namespace WebCore {
-// TODO: ref-counting correctness checking.
-// See http://bugs.webkit.org/show_bug.cgi?id=16115
-
-static void menuItemActivated(GtkMenuItem* item, ContextMenuController* controller)
-{
- ContextMenuItem contextItem(item);
- controller->contextMenuItemSelected(&contextItem);
-}
-
-ContextMenu::ContextMenu(const HitTestResult& result)
- : m_hitTestResult(result)
+ContextMenu::ContextMenu()
{
m_platformDescription = GTK_MENU(gtk_menu_new());
@@ -51,15 +39,9 @@ ContextMenu::~ContextMenu()
void ContextMenu::appendItem(ContextMenuItem& item)
{
ASSERT(m_platformDescription);
- checkOrEnableIfNeeded(item);
- ContextMenuItemType type = item.type();
- GtkMenuItem* platformItem = ContextMenuItem::createNativeMenuItem(item.releasePlatformDescription());
+ GtkMenuItem* platformItem = item.releasePlatformDescription();
ASSERT(platformItem);
-
- if (type == ActionType || type == CheckableActionType)
- g_signal_connect(platformItem, "activate", G_CALLBACK(menuItemActivated), controller());
-
gtk_menu_shell_append(GTK_MENU_SHELL(m_platformDescription), GTK_WIDGET(platformItem));
gtk_widget_show(GTK_WIDGET(platformItem));
}
diff --git a/WebCore/platform/gtk/ContextMenuItemGtk.cpp b/WebCore/platform/gtk/ContextMenuItemGtk.cpp
index 68d0a9a..4d79f13 100644
--- a/WebCore/platform/gtk/ContextMenuItemGtk.cpp
+++ b/WebCore/platform/gtk/ContextMenuItemGtk.cpp
@@ -18,12 +18,14 @@
*/
#include "config.h"
-#include "ContextMenu.h"
+
#include "ContextMenuItem.h"
-#include "NotImplemented.h"
-#include <wtf/text/CString.h>
+#include "ContextMenu.h"
+#include "GOwnPtr.h"
+#include "NotImplemented.h"
#include <gtk/gtk.h>
+#include <wtf/text/CString.h>
#define WEBKIT_CONTEXT_MENU_ACTION "webkit-context-menu"
@@ -114,30 +116,9 @@ static const char* gtkStockIDFromContextMenuAction(const ContextMenuAction& acti
}
// Extract the ActionType from the menu item
-ContextMenuItem::ContextMenuItem(GtkMenuItem* item)
- : m_platformDescription()
+ContextMenuItem::ContextMenuItem(PlatformMenuItemDescription item)
+ : m_platformDescription(item)
{
- if (GTK_IS_SEPARATOR_MENU_ITEM(item))
- m_platformDescription.type = SeparatorType;
- else if (gtk_menu_item_get_submenu(item))
- m_platformDescription.type = SubmenuType;
- else if (GTK_IS_CHECK_MENU_ITEM(item)) {
- m_platformDescription.type = CheckableActionType;
- m_platformDescription.checked = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(item));
- } else
- m_platformDescription.type = ActionType;
-#if GTK_CHECK_VERSION (2, 16, 0)
- m_platformDescription.title = String::fromUTF8(gtk_menu_item_get_label(GTK_MENU_ITEM(item)));
-#else
- GtkWidget* label = gtk_bin_get_child(GTK_BIN(item));
- m_platformDescription.title = String::fromUTF8(gtk_label_get_label(GTK_LABEL(label)));
-#endif
-
- m_platformDescription.action = *static_cast<ContextMenuAction*>(g_object_get_data(G_OBJECT(item), WEBKIT_CONTEXT_MENU_ACTION));
-
- m_platformDescription.subMenu = GTK_MENU(gtk_menu_item_get_submenu(item));
- if (m_platformDescription.subMenu)
- g_object_ref(m_platformDescription.subMenu);
}
ContextMenuItem::ContextMenuItem(ContextMenu*)
@@ -147,114 +128,100 @@ ContextMenuItem::ContextMenuItem(ContextMenu*)
ContextMenuItem::ContextMenuItem(ContextMenuItemType type, ContextMenuAction action, const String& title, ContextMenu* subMenu)
{
- m_platformDescription.type = type;
- m_platformDescription.action = action;
- m_platformDescription.title = title;
+ if (type == SeparatorType) {
+ m_platformDescription = GTK_MENU_ITEM(gtk_separator_menu_item_new());
+ return;
+ }
- setSubMenu(subMenu);
-}
+ GOwnPtr<char> actionName(g_strdup_printf("context-menu-action-%d", action));
+ GtkAction* platformAction = 0;
-ContextMenuItem::~ContextMenuItem()
-{
- if (m_platformDescription.subMenu)
- g_object_unref(m_platformDescription.subMenu);
-}
-
-GtkMenuItem* ContextMenuItem::createNativeMenuItem(const PlatformMenuItemDescription& menu)
-{
- GtkMenuItem* item = 0;
- if (menu.type == SeparatorType)
- item = GTK_MENU_ITEM(gtk_separator_menu_item_new());
- else {
- if (menu.type == CheckableActionType) {
- item = GTK_MENU_ITEM(gtk_check_menu_item_new_with_mnemonic(menu.title.utf8().data()));
- gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), menu.checked);
- } else {
- if (const gchar* stockID = gtkStockIDFromContextMenuAction(menu.action)) {
- item = GTK_MENU_ITEM(gtk_image_menu_item_new_with_mnemonic(menu.title.utf8().data()));
- GtkWidget* image = gtk_image_new_from_stock(stockID, GTK_ICON_SIZE_MENU);
- gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), image);
- } else
- item = GTK_MENU_ITEM(gtk_menu_item_new_with_mnemonic(menu.title.utf8().data()));
- }
+ if (type == CheckableActionType)
+ platformAction = GTK_ACTION(gtk_toggle_action_new(actionName.get(), title.utf8().data(), 0, gtkStockIDFromContextMenuAction(action)));
+ else
+ platformAction = gtk_action_new(actionName.get(), title.utf8().data(), 0, gtkStockIDFromContextMenuAction(action));
- ContextMenuAction* menuAction = static_cast<ContextMenuAction*>(malloc(sizeof(ContextMenuAction*)));
- *menuAction = menu.action;
- g_object_set_data(G_OBJECT(item), WEBKIT_CONTEXT_MENU_ACTION, menuAction);
+ m_platformDescription = GTK_MENU_ITEM(gtk_action_create_menu_item(platformAction));
+ g_object_unref(platformAction);
- gtk_widget_set_sensitive(GTK_WIDGET(item), menu.enabled);
+ g_object_set_data(G_OBJECT(m_platformDescription.get()), WEBKIT_CONTEXT_MENU_ACTION, GINT_TO_POINTER(action));
- if (menu.subMenu)
- gtk_menu_item_set_submenu(item, GTK_WIDGET(menu.subMenu));
- }
+ if (subMenu)
+ setSubMenu(subMenu);
+}
- return item;
+ContextMenuItem::~ContextMenuItem()
+{
}
PlatformMenuItemDescription ContextMenuItem::releasePlatformDescription()
{
- PlatformMenuItemDescription description = m_platformDescription;
- m_platformDescription = PlatformMenuItemDescription();
- return description;
+ return m_platformDescription.leakRef();
}
ContextMenuItemType ContextMenuItem::type() const
{
- return m_platformDescription.type;
+ if (GTK_IS_SEPARATOR_MENU_ITEM(m_platformDescription.get()))
+ return SeparatorType;
+ if (GTK_IS_CHECK_MENU_ITEM(m_platformDescription.get()))
+ return CheckableActionType;
+ if (gtk_menu_item_get_submenu(m_platformDescription.get()))
+ return SubmenuType;
+ return ActionType;
}
void ContextMenuItem::setType(ContextMenuItemType type)
{
- m_platformDescription.type = type;
+ if (type == SeparatorType)
+ m_platformDescription = GTK_MENU_ITEM(gtk_separator_menu_item_new());
}
ContextMenuAction ContextMenuItem::action() const
{
- return m_platformDescription.action;
+ return static_cast<ContextMenuAction>(GPOINTER_TO_INT(g_object_get_data(G_OBJECT(m_platformDescription.get()), WEBKIT_CONTEXT_MENU_ACTION)));
}
void ContextMenuItem::setAction(ContextMenuAction action)
{
- m_platformDescription.action = action;
+ g_object_set_data(G_OBJECT(m_platformDescription.get()), WEBKIT_CONTEXT_MENU_ACTION, GINT_TO_POINTER(action));
}
String ContextMenuItem::title() const
{
- return m_platformDescription.title;
+ GtkAction* action = gtk_activatable_get_related_action(GTK_ACTIVATABLE(m_platformDescription.get()));
+ return action ? String(gtk_action_get_label(action)) : String();
}
void ContextMenuItem::setTitle(const String& title)
{
- m_platformDescription.title = title;
+ GtkAction* action = gtk_activatable_get_related_action(GTK_ACTIVATABLE(m_platformDescription.get()));
+ if (action)
+ gtk_action_set_label(action, title.utf8().data());
}
PlatformMenuDescription ContextMenuItem::platformSubMenu() const
{
- return m_platformDescription.subMenu;
+ GtkWidget* subMenu = gtk_menu_item_get_submenu(m_platformDescription.get());
+ return subMenu ? GTK_MENU(subMenu) : 0;
}
void ContextMenuItem::setSubMenu(ContextMenu* menu)
{
- if (m_platformDescription.subMenu)
- g_object_unref(m_platformDescription.subMenu);
-
- if (!menu)
- return;
-
- m_platformDescription.subMenu = menu->releasePlatformDescription();
- m_platformDescription.type = SubmenuType;
-
- g_object_ref_sink(G_OBJECT(m_platformDescription.subMenu));
+ gtk_menu_item_set_submenu(m_platformDescription.get(), GTK_WIDGET(menu->platformDescription()));
}
void ContextMenuItem::setChecked(bool shouldCheck)
{
- m_platformDescription.checked = shouldCheck;
+ GtkAction* action = gtk_activatable_get_related_action(GTK_ACTIVATABLE(m_platformDescription.get()));
+ if (action && GTK_IS_TOGGLE_ACTION(action))
+ gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), shouldCheck);
}
void ContextMenuItem::setEnabled(bool shouldEnable)
{
- m_platformDescription.enabled = shouldEnable;
+ GtkAction* action = gtk_activatable_get_related_action(GTK_ACTIVATABLE(m_platformDescription.get()));
+ if (action)
+ gtk_action_set_sensitive(action, shouldEnable);
}
}
diff --git a/WebCore/platform/gtk/GtkVersioning.h b/WebCore/platform/gtk/GtkVersioning.h
index ea15a54..11d1f8a 100644
--- a/WebCore/platform/gtk/GtkVersioning.h
+++ b/WebCore/platform/gtk/GtkVersioning.h
@@ -31,7 +31,7 @@ G_BEGIN_DECLS
// Macros to avoid deprecation checking churn
#ifndef GTK_API_VERSION_2
-#define GDK_DISPLAY() (GDK_DISPLAY_XDISPLAY(gdk_display_get_default()))
+#define GDK_WINDOW_XWINDOW(window) (gdk_x11_window_get_xid(window))
#else
GdkPixbuf* gdk_pixbuf_get_from_surface(cairo_surface_t* surface, int srcX, int srcY,
int width, int height);
diff --git a/WebCore/platform/gtk/PasteboardHelper.cpp b/WebCore/platform/gtk/PasteboardHelper.cpp
index 228d5e9..4428be0 100644
--- a/WebCore/platform/gtk/PasteboardHelper.cpp
+++ b/WebCore/platform/gtk/PasteboardHelper.cpp
@@ -34,11 +34,11 @@
namespace WebCore {
-static GdkAtom textPlainAtom = gdk_atom_intern("text/plain;charset=utf-8", FALSE);
-static GdkAtom markupAtom = gdk_atom_intern("text/html", FALSE);
-static GdkAtom netscapeURLAtom = gdk_atom_intern("_NETSCAPE_URL", FALSE);
-static GdkAtom uriListAtom = gdk_atom_intern("text/uri-list", FALSE);
-static String gMarkupPrefix = "<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">";
+static GdkAtom textPlainAtom;
+static GdkAtom markupAtom;
+static GdkAtom netscapeURLAtom;
+static GdkAtom uriListAtom;
+static String gMarkupPrefix;
static void removeMarkupPrefix(String& markup)
{
@@ -49,9 +49,26 @@ static void removeMarkupPrefix(String& markup)
markup.remove(0, gMarkupPrefix.length());
}
+static void initGdkAtoms()
+{
+ static gboolean initialized = FALSE;
+
+ if (initialized)
+ return;
+
+ initialized = TRUE;
+
+ textPlainAtom = gdk_atom_intern("text/plain;charset=utf-8", FALSE);
+ markupAtom = gdk_atom_intern("text/html", FALSE);
+ netscapeURLAtom = gdk_atom_intern("_NETSCAPE_URL", FALSE);
+ uriListAtom = gdk_atom_intern("text/uri-list", FALSE);
+ gMarkupPrefix = "<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">";
+}
+
PasteboardHelper::PasteboardHelper()
: m_targetList(gtk_target_list_new(0, 0))
{
+ initGdkAtoms();
}
PasteboardHelper::~PasteboardHelper()
diff --git a/WebCore/platform/gtk/PlatformScreenGtk.cpp b/WebCore/platform/gtk/PlatformScreenGtk.cpp
index 9c70d0e..40b509e 100644
--- a/WebCore/platform/gtk/PlatformScreenGtk.cpp
+++ b/WebCore/platform/gtk/PlatformScreenGtk.cpp
@@ -121,7 +121,7 @@ FloatRect screenAvailableRect(Widget* widget)
if (!gtk_widget_get_realized(container))
return screenRect(widget);
- GdkDrawable* rootWindow = GDK_DRAWABLE(gtk_widget_get_root_window(container));
+ GdkWindow* rootWindow = gtk_widget_get_root_window(container);
GdkDisplay* display = gdk_window_get_display(rootWindow);
Atom xproperty = gdk_x11_get_xatom_by_name_for_display(display, "_NET_WORKAREA");
diff --git a/WebCore/platform/gtk/PopupMenuGtk.cpp b/WebCore/platform/gtk/PopupMenuGtk.cpp
index e7ff78e..b2466c5 100644
--- a/WebCore/platform/gtk/PopupMenuGtk.cpp
+++ b/WebCore/platform/gtk/PopupMenuGtk.cpp
@@ -5,6 +5,7 @@
* Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com
* Copyright (C) 2008 Collabora Ltd.
* Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright (C) 2010 Igalia S.L.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -27,16 +28,22 @@
#include "PopupMenuGtk.h"
#include "FrameView.h"
+#include "GOwnPtr.h"
#include "GtkVersioning.h"
#include "HostWindow.h"
#include "PlatformString.h"
-#include <wtf/text/CString.h>
+#include <gdk/gdk.h>
#include <gtk/gtk.h>
+#include <wtf/text/CString.h>
namespace WebCore {
+static const uint32_t gSearchTimeoutMs = 1000;
+
PopupMenuGtk::PopupMenuGtk(PopupMenuClient* client)
: m_popupClient(client)
+ , m_previousKeyEventCharacter(0)
+ , m_currentlySelectedMenuItem(0)
{
}
@@ -54,12 +61,16 @@ void PopupMenuGtk::show(const IntRect& rect, FrameView* view, int index)
if (!m_popup) {
m_popup = GTK_MENU(gtk_menu_new());
- g_signal_connect(m_popup.get(), "unmap", G_CALLBACK(menuUnmapped), this);
+ g_signal_connect(m_popup.get(), "unmap", G_CALLBACK(PopupMenuGtk::menuUnmapped), this);
+ g_signal_connect(m_popup.get(), "key-press-event", G_CALLBACK(PopupMenuGtk::keyPressEventCallback), this);
} else
gtk_container_foreach(GTK_CONTAINER(m_popup.get()), reinterpret_cast<GtkCallback>(menuRemoveItem), this);
- int x, y;
- gdk_window_get_origin(gtk_widget_get_window(GTK_WIDGET(view->hostWindow()->platformPageClient())), &x, &y);
+ int x = 0;
+ int y = 0;
+ GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(view->hostWindow()->platformPageClient()));
+ if (window)
+ gdk_window_get_origin(window, &x, &y);
m_menuPosition = view->contentsToWindow(rect.location());
m_menuPosition = IntPoint(m_menuPosition.x() + x, m_menuPosition.y() + y + rect.height());
m_indexMap.clear();
@@ -73,7 +84,8 @@ void PopupMenuGtk::show(const IntRect& rect, FrameView* view, int index)
item = gtk_menu_item_new_with_label(client()->itemText(i).utf8().data());
m_indexMap.add(item, i);
- g_signal_connect(item, "activate", G_CALLBACK(menuItemActivated), this);
+ g_signal_connect(item, "activate", G_CALLBACK(PopupMenuGtk::menuItemActivated), this);
+ g_signal_connect(item, "select", G_CALLBACK(PopupMenuGtk::selectItemCallback), this);
// FIXME: Apply the PopupMenuStyle from client()->itemStyle(i)
gtk_widget_set_sensitive(item, client()->itemIsEnabled(i));
@@ -138,6 +150,77 @@ void PopupMenuGtk::disconnectClient()
m_popupClient = 0;
}
+bool PopupMenuGtk::typeAheadFind(GdkEventKey* event)
+{
+ // If we were given a non-printable character just skip it.
+ gunichar unicodeCharacter = gdk_keyval_to_unicode(event->keyval);
+ if (!unicodeCharacter) {
+ resetTypeAheadFindState();
+ return false;
+ }
+
+ glong charactersWritten;
+ GOwnPtr<gunichar2> utf16String(g_ucs4_to_utf16(&unicodeCharacter, 1, 0, &charactersWritten, 0));
+ if (!utf16String) {
+ resetTypeAheadFindState();
+ return false;
+ }
+
+ // If the character is the same as the last character, the user is probably trying to
+ // cycle through the menulist entries. This matches the WebCore behavior for collapsed
+ // menulists.
+ bool repeatingCharacter = unicodeCharacter != m_previousKeyEventCharacter;
+ if (event->time - m_previousKeyEventTimestamp > gSearchTimeoutMs)
+ m_currentSearchString = String(static_cast<UChar*>(utf16String.get()), charactersWritten);
+ else if (repeatingCharacter)
+ m_currentSearchString.append(String(static_cast<UChar*>(utf16String.get()), charactersWritten));
+
+ m_previousKeyEventTimestamp = event->time;
+ m_previousKeyEventCharacter = unicodeCharacter;
+
+ // Like the Chromium port, we case fold before searching, because
+ // strncmp does not handle non-ASCII characters.
+ GOwnPtr<gchar> searchStringWithCaseFolded(g_utf8_casefold(m_currentSearchString.utf8().data(), -1));
+ size_t prefixLength = strlen(searchStringWithCaseFolded.get());
+
+ GList* children = gtk_container_get_children(GTK_CONTAINER(m_popup.get()));
+ if (!children)
+ return true;
+
+ // If a menu item has already been selected, start searching from the current
+ // item down the list. This will make multiple key presses of the same character
+ // advance the selection.
+ GList* currentChild = children;
+ if (m_currentlySelectedMenuItem) {
+ currentChild = g_list_find(children, m_currentlySelectedMenuItem);
+ if (!currentChild) {
+ m_currentlySelectedMenuItem = 0;
+ currentChild = children;
+ }
+
+ // Repeating characters should iterate.
+ if (repeatingCharacter) {
+ if (GList* nextChild = g_list_next(currentChild))
+ currentChild = nextChild;
+ }
+ }
+
+ GList* firstChild = currentChild;
+ do {
+ currentChild = g_list_next(currentChild);
+ if (!currentChild)
+ currentChild = children;
+
+ GOwnPtr<gchar> itemText(g_utf8_casefold(gtk_menu_item_get_label(GTK_MENU_ITEM(currentChild->data)), -1));
+ if (!strncmp(searchStringWithCaseFolded.get(), itemText.get(), prefixLength)) {
+ gtk_menu_shell_select_item(GTK_MENU_SHELL(m_popup.get()), GTK_WIDGET(currentChild->data));
+ return true;
+ }
+ } while (currentChild != firstChild);
+
+ return true;
+}
+
void PopupMenuGtk::menuItemActivated(GtkMenuItem* item, PopupMenuGtk* that)
{
ASSERT(that->client());
@@ -148,6 +231,7 @@ void PopupMenuGtk::menuItemActivated(GtkMenuItem* item, PopupMenuGtk* that)
void PopupMenuGtk::menuUnmapped(GtkWidget*, PopupMenuGtk* that)
{
ASSERT(that->client());
+ that->resetTypeAheadFindState();
that->client()->popupDidHide();
}
@@ -158,11 +242,29 @@ void PopupMenuGtk::menuPositionFunction(GtkMenu*, gint* x, gint* y, gboolean* pu
*pushIn = true;
}
+void PopupMenuGtk::resetTypeAheadFindState()
+{
+ m_currentlySelectedMenuItem = 0;
+ m_previousKeyEventCharacter = 0;
+ m_currentSearchString = "";
+}
+
void PopupMenuGtk::menuRemoveItem(GtkWidget* widget, PopupMenuGtk* that)
{
ASSERT(that->m_popup);
gtk_container_remove(GTK_CONTAINER(that->m_popup.get()), widget);
}
+int PopupMenuGtk::selectItemCallback(GtkMenuItem* item, PopupMenuGtk* that)
+{
+ that->m_currentlySelectedMenuItem = GTK_WIDGET(item);
+ return FALSE;
+}
+
+int PopupMenuGtk::keyPressEventCallback(GtkWidget* widget, GdkEventKey* event, PopupMenuGtk* that)
+{
+ return that->typeAheadFind(event);
+}
+
}
diff --git a/WebCore/platform/gtk/PopupMenuGtk.h b/WebCore/platform/gtk/PopupMenuGtk.h
index 8848e06..e47fda6 100644
--- a/WebCore/platform/gtk/PopupMenuGtk.h
+++ b/WebCore/platform/gtk/PopupMenuGtk.h
@@ -24,11 +24,12 @@
#include "IntRect.h"
#include "PopupMenu.h"
#include "PopupMenuClient.h"
-#include <glib.h>
#include <wtf/HashMap.h>
#include <wtf/PassRefPtr.h>
#include <wtf/RefCounted.h>
+typedef struct _GdkEventKey GdkEventKey;
+
namespace WebCore {
class FrameView;
@@ -43,19 +44,27 @@ public:
virtual void hide();
virtual void updateFromElement();
virtual void disconnectClient();
+ bool typeAheadFind(GdkEventKey*);
private:
PopupMenuClient* client() const { return m_popupClient; }
+ void resetTypeAheadFindState();
static void menuItemActivated(GtkMenuItem* item, PopupMenuGtk*);
static void menuUnmapped(GtkWidget*, PopupMenuGtk*);
static void menuPositionFunction(GtkMenu*, gint*, gint*, gboolean*, PopupMenuGtk*);
static void menuRemoveItem(GtkWidget*, PopupMenuGtk*);
+ static int selectItemCallback(GtkMenuItem*, PopupMenuGtk*);
+ static int keyPressEventCallback(GtkWidget*, GdkEventKey*, PopupMenuGtk*);
PopupMenuClient* m_popupClient;
IntPoint m_menuPosition;
PlatformRefPtr<GtkMenu> m_popup;
HashMap<GtkWidget*, int> m_indexMap;
+ String m_currentSearchString;
+ uint32_t m_previousKeyEventTimestamp;
+ unsigned int m_previousKeyEventCharacter;
+ GtkWidget* m_currentlySelectedMenuItem;
};
}
diff --git a/WebCore/platform/gtk/RenderThemeGtk.cpp b/WebCore/platform/gtk/RenderThemeGtk.cpp
index fe6c9e9..73b2d6b 100644
--- a/WebCore/platform/gtk/RenderThemeGtk.cpp
+++ b/WebCore/platform/gtk/RenderThemeGtk.cpp
@@ -55,6 +55,19 @@ namespace WebCore {
using namespace HTMLNames;
+static void paintStockIcon(GraphicsContext* context, const IntPoint& iconPoint, GtkStyle* style, const char* iconName,
+ GtkTextDirection direction, GtkStateType state, GtkIconSize iconSize)
+{
+ GtkIconSet* iconSet = gtk_style_lookup_icon_set(style, iconName);
+ PlatformRefPtr<GdkPixbuf> icon = adoptPlatformRef(gtk_icon_set_render_icon(iconSet, style, direction, state, iconSize, 0, 0));
+
+ cairo_t* cr = context->platformContext();
+ cairo_save(cr);
+ gdk_cairo_set_source_pixbuf(cr, icon.get(), iconPoint.x(), iconPoint.y());
+ cairo_paint(cr);
+ cairo_restore(cr);
+}
+
#if ENABLE(VIDEO)
static HTMLMediaElement* getMediaElementFromRenderObject(RenderObject* o)
{
@@ -66,57 +79,46 @@ static HTMLMediaElement* getMediaElementFromRenderObject(RenderObject* o)
return static_cast<HTMLMediaElement*>(mediaNode);
}
-static gchar* getIconNameForTextDirection(const char* baseName)
+static GtkIconSize getMediaButtonIconSize(int mediaIconSize)
{
- GString* nameWithDirection = g_string_new(baseName);
- GtkTextDirection textDirection = gtk_widget_get_default_direction();
-
- if (textDirection == GTK_TEXT_DIR_RTL)
- g_string_append(nameWithDirection, "-rtl");
- else if (textDirection == GTK_TEXT_DIR_LTR)
- g_string_append(nameWithDirection, "-ltr");
-
- return g_string_free(nameWithDirection, FALSE);
+ GtkIconSize iconSize = gtk_icon_size_from_name("webkit-media-button-size");
+ if (!iconSize)
+ iconSize = gtk_icon_size_register("webkit-media-button-size", mediaIconSize, mediaIconSize);
+ return iconSize;
}
-void RenderThemeGtk::initMediaStyling(GtkStyle* style, bool force)
+void RenderThemeGtk::initMediaColors()
{
- static bool stylingInitialized = false;
+ GtkStyle* style = gtk_widget_get_style(GTK_WIDGET(gtkContainer()));
+ m_panelColor = style->bg[GTK_STATE_NORMAL];
+ m_sliderColor = style->bg[GTK_STATE_ACTIVE];
+ m_sliderThumbColor = style->bg[GTK_STATE_SELECTED];
+}
- if (!stylingInitialized || force) {
- m_panelColor = style->bg[GTK_STATE_NORMAL];
- m_sliderColor = style->bg[GTK_STATE_ACTIVE];
- m_sliderThumbColor = style->bg[GTK_STATE_SELECTED];
+void RenderThemeGtk::initMediaButtons()
+{
+ static bool iconsInitialized = false;
- // Names of these icons can vary because of text direction.
- gchar* playButtonIconName = getIconNameForTextDirection("gtk-media-play");
- gchar* seekBackButtonIconName = getIconNameForTextDirection("gtk-media-rewind");
- gchar* seekForwardButtonIconName = getIconNameForTextDirection("gtk-media-forward");
+ if (iconsInitialized)
+ return;
- m_fullscreenButton.clear();
- m_muteButton.clear();
- m_unmuteButton.clear();
- m_playButton.clear();
- m_pauseButton.clear();
- m_seekBackButton.clear();
- m_seekForwardButton.clear();
+ PlatformRefPtr<GtkIconFactory> iconFactory = adoptPlatformRef(gtk_icon_factory_new());
+ GtkIconSource* iconSource = gtk_icon_source_new();
+ const char* icons[] = { "audio-volume-high", "audio-volume-muted" };
- m_fullscreenButton = Image::loadPlatformThemeIcon("gtk-fullscreen", m_mediaIconSize);
- // Note that the muteButton and unmuteButton take icons reflecting
- // the *current* state. Hence, the unmuteButton represents the *muted*
- // status, the muteButton represents the then current *unmuted* status.
- m_muteButton = Image::loadPlatformThemeIcon("audio-volume-high", m_mediaIconSize);
- m_unmuteButton = Image::loadPlatformThemeIcon("audio-volume-muted", m_mediaIconSize);
- m_playButton = Image::loadPlatformThemeIcon(reinterpret_cast<const char*>(playButtonIconName), m_mediaIconSize);
- m_pauseButton = Image::loadPlatformThemeIcon("gtk-media-pause", m_mediaIconSize);
- m_seekBackButton = Image::loadPlatformThemeIcon(reinterpret_cast<const char*>(seekBackButtonIconName), m_mediaIconSize);
- m_seekForwardButton = Image::loadPlatformThemeIcon(reinterpret_cast<const char*>(seekForwardButtonIconName), m_mediaIconSize);
+ gtk_icon_factory_add_default(iconFactory.get());
- g_free(playButtonIconName);
- g_free(seekBackButtonIconName);
- g_free(seekForwardButtonIconName);
- stylingInitialized = true;
+ for (size_t i = 0; i < G_N_ELEMENTS(icons); ++i) {
+ gtk_icon_source_set_icon_name(iconSource, icons[i]);
+ GtkIconSet* iconSet = gtk_icon_set_new();
+ gtk_icon_set_add_source(iconSet, iconSource);
+ gtk_icon_factory_add(iconFactory.get(), icons[i], iconSet);
+ gtk_icon_set_unref(iconSet);
}
+
+ gtk_icon_source_free(iconSource);
+
+ iconsInitialized = true;
}
#endif
@@ -146,13 +148,6 @@ RenderThemeGtk::RenderThemeGtk()
, m_mediaSliderHeight(14)
, m_mediaSliderThumbWidth(12)
, m_mediaSliderThumbHeight(12)
- , m_fullscreenButton(0)
- , m_muteButton(0)
- , m_unmuteButton(0)
- , m_playButton(0)
- , m_pauseButton(0)
- , m_seekBackButton(0)
- , m_seekForwardButton(0)
#ifdef GTK_API_VERSION_2
, m_themePartsHaveRGBAColormap(true)
#endif
@@ -176,7 +171,8 @@ RenderThemeGtk::RenderThemeGtk()
++mozGtkRefCount;
#if ENABLE(VIDEO)
- initMediaStyling(gtk_rc_get_style(GTK_WIDGET(gtkContainer())), false);
+ initMediaColors();
+ initMediaButtons();
#endif
}
@@ -187,14 +183,6 @@ RenderThemeGtk::~RenderThemeGtk()
if (!mozGtkRefCount)
moz_gtk_shutdown();
- m_fullscreenButton.clear();
- m_muteButton.clear();
- m_unmuteButton.clear();
- m_playButton.clear();
- m_pauseButton.clear();
- m_seekBackButton.clear();
- m_seekForwardButton.clear();
-
gtk_widget_destroy(m_gtkWindow);
}
@@ -229,6 +217,17 @@ static bool supportsFocus(ControlPart appearance)
}
}
+GtkStateType RenderThemeGtk::getGtkStateType(RenderObject* object)
+{
+ if (!isEnabled(object) || isReadOnlyControl(object))
+ return GTK_STATE_INSENSITIVE;
+ if (isPressed(object))
+ return GTK_STATE_ACTIVE;
+ if (isHovered(object))
+ return GTK_STATE_PRELIGHT;
+ return GTK_STATE_NORMAL;
+}
+
bool RenderThemeGtk::supportsFocusRing(const RenderStyle* style) const
{
return supportsFocus(style->appearance());
@@ -266,23 +265,16 @@ static GtkTextDirection gtkTextDirection(TextDirection direction)
}
}
-static void adjustMozillaStyle(const RenderThemeGtk* theme, RenderStyle* style, GtkThemeWidgetType type)
+GtkStateType RenderThemeGtk::gtkIconState(RenderObject* renderObject)
{
- gint left, top, right, bottom;
- GtkTextDirection direction = gtkTextDirection(style->direction());
- gboolean inhtml = true;
-
- if (moz_gtk_get_widget_border(type, &left, &top, &right, &bottom, direction, inhtml) != MOZ_GTK_SUCCESS)
- return;
+ if (!isEnabled(renderObject))
+ return GTK_STATE_INSENSITIVE;
+ if (isPressed(renderObject))
+ return GTK_STATE_ACTIVE;
+ if (isHovered(renderObject))
+ return GTK_STATE_PRELIGHT;
- // FIXME: This approach is likely to be incorrect. See other ports and layout tests to see the problem.
- const int xpadding = 1;
- const int ypadding = 1;
-
- style->setPaddingLeft(Length(xpadding + left, Fixed));
- style->setPaddingTop(Length(ypadding + top, Fixed));
- style->setPaddingRight(Length(xpadding + right, Fixed));
- style->setPaddingBottom(Length(ypadding + bottom, Fixed));
+ return GTK_STATE_NORMAL;
}
bool RenderThemeGtk::paintRenderObject(GtkThemeWidgetType type, RenderObject* renderObject, GraphicsContext* context, const IntRect& rect, int flags)
@@ -306,14 +298,7 @@ bool RenderThemeGtk::paintRenderObject(GtkThemeWidgetType type, RenderObject* re
widgetState.disabled = !isEnabled(renderObject) || isReadOnlyControl(renderObject);
widgetState.isDefault = false;
widgetState.canDefault = false;
-
- // FIXME: The depressed value should probably apply for other theme parts too.
- // It must be used for range thumbs, because otherwise when the thumb is pressed,
- // the rendering is incorrect.
- if (type == MOZ_GTK_SCALE_THUMB_HORIZONTAL || type == MOZ_GTK_SCALE_THUMB_VERTICAL)
- widgetState.depressed = isPressed(renderObject);
- else
- widgetState.depressed = false;
+ widgetState.depressed = false;
WidgetRenderingContext widgetContext(context, rect);
return !widgetContext.paintMozillaWidget(type, &widgetState, flags, gtkTextDirection(renderObject->style()->direction()));
@@ -366,9 +351,56 @@ void RenderThemeGtk::adjustButtonStyle(CSSStyleSelector* selector, RenderStyle*
style->setLineHeight(RenderStyle::initialLineHeight());
}
-bool RenderThemeGtk::paintButton(RenderObject* o, const PaintInfo& i, const IntRect& rect)
+bool RenderThemeGtk::paintButton(RenderObject* object, const PaintInfo& info, const IntRect& rect)
{
- return paintRenderObject(MOZ_GTK_BUTTON, o, i.context, rect, GTK_RELIEF_NORMAL);
+ if (info.context->paintingDisabled())
+ return false;
+
+ GtkWidget* widget = gtkButton();
+ IntRect buttonRect(IntPoint(), rect.size());
+ IntRect focusRect(buttonRect);
+
+ GtkStateType state = getGtkStateType(object);
+ gtk_widget_set_state(widget, state);
+ gtk_widget_set_direction(widget, gtkTextDirection(object->style()->direction()));
+
+ if (isFocused(object)) {
+ if (isEnabled(object)) {
+#if !GTK_CHECK_VERSION(2, 22, 0)
+ GTK_WIDGET_SET_FLAGS(widget, GTK_HAS_FOCUS);
+#endif
+ g_object_set(widget, "has-focus", TRUE, NULL);
+ }
+
+ gboolean interiorFocus = 0, focusWidth = 0, focusPadding = 0;
+ gtk_widget_style_get(widget,
+ "interior-focus", &interiorFocus,
+ "focus-line-width", &focusWidth,
+ "focus-padding", &focusPadding, NULL);
+ // If we are using exterior focus, we shrink the button rect down before
+ // drawing. If we are using interior focus we shrink the focus rect. This
+ // approach originates from the Mozilla theme drawing code (gtk2drawing.c).
+ if (interiorFocus) {
+ GtkStyle* style = gtk_widget_get_style(widget);
+ focusRect.inflateX(-style->xthickness - focusPadding);
+ focusRect.inflateY(-style->ythickness - focusPadding);
+ } else {
+ buttonRect.inflateX(-focusWidth - focusPadding);
+ buttonRect.inflateY(-focusPadding - focusPadding);
+ }
+ }
+
+ WidgetRenderingContext widgetContext(info.context, rect);
+ GtkShadowType shadowType = state == GTK_STATE_ACTIVE ? GTK_SHADOW_IN : GTK_SHADOW_OUT;
+ widgetContext.gtkPaintBox(buttonRect, widget, state, shadowType, "button");
+ if (isFocused(object))
+ widgetContext.gtkPaintFocus(focusRect, widget, state, "button");
+
+#if !GTK_CHECK_VERSION(2, 22, 0)
+ GTK_WIDGET_UNSET_FLAGS(widget, GTK_HAS_FOCUS);
+#endif
+ g_object_set(widget, "has-focus", FALSE, NULL);
+ return false;
}
static void getComboBoxPadding(RenderStyle* style, int& left, int& top, int& right, int& bottom)
@@ -433,13 +465,27 @@ bool RenderThemeGtk::paintMenuListButton(RenderObject* object, const PaintInfo&
return paintMenuList(object, info, rect);
}
+static void setTextInputBorders(RenderStyle* style)
+{
+ // If this control isn't drawn using the native theme, we don't touch the borders.
+ if (style->appearance() == NoControlPart)
+ return;
+
+ // We cannot give a proper rendering when border radius is active, unfortunately.
+ style->resetBorderRadius();
+
+ int left = 0, top = 0, right = 0, bottom = 0;
+ moz_gtk_get_widget_border(MOZ_GTK_ENTRY, &left, &top, &right, &bottom,
+ gtkTextDirection(style->direction()), TRUE);
+ style->setBorderLeftWidth(left);
+ style->setBorderTopWidth(top);
+ style->setBorderRightWidth(right);
+ style->setBorderBottomWidth(bottom);
+}
+
void RenderThemeGtk::adjustTextFieldStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
{
- style->resetBorder();
- style->resetPadding();
- style->setHeight(Length(Auto));
- style->setWhiteSpace(PRE);
- adjustMozillaStyle(this, style, MOZ_GTK_ENTRY);
+ setTextInputBorders(style);
}
bool RenderThemeGtk::paintTextField(RenderObject* o, const PaintInfo& i, const IntRect& rect)
@@ -447,6 +493,11 @@ bool RenderThemeGtk::paintTextField(RenderObject* o, const PaintInfo& i, const I
return paintRenderObject(MOZ_GTK_ENTRY, o, i.context, rect);
}
+void RenderThemeGtk::adjustTextAreaStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+ setTextInputBorders(style);
+}
+
bool RenderThemeGtk::paintTextArea(RenderObject* o, const PaintInfo& i, const IntRect& r)
{
return paintTextField(o, i, r);
@@ -467,32 +518,33 @@ void RenderThemeGtk::adjustSearchFieldResultsDecorationStyle(CSSStyleSelector* s
style->resetBorder();
style->resetPadding();
- // FIXME: This should not be hard-coded.
- IntSize size = IntSize(14, 14);
- style->setWidth(Length(size.width(), Fixed));
- style->setHeight(Length(size.height(), Fixed));
+ gint width = 0, height = 0;
+ gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &width, &height);
+ style->setWidth(Length(width, Fixed));
+ style->setHeight(Length(height, Fixed));
}
-static IntRect centerRectVerticallyInParentInputElement(RenderObject* object, const IntRect& rect)
+static IntPoint centerRectVerticallyInParentInputElement(RenderObject* object, const IntRect& rect)
{
- IntRect centeredRect(rect);
Node* input = object->node()->shadowAncestorNode(); // Get the renderer of <input> element.
- if (!input->renderer()->isBox())
- return centeredRect;
+ if (!input->renderer()->isBox())
+ return rect.topLeft();
// If possible center the y-coordinate of the rect vertically in the parent input element.
// We also add one pixel here to ensure that the y coordinate is rounded up for box heights
// that are even, which looks in relation to the box text.
IntRect inputContentBox = toRenderBox(input->renderer())->absoluteContentBox();
- centeredRect.setY(inputContentBox.y() + (inputContentBox.height() - centeredRect.height() + 1) / 2);
- return centeredRect;
+
+ return IntPoint(rect.x(), inputContentBox.y() + (inputContentBox.height() - rect.height() + 1) / 2);
}
-bool RenderThemeGtk::paintSearchFieldResultsDecoration(RenderObject* object, const PaintInfo& i, const IntRect& rect)
+bool RenderThemeGtk::paintSearchFieldResultsDecoration(RenderObject* renderObject, const PaintInfo& paintInfo, const IntRect& rect)
{
- static Image* searchImage = Image::loadPlatformThemeIcon(GTK_STOCK_FIND, rect.width()).releaseRef();
- IntRect centeredRect(centerRectVerticallyInParentInputElement(object, rect));
- i.context->drawImage(searchImage, ColorSpaceDeviceRGB, centeredRect);
+ GtkStyle* style = gtk_widget_get_style(GTK_WIDGET(gtkEntry()));
+ IntPoint iconPoint(centerRectVerticallyInParentInputElement(renderObject, rect));
+ paintStockIcon(paintInfo.context, iconPoint, style, GTK_STOCK_FIND,
+ gtkTextDirection(renderObject->style()->direction()),
+ gtkIconState(renderObject), GTK_ICON_SIZE_MENU);
return false;
}
@@ -501,24 +553,26 @@ void RenderThemeGtk::adjustSearchFieldCancelButtonStyle(CSSStyleSelector* select
style->resetBorder();
style->resetPadding();
- // FIXME: This should not be hard-coded.
- IntSize size = IntSize(14, 14);
- style->setWidth(Length(size.width(), Fixed));
- style->setHeight(Length(size.height(), Fixed));
+ gint width = 0, height = 0;
+ gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &width, &height);
+ style->setWidth(Length(width, Fixed));
+ style->setHeight(Length(height, Fixed));
}
-bool RenderThemeGtk::paintSearchFieldCancelButton(RenderObject* object, const PaintInfo& i, const IntRect& rect)
+bool RenderThemeGtk::paintSearchFieldCancelButton(RenderObject* renderObject, const PaintInfo& paintInfo, const IntRect& rect)
{
- // TODO: Brightening up the image on hover is desirable here, I believe.
- static Image* cancelImage = Image::loadPlatformThemeIcon(GTK_STOCK_CLEAR, rect.width()).releaseRef();
- IntRect centeredRect(centerRectVerticallyInParentInputElement(object, rect));
- i.context->drawImage(cancelImage, ColorSpaceDeviceRGB, centeredRect);
+ GtkStyle* style = gtk_widget_get_style(GTK_WIDGET(gtkEntry()));
+ IntPoint iconPoint(centerRectVerticallyInParentInputElement(renderObject, rect));
+ paintStockIcon(paintInfo.context, iconPoint, style, GTK_STOCK_CLEAR,
+ gtkTextDirection(renderObject->style()->direction()),
+ gtkIconState(renderObject), GTK_ICON_SIZE_MENU);
return false;
}
void RenderThemeGtk::adjustSearchFieldStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
{
- adjustTextFieldStyle(selector, style, e);
+ style->setLineHeight(RenderStyle::initialLineHeight());
+ setTextInputBorders(style);
}
bool RenderThemeGtk::paintSearchField(RenderObject* o, const PaintInfo& i, const IntRect& rect)
@@ -528,14 +582,30 @@ bool RenderThemeGtk::paintSearchField(RenderObject* o, const PaintInfo& i, const
bool RenderThemeGtk::paintSliderTrack(RenderObject* object, const PaintInfo& info, const IntRect& rect)
{
+ if (info.context->paintingDisabled())
+ return false;
+
ControlPart part = object->style()->appearance();
ASSERT(part == SliderHorizontalPart || part == SliderVerticalPart);
- GtkThemeWidgetType gtkPart = MOZ_GTK_SCALE_HORIZONTAL;
- if (part == SliderVerticalPart)
- gtkPart = MOZ_GTK_SCALE_VERTICAL;
+ // We shrink the trough rect slightly to make room for the focus indicator.
+ IntRect troughRect(IntPoint(), rect.size()); // This is relative to rect.
+ GtkWidget* widget = 0;
+ if (part == SliderVerticalPart) {
+ widget = gtkVScale();
+ troughRect.inflateY(-gtk_widget_get_style(widget)->ythickness);
+ } else {
+ widget = gtkHScale();
+ troughRect.inflateX(-gtk_widget_get_style(widget)->xthickness);
+ }
+ gtk_widget_set_direction(widget, gtkTextDirection(object->style()->direction()));
+
+ WidgetRenderingContext widgetContext(info.context, rect);
+ widgetContext.gtkPaintBox(troughRect, widget, GTK_STATE_ACTIVE, GTK_SHADOW_OUT, "trough");
+ if (isFocused(object))
+ widgetContext.gtkPaintFocus(IntRect(IntPoint(), rect.size()), widget, getGtkStateType(object), "trough");
- return paintRenderObject(gtkPart, object, info.context, rect);
+ return false;
}
void RenderThemeGtk::adjustSliderTrackStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
@@ -545,14 +615,34 @@ void RenderThemeGtk::adjustSliderTrackStyle(CSSStyleSelector*, RenderStyle* styl
bool RenderThemeGtk::paintSliderThumb(RenderObject* object, const PaintInfo& info, const IntRect& rect)
{
+ if (info.context->paintingDisabled())
+ return false;
+
ControlPart part = object->style()->appearance();
ASSERT(part == SliderThumbHorizontalPart || part == SliderThumbVerticalPart);
- GtkThemeWidgetType gtkPart = MOZ_GTK_SCALE_THUMB_HORIZONTAL;
- if (part == SliderThumbVerticalPart)
- gtkPart = MOZ_GTK_SCALE_THUMB_VERTICAL;
-
- return paintRenderObject(gtkPart, object, info.context, rect);
+ GtkWidget* widget = 0;
+ const char* detail = 0;
+ GtkOrientation orientation;
+ if (part == SliderThumbVerticalPart) {
+ widget = gtkVScale();
+ detail = "vscale";
+ orientation = GTK_ORIENTATION_VERTICAL;
+ } else {
+ widget = gtkHScale();
+ detail = "hscale";
+ orientation = GTK_ORIENTATION_HORIZONTAL;
+ }
+ gtk_widget_set_direction(widget, gtkTextDirection(object->style()->direction()));
+
+ // Only some themes have slider thumbs respond to clicks and some don't. This information is
+ // gathered via the 'activate-slider' property, but it's deprecated in GTK+ 2.22 and removed in
+ // GTK+ 3.x. The drawback of not honoring it is that slider thumbs change color when you click
+ // on them.
+ IntRect thumbRect(IntPoint(), rect.size());
+ WidgetRenderingContext widgetContext(info.context, rect);
+ widgetContext.gtkPaintSlider(thumbRect, widget, getGtkStateType(object), GTK_SHADOW_OUT, detail, orientation);
+ return false;
}
void RenderThemeGtk::adjustSliderThumbStyle(CSSStyleSelector*, RenderStyle* style, Element*) const
@@ -567,14 +657,27 @@ void RenderThemeGtk::adjustSliderThumbSize(RenderObject* o) const
if (part == MediaSliderThumbPart) {
o->style()->setWidth(Length(m_mediaSliderThumbWidth, Fixed));
o->style()->setHeight(Length(m_mediaSliderThumbHeight, Fixed));
- } else
+ return;
+ }
+ if (part == MediaVolumeSliderThumbPart)
+ return;
#endif
- if (part == SliderThumbHorizontalPart || part == SliderThumbVerticalPart) {
- gint width, height;
- moz_gtk_get_scalethumb_metrics(part == SliderThumbHorizontalPart ? GTK_ORIENTATION_HORIZONTAL : GTK_ORIENTATION_VERTICAL, &width, &height);
- o->style()->setWidth(Length(width, Fixed));
- o->style()->setHeight(Length(height, Fixed));
+
+ GtkWidget* widget = part == SliderThumbHorizontalPart ? gtkHScale() : gtkVScale();
+ int length = 0, width = 0;
+ gtk_widget_style_get(widget,
+ "slider_length", &length,
+ "slider_width", &width,
+ NULL);
+
+ if (part == SliderThumbHorizontalPart) {
+ o->style()->setWidth(Length(length, Fixed));
+ o->style()->setHeight(Length(width, Fixed));
+ return;
}
+ ASSERT(part == SliderThumbVerticalPart);
+ o->style()->setWidth(Length(width, Fixed));
+ o->style()->setHeight(Length(length, Fixed));
}
Color RenderThemeGtk::platformActiveSelectionBackgroundColor() const
@@ -700,17 +803,30 @@ static void gtkStyleSetCallback(GtkWidget* widget, GtkStyle* previous, RenderThe
renderTheme->platformColorsDidChange();
}
-GtkContainer* RenderThemeGtk::gtkContainer() const
+void RenderThemeGtk::setupWidgetAndAddToContainer(GtkWidget* widget, GtkWidget* window) const
+{
+ gtk_container_add(GTK_CONTAINER(window), widget);
+ gtk_widget_realize(widget);
+ g_object_set_data(G_OBJECT(widget), "transparent-bg-hint", GINT_TO_POINTER(TRUE));
+
+ // FIXME: Perhaps this should only be called for the containing window or parent container.
+ g_signal_connect(widget, "style-set", G_CALLBACK(gtkStyleSetCallback), const_cast<RenderThemeGtk*>(this));
+}
+
+GtkWidget* RenderThemeGtk::gtkContainer() const
{
if (m_gtkContainer)
return m_gtkContainer;
m_gtkWindow = gtk_window_new(GTK_WINDOW_POPUP);
- m_gtkContainer = GTK_CONTAINER(gtk_fixed_new());
- g_signal_connect(m_gtkWindow, "style-set", G_CALLBACK(gtkStyleSetCallback), const_cast<RenderThemeGtk*>(this));
- gtk_container_add(GTK_CONTAINER(m_gtkWindow), GTK_WIDGET(m_gtkContainer));
+#ifdef GTK_API_VERSION_2
+ gtk_widget_set_colormap(m_gtkWindow, m_themeParts.colormap);
+#endif
gtk_widget_realize(m_gtkWindow);
+ gtk_widget_set_name(m_gtkWindow, "MozillaGtkWidget");
+ m_gtkContainer = gtk_fixed_new();
+ setupWidgetAndAddToContainer(m_gtkContainer, m_gtkWindow);
return m_gtkContainer;
}
@@ -718,12 +834,8 @@ GtkWidget* RenderThemeGtk::gtkButton() const
{
if (m_gtkButton)
return m_gtkButton;
-
m_gtkButton = gtk_button_new();
- g_signal_connect(m_gtkButton, "style-set", G_CALLBACK(gtkStyleSetCallback), const_cast<RenderThemeGtk*>(this));
- gtk_container_add(gtkContainer(), m_gtkButton);
- gtk_widget_realize(m_gtkButton);
-
+ setupWidgetAndAddToContainer(m_gtkButton, gtkContainer());
return m_gtkButton;
}
@@ -731,12 +843,8 @@ GtkWidget* RenderThemeGtk::gtkEntry() const
{
if (m_gtkEntry)
return m_gtkEntry;
-
m_gtkEntry = gtk_entry_new();
- g_signal_connect(m_gtkEntry, "style-set", G_CALLBACK(gtkStyleSetCallback), const_cast<RenderThemeGtk*>(this));
- gtk_container_add(gtkContainer(), m_gtkEntry);
- gtk_widget_realize(m_gtkEntry);
-
+ setupWidgetAndAddToContainer(m_gtkEntry, gtkContainer());
return m_gtkEntry;
}
@@ -744,15 +852,29 @@ GtkWidget* RenderThemeGtk::gtkTreeView() const
{
if (m_gtkTreeView)
return m_gtkTreeView;
-
m_gtkTreeView = gtk_tree_view_new();
- g_signal_connect(m_gtkTreeView, "style-set", G_CALLBACK(gtkStyleSetCallback), const_cast<RenderThemeGtk*>(this));
- gtk_container_add(gtkContainer(), m_gtkTreeView);
- gtk_widget_realize(m_gtkTreeView);
-
+ setupWidgetAndAddToContainer(m_gtkTreeView, gtkContainer());
return m_gtkTreeView;
}
+GtkWidget* RenderThemeGtk::gtkVScale() const
+{
+ if (m_gtkVScale)
+ return m_gtkVScale;
+ m_gtkVScale = gtk_vscale_new(0);
+ setupWidgetAndAddToContainer(m_gtkVScale, gtkContainer());
+ return m_gtkVScale;
+}
+
+GtkWidget* RenderThemeGtk::gtkHScale() const
+{
+ if (m_gtkHScale)
+ return m_gtkHScale;
+ m_gtkHScale = gtk_hscale_new(0);
+ setupWidgetAndAddToContainer(m_gtkHScale, gtkContainer());
+ return m_gtkHScale;
+}
+
GtkWidget* RenderThemeGtk::gtkScrollbar()
{
return moz_gtk_get_scrollbar_widget();
@@ -761,7 +883,7 @@ GtkWidget* RenderThemeGtk::gtkScrollbar()
void RenderThemeGtk::platformColorsDidChange()
{
#if ENABLE(VIDEO)
- initMediaStyling(gtk_rc_get_style(GTK_WIDGET(gtkContainer())), true);
+ initMediaColors();
#endif
RenderTheme::platformColorsDidChange();
}
@@ -772,49 +894,50 @@ String RenderThemeGtk::extraMediaControlsStyleSheet()
return String(mediaControlsGtkUserAgentStyleSheet, sizeof(mediaControlsGtkUserAgentStyleSheet));
}
-static inline bool paintMediaButton(GraphicsContext* context, const IntRect& r, Image* image, Color panelColor, int mediaIconSize)
+bool RenderThemeGtk::paintMediaButton(RenderObject* renderObject, GraphicsContext* context, const IntRect& rect, const char* iconName)
{
- context->fillRect(FloatRect(r), panelColor, ColorSpaceDeviceRGB);
- context->drawImage(image, ColorSpaceDeviceRGB,
- IntRect(r.x() + (r.width() - mediaIconSize) / 2,
- r.y() + (r.height() - mediaIconSize) / 2,
- mediaIconSize, mediaIconSize));
+ GtkStyle* style = gtk_widget_get_style(GTK_WIDGET(gtkContainer()));
+ IntPoint iconPoint(rect.x() + (rect.width() - m_mediaIconSize) / 2,
+ rect.y() + (rect.height() - m_mediaIconSize) / 2);
+ context->fillRect(FloatRect(rect), m_panelColor, ColorSpaceDeviceRGB);
+ paintStockIcon(context, iconPoint, style, iconName, gtkTextDirection(renderObject->style()->direction()),
+ gtkIconState(renderObject), getMediaButtonIconSize(m_mediaIconSize));
return false;
}
-bool RenderThemeGtk::paintMediaFullscreenButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
+bool RenderThemeGtk::paintMediaFullscreenButton(RenderObject* renderObject, const PaintInfo& paintInfo, const IntRect& rect)
{
- return paintMediaButton(paintInfo.context, r, m_fullscreenButton.get(), m_panelColor, m_mediaIconSize);
+ return paintMediaButton(renderObject, paintInfo.context, rect, GTK_STOCK_FULLSCREEN);
}
-bool RenderThemeGtk::paintMediaMuteButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
+bool RenderThemeGtk::paintMediaMuteButton(RenderObject* renderObject, const PaintInfo& paintInfo, const IntRect& rect)
{
- HTMLMediaElement* mediaElement = getMediaElementFromRenderObject(o);
+ HTMLMediaElement* mediaElement = getMediaElementFromRenderObject(renderObject);
if (!mediaElement)
return false;
- return paintMediaButton(paintInfo.context, r, mediaElement->muted() ? m_unmuteButton.get() : m_muteButton.get(), m_panelColor, m_mediaIconSize);
+ return paintMediaButton(renderObject, paintInfo.context, rect, mediaElement->muted() ? "audio-volume-muted" : "audio-volume-high");
}
-bool RenderThemeGtk::paintMediaPlayButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
+bool RenderThemeGtk::paintMediaPlayButton(RenderObject* renderObject, const PaintInfo& paintInfo, const IntRect& rect)
{
- Node* node = o->node();
+ Node* node = renderObject->node();
if (!node)
return false;
MediaControlPlayButtonElement* button = static_cast<MediaControlPlayButtonElement*>(node);
- return paintMediaButton(paintInfo.context, r, button->displayType() == MediaPlayButton ? m_playButton.get() : m_pauseButton.get(), m_panelColor, m_mediaIconSize);
+ return paintMediaButton(renderObject, paintInfo.context, rect, button->displayType() == MediaPlayButton ? GTK_STOCK_MEDIA_PLAY : GTK_STOCK_MEDIA_PAUSE);
}
-bool RenderThemeGtk::paintMediaSeekBackButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
+bool RenderThemeGtk::paintMediaSeekBackButton(RenderObject* renderObject, const PaintInfo& paintInfo, const IntRect& rect)
{
- return paintMediaButton(paintInfo.context, r, m_seekBackButton.get(), m_panelColor, m_mediaIconSize);
+ return paintMediaButton(renderObject, paintInfo.context, rect, GTK_STOCK_MEDIA_REWIND);
}
-bool RenderThemeGtk::paintMediaSeekForwardButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
+bool RenderThemeGtk::paintMediaSeekForwardButton(RenderObject* renderObject, const PaintInfo& paintInfo, const IntRect& rect)
{
- return paintMediaButton(paintInfo.context, r, m_seekForwardButton.get(), m_panelColor, m_mediaIconSize);
+ return paintMediaButton(renderObject, paintInfo.context, rect, GTK_STOCK_MEDIA_FORWARD);
}
bool RenderThemeGtk::paintMediaSliderTrack(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
@@ -852,7 +975,7 @@ bool RenderThemeGtk::paintMediaSliderTrack(RenderObject* o, const PaintInfo& pai
rangeRect = trackRect;
rangeRect.setWidth(width);
} else {
- rangeRect.setLocation(IntPoint((start * totalWidth) / mediaDuration, trackRect.y()));
+ rangeRect.setLocation(IntPoint(trackRect.x() + start / mediaDuration* totalWidth, trackRect.y()));
rangeRect.setSize(IntSize(width, trackRect.height()));
}
diff --git a/WebCore/platform/gtk/RenderThemeGtk.h b/WebCore/platform/gtk/RenderThemeGtk.h
index ac08cf1..d377c45 100644
--- a/WebCore/platform/gtk/RenderThemeGtk.h
+++ b/WebCore/platform/gtk/RenderThemeGtk.h
@@ -100,6 +100,7 @@ protected:
virtual void adjustTextFieldStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
virtual bool paintTextField(RenderObject*, const PaintInfo&, const IntRect&);
+ void adjustTextAreaStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
virtual bool paintTextArea(RenderObject*, const PaintInfo&, const IntRect&);
int popupInternalPaddingLeft(RenderStyle*) const;
@@ -137,7 +138,8 @@ protected:
virtual void adjustSliderThumbSize(RenderObject* object) const;
#if ENABLE(VIDEO)
- virtual void initMediaStyling(GtkStyle* style, bool force);
+ void initMediaColors();
+ void initMediaButtons();
virtual bool paintMediaFullscreenButton(RenderObject*, const PaintInfo&, const IntRect&);
virtual bool paintMediaPlayButton(RenderObject*, const PaintInfo&, const IntRect&);
virtual bool paintMediaMuteButton(RenderObject*, const PaintInfo&, const IntRect&);
@@ -155,26 +157,28 @@ protected:
#endif
private:
- /*
- * hold the state
- */
GtkWidget* gtkButton() const;
GtkWidget* gtkEntry() const;
GtkWidget* gtkTreeView() const;
+ GtkWidget* gtkVScale() const;
+ GtkWidget* gtkHScale() const;
+ GtkWidget* gtkContainer() const;
- /*
- * unmapped GdkWindow having a container. This is holding all
- * our fake widgets
- */
- GtkContainer* gtkContainer() const;
-
+ void setupWidgetAndAddToContainer(GtkWidget*, GtkWidget*) const;
+ GtkStateType getGtkStateType(RenderObject* object);
bool paintRenderObject(GtkThemeWidgetType, RenderObject*, GraphicsContext*, const IntRect& rect, int flags = 0);
+#if ENABLE(VIDEO)
+ bool paintMediaButton(RenderObject*, GraphicsContext*, const IntRect&, const char* iconName);
+#endif
+ GtkStateType gtkIconState(RenderObject*);
mutable GtkWidget* m_gtkWindow;
- mutable GtkContainer* m_gtkContainer;
+ mutable GtkWidget* m_gtkContainer;
mutable GtkWidget* m_gtkButton;
mutable GtkWidget* m_gtkEntry;
mutable GtkWidget* m_gtkTreeView;
+ mutable GtkWidget* m_gtkVScale;
+ mutable GtkWidget* m_gtkHScale;
mutable Color m_panelColor;
mutable Color m_sliderColor;
@@ -185,13 +189,6 @@ private:
const int m_mediaSliderThumbWidth;
const int m_mediaSliderThumbHeight;
- RefPtr<Image> m_fullscreenButton;
- RefPtr<Image> m_muteButton;
- RefPtr<Image> m_unmuteButton;
- RefPtr<Image> m_playButton;
- RefPtr<Image> m_pauseButton;
- RefPtr<Image> m_seekBackButton;
- RefPtr<Image> m_seekForwardButton;
GtkThemeParts m_themeParts;
#ifdef GTK_API_VERSION_2
bool m_themePartsHaveRGBAColormap;
diff --git a/WebCore/platform/gtk/WidgetGtk.cpp b/WebCore/platform/gtk/WidgetGtk.cpp
index db316d5..ee1005c 100644
--- a/WebCore/platform/gtk/WidgetGtk.cpp
+++ b/WebCore/platform/gtk/WidgetGtk.cpp
@@ -60,7 +60,7 @@ void Widget::setFocus(bool focused)
gtk_widget_grab_focus(platformWidget() ? platformWidget() : GTK_WIDGET(root()->hostWindow()->platformPageClient()));
}
-static GdkDrawable* gdkDrawable(PlatformWidget widget)
+static GdkWindow* gdkWindow(PlatformWidget widget)
{
return widget ? gtk_widget_get_window(widget) : 0;
}
@@ -78,7 +78,7 @@ void Widget::setCursor(const Cursor& cursor)
if (platformCursor == lastSetCursor)
return;
- gdk_window_set_cursor(gdkDrawable(platformWidget()) ? GDK_WINDOW(gdkDrawable(platformWidget())) : gtk_widget_get_window(GTK_WIDGET(root()->hostWindow()->platformPageClient())), platformCursor);
+ gdk_window_set_cursor(gdkWindow(platformWidget()) ? gdkWindow(platformWidget()) : gtk_widget_get_window(GTK_WIDGET(root()->hostWindow()->platformPageClient())), platformCursor);
lastSetCursor = platformCursor;
}
diff --git a/WebCore/platform/gtk/WidgetRenderingContext.h b/WebCore/platform/gtk/WidgetRenderingContext.h
index 3bb8065..7334656 100644
--- a/WebCore/platform/gtk/WidgetRenderingContext.h
+++ b/WebCore/platform/gtk/WidgetRenderingContext.h
@@ -34,7 +34,11 @@ class WidgetRenderingContext {
public:
WidgetRenderingContext(GraphicsContext*, const IntRect&);
~WidgetRenderingContext();
+
bool paintMozillaWidget(GtkThemeWidgetType, GtkWidgetState*, int flags, GtkTextDirection = GTK_TEXT_DIR_NONE);
+ void gtkPaintBox(const IntRect&, GtkWidget*, GtkStateType, GtkShadowType, const gchar*);
+ void gtkPaintFocus(const IntRect&, GtkWidget*, GtkStateType, const gchar*);
+ void gtkPaintSlider(const IntRect&, GtkWidget*, GtkStateType, GtkShadowType, const gchar*, GtkOrientation);
private:
GraphicsContext* m_graphicsContext;
diff --git a/WebCore/platform/gtk/WidgetRenderingContextGtk2.cpp b/WebCore/platform/gtk/WidgetRenderingContextGtk2.cpp
index b8712d2..e85c570 100644
--- a/WebCore/platform/gtk/WidgetRenderingContextGtk2.cpp
+++ b/WebCore/platform/gtk/WidgetRenderingContextGtk2.cpp
@@ -89,9 +89,9 @@ WidgetRenderingContext::WidgetRenderingContext(GraphicsContext* graphicsContext,
// Fallback: We failed to create an RGBA colormap earlier, so we cannot properly paint
// to a temporary surface and preserve transparency. To ensure decent widget rendering, just
// paint directly to the target drawable. This will not render CSS rotational transforms properly.
- if (!theme->m_themePartsHaveRGBAColormap && graphicsContext->gdkDrawable()) {
+ if (!theme->m_themePartsHaveRGBAColormap && graphicsContext->gdkWindow()) {
m_paintRect = graphicsContext->getCTM().mapRect(targetRect);
- m_target = graphicsContext->gdkDrawable();
+ m_target = graphicsContext->gdkWindow();
return;
}
@@ -131,7 +131,7 @@ WidgetRenderingContext::~WidgetRenderingContext()
{
// We do not need to blit back to the target in the fallback case. See above.
RenderThemeGtk* theme = static_cast<RenderThemeGtk*>(RenderTheme::defaultTheme().get());
- if (!theme->m_themePartsHaveRGBAColormap && m_graphicsContext->gdkDrawable())
+ if (!theme->m_themePartsHaveRGBAColormap && m_graphicsContext->gdkWindow())
return;
// Don't paint the results back if there was an error.
@@ -165,6 +165,27 @@ bool WidgetRenderingContext::paintMozillaWidget(GtkThemeWidgetType type, GtkWidg
return !m_hadError;
}
+void WidgetRenderingContext::gtkPaintBox(const IntRect& rect, GtkWidget* widget, GtkStateType stateType, GtkShadowType shadowType, const gchar* detail)
+{
+ GdkRectangle paintRect = { m_paintRect.x + rect.x(), m_paintRect.y + rect.y(), rect.width(), rect.height() };
+ gtk_paint_box(gtk_widget_get_style(widget), m_target, stateType, shadowType, &m_paintRect,
+ widget, detail, paintRect.x, paintRect.y, paintRect.width, paintRect.height);
+}
+
+void WidgetRenderingContext::gtkPaintFocus(const IntRect& rect, GtkWidget* widget, GtkStateType stateType, const gchar* detail)
+{
+ GdkRectangle paintRect = { m_paintRect.x + rect.x(), m_paintRect.y + rect.y(), rect.width(), rect.height() };
+ gtk_paint_focus(gtk_widget_get_style(widget), m_target, stateType, &m_paintRect, widget,
+ detail, paintRect.x, paintRect.y, paintRect.width, paintRect.height);
+}
+
+void WidgetRenderingContext::gtkPaintSlider(const IntRect& rect, GtkWidget* widget, GtkStateType stateType, GtkShadowType shadowType, const gchar* detail, GtkOrientation orientation)
+{
+ GdkRectangle paintRect = { m_paintRect.x + rect.x(), m_paintRect.y + rect.y(), rect.width(), rect.height() };
+ gtk_paint_slider(gtk_widget_get_style(widget), m_target, stateType, shadowType, &m_paintRect, widget,
+ detail, paintRect.x, paintRect.y, paintRect.width, paintRect.height, orientation);
+}
+
}
#endif // GTK_API_VERSION_2
diff --git a/WebCore/platform/gtk/WidgetRenderingContextGtk3.cpp b/WebCore/platform/gtk/WidgetRenderingContextGtk3.cpp
index e5f1823..69c4af5 100644
--- a/WebCore/platform/gtk/WidgetRenderingContextGtk3.cpp
+++ b/WebCore/platform/gtk/WidgetRenderingContextGtk3.cpp
@@ -47,6 +47,27 @@ bool WidgetRenderingContext::paintMozillaWidget(GtkThemeWidgetType type, GtkWidg
return !m_hadError;
}
+void WidgetRenderingContext::gtkPaintBox(const IntRect& rect, GtkWidget* widget, GtkStateType stateType, GtkShadowType shadowType, const gchar* detail)
+{
+ GdkRectangle paintRect = { m_paintRect.x + rect.x(), m_paintRect.y + rect.y(), rect.width(), rect.height() };
+ gtk_paint_box(gtk_widget_get_style(widget), m_target, stateType, shadowType, widget,
+ detail, paintRect.x, paintRect.y, paintRect.width, paintRect.height);
+}
+
+void WidgetRenderingContext::gtkPaintFocus(const IntRect& rect, GtkWidget* widget, GtkStateType stateType, const gchar* detail)
+{
+ GdkRectangle paintRect = { m_paintRect.x + rect.x(), m_paintRect.y + rect.y(), rect.width(), rect.height() };
+ gtk_paint_focus(gtk_widget_get_style(widget), m_target, stateType, widget,
+ detail, paintRect.x, paintRect.y, paintRect.width, paintRect.height);
+}
+
+void WidgetRenderingContext::gtkPaintSlider(const IntRect& rect, GtkWidget* widget, GtkStateType stateType, GtkShadowType shadowType, const gchar* detail, GtkOrientation orientation)
+{
+ GdkRectangle paintRect = { m_paintRect.x + rect.x(), m_paintRect.y + rect.y(), rect.width(), rect.height() };
+ gtk_paint_slider(gtk_widget_get_style(widget), m_target, stateType, shadowType, widget,
+ detail, paintRect.x, paintRect.y, paintRect.width, paintRect.height, orientation);
+}
+
}
#endif // !GTK_API_VERSION_2
diff --git a/WebCore/platform/gtk/gtk2drawing.c b/WebCore/platform/gtk/gtk2drawing.c
index 2f2edb6..3ebd332 100644
--- a/WebCore/platform/gtk/gtk2drawing.c
+++ b/WebCore/platform/gtk/gtk2drawing.c
@@ -185,20 +185,6 @@ ensure_scrollbar_widget()
}
static gint
-ensure_scale_widget()
-{
- if (!gParts->hScaleWidget) {
- gParts->hScaleWidget = gtk_hscale_new(NULL);
- setup_widget_prototype(gParts->hScaleWidget);
- }
- if (!gParts->vScaleWidget) {
- gParts->vScaleWidget = gtk_vscale_new(NULL);
- setup_widget_prototype(gParts->vScaleWidget);
- }
- return MOZ_GTK_SUCCESS;
-}
-
-static gint
ensure_entry_widget()
{
if (!gParts->entryWidget) {
@@ -921,83 +907,6 @@ moz_gtk_scrollbar_thumb_paint(GtkThemeWidgetType widget,
}
static gint
-moz_gtk_scale_paint(GdkDrawable* drawable, GdkRectangle* rect,
- GdkRectangle* cliprect, GtkWidgetState* state,
- GtkOrientation flags, GtkTextDirection direction)
-{
- gint x = 0, y = 0;
- GtkStateType state_type = ConvertGtkState(state);
- GtkStyle* style;
- GtkWidget* widget;
-
- ensure_scale_widget();
- widget = ((flags == GTK_ORIENTATION_HORIZONTAL) ? gParts->hScaleWidget : gParts->vScaleWidget);
- gtk_widget_set_direction(widget, direction);
-
- style = gtk_widget_get_style(widget);
-
- if (flags == GTK_ORIENTATION_HORIZONTAL) {
- x = XTHICKNESS(style);
- y++;
- }
- else {
- x++;
- y = YTHICKNESS(style);
- }
-
- TSOffsetStyleGCs(style, rect->x, rect->y);
- gtk_style_apply_default_background(style, drawable, TRUE, GTK_STATE_NORMAL,
- cliprect, rect->x, rect->y,
- rect->width, rect->height);
-
- gtk_paint_box(style, drawable, GTK_STATE_ACTIVE, GTK_SHADOW_IN, cliprect,
- widget, "trough", rect->x + x, rect->y + y,
- rect->width - 2*x, rect->height - 2*y);
-
- if (state->focused)
- gtk_paint_focus(style, drawable, state_type, cliprect, widget, "trough",
- rect->x, rect->y, rect->width, rect->height);
-
- return MOZ_GTK_SUCCESS;
-}
-
-static gint
-moz_gtk_scale_thumb_paint(GdkDrawable* drawable, GdkRectangle* rect,
- GdkRectangle* cliprect, GtkWidgetState* state,
- GtkOrientation flags, GtkTextDirection direction)
-{
- GtkStateType state_type = ConvertGtkState(state);
- GtkStyle* style;
- GtkWidget* widget;
- gint thumb_width, thumb_height, x, y;
-
- ensure_scale_widget();
- widget = ((flags == GTK_ORIENTATION_HORIZONTAL) ? gParts->hScaleWidget : gParts->vScaleWidget);
- gtk_widget_set_direction(widget, direction);
-
- style = gtk_widget_get_style(widget);
-
- /* determine the thumb size, and position the thumb in the center in the opposite axis */
- if (flags == GTK_ORIENTATION_HORIZONTAL) {
- moz_gtk_get_scalethumb_metrics(GTK_ORIENTATION_HORIZONTAL, &thumb_width, &thumb_height);
- x = rect->x;
- y = rect->y + (rect->height - thumb_height) / 2;
- }
- else {
- moz_gtk_get_scalethumb_metrics(GTK_ORIENTATION_VERTICAL, &thumb_height, &thumb_width);
- x = rect->x + (rect->width - thumb_width) / 2;
- y = rect->y;
- }
-
- TSOffsetStyleGCs(style, rect->x, rect->y);
- gtk_paint_slider(style, drawable, state_type, GTK_SHADOW_OUT, cliprect,
- widget, (flags == GTK_ORIENTATION_HORIZONTAL) ? "hscale" : "vscale",
- x, y, thumb_width, thumb_height, flags);
-
- return MOZ_GTK_SUCCESS;
-}
-
-static gint
moz_gtk_entry_paint(GdkDrawable* drawable, GdkRectangle* rect,
GdkRectangle* cliprect, GtkWidgetState* state,
GtkWidget* widget, GtkTextDirection direction)
@@ -1310,14 +1219,6 @@ moz_gtk_get_widget_border(GtkThemeWidgetType widget, gint* left, gint* top,
ensure_progress_widget();
w = gParts->progresWidget;
break;
- case MOZ_GTK_SCALE_HORIZONTAL:
- ensure_scale_widget();
- w = gParts->hScaleWidget;
- break;
- case MOZ_GTK_SCALE_VERTICAL:
- ensure_scale_widget();
- w = gParts->vScaleWidget;
- break;
/* These widgets have no borders, since they are not containers. */
case MOZ_GTK_CHECKBUTTON:
case MOZ_GTK_RADIOBUTTON:
@@ -1326,8 +1227,6 @@ moz_gtk_get_widget_border(GtkThemeWidgetType widget, gint* left, gint* top,
case MOZ_GTK_SCROLLBAR_TRACK_VERTICAL:
case MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL:
case MOZ_GTK_SCROLLBAR_THUMB_VERTICAL:
- case MOZ_GTK_SCALE_THUMB_HORIZONTAL:
- case MOZ_GTK_SCALE_THUMB_VERTICAL:
case MOZ_GTK_PROGRESS_CHUNK:
*left = *top = *right = *bottom = 0;
return MOZ_GTK_SUCCESS;
@@ -1344,22 +1243,6 @@ moz_gtk_get_widget_border(GtkThemeWidgetType widget, gint* left, gint* top,
}
gint
-moz_gtk_get_scalethumb_metrics(GtkOrientation orient, gint* thumb_length, gint* thumb_height)
-{
- GtkWidget* widget;
-
- ensure_scale_widget();
- widget = ((orient == GTK_ORIENTATION_HORIZONTAL) ? gParts->hScaleWidget : gParts->vScaleWidget);
-
- gtk_widget_style_get (widget,
- "slider_length", thumb_length,
- "slider_width", thumb_height,
- NULL);
-
- return MOZ_GTK_SUCCESS;
-}
-
-gint
moz_gtk_get_scrollbar_metrics(MozGtkScrollbarMetrics *metrics)
{
ensure_scrollbar_widget();
@@ -1424,16 +1307,6 @@ moz_gtk_widget_paint(GtkThemeWidgetType widget, GdkDrawable* drawable,
case MOZ_GTK_SCROLLED_WINDOW:
return moz_gtk_scrolled_window_paint(drawable, rect, cliprect, state);
break;
- case MOZ_GTK_SCALE_HORIZONTAL:
- case MOZ_GTK_SCALE_VERTICAL:
- return moz_gtk_scale_paint(drawable, rect, cliprect, state,
- (GtkOrientation) flags, direction);
- break;
- case MOZ_GTK_SCALE_THUMB_HORIZONTAL:
- case MOZ_GTK_SCALE_THUMB_VERTICAL:
- return moz_gtk_scale_thumb_paint(drawable, rect, cliprect, state,
- (GtkOrientation) flags, direction);
- break;
case MOZ_GTK_ENTRY:
ensure_entry_widget();
return moz_gtk_entry_paint(drawable, rect, cliprect, state,
diff --git a/WebCore/platform/gtk/gtk3drawing.c b/WebCore/platform/gtk/gtk3drawing.c
index 880eb6d..d3bdd56 100644
--- a/WebCore/platform/gtk/gtk3drawing.c
+++ b/WebCore/platform/gtk/gtk3drawing.c
@@ -178,20 +178,6 @@ ensure_scrollbar_widget()
}
static gint
-ensure_scale_widget()
-{
- if (!gParts->hScaleWidget) {
- gParts->hScaleWidget = gtk_hscale_new(NULL);
- setup_widget_prototype(gParts->hScaleWidget);
- }
- if (!gParts->vScaleWidget) {
- gParts->vScaleWidget = gtk_vscale_new(NULL);
- setup_widget_prototype(gParts->vScaleWidget);
- }
- return MOZ_GTK_SUCCESS;
-}
-
-static gint
ensure_entry_widget()
{
if (!gParts->entryWidget) {
@@ -848,82 +834,6 @@ moz_gtk_scrollbar_thumb_paint(GtkThemeWidgetType widget,
}
static gint
-moz_gtk_scale_paint(cairo_t* cr, GdkRectangle* rect,
- GtkWidgetState* state, GtkOrientation flags,
- GtkTextDirection direction)
-{
- gint x = 0, y = 0;
- GtkStateType state_type = ConvertGtkState(state);
- GtkStyle* style;
- GtkWidget* widget;
-
- ensure_scale_widget();
- widget = ((flags == GTK_ORIENTATION_HORIZONTAL) ? gParts->hScaleWidget : gParts->vScaleWidget);
- gtk_widget_set_direction(widget, direction);
-
- style = gtk_widget_get_style(widget);
-
- if (flags == GTK_ORIENTATION_HORIZONTAL) {
- x = XTHICKNESS(style);
- y++;
- }
- else {
- x++;
- y = YTHICKNESS(style);
- }
-
- gtk_style_apply_default_background(style, cr, gtk_widget_get_window (widget),
- GTK_STATE_NORMAL,
- rect->x, rect->y,
- rect->width, rect->height);
-
- gtk_paint_box(style, cr, GTK_STATE_ACTIVE, GTK_SHADOW_IN,
- widget, "trough", rect->x + x, rect->y + y,
- rect->width - 2*x, rect->height - 2*y);
-
- if (state->focused)
- gtk_paint_focus(style, cr, state_type, widget, "trough",
- rect->x, rect->y, rect->width, rect->height);
-
- return MOZ_GTK_SUCCESS;
-}
-
-static gint
-moz_gtk_scale_thumb_paint(cairo_t* cr, GdkRectangle* rect,
- GtkWidgetState* state, GtkOrientation flags,
- GtkTextDirection direction)
-{
- GtkStateType state_type = ConvertGtkState(state);
- GtkStyle* style;
- GtkWidget* widget;
- gint thumb_width, thumb_height, x, y;
-
- ensure_scale_widget();
- widget = ((flags == GTK_ORIENTATION_HORIZONTAL) ? gParts->hScaleWidget : gParts->vScaleWidget);
- gtk_widget_set_direction(widget, direction);
-
- style = gtk_widget_get_style(widget);
-
- /* determine the thumb size, and position the thumb in the center in the opposite axis */
- if (flags == GTK_ORIENTATION_HORIZONTAL) {
- moz_gtk_get_scalethumb_metrics(GTK_ORIENTATION_HORIZONTAL, &thumb_width, &thumb_height);
- x = rect->x;
- y = rect->y + (rect->height - thumb_height) / 2;
- }
- else {
- moz_gtk_get_scalethumb_metrics(GTK_ORIENTATION_VERTICAL, &thumb_height, &thumb_width);
- x = rect->x + (rect->width - thumb_width) / 2;
- y = rect->y;
- }
-
- gtk_paint_slider(style, cr, state_type, GTK_SHADOW_OUT,
- widget, (flags == GTK_ORIENTATION_HORIZONTAL) ? "hscale" : "vscale",
- x, y, thumb_width, thumb_height, flags);
-
- return MOZ_GTK_SUCCESS;
-}
-
-static gint
moz_gtk_entry_paint(cairo_t* cr, GdkRectangle* rect,
GtkWidgetState* state, GtkWidget* widget,
GtkTextDirection direction)
@@ -1227,14 +1137,6 @@ moz_gtk_get_widget_border(GtkThemeWidgetType widget, gint* left, gint* top,
ensure_progress_widget();
w = gParts->progresWidget;
break;
- case MOZ_GTK_SCALE_HORIZONTAL:
- ensure_scale_widget();
- w = gParts->hScaleWidget;
- break;
- case MOZ_GTK_SCALE_VERTICAL:
- ensure_scale_widget();
- w = gParts->vScaleWidget;
- break;
/* These widgets have no borders, since they are not containers. */
case MOZ_GTK_CHECKBUTTON:
case MOZ_GTK_RADIOBUTTON:
@@ -1243,8 +1145,6 @@ moz_gtk_get_widget_border(GtkThemeWidgetType widget, gint* left, gint* top,
case MOZ_GTK_SCROLLBAR_TRACK_VERTICAL:
case MOZ_GTK_SCROLLBAR_THUMB_HORIZONTAL:
case MOZ_GTK_SCROLLBAR_THUMB_VERTICAL:
- case MOZ_GTK_SCALE_THUMB_HORIZONTAL:
- case MOZ_GTK_SCALE_THUMB_VERTICAL:
case MOZ_GTK_PROGRESS_CHUNK:
*left = *top = *right = *bottom = 0;
return MOZ_GTK_SUCCESS;
@@ -1261,22 +1161,6 @@ moz_gtk_get_widget_border(GtkThemeWidgetType widget, gint* left, gint* top,
}
gint
-moz_gtk_get_scalethumb_metrics(GtkOrientation orient, gint* thumb_length, gint* thumb_height)
-{
- GtkWidget* widget;
-
- ensure_scale_widget();
- widget = ((orient == GTK_ORIENTATION_HORIZONTAL) ? gParts->hScaleWidget : gParts->vScaleWidget);
-
- gtk_widget_style_get (widget,
- "slider_length", thumb_length,
- "slider_width", thumb_height,
- NULL);
-
- return MOZ_GTK_SUCCESS;
-}
-
-gint
moz_gtk_get_scrollbar_metrics(MozGtkScrollbarMetrics *metrics)
{
ensure_scrollbar_widget();
@@ -1340,16 +1224,6 @@ moz_gtk_widget_paint(GtkThemeWidgetType widget, cairo_t* cr,
case MOZ_GTK_SCROLLED_WINDOW:
return moz_gtk_scrolled_window_paint(cr, rect, state);
break;
- case MOZ_GTK_SCALE_HORIZONTAL:
- case MOZ_GTK_SCALE_VERTICAL:
- return moz_gtk_scale_paint(cr, rect, state,
- (GtkOrientation) flags, direction);
- break;
- case MOZ_GTK_SCALE_THUMB_HORIZONTAL:
- case MOZ_GTK_SCALE_THUMB_VERTICAL:
- return moz_gtk_scale_thumb_paint(cr, rect, state,
- (GtkOrientation) flags, direction);
- break;
case MOZ_GTK_ENTRY:
ensure_entry_widget();
return moz_gtk_entry_paint(cr, rect, state,
diff --git a/WebCore/platform/gtk/gtkdrawing.h b/WebCore/platform/gtk/gtkdrawing.h
index a981543..9d13a07 100644
--- a/WebCore/platform/gtk/gtkdrawing.h
+++ b/WebCore/platform/gtk/gtkdrawing.h
@@ -93,8 +93,6 @@ typedef struct _GtkThemeParts {
GtkWidget* radiobuttonWidget;
GtkWidget* horizScrollbarWidget;
GtkWidget* vertScrollbarWidget;
- GtkWidget* hScaleWidget;
- GtkWidget* vScaleWidget;
GtkWidget* entryWidget;
GtkWidget* comboBoxWidget;
GtkWidget* comboBoxButtonWidget;
@@ -147,12 +145,6 @@ typedef enum {
MOZ_GTK_SCROLLBAR_THUMB_VERTICAL,
/* Paints the background of a scrolled window */
MOZ_GTK_SCROLLED_WINDOW,
- /* Paints a GtkScale. */
- MOZ_GTK_SCALE_HORIZONTAL,
- MOZ_GTK_SCALE_VERTICAL,
- /* Paints a GtkScale thumb. */
- MOZ_GTK_SCALE_THUMB_HORIZONTAL,
- MOZ_GTK_SCALE_THUMB_VERTICAL,
MOZ_GTK_ENTRY,
/* Paints a GtkOptionMenu. */
MOZ_GTK_DROPDOWN,
@@ -277,17 +269,6 @@ moz_gtk_widget_get_focus(GtkWidget* widget, gboolean* interior_focus,
gint* focus_width, gint* focus_pad);
/**
- * Get the desired size of a GtkScale thumb
- * orient: [IN] the scale orientation
- * thumb_length: [OUT] the length of the thumb
- * thumb_height: [OUT] the height of the thumb
- *
- * returns: MOZ_GTK_SUCCESS if there was no error, an error code otherwise
- */
-gint
-moz_gtk_get_scalethumb_metrics(GtkOrientation orient, gint* thumb_length, gint* thumb_height);
-
-/**
* Get the desired metrics for a GtkScrollbar
* metrics: [IN] struct which will contain the metrics
*
diff --git a/WebCore/platform/haiku/ContextMenuHaiku.cpp b/WebCore/platform/haiku/ContextMenuHaiku.cpp
index b978433..aaff99b 100644
--- a/WebCore/platform/haiku/ContextMenuHaiku.cpp
+++ b/WebCore/platform/haiku/ContextMenuHaiku.cpp
@@ -75,9 +75,8 @@ private:
int m_result;
};
-ContextMenu::ContextMenu(const HitTestResult& result)
- : m_hitTestResult(result)
- , m_platformDescription(new BMenu("context_menu"))
+ContextMenu::ContextMenu()
+ : m_platformDescription(new BMenu("context_menu"))
{
}
@@ -88,8 +87,6 @@ ContextMenu::~ContextMenu()
void ContextMenu::appendItem(ContextMenuItem& item)
{
- checkOrEnableIfNeeded(item);
-
BMenuItem* menuItem = item.releasePlatformDescription();
if (menuItem)
m_platformDescription->AddItem(menuItem);
@@ -102,8 +99,6 @@ unsigned ContextMenu::itemCount() const
void ContextMenu::insertItem(unsigned position, ContextMenuItem& item)
{
- checkOrEnableIfNeeded(item);
-
BMenuItem* menuItem = item.releasePlatformDescription();
if (menuItem)
m_platformDescription->AddItem(menuItem, position);
diff --git a/WebCore/platform/image-decoders/ImageDecoder.cpp b/WebCore/platform/image-decoders/ImageDecoder.cpp
index 49c2a61..cc23b2a 100644
--- a/WebCore/platform/image-decoders/ImageDecoder.cpp
+++ b/WebCore/platform/image-decoders/ImageDecoder.cpp
@@ -53,11 +53,15 @@ static unsigned copyFromSharedBuffer(char* buffer, unsigned bufferLength, const
return bytesExtracted;
}
+<<<<<<< HEAD
#if !OS(ANDROID)
// This method requires BMPImageDecoder, PNGImageDecoder, ICOImageDecoder and
// JPEGDecoder, which aren't used on Android, and which don't all compile.
// TODO: Find a better fix.
ImageDecoder* ImageDecoder::create(const SharedBuffer& data, bool premultiplyAlpha, bool ignoreGammaAndColorProfile)
+=======
+ImageDecoder* ImageDecoder::create(const SharedBuffer& data, ImageSource::AlphaOption alphaOption, ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption)
+>>>>>>> webkit.org at r74534 (trunk)
{
// We need at least 4 bytes to figure out what kind of image we're dealing
// with.
@@ -69,15 +73,15 @@ ImageDecoder* ImageDecoder::create(const SharedBuffer& data, bool premultiplyAlp
// GIFs begin with GIF8(7 or 9).
if (strncmp(contents, "GIF8", 4) == 0)
- return new GIFImageDecoder(premultiplyAlpha, ignoreGammaAndColorProfile);
+ return new GIFImageDecoder(alphaOption, gammaAndColorProfileOption);
// Test for PNG.
if (!memcmp(contents, "\x89\x50\x4E\x47", 4))
- return new PNGImageDecoder(premultiplyAlpha, ignoreGammaAndColorProfile);
+ return new PNGImageDecoder(alphaOption, gammaAndColorProfileOption);
// JPEG
if (!memcmp(contents, "\xFF\xD8\xFF", 3))
- return new JPEGImageDecoder(premultiplyAlpha, ignoreGammaAndColorProfile);
+ return new JPEGImageDecoder(alphaOption, gammaAndColorProfileOption);
#if USE(WEBP)
if (!memcmp(contents, "RIFF", 4)) {
@@ -87,19 +91,19 @@ ImageDecoder* ImageDecoder::create(const SharedBuffer& data, bool premultiplyAlp
unsigned length = copyFromSharedBuffer(header, webpExtraMarker, data, webpExtraMarkeroffset);
if (length >= webpExtraMarker) {
if (!memcmp(header, "WEBPVP", webpExtraMarker))
- return new WEBPImageDecoder(premultiplyAlpha, ignoreGammaAndColorProfile);
+ return new WEBPImageDecoder(alphaOption, gammaAndColorProfileOption);
}
}
#endif
// BMP
if (strncmp(contents, "BM", 2) == 0)
- return new BMPImageDecoder(premultiplyAlpha, ignoreGammaAndColorProfile);
+ return new BMPImageDecoder(alphaOption, gammaAndColorProfileOption);
// ICOs always begin with a 2-byte 0 followed by a 2-byte 1.
// CURs begin with 2-byte 0 followed by 2-byte 2.
if (!memcmp(contents, "\x00\x00\x01\x00", 4) || !memcmp(contents, "\x00\x00\x02\x00", 4))
- return new ICOImageDecoder(premultiplyAlpha, ignoreGammaAndColorProfile);
+ return new ICOImageDecoder(alphaOption, gammaAndColorProfileOption);
// Give up. We don't know what the heck this is.
return 0;
diff --git a/WebCore/platform/image-decoders/ImageDecoder.h b/WebCore/platform/image-decoders/ImageDecoder.h
index ceb8f9b..c3d73c0 100644
--- a/WebCore/platform/image-decoders/ImageDecoder.h
+++ b/WebCore/platform/image-decoders/ImageDecoder.h
@@ -233,10 +233,10 @@ namespace WebCore {
// m_maxNumPixels. (Not supported by all image decoders yet)
class ImageDecoder : public Noncopyable {
public:
- ImageDecoder(bool premultiplyAlpha, bool ignoreGammaAndColorProfile)
+ ImageDecoder(ImageSource::AlphaOption alphaOption, ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption)
: m_scaled(false)
- , m_premultiplyAlpha(premultiplyAlpha)
- , m_ignoreGammaAndColorProfile(ignoreGammaAndColorProfile)
+ , m_premultiplyAlpha(alphaOption == ImageSource::AlphaPremultiplied)
+ , m_ignoreGammaAndColorProfile(gammaAndColorProfileOption == ImageSource::GammaAndColorProfileIgnored)
, m_sizeAvailable(false)
, m_maxNumPixels(-1)
, m_isAllDataReceived(false)
@@ -249,7 +249,7 @@ namespace WebCore {
// Factory function to create an ImageDecoder. Ports that subclass
// ImageDecoder can provide their own implementation of this to avoid
// needing to write a dedicated setData() implementation.
- static ImageDecoder* create(const SharedBuffer& data, bool premultiplyAlpha, bool ignoreGammaAndColorProfile);
+ static ImageDecoder* create(const SharedBuffer& data, ImageSource::AlphaOption, ImageSource::GammaAndColorProfileOption);
// The the filename extension usually associated with an undecoded image
// of this type.
diff --git a/WebCore/platform/image-decoders/bmp/BMPImageDecoder.cpp b/WebCore/platform/image-decoders/bmp/BMPImageDecoder.cpp
index 219a1e2..220a1ed 100644
--- a/WebCore/platform/image-decoders/bmp/BMPImageDecoder.cpp
+++ b/WebCore/platform/image-decoders/bmp/BMPImageDecoder.cpp
@@ -40,8 +40,9 @@ namespace WebCore {
// don't pack).
static const size_t sizeOfFileHeader = 14;
-BMPImageDecoder::BMPImageDecoder(bool premultiplyAlpha, bool ignoreGammaAndColorProfile)
- : ImageDecoder(premultiplyAlpha, ignoreGammaAndColorProfile)
+BMPImageDecoder::BMPImageDecoder(ImageSource::AlphaOption alphaOption,
+ ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption)
+ : ImageDecoder(alphaOption, gammaAndColorProfileOption)
, m_decodedOffset(0)
{
}
diff --git a/WebCore/platform/image-decoders/bmp/BMPImageDecoder.h b/WebCore/platform/image-decoders/bmp/BMPImageDecoder.h
index 695fab4..5f4ed82 100644
--- a/WebCore/platform/image-decoders/bmp/BMPImageDecoder.h
+++ b/WebCore/platform/image-decoders/bmp/BMPImageDecoder.h
@@ -39,7 +39,7 @@ namespace WebCore {
// This class decodes the BMP image format.
class BMPImageDecoder : public ImageDecoder {
public:
- BMPImageDecoder(bool premultiplyAlpha, bool ignoreGammaAndColorProfile);
+ BMPImageDecoder(ImageSource::AlphaOption, ImageSource::GammaAndColorProfileOption);
// ImageDecoder
virtual String filenameExtension() const { return "bmp"; }
diff --git a/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp b/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp
index dfdf35e..e92f264 100644
--- a/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp
+++ b/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp
@@ -29,8 +29,9 @@
namespace WebCore {
-GIFImageDecoder::GIFImageDecoder(bool premultiplyAlpha, bool ignoreGammaAndColorProfile)
- : ImageDecoder(premultiplyAlpha, ignoreGammaAndColorProfile)
+GIFImageDecoder::GIFImageDecoder(ImageSource::AlphaOption alphaOption,
+ ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption)
+ : ImageDecoder(alphaOption, gammaAndColorProfileOption)
, m_alreadyScannedThisDataForFrameCount(true)
, m_repetitionCount(cAnimationLoopOnce)
, m_readOffset(0)
diff --git a/WebCore/platform/image-decoders/gif/GIFImageDecoder.h b/WebCore/platform/image-decoders/gif/GIFImageDecoder.h
index 5b4ca10..64240d4 100644
--- a/WebCore/platform/image-decoders/gif/GIFImageDecoder.h
+++ b/WebCore/platform/image-decoders/gif/GIFImageDecoder.h
@@ -36,7 +36,7 @@ namespace WebCore {
// This class decodes the GIF image format.
class GIFImageDecoder : public ImageDecoder {
public:
- GIFImageDecoder(bool premultiplyAlpha, bool ignoreGammaAndColorProfile);
+ GIFImageDecoder(ImageSource::AlphaOption, ImageSource::GammaAndColorProfileOption);
virtual ~GIFImageDecoder();
enum GIFQuery { GIFFullQuery, GIFSizeQuery, GIFFrameCountQuery };
diff --git a/WebCore/platform/image-decoders/ico/ICOImageDecoder.cpp b/WebCore/platform/image-decoders/ico/ICOImageDecoder.cpp
index b07cf92..92a7dcf 100644
--- a/WebCore/platform/image-decoders/ico/ICOImageDecoder.cpp
+++ b/WebCore/platform/image-decoders/ico/ICOImageDecoder.cpp
@@ -44,8 +44,9 @@ namespace WebCore {
static const size_t sizeOfDirectory = 6;
static const size_t sizeOfDirEntry = 16;
-ICOImageDecoder::ICOImageDecoder(bool premultiplyAlpha, bool ignoreGammaAndColorProfile)
- : ImageDecoder(premultiplyAlpha, ignoreGammaAndColorProfile)
+ICOImageDecoder::ICOImageDecoder(ImageSource::AlphaOption alphaOption,
+ ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption)
+ : ImageDecoder(alphaOption, gammaAndColorProfileOption)
, m_decodedOffset(0)
{
}
@@ -201,7 +202,9 @@ bool ICOImageDecoder::decodeAtIndex(size_t index)
}
if (!m_pngDecoders[index]) {
- m_pngDecoders[index].set(new PNGImageDecoder(m_premultiplyAlpha, m_ignoreGammaAndColorProfile));
+ m_pngDecoders[index].set(
+ new PNGImageDecoder(m_premultiplyAlpha ? ImageSource::AlphaPremultiplied : ImageSource::AlphaNotPremultiplied,
+ m_ignoreGammaAndColorProfile ? ImageSource::GammaAndColorProfileIgnored : ImageSource::GammaAndColorProfileApplied));
setDataForPNGDecoderAtIndex(index);
}
// Fail if the size the PNGImageDecoder calculated does not match the size
diff --git a/WebCore/platform/image-decoders/ico/ICOImageDecoder.h b/WebCore/platform/image-decoders/ico/ICOImageDecoder.h
index dc631f4..c2af6a3 100644
--- a/WebCore/platform/image-decoders/ico/ICOImageDecoder.h
+++ b/WebCore/platform/image-decoders/ico/ICOImageDecoder.h
@@ -40,7 +40,7 @@ namespace WebCore {
// This class decodes the ICO and CUR image formats.
class ICOImageDecoder : public ImageDecoder {
public:
- ICOImageDecoder(bool premultiplyAlpha, bool ignoreGammaAndColorProfile);
+ ICOImageDecoder(ImageSource::AlphaOption, ImageSource::GammaAndColorProfileOption);
virtual ~ICOImageDecoder();
// ImageDecoder
diff --git a/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp b/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp
index 855ba24..632d428 100644
--- a/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp
+++ b/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.cpp
@@ -222,12 +222,6 @@ public:
// jpeglib cannot convert these to rgb, but it can convert ycck
// to cmyk.
m_info.out_color_space = JCS_CMYK;
-
- // Same as with grayscale images, we convert CMYK images to RGBA
- // ones. When we keep the color profiles of these CMYK images,
- // CoreGraphics will convert their colors again. So, we discard
- // their color profiles to prevent color corruption.
- m_decoder->setIgnoreGammaAndColorProfile(true);
break;
default:
return m_decoder->setFailed();
@@ -404,8 +398,9 @@ void term_source(j_decompress_ptr jd)
src->decoder->decoder()->jpegComplete();
}
-JPEGImageDecoder::JPEGImageDecoder(bool premultiplyAlpha, bool ignoreGammaAndColorProfile)
- : ImageDecoder(premultiplyAlpha, ignoreGammaAndColorProfile)
+JPEGImageDecoder::JPEGImageDecoder(ImageSource::AlphaOption alphaOption,
+ ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption)
+ : ImageDecoder(alphaOption, gammaAndColorProfileOption)
{
}
diff --git a/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h b/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h
index a60b387..63f29ab 100644
--- a/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h
+++ b/WebCore/platform/image-decoders/jpeg/JPEGImageDecoder.h
@@ -37,7 +37,7 @@ namespace WebCore {
// This class decodes the JPEG image format.
class JPEGImageDecoder : public ImageDecoder {
public:
- JPEGImageDecoder(bool premultiplyAlpha, bool ignoreGammaAndColorProfile);
+ JPEGImageDecoder(ImageSource::AlphaOption, ImageSource::GammaAndColorProfileOption);
virtual ~JPEGImageDecoder();
// ImageDecoder
diff --git a/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp b/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp
index 794a474..3fe4d3c 100644
--- a/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp
+++ b/WebCore/platform/image-decoders/png/PNGImageDecoder.cpp
@@ -169,8 +169,9 @@ private:
unsigned m_currentBufferSize;
};
-PNGImageDecoder::PNGImageDecoder(bool premultiplyAlpha, bool ignoreGammaAndColorProfile)
- : ImageDecoder(premultiplyAlpha, ignoreGammaAndColorProfile)
+PNGImageDecoder::PNGImageDecoder(ImageSource::AlphaOption alphaOption,
+ ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption)
+ : ImageDecoder(alphaOption, gammaAndColorProfileOption)
, m_doNothingOnFailure(false)
{
}
diff --git a/WebCore/platform/image-decoders/png/PNGImageDecoder.h b/WebCore/platform/image-decoders/png/PNGImageDecoder.h
index 68b0c1f..1e8902f 100644
--- a/WebCore/platform/image-decoders/png/PNGImageDecoder.h
+++ b/WebCore/platform/image-decoders/png/PNGImageDecoder.h
@@ -36,7 +36,7 @@ namespace WebCore {
// This class decodes the PNG image format.
class PNGImageDecoder : public ImageDecoder {
public:
- PNGImageDecoder(bool premultiplyAlpha, bool ignoreGammaAndColorProfile);
+ PNGImageDecoder(ImageSource::AlphaOption, ImageSource::GammaAndColorProfileOption);
virtual ~PNGImageDecoder();
// ImageDecoder
diff --git a/WebCore/platform/image-decoders/webp/WEBPImageDecoder.cpp b/WebCore/platform/image-decoders/webp/WEBPImageDecoder.cpp
index 0fc0bd5..a988d9c 100644
--- a/WebCore/platform/image-decoders/webp/WEBPImageDecoder.cpp
+++ b/WebCore/platform/image-decoders/webp/WEBPImageDecoder.cpp
@@ -35,8 +35,9 @@
namespace WebCore {
-WEBPImageDecoder::WEBPImageDecoder(bool premultiplyAlpha, bool ignoreGammaAndColorProfile)
- : ImageDecoder(premultiplyAlpha, ignoreGammaAndColorProfile)
+WEBPImageDecoder::WEBPImageDecoder(ImageSource::AlphaOption alphaOption,
+ ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption)
+ : ImageDecoder(alphaOption, gammaAndColorProfileOption)
{
}
diff --git a/WebCore/platform/image-decoders/webp/WEBPImageDecoder.h b/WebCore/platform/image-decoders/webp/WEBPImageDecoder.h
index 57b1dae..6cf8870 100644
--- a/WebCore/platform/image-decoders/webp/WEBPImageDecoder.h
+++ b/WebCore/platform/image-decoders/webp/WEBPImageDecoder.h
@@ -37,7 +37,7 @@ namespace WebCore {
class WEBPImageDecoder : public ImageDecoder {
public:
- WEBPImageDecoder(bool premultiplyAlpha, bool ignoreGammaAndColorProfile);
+ WEBPImageDecoder(ImageSource::AlphaOption, ImageSource::GammaAndColorProfileOption);
virtual ~WEBPImageDecoder();
virtual String filenameExtension() const { return "vp8"; }
virtual bool isSizeAvailable();
diff --git a/WebCore/platform/image-encoders/skia/JPEGImageEncoder.cpp b/WebCore/platform/image-encoders/skia/JPEGImageEncoder.cpp
new file mode 100644
index 0000000..d4e1481
--- /dev/null
+++ b/WebCore/platform/image-encoders/skia/JPEGImageEncoder.cpp
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2010, Google 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:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 THE COPYRIGHT
+ * OWNER 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 "JPEGImageEncoder.h"
+
+#include "IntSize.h"
+#include "SkBitmap.h"
+#include "SkUnPreMultiply.h"
+#include "SkColorPriv.h"
+extern "C" {
+#include <stdio.h> // jpeglib.h needs stdio.h FILE
+#include "jpeglib.h"
+#include <setjmp.h>
+}
+
+namespace WebCore {
+
+struct JPEGOutputBuffer : public jpeg_destination_mgr {
+ Vector<unsigned char>* output;
+ Vector<unsigned char> buffer;
+};
+
+static void prepareOutput(j_compress_ptr cinfo)
+{
+ JPEGOutputBuffer* out = static_cast<JPEGOutputBuffer*>(cinfo->dest);
+ const size_t internalBufferSize = 8192;
+ out->buffer.resize(internalBufferSize);
+ out->next_output_byte = out->buffer.data();
+ out->free_in_buffer = out->buffer.size();
+}
+
+static boolean writeOutput(j_compress_ptr cinfo)
+{
+ JPEGOutputBuffer* out = static_cast<JPEGOutputBuffer*>(cinfo->dest);
+ out->output->append(out->buffer.data(), out->buffer.size());
+ out->next_output_byte = out->buffer.data();
+ out->free_in_buffer = out->buffer.size();
+ return TRUE;
+}
+
+static void finishOutput(j_compress_ptr cinfo)
+{
+ JPEGOutputBuffer* out = static_cast<JPEGOutputBuffer*>(cinfo->dest);
+ const size_t size = out->buffer.size() - out->free_in_buffer;
+ out->output->append(out->buffer.data(), size);
+}
+
+static void handleError(j_common_ptr common)
+{
+ jmp_buf* jumpBufferPtr = static_cast<jmp_buf*>(common->client_data);
+ longjmp(*jumpBufferPtr, -1);
+}
+
+// FIXME: is alpha unpremultiplication correct, or should the alpha channel
+// be ignored? See bug http://webkit.org/b/40147.
+void preMultipliedBGRAtoRGB(const SkPMColor* input, unsigned int pixels, unsigned char* output)
+{
+ static const SkUnPreMultiply::Scale* scale = SkUnPreMultiply::GetScaleTable();
+
+ for (; pixels-- > 0; ++input) {
+ const unsigned alpha = SkGetPackedA32(*input);
+ if ((alpha != 0) && (alpha != 255)) {
+ *output++ = SkUnPreMultiply::ApplyScale(scale[alpha], SkGetPackedR32(*input));
+ *output++ = SkUnPreMultiply::ApplyScale(scale[alpha], SkGetPackedG32(*input));
+ *output++ = SkUnPreMultiply::ApplyScale(scale[alpha], SkGetPackedB32(*input));
+ } else {
+ *output++ = SkGetPackedR32(*input);
+ *output++ = SkGetPackedG32(*input);
+ *output++ = SkGetPackedB32(*input);
+ }
+ }
+}
+
+bool JPEGImageEncoder::encode(const SkBitmap& bitmap, int quality, Vector<unsigned char>* output)
+{
+ if (bitmap.config() != SkBitmap::kARGB_8888_Config)
+ return false; // Only support ARGB 32 bpp skia bitmaps.
+
+ SkAutoLockPixels bitmapLock(bitmap);
+ IntSize imageSize(bitmap.width(), bitmap.height());
+ imageSize.clampNegativeToZero();
+ JPEGOutputBuffer destination;
+ destination.output = output;
+ Vector<JSAMPLE> row;
+
+ jpeg_compress_struct cinfo;
+ jpeg_error_mgr error;
+ cinfo.err = jpeg_std_error(&error);
+ error.error_exit = handleError;
+ jmp_buf jumpBuffer;
+ cinfo.client_data = &jumpBuffer;
+
+ if (setjmp(jumpBuffer)) {
+ jpeg_destroy_compress(&cinfo);
+ return false;
+ }
+
+ jpeg_create_compress(&cinfo);
+ cinfo.dest = &destination;
+ cinfo.dest->init_destination = prepareOutput;
+ cinfo.dest->empty_output_buffer = writeOutput;
+ cinfo.dest->term_destination = finishOutput;
+ cinfo.image_height = imageSize.height();
+ cinfo.image_width = imageSize.width();
+ cinfo.in_color_space = JCS_RGB;
+ cinfo.input_components = 3;
+
+ jpeg_set_defaults(&cinfo);
+ jpeg_set_quality(&cinfo, quality, TRUE);
+ jpeg_start_compress(&cinfo, TRUE);
+
+ const SkPMColor* pixels = static_cast<SkPMColor*>(bitmap.getPixels());
+ row.resize(cinfo.image_width * cinfo.input_components);
+ while (cinfo.next_scanline < cinfo.image_height) {
+ preMultipliedBGRAtoRGB(pixels, cinfo.image_width, row.data());
+ jpeg_write_scanlines(&cinfo, row.dataSlot(), 1);
+ pixels += cinfo.image_width;
+ }
+
+ jpeg_finish_compress(&cinfo);
+ jpeg_destroy_compress(&cinfo);
+ return true;
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/image-encoders/skia/JPEGImageEncoder.h b/WebCore/platform/image-encoders/skia/JPEGImageEncoder.h
new file mode 100644
index 0000000..f2ac52d
--- /dev/null
+++ b/WebCore/platform/image-encoders/skia/JPEGImageEncoder.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2010, Google 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:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "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 THE COPYRIGHT
+ * OWNER 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.
+ */
+
+#ifndef JPEGImageEncoder_h
+#define JPEGImageEncoder_h
+
+#include "Vector.h"
+
+class SkBitmap;
+
+namespace WebCore {
+
+class JPEGImageEncoder {
+public:
+ // Encode the input bitmap with a compression quality in [0-100].
+ static bool encode(const SkBitmap&, int quality, Vector<unsigned char>*);
+
+ // For callers: provide a reasonable compression quality default.
+ enum Quality { DefaultCompressionQuality = 92 };
+};
+
+} // namespace WebCore
+
+#endif
diff --git a/WebCore/platform/image-encoders/skia/PNGImageEncoder.cpp b/WebCore/platform/image-encoders/skia/PNGImageEncoder.cpp
index a2e8760..9fc82c4 100644
--- a/WebCore/platform/image-encoders/skia/PNGImageEncoder.cpp
+++ b/WebCore/platform/image-encoders/skia/PNGImageEncoder.cpp
@@ -1,10 +1,10 @@
/*
- * Copyright (c) 2006-2009, Google Inc. All rights reserved.
- *
+ * Copyright (c) 2010, Google 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:
- *
+ *
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
@@ -14,7 +14,7 @@
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -29,172 +29,66 @@
*/
#include "config.h"
-
-#include "IntSize.h"
-#include "OwnArrayPtr.h"
#include "PNGImageEncoder.h"
-#include "Vector.h"
+#include "IntSize.h"
#include "SkBitmap.h"
#include "SkUnPreMultiply.h"
-
extern "C" {
#include "png.h"
}
namespace WebCore {
-// Converts BGRA->RGBA and RGBA->BGRA.
-static void convertBetweenBGRAandRGBA(const unsigned char* input, int numberOfPixels,
- unsigned char* output)
+static void writeOutput(png_structp png, png_bytep data, png_size_t size)
{
- for (int x = 0; x < numberOfPixels; x++) {
- const unsigned char* pixelIn = &input[x * 4];
- unsigned char* pixelOut = &output[x * 4];
- pixelOut[0] = pixelIn[2];
- pixelOut[1] = pixelIn[1];
- pixelOut[2] = pixelIn[0];
- pixelOut[3] = pixelIn[3];
- }
+ static_cast<Vector<unsigned char>*>(png->io_ptr)->append(data, size);
}
-// Converts BGRA->RGBA and RGBA->BGRA and undoes alpha premultiplication.
-static void preMultipliedBGRAtoRGBA(const unsigned char* input, int numberOfPixels,
- unsigned char* output)
+static void preMultipliedBGRAtoRGBA(const SkPMColor* input, int pixels, unsigned char* output)
{
- SkBitmap inputBitmap;
- inputBitmap.setConfig(SkBitmap::kARGB_8888_Config, numberOfPixels, 1);
- inputBitmap.setPixels(const_cast<unsigned char*>(input));
- for (int x = 0; x < numberOfPixels; x++) {
- uint32_t srcPixel = *inputBitmap.getAddr32(x, 0);
- SkColor unmultiplied = SkUnPreMultiply::PMColorToColor(srcPixel);
- unsigned char* pixelOut = &output[x * 4];
- pixelOut[0] = SkColorGetR(unmultiplied);
- pixelOut[1] = SkColorGetG(unmultiplied);
- pixelOut[2] = SkColorGetB(unmultiplied);
- pixelOut[3] = SkColorGetA(unmultiplied);
+ while (pixels-- > 0) {
+ SkColor unmultiplied = SkUnPreMultiply::PMColorToColor(*input++);
+ *output++ = SkColorGetR(unmultiplied);
+ *output++ = SkColorGetG(unmultiplied);
+ *output++ = SkColorGetB(unmultiplied);
+ *output++ = SkColorGetA(unmultiplied);
}
}
-
-// Encoder --------------------------------------------------------------------
-//
-// This section of the code is based on nsPNGEncoder.cpp in Mozilla
-// (Copyright 2005 Google Inc.)
-
-// Passed around as the io_ptr in the png structs so our callbacks know where
-// to write data.
-struct PNGEncoderState {
- PNGEncoderState(Vector<unsigned char>* o) : m_out(o) {}
- Vector<unsigned char>* m_out;
-};
-
-// Called by libpng to flush its internal buffer to ours.
-void encoderWriteCallback(png_structp png, png_bytep data, png_size_t size)
+bool PNGImageEncoder::encode(const SkBitmap& bitmap, Vector<unsigned char>* output)
{
- PNGEncoderState* state = static_cast<PNGEncoderState*>(png_get_io_ptr(png));
- ASSERT(state->m_out);
+ if (bitmap.config() != SkBitmap::kARGB_8888_Config)
+ return false; // Only support ARGB 32 bpp skia bitmaps.
- size_t oldSize = state->m_out->size();
- state->m_out->resize(oldSize + size);
- memcpy(&(*state->m_out)[oldSize], data, size);
-}
-
-// Automatically destroys the given write structs on destruction to make
-// cleanup and error handling code cleaner.
-class PNGWriteStructDestroyer {
-public:
- PNGWriteStructDestroyer(png_struct** ps, png_info** pi)
- : m_pngStruct(ps)
- , m_pngInfo(pi) {
- }
-
- ~PNGWriteStructDestroyer() {
- png_destroy_write_struct(m_pngStruct, m_pngInfo);
- }
-
-private:
- png_struct** m_pngStruct;
- png_info** m_pngInfo;
-};
-
-static bool encodeImpl(const unsigned char* input,
- const IntSize& size,
- int bytesPerRow,
- Vector<unsigned char>* output,
- void (*conversionFunc)(const unsigned char*, int, unsigned char*)
- )
-{
- int inputColorComponents = 4;
- int outputColorComponents = 4;
- int pngOutputColorType = PNG_COLOR_TYPE_RGB_ALPHA;
- IntSize imageSize(size);
+ SkAutoLockPixels bitmapLock(bitmap);
+ IntSize imageSize(bitmap.width(), bitmap.height());
imageSize.clampNegativeToZero();
+ Vector<unsigned char> row;
- // Row stride should be at least as long as the length of the data.
- if (inputColorComponents * imageSize.width() > bytesPerRow) {
- ASSERT(false);
- return false;
- }
-
- png_struct* pngPtr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
- if (!pngPtr)
- return false;
-
- png_info* infoPtr = png_create_info_struct(pngPtr);
- if (!infoPtr) {
- png_destroy_write_struct(&pngPtr, NULL);
+ png_struct* png = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
+ png_info* info = png_create_info_struct(png);
+ if (!png || !info || setjmp(png_jmpbuf(png))) {
+ png_destroy_write_struct(png ? &png : 0, info ? &info : 0);
return false;
}
- PNGWriteStructDestroyer destroyer(&pngPtr, &infoPtr);
-
- if (setjmp(png_jmpbuf(pngPtr))) {
- // The destroyer will ensure that the structures are cleaned up in this
- // case, even though we may get here as a jump from random parts of the
- // PNG library called below.
- return false;
- }
-
- // Set our callback for libpng to give us the data.
- PNGEncoderState state(output);
- png_set_write_fn(pngPtr, &state, encoderWriteCallback, NULL);
-
- png_set_IHDR(pngPtr, infoPtr, imageSize.width(), imageSize.height(), 8, pngOutputColorType,
- PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
- PNG_FILTER_TYPE_DEFAULT);
- png_write_info(pngPtr, infoPtr);
- OwnArrayPtr<unsigned char> rowPixels(new unsigned char[imageSize.width() * outputColorComponents]);
- for (int y = 0; y < imageSize.height(); y ++) {
- conversionFunc(&input[y * bytesPerRow], imageSize.width(), rowPixels.get());
- png_write_row(pngPtr, rowPixels.get());
+ png_set_write_fn(png, output, writeOutput, 0);
+ png_set_IHDR(png, info, imageSize.width(), imageSize.height(),
+ 8, PNG_COLOR_TYPE_RGB_ALPHA, 0, 0, 0);
+ png_write_info(png, info);
+
+ const SkPMColor* pixels = static_cast<SkPMColor*>(bitmap.getPixels());
+ row.resize(imageSize.width() * bitmap.bytesPerPixel());
+ for (int y = 0; y < imageSize.height(); ++y) {
+ preMultipliedBGRAtoRGBA(pixels, imageSize.width(), row.data());
+ png_write_row(png, row.data());
+ pixels += imageSize.width();
}
- png_write_end(pngPtr, infoPtr);
+ png_write_end(png, info);
+ png_destroy_write_struct(&png, &info);
return true;
}
-
-// static
-bool PNGImageEncoder::encode(const SkBitmap& image, Vector<unsigned char>* output)
-{
- if (image.config() != SkBitmap::kARGB_8888_Config)
- return false; // Only support ARGB at 8 bpp now.
-
- image.lockPixels();
- bool result = encodeImpl(static_cast<unsigned char*>(
- image.getPixels()), IntSize(image.width(), image.height()),
- image.rowBytes(), output, preMultipliedBGRAtoRGBA);
- image.unlockPixels();
- return result;
-}
-
-// static
-bool PNGImageEncoder::encode(const unsigned char* input, const IntSize& size,
- int bytesPerRow,
- Vector<unsigned char>* output)
-{
- return encodeImpl(input, size, bytesPerRow, output, convertBetweenBGRAandRGBA);
-}
-
-} // namespace WebCore
+} // namespace WebCore
diff --git a/WebCore/platform/image-encoders/skia/PNGImageEncoder.h b/WebCore/platform/image-encoders/skia/PNGImageEncoder.h
index b5865d2..b8dfec3 100644
--- a/WebCore/platform/image-encoders/skia/PNGImageEncoder.h
+++ b/WebCore/platform/image-encoders/skia/PNGImageEncoder.h
@@ -1,10 +1,10 @@
/*
- * Copyright (c) 2006-2009, Google Inc. All rights reserved.
+ * Copyright (c) 2010, Google 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:
- *
+ *
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
@@ -14,7 +14,7 @@
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -33,23 +33,16 @@
#include "Vector.h"
-class IntSize;
class SkBitmap;
namespace WebCore {
- // Interface for encoding PNG data. This is a wrapper around libpng.
- class PNGImageEncoder {
- public:
- // Encodes the specific SkBitmap into the supplied vector.
- static bool encode(const SkBitmap&, WTF::Vector<unsigned char>* output);
-
- // Encodes the specified image data into the supplied vector.
- // w, h give the size of the image and bytes_per_row gives the bytes
- // per row.
- static bool encode(const unsigned char* input, const IntSize& size, int bytesPerRow, WTF::Vector<unsigned char>* output);
- };
+// Interface for encoding PNG data. This is a wrapper around libpng.
+class PNGImageEncoder {
+public:
+ static bool encode(const SkBitmap&, Vector<unsigned char>* output);
+};
-} // namespace WebCore
+} // namespace WebCore
#endif
diff --git a/WebCore/platform/mac/ContextMenuMac.mm b/WebCore/platform/mac/ContextMenuMac.mm
index 7c91028..c9451b9 100644
--- a/WebCore/platform/mac/ContextMenuMac.mm
+++ b/WebCore/platform/mac/ContextMenuMac.mm
@@ -28,92 +28,27 @@
#if ENABLE(CONTEXT_MENUS)
-#include "ContextMenuController.h"
-
-@interface WebCoreMenuTarget : NSObject {
- WebCore::ContextMenuController* _menuController;
-}
-+ (WebCoreMenuTarget*)sharedMenuTarget;
-- (WebCore::ContextMenuController*)menuController;
-- (void)setMenuController:(WebCore::ContextMenuController*)menuController;
-- (void)forwardContextMenuAction:(id)sender;
-- (BOOL)validateMenuItem:(NSMenuItem *)item;
-@end
-
-static WebCoreMenuTarget* target;
-
-@implementation WebCoreMenuTarget
-
-+ (WebCoreMenuTarget*)sharedMenuTarget
-{
- if (!target)
- target = [[WebCoreMenuTarget alloc] init];
- return target;
-}
-
-- (WebCore::ContextMenuController*)menuController
-{
- return _menuController;
-}
-
-- (void)setMenuController:(WebCore::ContextMenuController*)menuController
-{
- _menuController = menuController;
-}
-
-- (void)forwardContextMenuAction:(id)sender
-{
- WebCore::ContextMenuItem item(WebCore::ActionType, static_cast<WebCore::ContextMenuAction>([sender tag]), [sender title]);
- _menuController->contextMenuItemSelected(&item);
-}
-
-- (BOOL)validateMenuItem:(NSMenuItem *)item
-{
- WebCore::ContextMenuItem coreItem(item);
- ASSERT(_menuController->contextMenu());
- _menuController->contextMenu()->checkOrEnableIfNeeded(coreItem);
- return coreItem.enabled();
-}
-
-@end
-
namespace WebCore {
-ContextMenu::ContextMenu(const HitTestResult& result)
- : m_hitTestResult(result)
+ContextMenu::ContextMenu()
{
NSMutableArray* array = [[NSMutableArray alloc] init];
m_platformDescription = array;
[array release];
-
- [[WebCoreMenuTarget sharedMenuTarget] setMenuController:controller()];
}
-ContextMenu::ContextMenu(const HitTestResult& result, const PlatformMenuDescription menu)
- : m_hitTestResult(result)
- , m_platformDescription(menu)
+ContextMenu::ContextMenu(const PlatformMenuDescription menu)
+ : m_platformDescription(menu)
{
- [[WebCoreMenuTarget sharedMenuTarget] setMenuController:controller()];
}
ContextMenu::~ContextMenu()
{
}
-
-static void setMenuItemTarget(NSMenuItem* menuItem)
-{
- [menuItem setTarget:[WebCoreMenuTarget sharedMenuTarget]];
- [menuItem setAction:@selector(forwardContextMenuAction:)];
-}
void ContextMenu::appendItem(ContextMenuItem& item)
{
- checkOrEnableIfNeeded(item);
-
- ContextMenuItemType type = item.type();
NSMenuItem* platformItem = item.releasePlatformDescription();
- if (type == ActionType)
- setMenuItemTarget(platformItem);
[m_platformDescription.get() addObject:platformItem];
[platformItem release];
@@ -121,12 +56,7 @@ void ContextMenu::appendItem(ContextMenuItem& item)
void ContextMenu::insertItem(unsigned position, ContextMenuItem& item)
{
- checkOrEnableIfNeeded(item);
-
- ContextMenuItemType type = item.type();
NSMenuItem* platformItem = item.releasePlatformDescription();
- if (type == ActionType)
- setMenuItemTarget(platformItem);
[m_platformDescription.get() insertObject:platformItem atIndex:position];
[platformItem release];
diff --git a/WebCore/platform/mac/GeolocationServiceMac.h b/WebCore/platform/mac/GeolocationServiceMac.h
deleted file mode 100644
index 4beefca..0000000
--- a/WebCore/platform/mac/GeolocationServiceMac.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2009 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.
- */
-
-#ifndef GeolocationServiceMac_h
-#define GeolocationServiceMac_h
-
-#if ENABLE(GEOLOCATION)
-
-#include "GeolocationService.h"
-#include <wtf/PassRefPtr.h>
-#include <wtf/RefPtr.h>
-#include <wtf/RetainPtr.h>
-
-#ifdef __OBJC__
-@class CLLocationManager;
-@class WebCoreCoreLocationObserver;
-#else
-class CLLocationManager;
-class WebCoreCoreLocationObserver;
-#endif
-
-namespace WebCore {
-
-class GeolocationServiceMac : public GeolocationService {
-public:
- static GeolocationService* create(GeolocationServiceClient*);
- virtual ~GeolocationServiceMac();
-
- virtual bool startUpdating(PositionOptions*);
- virtual void stopUpdating();
-
- virtual void suspend();
- virtual void resume();
-
- virtual Geoposition* lastPosition() const { return m_lastPosition.get(); }
- virtual PositionError* lastError() const { return m_lastError.get(); }
-
- void positionChanged(PassRefPtr<Geoposition>);
- void errorOccurred(PassRefPtr<PositionError>);
-
-private:
- GeolocationServiceMac(GeolocationServiceClient*);
-
- RetainPtr<CLLocationManager> m_locationManager;
- RetainPtr<WebCoreCoreLocationObserver> m_objcObserver;
-
- RefPtr<Geoposition> m_lastPosition;
- RefPtr<PositionError> m_lastError;
-};
-
-} // namespace WebCore
-
-#endif // ENABLE(GEOLOCATION)
-
-#endif // GeolocationServiceMac_h
diff --git a/WebCore/platform/mac/GeolocationServiceMac.mm b/WebCore/platform/mac/GeolocationServiceMac.mm
deleted file mode 100644
index 9c781ad..0000000
--- a/WebCore/platform/mac/GeolocationServiceMac.mm
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * Copyright (C) 2009 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.
- */
-
-#import "config.h"
-
-#if ENABLE(GEOLOCATION) && !ENABLE(CLIENT_BASED_GEOLOCATION)
-
-#import "GeolocationServiceMac.h"
-
-#import "Geoposition.h"
-#import "PositionError.h"
-#import "PositionOptions.h"
-#import "SoftLinking.h"
-#import <CoreLocation/CoreLocation.h>
-#import <objc/objc-runtime.h>
-#import <wtf/RefPtr.h>
-#import <wtf/UnusedParam.h>
-
-SOFT_LINK_FRAMEWORK(CoreLocation)
-
-SOFT_LINK_CLASS(CoreLocation, CLLocationManager)
-SOFT_LINK_CLASS(CoreLocation, CLLocation)
-
-SOFT_LINK_CONSTANT(CoreLocation, kCLLocationAccuracyBest, double)
-SOFT_LINK_CONSTANT(CoreLocation, kCLLocationAccuracyHundredMeters, double)
-
-#define kCLLocationAccuracyBest getkCLLocationAccuracyBest()
-#define kCLLocationAccuracyHundredMeters getkCLLocationAccuracyHundredMeters()
-
-using namespace WebCore;
-
-@interface WebCoreCoreLocationObserver : NSObject<CLLocationManagerDelegate>
-{
- GeolocationServiceMac* m_callback;
-}
-
-- (id)initWithCallback:(GeolocationServiceMac*)callback;
-
-- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation;
-- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error;
-
-@end
-
-namespace WebCore {
-
-GeolocationService* GeolocationServiceMac::create(GeolocationServiceClient* client)
-{
- return new GeolocationServiceMac(client);
-}
-
-GeolocationService::FactoryFunction* GeolocationService::s_factoryFunction = &GeolocationServiceMac::create;
-
-GeolocationServiceMac::GeolocationServiceMac(GeolocationServiceClient* client)
- : GeolocationService(client)
- , m_objcObserver(AdoptNS, [[WebCoreCoreLocationObserver alloc] initWithCallback:this])
-{
-}
-
-GeolocationServiceMac::~GeolocationServiceMac()
-{
- [m_locationManager.get() stopUpdatingLocation];
- m_locationManager.get().delegate = nil;
-}
-
-bool GeolocationServiceMac::startUpdating(PositionOptions* options)
-{
- #define CLLocationManager getCLLocationManagerClass()
- if (!m_locationManager.get()) {
- m_locationManager.adoptNS([[CLLocationManager alloc] init]);
- m_locationManager.get().delegate = m_objcObserver.get();
- }
-
- if (!m_locationManager.get().locationServicesEnabled)
- return false;
-
- if (options) {
- // CLLocationAccuracy values suggested by Ron Huang.
- CLLocationAccuracy accuracy = options->enableHighAccuracy() ? kCLLocationAccuracyBest : kCLLocationAccuracyHundredMeters;
- m_locationManager.get().desiredAccuracy = accuracy;
- }
-
- // This can safely be called multiple times.
- [m_locationManager.get() startUpdatingLocation];
-
- return true;
- #undef CLLocationManager
-}
-
-void GeolocationServiceMac::stopUpdating()
-{
- [m_locationManager.get() stopUpdatingLocation];
-}
-
-void GeolocationServiceMac::suspend()
-{
- [m_locationManager.get() stopUpdatingLocation];
-}
-
-void GeolocationServiceMac::resume()
-{
- [m_locationManager.get() startUpdatingLocation];
-}
-
-void GeolocationServiceMac::positionChanged(PassRefPtr<Geoposition> position)
-{
- m_lastPosition = position;
- GeolocationService::positionChanged();
-}
-
-void GeolocationServiceMac::errorOccurred(PassRefPtr<PositionError> error)
-{
- m_lastError = error;
- GeolocationService::errorOccurred();
-}
-
-} // namespace WebCore
-
-@implementation WebCoreCoreLocationObserver
-
-- (id)initWithCallback:(GeolocationServiceMac *)callback
-{
- self = [super init];
- if (self)
- m_callback = callback;
- return self;
-}
-
-- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
-{
- ASSERT(m_callback);
- ASSERT(newLocation);
- UNUSED_PARAM(manager);
- UNUSED_PARAM(oldLocation);
-
- // Normalize
- bool canProvideAltitude = true;
- bool canProvideAltitudeAccuracy = true;
- double altitude = newLocation.altitude;
- double altitudeAccuracy = newLocation.verticalAccuracy;
- if (altitudeAccuracy < 0.0) {
- canProvideAltitude = false;
- canProvideAltitudeAccuracy = false;
- }
-
- bool canProvideSpeed = true;
- double speed = newLocation.speed;
- if (speed < 0.0)
- canProvideSpeed = false;
-
- bool canProvideHeading = true;
- double heading = newLocation.course;
- if (heading < 0.0)
- canProvideHeading = false;
-
- WTF::RefPtr<WebCore::Coordinates> newCoordinates = WebCore::Coordinates::create(
- newLocation.coordinate.latitude,
- newLocation.coordinate.longitude,
- canProvideAltitude,
- altitude,
- newLocation.horizontalAccuracy,
- canProvideAltitudeAccuracy,
- altitudeAccuracy,
- canProvideHeading,
- heading,
- canProvideSpeed,
- speed);
- WTF::RefPtr<WebCore::Geoposition> newPosition = WebCore::Geoposition::create(
- newCoordinates.release(),
- [newLocation.timestamp timeIntervalSince1970] * 1000.0); // seconds -> milliseconds
-
- m_callback->positionChanged(newPosition.release());
-}
-
-- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
-{
- ASSERT(m_callback);
- ASSERT(error);
-
- UNUSED_PARAM(manager);
-
- PositionError::ErrorCode code;
- switch ([error code]) {
- case kCLErrorDenied:
- code = PositionError::PERMISSION_DENIED;
- break;
- case kCLErrorLocationUnknown:
- code = PositionError::POSITION_UNAVAILABLE;
- break;
- default:
- code = PositionError::POSITION_UNAVAILABLE;
- break;
- }
-
- m_callback->errorOccurred(PositionError::create(code, [error localizedDescription]));
-}
-
-@end
-
-#endif // ENABLE(GEOLOCATION)
diff --git a/WebCore/platform/mac/ScrollAnimatorMac.cpp b/WebCore/platform/mac/ScrollAnimatorMac.cpp
deleted file mode 100644
index f127a62..0000000
--- a/WebCore/platform/mac/ScrollAnimatorMac.cpp
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2010 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. AND ITS CONTRIBUTORS ``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 ITS 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"
-
-#if ENABLE(SMOOTH_SCROLLING)
-
-#include "ScrollAnimatorMac.h"
-
-namespace WebCore {
-
-ScrollAnimator* ScrollAnimator::create(ScrollbarClient* client)
-{
- return new ScrollAnimatorMac(client);
-}
-
-ScrollAnimatorMac::ScrollAnimatorMac(ScrollbarClient* client)
- : ScrollAnimator(client)
-{
-}
-
-ScrollAnimatorMac::~ScrollAnimatorMac()
-{
-}
-
-bool ScrollAnimatorMac::scroll(ScrollbarOrientation orientation, ScrollGranularity granularity, float step, float multiplier)
-{
- return ScrollAnimator::scroll(orientation, granularity, step, multiplier);
-}
-
-void ScrollAnimatorMac::setScrollPositionAndStopAnimation(ScrollbarOrientation orientation, float pos)
-{
- return ScrollAnimator::setScrollPositionAndStopAnimation(orientation, pos);
-}
-
-} // namespace WebCore
-
-#endif // ENABLE(SMOOTH_SCROLLING)
diff --git a/WebCore/platform/mac/ScrollAnimatorMac.h b/WebCore/platform/mac/ScrollAnimatorMac.h
index 3beaa4e..234e43c 100644
--- a/WebCore/platform/mac/ScrollAnimatorMac.h
+++ b/WebCore/platform/mac/ScrollAnimatorMac.h
@@ -28,8 +28,15 @@
#if ENABLE(SMOOTH_SCROLLING)
+#include "FloatPoint.h"
#include "ScrollAnimator.h"
-#include "Timer.h"
+#include <wtf/RetainPtr.h>
+
+#ifdef __OBJC__
+@class ScrollAnimationHelperDelegate;
+#else
+class ScrollAnimationHelperDelegate;
+#endif
namespace WebCore {
@@ -40,6 +47,14 @@ public:
virtual bool scroll(ScrollbarOrientation, ScrollGranularity, float step, float multiplier);
virtual void setScrollPositionAndStopAnimation(ScrollbarOrientation, float position);
+
+ // Called by the ScrollAnimationHelperDelegate.
+ FloatPoint currentPosition() const;
+ void immediateScrollToPoint(const FloatPoint& newPosition);
+
+private:
+ RetainPtr<id> m_scrollAnimationHelper;
+ RetainPtr<ScrollAnimationHelperDelegate> m_scrollAnimationHelperDelegate;
};
} // namespace WebCore
diff --git a/WebCore/platform/mac/ScrollAnimatorMac.mm b/WebCore/platform/mac/ScrollAnimatorMac.mm
new file mode 100644
index 0000000..ca71bd3
--- /dev/null
+++ b/WebCore/platform/mac/ScrollAnimatorMac.mm
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2010 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. AND ITS CONTRIBUTORS ``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 ITS 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"
+
+#if ENABLE(SMOOTH_SCROLLING)
+
+#include "ScrollAnimatorMac.h"
+#include "ScrollbarClient.h"
+
+@interface NSObject (NSScrollAnimationHelperDetails)
+- (id)initWithDelegate:(id)delegate;
+- (void)_stopRun;
+- (BOOL)_isAnimating;
+- (NSPoint)targetOrigin;
+@end
+
+@interface ScrollAnimationHelperDelegate : NSObject
+{
+ WebCore::ScrollAnimatorMac* _animator;
+}
+
+- (id)initWithScrollAnimator:(WebCore::ScrollAnimatorMac*)scrollAnimator;
+
+- (NSRect)bounds;
+- (void)_immediateScrollToPoint:(NSPoint)newPosition;
+- (NSSize)convertSizeToBase:(NSSize)size;
+- (NSSize)convertSizeFromBase:(NSSize)size;
+
+- (id)superview; // Return nil.
+- (id)documentView; // Return nil.
+- (id)window; // Return nil.
+- (void)_recursiveRecomputeToolTips; // No-op.
+@end
+
+static NSSize abs(NSSize size)
+{
+ NSSize finalSize = size;
+ if (finalSize.width < 0)
+ finalSize.width = -finalSize.width;
+ if (finalSize.height < 0)
+ finalSize.height = -finalSize.height;
+ return finalSize;
+}
+
+@implementation ScrollAnimationHelperDelegate
+
+- (id)initWithScrollAnimator:(WebCore::ScrollAnimatorMac*)scrollAnimator
+{
+ self = [super init];
+ if (!self)
+ return nil;
+
+ _animator = scrollAnimator;
+ return self;
+}
+
+- (NSRect)bounds
+{
+ WebCore::FloatPoint currentPosition = _animator->currentPosition();
+ return NSMakeRect(currentPosition.x(), currentPosition.y(), 0, 0);
+}
+
+- (void)_immediateScrollToPoint:(NSPoint)newPosition
+{
+ _animator->immediateScrollToPoint(newPosition);
+}
+
+- (NSSize)convertSizeToBase:(NSSize)size
+{
+ return abs(size);
+}
+
+- (NSSize)convertSizeFromBase:(NSSize)size
+{
+ return abs(size);
+}
+
+- (id)superview
+{
+ return nil;
+}
+
+- (id)documentView
+{
+ return nil;
+}
+
+- (id)window
+{
+ return nil;
+}
+
+- (void)_recursiveRecomputeToolTips
+{
+}
+
+@end
+
+namespace WebCore {
+
+ScrollAnimator* ScrollAnimator::create(ScrollbarClient* client)
+{
+ return new ScrollAnimatorMac(client);
+}
+
+ScrollAnimatorMac::ScrollAnimatorMac(ScrollbarClient* client)
+ : ScrollAnimator(client)
+{
+ m_scrollAnimationHelperDelegate.adoptNS([[ScrollAnimationHelperDelegate alloc] initWithScrollAnimator:this]);
+ m_scrollAnimationHelper.adoptNS([[NSClassFromString(@"NSScrollAnimationHelper") alloc] initWithDelegate:m_scrollAnimationHelperDelegate.get()]);
+}
+
+ScrollAnimatorMac::~ScrollAnimatorMac()
+{
+}
+
+bool ScrollAnimatorMac::scroll(ScrollbarOrientation orientation, ScrollGranularity granularity, float step, float multiplier)
+{
+ if (![[NSUserDefaults standardUserDefaults] boolForKey:@"AppleScrollAnimationEnabled"])
+ return ScrollAnimator::scroll(orientation, granularity, step, multiplier);
+
+ if (granularity == ScrollByPixel)
+ return ScrollAnimator::scroll(orientation, granularity, step, multiplier);
+
+ float currentPos = orientation == HorizontalScrollbar ? m_currentPosX : m_currentPosY;
+ float newPos = std::max<float>(std::min<float>(currentPos + (step * multiplier), static_cast<float>(m_client->scrollSize(orientation))), 0);
+ if (currentPos == newPos)
+ return false;
+
+ NSPoint newPoint;
+ if ([m_scrollAnimationHelper.get() _isAnimating]) {
+ NSPoint targetOrigin = [m_scrollAnimationHelper.get() targetOrigin];
+ newPoint = orientation == HorizontalScrollbar ? NSMakePoint(newPos, targetOrigin.y) : NSMakePoint(targetOrigin.x, newPos);
+ } else
+ newPoint = orientation == HorizontalScrollbar ? NSMakePoint(newPos, m_currentPosY) : NSMakePoint(m_currentPosX, newPos);
+
+ [m_scrollAnimationHelper.get() scrollToPoint:newPoint];
+ return true;
+}
+
+void ScrollAnimatorMac::setScrollPositionAndStopAnimation(ScrollbarOrientation orientation, float pos)
+{
+ [m_scrollAnimationHelper.get() _stopRun];
+ ScrollAnimator::setScrollPositionAndStopAnimation(orientation, pos);
+}
+
+FloatPoint ScrollAnimatorMac::currentPosition() const
+{
+ return FloatPoint(m_currentPosX, m_currentPosY);
+}
+
+void ScrollAnimatorMac::immediateScrollToPoint(const FloatPoint& newPosition)
+{
+ m_currentPosX = newPosition.x();
+ m_currentPosY = newPosition.y();
+
+ m_client->setScrollOffsetFromAnimation(IntPoint(m_currentPosX, m_currentPosY));
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(SMOOTH_SCROLLING)
diff --git a/WebCore/platform/mac/ScrollViewMac.mm b/WebCore/platform/mac/ScrollViewMac.mm
index 7e415da..93ec971 100644
--- a/WebCore/platform/mac/ScrollViewMac.mm
+++ b/WebCore/platform/mac/ScrollViewMac.mm
@@ -147,7 +147,8 @@ void ScrollView::platformSetScrollbarsSuppressed(bool repaintOnUnsuppress)
void ScrollView::platformSetScrollPosition(const IntPoint& scrollPoint)
{
BEGIN_BLOCK_OBJC_EXCEPTIONS;
- NSPoint tempPoint = { max(-[scrollView() scrollOriginX], scrollPoint.x()), max(0, scrollPoint.y()) }; // Don't use NSMakePoint to work around 4213314.
+ NSPoint floatPoint = scrollPoint;
+ NSPoint tempPoint = { max(-[scrollView() scrollOrigin].x, floatPoint.x), max(-[scrollView() scrollOrigin].y, floatPoint.y) }; // Don't use NSMakePoint to work around 4213314.
[documentView() scrollPoint:tempPoint];
END_BLOCK_OBJC_EXCEPTIONS;
}
@@ -202,10 +203,10 @@ bool ScrollView::platformIsOffscreen() const
return ![platformWidget() window] || ![[platformWidget() window] isVisible];
}
-void ScrollView::platformSetScrollOriginX(int x)
+void ScrollView::platformSetScrollOrigin(const IntPoint& origin, bool updatePosition)
{
BEGIN_BLOCK_OBJC_EXCEPTIONS;
- [scrollView() setScrollOriginX:x];
+ [scrollView() setScrollOrigin:origin updatePosition:updatePosition];
END_BLOCK_OBJC_EXCEPTIONS;
}
diff --git a/WebCore/platform/mac/WebCoreSystemInterface.h b/WebCore/platform/mac/WebCoreSystemInterface.h
index 201266e..0c78c23 100644
--- a/WebCore/platform/mac/WebCoreSystemInterface.h
+++ b/WebCore/platform/mac/WebCoreSystemInterface.h
@@ -29,6 +29,10 @@
#include <ApplicationServices/ApplicationServices.h>
#include <objc/objc.h>
+#if PLATFORM(MAC) && PLATFORM(CA) && !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
+#include <IOSurface/IOSurface.h>
+#endif
+
typedef struct _NSRange NSRange;
#ifdef NSGEOMETRY_TYPES_SAME_AS_CGGEOMETRY_TYPES
@@ -179,6 +183,9 @@ extern CFIndex (*wkGetHyphenationLocationBeforeIndex)(CFStringRef string, CFInde
extern CTLineRef (*wkCreateCTLineWithUniCharProvider)(const UniChar* (*provide)(CFIndex stringIndex, CFIndex* charCount, CFDictionaryRef* attributes, void*), void (*dispose)(const UniChar* chars, void*), void*);
#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
extern CTTypesetterRef (*wkCreateCTTypesetterWithUniCharProviderAndOptions)(const UniChar* (*provide)(CFIndex stringIndex, CFIndex* charCount, CFDictionaryRef* attributes, void*), void (*dispose)(const UniChar* chars, void*), void*, CFDictionaryRef options);
+
+extern CGContextRef (*wkIOSurfaceContextCreate)(IOSurfaceRef surface, unsigned width, unsigned height, CGColorSpaceRef colorSpace);
+extern CGImageRef (*wkIOSurfaceContextCreateImage)(CGContextRef context);
#endif
}
diff --git a/WebCore/platform/mac/WebCoreSystemInterface.mm b/WebCore/platform/mac/WebCoreSystemInterface.mm
index 9c0c441..df3c77c 100644
--- a/WebCore/platform/mac/WebCoreSystemInterface.mm
+++ b/WebCore/platform/mac/WebCoreSystemInterface.mm
@@ -122,4 +122,7 @@ CFIndex (*wkGetHyphenationLocationBeforeIndex)(CFStringRef string, CFIndex index
CTLineRef (*wkCreateCTLineWithUniCharProvider)(const UniChar* (*provide)(CFIndex stringIndex, CFIndex* charCount, CFDictionaryRef* attributes, void*), void (*dispose)(const UniChar* chars, void*), void*);
#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
CTTypesetterRef (*wkCreateCTTypesetterWithUniCharProviderAndOptions)(const UniChar* (*provide)(CFIndex stringIndex, CFIndex* charCount, CFDictionaryRef* attributes, void*), void (*dispose)(const UniChar* chars, void*), void*, CFDictionaryRef options);
+
+CGContextRef (*wkIOSurfaceContextCreate)(IOSurfaceRef surface, unsigned width, unsigned height, CGColorSpaceRef colorSpace);
+CGImageRef (*wkIOSurfaceContextCreateImage)(CGContextRef context);
#endif
diff --git a/WebCore/platform/mock/GeolocationClientMock.cpp b/WebCore/platform/mock/GeolocationClientMock.cpp
index 3c4697f..5255b34 100644
--- a/WebCore/platform/mock/GeolocationClientMock.cpp
+++ b/WebCore/platform/mock/GeolocationClientMock.cpp
@@ -41,8 +41,10 @@ namespace WebCore {
GeolocationClientMock::GeolocationClientMock()
: m_controller(0)
- , m_timer(this, &GeolocationClientMock::timerFired)
+ , m_controllerTimer(this, &GeolocationClientMock::controllerTimerFired)
+ , m_permissionTimer(this, &GeolocationClientMock::permissionTimerFired)
, m_isActive(false)
+ , m_permissionState(PermissionStateUnset)
{
}
@@ -71,10 +73,55 @@ void GeolocationClientMock::setError(PassRefPtr<GeolocationError> error)
asyncUpdateController();
}
+void GeolocationClientMock::setPermission(bool allowed)
+{
+ m_permissionState = allowed ? PermissionStateAllowed : PermissionStateDenied;
+ asyncUpdatePermission();
+}
+
+void GeolocationClientMock::requestPermission(Geolocation* geolocation)
+{
+ m_pendingPermission.add(geolocation);
+ if (m_permissionState != PermissionStateUnset)
+ asyncUpdatePermission();
+}
+
+void GeolocationClientMock::cancelPermissionRequest(Geolocation* geolocation)
+{
+ // Called from Geolocation::disconnectFrame() in response to Frame destruction.
+ m_pendingPermission.remove(geolocation);
+ if (m_pendingPermission.isEmpty() && m_permissionTimer.isActive())
+ m_permissionTimer.stop();
+}
+
+void GeolocationClientMock::asyncUpdatePermission()
+{
+ ASSERT(m_permissionState != PermissionStateUnset);
+ if (!m_permissionTimer.isActive())
+ m_permissionTimer.startOneShot(0);
+}
+
+void GeolocationClientMock::permissionTimerFired(WebCore::Timer<GeolocationClientMock>* timer)
+{
+ ASSERT_UNUSED(timer, timer == &m_permissionTimer);
+ ASSERT(m_permissionState != PermissionStateUnset);
+ bool allowed = m_permissionState == PermissionStateAllowed;
+ GeolocationSet::iterator end = m_pendingPermission.end();
+
+ // Once permission has been set (or denied) on a Geolocation object, there can be
+ // no further requests for permission to the mock. Consequently the callbacks
+ // which fire synchronously from Geolocation::setIsAllowed() cannot reentrantly modify
+ // m_pendingPermission.
+ for (GeolocationSet::iterator it = m_pendingPermission.begin(); it != end; ++it)
+ (*it)->setIsAllowed(allowed);
+ m_pendingPermission.clear();
+}
+
void GeolocationClientMock::reset()
{
m_lastPosition = 0;
m_lastError = 0;
+ m_permissionState = PermissionStateUnset;
}
void GeolocationClientMock::geolocationDestroyed()
@@ -93,7 +140,7 @@ void GeolocationClientMock::stopUpdating()
{
ASSERT(m_isActive);
m_isActive = false;
- m_timer.stop();
+ m_controllerTimer.stop();
}
void GeolocationClientMock::setEnableHighAccuracy(bool)
@@ -110,18 +157,13 @@ GeolocationPosition* GeolocationClientMock::lastPosition()
void GeolocationClientMock::asyncUpdateController()
{
ASSERT(m_controller);
- if (m_isActive && !m_timer.isActive())
- m_timer.startOneShot(0);
-}
-
-void GeolocationClientMock::timerFired(Timer<GeolocationClientMock>* timer)
-{
- ASSERT_UNUSED(timer, timer == &m_timer);
- updateController();
+ if (m_isActive && !m_controllerTimer.isActive())
+ m_controllerTimer.startOneShot(0);
}
-void GeolocationClientMock::updateController()
+void GeolocationClientMock::controllerTimerFired(Timer<GeolocationClientMock>* timer)
{
+ ASSERT_UNUSED(timer, timer == &m_controllerTimer);
ASSERT(m_controller);
if (m_lastPosition.get())
diff --git a/WebCore/platform/mock/GeolocationClientMock.h b/WebCore/platform/mock/GeolocationClientMock.h
index f57afa9..df35316 100644
--- a/WebCore/platform/mock/GeolocationClientMock.h
+++ b/WebCore/platform/mock/GeolocationClientMock.h
@@ -37,6 +37,7 @@
#include "PlatformString.h"
#include "Timer.h"
+#include <wtf/HashSet.h>
#include <wtf/PassRefPtr.h>
#include <wtf/RefPtr.h>
@@ -57,6 +58,7 @@ public:
void setError(PassRefPtr<GeolocationError>);
void setPosition(PassRefPtr<GeolocationPosition>);
+ void setPermission(bool allowed);
// GeolocationClient
virtual void geolocationDestroyed();
@@ -64,17 +66,30 @@ public:
virtual void stopUpdating();
virtual void setEnableHighAccuracy(bool);
virtual GeolocationPosition* lastPosition();
+ virtual void requestPermission(Geolocation*);
+ virtual void cancelPermissionRequest(Geolocation*);
private:
- void timerFired(Timer<GeolocationClientMock>*);
void asyncUpdateController();
- void updateController();
+ void controllerTimerFired(Timer<GeolocationClientMock>*);
+
+ void asyncUpdatePermission();
+ void permissionTimerFired(Timer<GeolocationClientMock>*);
GeolocationController* m_controller;
RefPtr<GeolocationPosition> m_lastPosition;
RefPtr<GeolocationError> m_lastError;
- Timer<GeolocationClientMock> m_timer;
+ Timer<GeolocationClientMock> m_controllerTimer;
+ Timer<GeolocationClientMock> m_permissionTimer;
bool m_isActive;
+
+ enum PermissionState {
+ PermissionStateUnset,
+ PermissionStateAllowed,
+ PermissionStateDenied,
+ } m_permissionState;
+ typedef WTF::HashSet<RefPtr<Geolocation> > GeolocationSet;
+ GeolocationSet m_pendingPermission;
};
}
diff --git a/WebCore/platform/network/ResourceRequestBase.cpp b/WebCore/platform/network/ResourceRequestBase.cpp
index 5312007..ae8316a 100644
--- a/WebCore/platform/network/ResourceRequestBase.cpp
+++ b/WebCore/platform/network/ResourceRequestBase.cpp
@@ -234,6 +234,16 @@ void ResourceRequestBase::setHTTPHeaderField(const char* name, const String& val
setHTTPHeaderField(AtomicString(name), value);
}
+void ResourceRequestBase::clearHTTPAuthorization()
+{
+ updateResourceRequest();
+
+ m_httpHeaderFields.remove("Authorization");
+
+ if (url().protocolInHTTPFamily())
+ m_platformRequestUpdated = false;
+}
+
void ResourceRequestBase::clearHTTPReferrer()
{
updateResourceRequest();
diff --git a/WebCore/platform/network/ResourceRequestBase.h b/WebCore/platform/network/ResourceRequestBase.h
index 33a184e..5cb7ee3 100644
--- a/WebCore/platform/network/ResourceRequestBase.h
+++ b/WebCore/platform/network/ResourceRequestBase.h
@@ -100,6 +100,8 @@ namespace WebCore {
void addHTTPHeaderField(const AtomicString& name, const String& value);
void addHTTPHeaderFields(const HTTPHeaderMap& headerFields);
+ void clearHTTPAuthorization();
+
String httpContentType() const { return httpHeaderField("Content-Type"); }
void setHTTPContentType(const String& httpContentType) { setHTTPHeaderField("Content-Type", httpContentType); }
diff --git a/WebCore/platform/network/SocketStreamErrorBase.cpp b/WebCore/platform/network/SocketStreamErrorBase.cpp
index 72fb44c..bbb5d55 100644
--- a/WebCore/platform/network/SocketStreamErrorBase.cpp
+++ b/WebCore/platform/network/SocketStreamErrorBase.cpp
@@ -42,7 +42,22 @@ SocketStreamError SocketStreamErrorBase::copy() const
bool SocketStreamErrorBase::compare(const SocketStreamError& a, const SocketStreamError& b)
{
- return a.errorCode() == b.errorCode();
+ if (a.isNull() && b.isNull())
+ return true;
+
+ if (a.isNull() || b.isNull())
+ return false;
+
+ if (a.errorCode() != b.errorCode())
+ return false;
+
+ if (a.failingURL() != b.failingURL())
+ return false;
+
+ if (a.localizedDescription() != b.localizedDescription())
+ return false;
+
+ return true;
}
} // namespace WebCore
diff --git a/WebCore/platform/network/SocketStreamErrorBase.h b/WebCore/platform/network/SocketStreamErrorBase.h
index b7ca35b..e6cc567 100644
--- a/WebCore/platform/network/SocketStreamErrorBase.h
+++ b/WebCore/platform/network/SocketStreamErrorBase.h
@@ -32,6 +32,8 @@
#ifndef SocketStreamErrorBase_h
#define SocketStreamErrorBase_h
+#include "PlatformString.h"
+
namespace WebCore {
class SocketStreamError;
@@ -44,6 +46,8 @@ namespace WebCore {
bool isNull() const { return m_isNull; }
int errorCode() const { return m_errorCode; }
+ const String& failingURL() const { return m_failingURL; }
+ const String& localizedDescription() const { return m_localizedDescription; }
static bool compare(const SocketStreamError&, const SocketStreamError&);
@@ -60,7 +64,17 @@ namespace WebCore {
{
}
+ SocketStreamErrorBase(int errorCode, const String& failingURL, const String& localizedDescription)
+ : m_errorCode(errorCode)
+ , m_failingURL(failingURL)
+ , m_localizedDescription(localizedDescription)
+ , m_isNull(false)
+ {
+ }
+
int m_errorCode;
+ String m_failingURL;
+ String m_localizedDescription;
bool m_isNull;
};
diff --git a/WebCore/platform/network/cf/DNSCFNet.cpp b/WebCore/platform/network/cf/DNSCFNet.cpp
index fbceb7d..166abbf 100644
--- a/WebCore/platform/network/cf/DNSCFNet.cpp
+++ b/WebCore/platform/network/cf/DNSCFNet.cpp
@@ -27,6 +27,7 @@
#include "config.h"
#include "DNS.h"
+#include "KURL.h"
#include "Timer.h"
#include <wtf/HashSet.h>
#include <wtf/RetainPtr.h>
@@ -37,6 +38,10 @@
#include "LoaderRunLoopCF.h"
#endif
+#if defined(BUILDING_ON_LEOPARD)
+#include <SystemConfiguration/SystemConfiguration.h>
+#endif
+
#ifdef BUILDING_ON_TIGER
// This function is available on Tiger, but not declared in the CFRunLoop.h header on Tiger.
extern "C" CFRunLoopRef CFRunLoopGetMain();
@@ -62,6 +67,37 @@ const int maxRequestsToQueue = 64;
// If there were queued names that couldn't be sent simultaneously, check the state of resolvers after this delay.
const double retryResolvingInSeconds = 0.1;
+static bool proxyIsEnabledInSystemPreferences()
+{
+ // Don't do DNS prefetch if proxies are involved. For many proxy types, the user agent is never exposed
+ // to the IP address during normal operation. Querying an internal DNS server may not help performance,
+ // as it doesn't necessarily look up the actual external IP. Also, if DNS returns a fake internal address,
+ // local caches may keep it even after re-connecting to another network.
+
+#if !defined(BUILDING_ON_LEOPARD)
+ RetainPtr<CFDictionaryRef> proxySettings(AdoptCF, CFNetworkCopySystemProxySettings());
+#else
+ RetainPtr<CFDictionaryRef> proxySettings(AdoptCF, SCDynamicStoreCopyProxies(0));
+#endif
+ if (!proxySettings)
+ return false;
+
+ static CFURLRef httpCFURL = KURL(ParsedURLString, "http://example.com/").createCFURL();
+ static CFURLRef httpsCFURL = KURL(ParsedURLString, "https://example.com/").createCFURL();
+
+ RetainPtr<CFArrayRef> httpProxyArray(AdoptCF, CFNetworkCopyProxiesForURL(httpCFURL, proxySettings.get()));
+ RetainPtr<CFArrayRef> httpsProxyArray(AdoptCF, CFNetworkCopyProxiesForURL(httpsCFURL, proxySettings.get()));
+
+ CFIndex httpProxyCount = CFArrayGetCount(httpProxyArray.get());
+ CFIndex httpsProxyCount = CFArrayGetCount(httpsProxyArray.get());
+ if (httpProxyCount == 1 && CFEqual(CFDictionaryGetValue(static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(httpProxyArray.get(), 0)), kCFProxyTypeKey), kCFProxyTypeNone))
+ httpProxyCount = 0;
+ if (httpsProxyCount == 1 && CFEqual(CFDictionaryGetValue(static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(httpsProxyArray.get(), 0)), kCFProxyTypeKey), kCFProxyTypeNone))
+ httpsProxyCount = 0;
+
+ return httpProxyCount || httpsProxyCount;
+}
+
class DNSResolveQueue : public TimerBase {
public:
static DNSResolveQueue& shared();
@@ -92,6 +128,9 @@ void DNSResolveQueue::add(const String& name)
{
// If there are no names queued, and few enough are in flight, resolve immediately (the mouse may be over a link).
if (!m_names.size()) {
+ if (proxyIsEnabledInSystemPreferences())
+ return;
+
if (atomicIncrement(&m_requestsInFlight) <= namesToResolveImmediately) {
resolve(name);
return;
@@ -115,6 +154,11 @@ void DNSResolveQueue::decrementRequestCount()
void DNSResolveQueue::fired()
{
+ if (proxyIsEnabledInSystemPreferences()) {
+ m_names.clear();
+ return;
+ }
+
int requestsAllowed = maxSimultaneousRequests - m_requestsInFlight;
for (; !m_names.isEmpty() && requestsAllowed > 0; --requestsAllowed) {
diff --git a/WebCore/platform/network/cf/ResourceHandleCFNet.cpp b/WebCore/platform/network/cf/ResourceHandleCFNet.cpp
index e48bd2d..f0773d2 100644
--- a/WebCore/platform/network/cf/ResourceHandleCFNet.cpp
+++ b/WebCore/platform/network/cf/ResourceHandleCFNet.cpp
@@ -481,6 +481,8 @@ void ResourceHandle::willSendRequest(ResourceRequest& request, const ResourceRes
d->m_pass = url.pass();
d->m_lastHTTPMethod = request.httpMethod();
request.removeCredentials();
+ if (!protocolHostAndPortAreEqual(request.url(), redirectResponse.url()))
+ request.clearHTTPAuthorization();
client()->willSendRequest(this, request, redirectResponse);
}
diff --git a/WebCore/platform/network/cf/ResourceResponseCFNet.cpp b/WebCore/platform/network/cf/ResourceResponseCFNet.cpp
index 469e5ad..9a83add 100644
--- a/WebCore/platform/network/cf/ResourceResponseCFNet.cpp
+++ b/WebCore/platform/network/cf/ResourceResponseCFNet.cpp
@@ -79,6 +79,11 @@ void ResourceResponse::platformLazyInit()
m_expectedContentLength = CFURLResponseGetExpectedContentLength(m_cfResponse.get());
m_textEncodingName = CFURLResponseGetTextEncodingName(m_cfResponse.get());
+ // Workaround for <rdar://problem/8757088>, can be removed once that is fixed.
+ unsigned textEncodingNameLength = m_textEncodingName.length();
+ if (textEncodingNameLength >= 2 && m_textEncodingName[0U] == '"' && m_textEncodingName[textEncodingNameLength - 1] == '"')
+ m_textEncodingName = m_textEncodingName.substring(1, textEncodingNameLength - 2);
+
m_lastModifiedDate = toTimeT(CFURLResponseGetLastModifiedDate(m_cfResponse.get()));
RetainPtr<CFStringRef> suggestedFilename(AdoptCF, CFURLResponseCopySuggestedFilename(m_cfResponse.get()));
diff --git a/WebCore/platform/network/cf/SocketStreamError.h b/WebCore/platform/network/cf/SocketStreamError.h
index 6a0b441..5a0ca07 100644
--- a/WebCore/platform/network/cf/SocketStreamError.h
+++ b/WebCore/platform/network/cf/SocketStreamError.h
@@ -42,7 +42,10 @@ public:
: SocketStreamErrorBase(errorCode)
{
}
-
+ SocketStreamError(int errorCode, const String& failingURL, const String& localizedDescription)
+ : SocketStreamErrorBase(errorCode, failingURL, localizedDescription)
+ {
+ }
};
} // namespace WebCore
diff --git a/WebCore/platform/network/cf/SocketStreamHandle.h b/WebCore/platform/network/cf/SocketStreamHandle.h
index 41d543a..df1d4a3 100644
--- a/WebCore/platform/network/cf/SocketStreamHandle.h
+++ b/WebCore/platform/network/cf/SocketStreamHandle.h
@@ -84,6 +84,10 @@ private:
void readStreamCallback(CFStreamEventType);
void writeStreamCallback(CFStreamEventType);
+#ifndef BUILDING_ON_TIGER
+ void reportErrorToClient(CFErrorRef);
+#endif
+
// No authentication for streams per se, but proxy may ask for credentials.
virtual void receivedCredential(const AuthenticationChallenge&, const Credential&);
virtual void receivedRequestToContinueWithoutCredential(const AuthenticationChallenge&);
diff --git a/WebCore/platform/network/cf/SocketStreamHandleCFNet.cpp b/WebCore/platform/network/cf/SocketStreamHandleCFNet.cpp
index 24b5835..821b1ca 100644
--- a/WebCore/platform/network/cf/SocketStreamHandleCFNet.cpp
+++ b/WebCore/platform/network/cf/SocketStreamHandleCFNet.cpp
@@ -39,6 +39,7 @@
#include "SocketStreamError.h"
#include "SocketStreamHandleClient.h"
#include <wtf/MainThread.h>
+#include <wtf/text/StringConcatenate.h>
#if defined(BUILDING_ON_TIGER) || defined(BUILDING_ON_LEOPARD)
#include <SystemConfiguration/SystemConfiguration.h>
@@ -530,8 +531,13 @@ void SocketStreamHandle::readStreamCallback(CFStreamEventType type)
ASSERT_NOT_REACHED();
break;
case kCFStreamEventErrorOccurred: {
+#ifndef BUILDING_ON_TIGER
+ RetainPtr<CFErrorRef> error(AdoptCF, CFReadStreamCopyError(m_readStream.get()));
+ reportErrorToClient(error.get());
+#else
CFStreamError error = CFReadStreamGetError(m_readStream.get());
m_client->didFail(this, SocketStreamError(error.error)); // FIXME: Provide a sensible error.
+#endif
break;
}
case kCFStreamEventEndEncountered:
@@ -574,8 +580,13 @@ void SocketStreamHandle::writeStreamCallback(CFStreamEventType type)
break;
}
case kCFStreamEventErrorOccurred: {
+#ifndef BUILDING_ON_TIGER
+ RetainPtr<CFErrorRef> error(AdoptCF, CFWriteStreamCopyError(m_writeStream.get()));
+ reportErrorToClient(error.get());
+#else
CFStreamError error = CFWriteStreamGetError(m_writeStream.get());
m_client->didFail(this, SocketStreamError(error.error)); // FIXME: Provide a sensible error.
+#endif
break;
}
case kCFStreamEventEndEncountered:
@@ -584,6 +595,29 @@ void SocketStreamHandle::writeStreamCallback(CFStreamEventType type)
}
}
+#ifndef BUILDING_ON_TIGER
+void SocketStreamHandle::reportErrorToClient(CFErrorRef error)
+{
+ CFIndex errorCode = CFErrorGetCode(error);
+ String description;
+
+#if PLATFORM(MAC)
+ if (CFEqual(CFErrorGetDomain(error), kCFErrorDomainOSStatus)) {
+ const char* descriptionOSStatus = GetMacOSStatusCommentString(static_cast<OSStatus>(errorCode));
+ if (descriptionOSStatus && descriptionOSStatus[0] != '\0')
+ description = makeString("OSStatus Error ", String::number(errorCode), ": ", descriptionOSStatus);
+ }
+#endif
+
+ if (description.isNull()) {
+ RetainPtr<CFStringRef> descriptionCF(AdoptCF, CFErrorCopyDescription(error));
+ description = String(descriptionCF.get());
+ }
+
+ m_client->didFail(this, SocketStreamError(static_cast<int>(errorCode), m_url.string(), description));
+}
+#endif // BUILDING_ON_TIGER
+
SocketStreamHandle::~SocketStreamHandle()
{
LOG(Network, "SocketStreamHandle %p dtor", this);
diff --git a/WebCore/platform/network/mac/AuthenticationChallenge.h b/WebCore/platform/network/mac/AuthenticationChallenge.h
index d74a92c..8f60933 100644
--- a/WebCore/platform/network/mac/AuthenticationChallenge.h
+++ b/WebCore/platform/network/mac/AuthenticationChallenge.h
@@ -49,6 +49,7 @@ public:
NSURLAuthenticationChallenge *nsURLAuthenticationChallenge() const { return m_nsChallenge.get(); }
void setAuthenticationClient(AuthenticationClient*); // Changes sender to one that invokes client methods.
+ AuthenticationClient* authenticationClient() const;
private:
friend class AuthenticationChallengeBase;
diff --git a/WebCore/platform/network/mac/AuthenticationMac.mm b/WebCore/platform/network/mac/AuthenticationMac.mm
index 1c05917..cdf643f 100644
--- a/WebCore/platform/network/mac/AuthenticationMac.mm
+++ b/WebCore/platform/network/mac/AuthenticationMac.mm
@@ -41,6 +41,7 @@ using namespace WebCore;
AuthenticationClient* m_client;
}
- (id)initWithAuthenticationClient:(AuthenticationClient*)client;
+- (AuthenticationClient*)client;
- (void)detachClient;
@end
@@ -55,6 +56,11 @@ using namespace WebCore;
return self;
}
+- (AuthenticationClient*)client
+{
+ return m_client;
+}
+
- (void)detachClient
{
m_client = 0;
@@ -123,6 +129,14 @@ void AuthenticationChallenge::setAuthenticationClient(AuthenticationClient* clie
}
}
+AuthenticationClient* AuthenticationChallenge::authenticationClient() const
+{
+ if ([m_sender.get() isMemberOfClass:[WebCoreAuthenticationClientAsChallengeSender class]])
+ return [static_cast<WebCoreAuthenticationClientAsChallengeSender*>(m_sender.get()) client];
+
+ return 0;
+}
+
bool AuthenticationChallenge::platformCompare(const AuthenticationChallenge& a, const AuthenticationChallenge& b)
{
if (a.sender() != b.sender())
diff --git a/WebCore/platform/network/mac/ResourceHandleMac.mm b/WebCore/platform/network/mac/ResourceHandleMac.mm
index daec366..caa33d7 100644
--- a/WebCore/platform/network/mac/ResourceHandleMac.mm
+++ b/WebCore/platform/network/mac/ResourceHandleMac.mm
@@ -552,6 +552,8 @@ void ResourceHandle::willSendRequest(ResourceRequest& request, const ResourceRes
d->m_pass = url.pass();
d->m_lastHTTPMethod = request.httpMethod();
request.removeCredentials();
+ if (!protocolHostAndPortAreEqual(request.url(), redirectResponse.url()))
+ request.clearHTTPAuthorization();
client()->willSendRequest(this, request, redirectResponse);
}
diff --git a/WebCore/platform/network/mac/ResourceResponseMac.mm b/WebCore/platform/network/mac/ResourceResponseMac.mm
index e1f1790..4376b64 100644
--- a/WebCore/platform/network/mac/ResourceResponseMac.mm
+++ b/WebCore/platform/network/mac/ResourceResponseMac.mm
@@ -74,6 +74,12 @@ void ResourceResponse::platformLazyInit()
m_mimeType = [m_nsResponse.get() MIMEType];
m_expectedContentLength = [m_nsResponse.get() expectedContentLength];
m_textEncodingName = [m_nsResponse.get() textEncodingName];
+
+ // Workaround for <rdar://problem/8757088>, can be removed once that is fixed.
+ unsigned textEncodingNameLength = m_textEncodingName.length();
+ if (textEncodingNameLength >= 2 && m_textEncodingName[0U] == '"' && m_textEncodingName[textEncodingNameLength - 1] == '"')
+ m_textEncodingName = m_textEncodingName.substring(1, textEncodingNameLength - 2);
+
m_suggestedFilename = [m_nsResponse.get() suggestedFilename];
if ([m_nsResponse.get() isKindOfClass:[NSHTTPURLResponse class]]) {
diff --git a/WebCore/platform/network/qt/AuthenticationChallenge.h b/WebCore/platform/network/qt/AuthenticationChallenge.h
index 753ac6f..ebbc0cd 100644
--- a/WebCore/platform/network/qt/AuthenticationChallenge.h
+++ b/WebCore/platform/network/qt/AuthenticationChallenge.h
@@ -29,6 +29,8 @@
namespace WebCore {
+class AuthenticationClient;
+
class AuthenticationChallenge : public AuthenticationChallengeBase {
public:
AuthenticationChallenge()
@@ -39,6 +41,9 @@ public:
: AuthenticationChallengeBase(protectionSpace, proposedCredential, previousFailureCount, response, error)
{
}
+
+ AuthenticationClient* authenticationClient() const { return 0; } // FIXME: Implement!
+
};
}
diff --git a/WebCore/platform/network/qt/QNetworkReplyHandler.cpp b/WebCore/platform/network/qt/QNetworkReplyHandler.cpp
index 01e624e..2ff7d9c 100644
--- a/WebCore/platform/network/qt/QNetworkReplyHandler.cpp
+++ b/WebCore/platform/network/qt/QNetworkReplyHandler.cpp
@@ -23,6 +23,7 @@
#include "HTTPParsers.h"
#include "MIMETypeRegistry.h"
+#include "QtNAMThreadSafeProxy.h"
#include "ResourceHandle.h"
#include "ResourceHandleClient.h"
#include "ResourceHandleInternal.h"
@@ -46,7 +47,7 @@
// It is fixed in Qt 4.6.3. See https://bugs.webkit.org/show_bug.cgi?id=32113
// and https://bugs.webkit.org/show_bug.cgi?id=36755
#if QT_VERSION > QT_VERSION_CHECK(4, 6, 2)
-#define SIGNAL_CONN Qt::DirectConnection
+#define SIGNAL_CONN Qt::AutoConnection
#else
#define SIGNAL_CONN Qt::QueuedConnection
#endif
@@ -56,8 +57,9 @@ static const int gMaxRecursionLimit = 10;
namespace WebCore {
// Take a deep copy of the FormDataElement
-FormDataIODevice::FormDataIODevice(FormData* data)
- : m_formElements(data ? data->elements() : Vector<FormDataElement>())
+FormDataIODevice::FormDataIODevice(FormData* data, QObject* parent)
+ : QIODevice(parent)
+ , m_formElements(data ? data->elements() : Vector<FormDataElement>())
, m_currentFile(0)
, m_currentDelta(0)
, m_fileSize(0)
@@ -184,7 +186,7 @@ QNetworkReplyHandler::QNetworkReplyHandler(ResourceHandle* handle, LoadMode load
, m_resourceHandle(handle)
, m_redirected(false)
, m_responseSent(false)
- , m_responseDataSent(false)
+ , m_responseContainsData(false)
, m_loadMode(loadMode)
, m_shouldStart(true)
, m_shouldFinish(false)
@@ -192,6 +194,9 @@ QNetworkReplyHandler::QNetworkReplyHandler(ResourceHandle* handle, LoadMode load
, m_shouldForwardData(false)
, m_redirectionTries(gMaxRecursionLimit)
{
+ // Make this a direct function call once we require 4.6.1+.
+ connect(this, SIGNAL(processQueuedItems()), this, SLOT(sendQueuedItems()), SIGNAL_CONN);
+
const ResourceRequest &r = m_resourceHandle->firstRequest();
if (r.httpMethod() == "GET")
@@ -222,6 +227,12 @@ QNetworkReplyHandler::QNetworkReplyHandler(ResourceHandle* handle, LoadMode load
start();
}
+QNetworkReplyHandler::~QNetworkReplyHandler()
+{
+ if (m_reply)
+ m_reply->deleteLater();
+}
+
void QNetworkReplyHandler::setLoadMode(LoadMode mode)
{
// https://bugs.webkit.org/show_bug.cgi?id=26556
@@ -231,9 +242,13 @@ void QNetworkReplyHandler::setLoadMode(LoadMode mode)
case LoadNormal:
m_loadMode = LoadResuming;
emit processQueuedItems();
+ // Restart forwarding only after processQueuedItems to make sure
+ // our buffered data was handled before any incoming data.
+ m_reply->setForwardingDefered(false);
break;
case LoadDeferred:
m_loadMode = LoadDeferred;
+ m_reply->setForwardingDefered(true);
break;
case LoadResuming:
Q_ASSERT(0); // should never happen
@@ -245,31 +260,30 @@ void QNetworkReplyHandler::abort()
{
m_resourceHandle = 0;
if (m_reply) {
- QNetworkReply* reply = release();
+ QtNetworkReplyThreadSafeProxy* reply = release();
reply->abort();
reply->deleteLater();
}
deleteLater();
}
-QNetworkReply* QNetworkReplyHandler::release()
+QtNetworkReplyThreadSafeProxy* QNetworkReplyHandler::release()
{
- QNetworkReply* reply = m_reply;
+ QtNetworkReplyThreadSafeProxy* reply = m_reply;
if (m_reply) {
disconnect(m_reply, 0, this, 0);
// We have queued connections to the QNetworkReply. Make sure any
// posted meta call events that were the result of a signal emission
// don't reach the slots in our instance.
QCoreApplication::removePostedEvents(this, QEvent::MetaCall);
- m_reply->setParent(0);
m_reply = 0;
}
return reply;
}
-static bool ignoreHttpError(QNetworkReply* reply, bool receivedData)
+static bool ignoreHttpError(QtNetworkReplyThreadSafeProxy* reply, bool receivedData)
{
- int httpStatusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
+ int httpStatusCode = reply->httpStatusCode();
if (httpStatusCode == 401 || httpStatusCode == 407)
return true;
@@ -300,29 +314,33 @@ void QNetworkReplyHandler::finish()
return;
}
- QNetworkReply* oldReply = m_reply;
+ if (!m_redirected) {
+ if (!m_reply->error() || ignoreHttpError(m_reply, m_responseContainsData))
+ client->didFinishLoading(m_resourceHandle, 0);
+ else {
+ QUrl url = m_reply->url();
+ int httpStatusCode = m_reply->httpStatusCode();
- if (m_redirected) {
- resetState();
- start();
- } else if (!m_reply->error() || ignoreHttpError(m_reply, m_responseDataSent)) {
- client->didFinishLoading(m_resourceHandle, 0);
+ if (httpStatusCode) {
+ ResourceError error("HTTP", httpStatusCode, url.toString(), QString::fromAscii(m_reply->httpReasonPhrase()));
+ client->didFail(m_resourceHandle, error);
+ } else {
+ ResourceError error("QtNetwork", m_reply->error(), url.toString(), m_reply->errorString());
+ client->didFail(m_resourceHandle, error);
+ }
+ }
+ if (m_reply) {
+ m_reply->deleteLater();
+ m_reply = 0;
+ }
} else {
- QUrl url = m_reply->url();
- int httpStatusCode = m_reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
-
- if (httpStatusCode) {
- ResourceError error("HTTP", httpStatusCode, url.toString(), m_reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString());
- client->didFail(m_resourceHandle, error);
- } else {
- ResourceError error("QtNetwork", m_reply->error(), url.toString(), m_reply->errorString());
- client->didFail(m_resourceHandle, error);
+ if (m_reply) {
+ m_reply->deleteLater();
+ m_reply = 0;
}
+ resetState();
+ start();
}
-
- oldReply->deleteLater();
- if (oldReply == m_reply)
- m_reply = 0;
}
void QNetworkReplyHandler::sendResponseIfNeeded()
@@ -331,7 +349,7 @@ void QNetworkReplyHandler::sendResponseIfNeeded()
if (m_shouldSendResponse)
return;
- if (m_reply->error() && !ignoreHttpError(m_reply, m_responseDataSent))
+ if (m_reply->error() && !ignoreHttpError(m_reply, m_responseContainsData))
return;
if (m_responseSent || !m_resourceHandle)
@@ -342,7 +360,7 @@ void QNetworkReplyHandler::sendResponseIfNeeded()
if (!client)
return;
- WTF::String contentType = m_reply->header(QNetworkRequest::ContentTypeHeader).toString();
+ WTF::String contentType = m_reply->contentTypeHeader();
WTF::String encoding = extractCharsetFromMediaType(contentType);
WTF::String mimeType = extractMIMETypeFromMediaType(contentType);
@@ -353,7 +371,7 @@ void QNetworkReplyHandler::sendResponseIfNeeded()
KURL url(m_reply->url());
ResourceResponse response(url, mimeType.lower(),
- m_reply->header(QNetworkRequest::ContentLengthHeader).toLongLong(),
+ m_reply->contentLengthHeader(),
encoding, String());
if (url.isLocalFile()) {
@@ -362,10 +380,10 @@ void QNetworkReplyHandler::sendResponseIfNeeded()
}
// The status code is equal to 0 for protocols not in the HTTP family.
- int statusCode = m_reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
+ int statusCode = m_reply->httpStatusCode();
if (url.protocolInHTTPFamily()) {
- String suggestedFilename = filenameFromHTTPContentDisposition(QString::fromAscii(m_reply->rawHeader("Content-Disposition")));
+ String suggestedFilename = filenameFromHTTPContentDisposition(QString::fromAscii(m_reply->contentDispositionHeader()));
if (!suggestedFilename.isEmpty())
response.setSuggestedFilename(suggestedFilename);
@@ -373,21 +391,15 @@ void QNetworkReplyHandler::sendResponseIfNeeded()
response.setSuggestedFilename(url.lastPathComponent());
response.setHTTPStatusCode(statusCode);
- response.setHTTPStatusText(m_reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toByteArray().constData());
+ response.setHTTPStatusText(m_reply->httpReasonPhrase().constData());
// Add remaining headers.
-#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
- foreach (const QNetworkReply::RawHeaderPair& pair, m_reply->rawHeaderPairs()) {
+ foreach (const QtNetworkReplyThreadSafeProxy::RawHeaderPair& pair, m_reply->rawHeaderPairs()) {
response.setHTTPHeaderField(QString::fromAscii(pair.first), QString::fromAscii(pair.second));
}
-#else
- foreach (const QByteArray& headerName, m_reply->rawHeaderList()) {
- response.setHTTPHeaderField(QString::fromAscii(headerName), QString::fromAscii(m_reply->rawHeader(headerName)));
- }
-#endif
}
- QUrl redirection = m_reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
+ QUrl redirection = m_reply->redirectionTarget();
if (redirection.isValid()) {
QUrl newUrl = m_reply->url().resolved(redirection);
@@ -432,11 +444,16 @@ void QNetworkReplyHandler::sendResponseIfNeeded()
client->didReceiveResponse(m_resourceHandle, response);
}
-void QNetworkReplyHandler::forwardData()
+void QNetworkReplyHandler::forwardData(const QByteArray &data)
{
m_shouldForwardData = (m_loadMode != LoadNormal);
- if (m_shouldForwardData)
+ if (m_shouldForwardData) {
+ m_bufferedData += data;
return;
+ }
+
+ if (!data.isEmpty())
+ m_responseContainsData = true;
sendResponseIfNeeded();
@@ -447,16 +464,12 @@ void QNetworkReplyHandler::forwardData()
if (!m_resourceHandle)
return;
- QByteArray data = m_reply->read(m_reply->bytesAvailable());
-
ResourceHandleClient* client = m_resourceHandle->client();
if (!client)
return;
- if (!data.isEmpty()) {
- m_responseDataSent = true;
+ if (!data.isEmpty())
client->didReceiveData(m_resourceHandle, data.constData(), data.length(), data.length() /*FixMe*/);
- }
}
void QNetworkReplyHandler::uploadProgress(qint64 bytesSent, qint64 bytesTotal)
@@ -493,41 +506,53 @@ void QNetworkReplyHandler::start()
&& (!url.toLocalFile().isEmpty() || url.scheme() == QLatin1String("data")))
m_method = QNetworkAccessManager::GetOperation;
+ m_reply = new QtNetworkReplyThreadSafeProxy(manager);
+ connect(m_reply, SIGNAL(finished()), this, SLOT(finish()), SIGNAL_CONN);
+
+ // For http(s) we know that the headers are complete upon metaDataChanged() emission, so we
+ // can send the response as early as possible
+ if (scheme == QLatin1String("http") || scheme == QLatin1String("https"))
+ connect(m_reply, SIGNAL(metaDataChanged()), this, SLOT(sendResponseIfNeeded()), SIGNAL_CONN);
+
+ connect(m_reply, SIGNAL(dataReceived(const QByteArray&)), this, SLOT(forwardData(const QByteArray&)), SIGNAL_CONN);
+
+ if (m_resourceHandle->firstRequest().reportUploadProgress())
+ connect(m_reply, SIGNAL(uploadProgress(qint64, qint64)), this, SLOT(uploadProgress(qint64, qint64)), SIGNAL_CONN);
+
switch (m_method) {
case QNetworkAccessManager::GetOperation:
- m_reply = manager->get(m_request);
+ m_reply->get(m_request);
break;
case QNetworkAccessManager::PostOperation: {
- FormDataIODevice* postDevice = new FormDataIODevice(d->m_firstRequest.httpBody());
+ FormDataIODevice* postDevice = new FormDataIODevice(d->m_firstRequest.httpBody(), this);
// We may be uploading files so prevent QNR from buffering data
m_request.setHeader(QNetworkRequest::ContentLengthHeader, postDevice->getFormDataSize());
m_request.setAttribute(QNetworkRequest::DoNotBufferUploadDataAttribute, QVariant(true));
- m_reply = manager->post(m_request, postDevice);
- postDevice->setParent(m_reply);
+ m_reply->post(m_request, postDevice);
break;
}
case QNetworkAccessManager::HeadOperation:
- m_reply = manager->head(m_request);
+ m_reply->head(m_request);
break;
case QNetworkAccessManager::PutOperation: {
- FormDataIODevice* putDevice = new FormDataIODevice(d->m_firstRequest.httpBody());
+ FormDataIODevice* putDevice = new FormDataIODevice(d->m_firstRequest.httpBody(), this);
// We may be uploading files so prevent QNR from buffering data
m_request.setHeader(QNetworkRequest::ContentLengthHeader, putDevice->getFormDataSize());
m_request.setAttribute(QNetworkRequest::DoNotBufferUploadDataAttribute, QVariant(true));
- m_reply = manager->put(m_request, putDevice);
- putDevice->setParent(m_reply);
+ m_reply->put(m_request, putDevice);
break;
}
case QNetworkAccessManager::DeleteOperation: {
- m_reply = manager->deleteResource(m_request);
+ m_reply->deleteResource(m_request);
break;
}
#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
case QNetworkAccessManager::CustomOperation:
- m_reply = manager->sendCustomRequest(m_request, m_resourceHandle->firstRequest().httpMethod().latin1().data());
+ m_reply->sendCustomRequest(m_request, m_resourceHandle->firstRequest().httpMethod().latin1().data());
break;
#endif
case QNetworkAccessManager::UnknownOperation: {
+ m_reply->deleteLater();
m_reply = 0;
ResourceHandleClient* client = m_resourceHandle->client();
if (client) {
@@ -539,36 +564,13 @@ void QNetworkReplyHandler::start()
return;
}
}
-
- m_reply->setParent(this);
-
- connect(m_reply, SIGNAL(finished()),
- this, SLOT(finish()), SIGNAL_CONN);
-
- // For http(s) we know that the headers are complete upon metaDataChanged() emission, so we
- // can send the response as early as possible
- if (scheme == QLatin1String("http") || scheme == QLatin1String("https"))
- connect(m_reply, SIGNAL(metaDataChanged()),
- this, SLOT(sendResponseIfNeeded()), SIGNAL_CONN);
-
- connect(m_reply, SIGNAL(readyRead()),
- this, SLOT(forwardData()), SIGNAL_CONN);
-
- if (m_resourceHandle->firstRequest().reportUploadProgress()) {
- connect(m_reply, SIGNAL(uploadProgress(qint64, qint64)),
- this, SLOT(uploadProgress(qint64, qint64)), SIGNAL_CONN);
- }
-
- // Make this a direct function call once we require 4.6.1+.
- connect(this, SIGNAL(processQueuedItems()),
- this, SLOT(sendQueuedItems()), SIGNAL_CONN);
}
void QNetworkReplyHandler::resetState()
{
m_redirected = false;
m_responseSent = false;
- m_responseDataSent = false;
+ m_responseContainsData = false;
m_shouldStart = true;
m_shouldFinish = false;
m_shouldSendResponse = false;
@@ -587,8 +589,10 @@ void QNetworkReplyHandler::sendQueuedItems()
if (m_shouldSendResponse)
sendResponseIfNeeded();
- if (m_shouldForwardData)
- forwardData();
+ if (m_shouldForwardData) {
+ forwardData(m_bufferedData);
+ m_bufferedData.clear();
+ }
if (m_shouldFinish)
finish();
diff --git a/WebCore/platform/network/qt/QNetworkReplyHandler.h b/WebCore/platform/network/qt/QNetworkReplyHandler.h
index 884a1a4..11638b3 100644
--- a/WebCore/platform/network/qt/QNetworkReplyHandler.h
+++ b/WebCore/platform/network/qt/QNetworkReplyHandler.h
@@ -23,6 +23,7 @@
#include <QNetworkRequest>
#include <QNetworkAccessManager>
+#include <QNetworkReply>
#include "FormData.h"
@@ -34,6 +35,7 @@ QT_END_NAMESPACE
namespace WebCore {
class ResourceHandle;
+class QtNetworkReplyThreadSafeProxy;
class QNetworkReplyHandler : public QObject
{
@@ -46,13 +48,12 @@ public:
};
QNetworkReplyHandler(ResourceHandle *handle, LoadMode);
+ ~QNetworkReplyHandler();
void setLoadMode(LoadMode);
- QNetworkReply* reply() const { return m_reply; }
-
void abort();
- QNetworkReply* release();
+ QtNetworkReplyThreadSafeProxy* release();
signals:
void processQueuedItems();
@@ -60,7 +61,7 @@ signals:
private slots:
void finish();
void sendResponseIfNeeded();
- void forwardData();
+ void forwardData(const QByteArray &data);
void sendQueuedItems();
void uploadProgress(qint64 bytesSent, qint64 bytesTotal);
@@ -69,11 +70,11 @@ private:
void resetState();
String httpMethod() const;
- QNetworkReply* m_reply;
+ QtNetworkReplyThreadSafeProxy* m_reply;
ResourceHandle* m_resourceHandle;
bool m_redirected;
bool m_responseSent;
- bool m_responseDataSent;
+ bool m_responseContainsData;
LoadMode m_loadMode;
QNetworkAccessManager::Operation m_method;
QNetworkRequest m_request;
@@ -84,6 +85,7 @@ private:
bool m_shouldSendResponse;
bool m_shouldForwardData;
int m_redirectionTries;
+ QByteArray m_bufferedData;
};
// Self destructing QIODevice for FormData
@@ -94,7 +96,7 @@ private:
class FormDataIODevice : public QIODevice {
Q_OBJECT
public:
- FormDataIODevice(FormData*);
+ FormDataIODevice(FormData*, QObject* parent = 0);
~FormDataIODevice();
bool isSequential() const;
diff --git a/WebCore/platform/network/qt/QtNAMThreadSafeProxy.cpp b/WebCore/platform/network/qt/QtNAMThreadSafeProxy.cpp
new file mode 100644
index 0000000..0caeb05
--- /dev/null
+++ b/WebCore/platform/network/qt/QtNAMThreadSafeProxy.cpp
@@ -0,0 +1,190 @@
+/*
+ Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#include "config.h"
+#include "QtNAMThreadSafeProxy.h"
+
+#include "Assertions.h"
+#include <QAbstractNetworkCache>
+#include <QNetworkAccessManager>
+#include <QNetworkCookieJar>
+#include <QStringList>
+
+// Use unused variables to be able to call qRegisterMetaType statically.
+static int dummyStaticVar1 = qRegisterMetaType<QFutureInterface<bool> >("QFutureInterface<bool>");
+static int dummyStaticVar2 = qRegisterMetaType<QFutureInterface<QList<QNetworkCookie> > >("QFutureInterface<QList<QNetworkCookie> >");
+
+namespace WebCore {
+
+QtNAMThreadSafeProxy::QtNAMThreadSafeProxy(QNetworkAccessManager *manager)
+ : m_manager(manager)
+{
+ moveToThread(manager->thread());
+
+ connect(this, SIGNAL(localSetCookiesRequested(const QUrl&, const QString&)), SLOT(localSetCookies(const QUrl&, const QString&)));
+ connect(this, SIGNAL(localCookiesForUrlRequested(QFutureInterface<QList<QNetworkCookie> >, const QUrl&)), SLOT(localCookiesForUrl(QFutureInterface<QList<QNetworkCookie> >, const QUrl&)));
+ connect(this, SIGNAL(localWillLoadFromCacheRequested(QFutureInterface<bool>, const QUrl&)), SLOT(localWillLoadFromCache(QFutureInterface<bool>, const QUrl&)));
+}
+
+void QtNAMThreadSafeProxy::localSetCookies(const QUrl& url, const QString& cookies)
+{
+ QList<QNetworkCookie> cookieList = QNetworkCookie::parseCookies(cookies.toAscii());
+ QList<QNetworkCookie>::Iterator it = cookieList.begin();
+ while (it != cookieList.end()) {
+ if (it->isHttpOnly())
+ it = cookieList.erase(it);
+ else
+ ++it;
+ }
+ m_manager->cookieJar()->setCookiesFromUrl(cookieList, url);
+}
+
+void QtNAMThreadSafeProxy::localCookiesForUrl(QFutureInterface<QList<QNetworkCookie> > fi, const QUrl& url)
+{
+ fi.reportResult(m_manager->cookieJar()->cookiesForUrl(url));
+ fi.reportFinished();
+}
+
+void QtNAMThreadSafeProxy::localWillLoadFromCache(QFutureInterface<bool> fi, const QUrl& url)
+{
+ bool retVal = false;
+ if (m_manager->cache())
+ retVal = m_manager->cache()->metaData(url).isValid();
+
+ fi.reportFinished(&retVal);
+}
+
+QtNetworkReplyThreadSafeProxy::QtNetworkReplyThreadSafeProxy(QNetworkAccessManager *manager)
+ : m_manager(manager)
+ , m_reply(0)
+ , m_forwardingDefered(false)
+ , m_contentLengthHeader(0)
+ , m_error(QNetworkReply::NoError)
+ , m_httpStatusCode(0)
+{
+ moveToThread(manager->thread());
+
+ // This might be unnecessarily heavy to do for each request while we could have the same wrapper for the manager instead
+ connect(this, SIGNAL(localGetRequested(const QNetworkRequest&)), SLOT(localGet(const QNetworkRequest&)));
+ connect(this, SIGNAL(localPostRequested(const QNetworkRequest&, QIODevice*)), SLOT(localPost(const QNetworkRequest&, QIODevice*)));
+ connect(this, SIGNAL(localHeadRequested(const QNetworkRequest&)), SLOT(localHead(const QNetworkRequest&)));
+ connect(this, SIGNAL(localPutRequested(const QNetworkRequest&, QIODevice*)), SLOT(localPut(const QNetworkRequest&, QIODevice*)));
+ connect(this, SIGNAL(localDeleteResourceRequested(const QNetworkRequest&)), SLOT(localDeleteResource(const QNetworkRequest&)));
+ connect(this, SIGNAL(localCustomRequestRequested(const QNetworkRequest&, const QByteArray&)), SLOT(localCustomRequest(const QNetworkRequest&, const QByteArray&)));
+ connect(this, SIGNAL(localAbortRequested()), SLOT(localAbort()));
+ connect(this, SIGNAL(localSetForwardingDeferedRequested(bool)), SLOT(localSetForwardingDefered(bool)));
+}
+
+QtNetworkReplyThreadSafeProxy::~QtNetworkReplyThreadSafeProxy()
+{
+ delete m_reply;
+}
+
+void QtNetworkReplyThreadSafeProxy::localGet(const QNetworkRequest& request)
+{
+ localSetReply(m_manager->get(request));
+}
+
+void QtNetworkReplyThreadSafeProxy::localPost(const QNetworkRequest& request, QIODevice* data)
+{
+ localSetReply(m_manager->post(request, data));
+}
+
+void QtNetworkReplyThreadSafeProxy::localHead(const QNetworkRequest& request)
+{
+ localSetReply(m_manager->head(request));
+}
+
+void QtNetworkReplyThreadSafeProxy::localPut(const QNetworkRequest& request, QIODevice* data)
+{
+ localSetReply(m_manager->put(request, data));
+}
+
+void QtNetworkReplyThreadSafeProxy::localDeleteResource(const QNetworkRequest& request)
+{
+ localSetReply(m_manager->deleteResource(request));
+}
+
+void QtNetworkReplyThreadSafeProxy::localCustomRequest(const QNetworkRequest& request, const QByteArray& verb)
+{
+#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
+ localSetReply(m_manager->sendCustomRequest(request, verb));
+#endif
+}
+
+void QtNetworkReplyThreadSafeProxy::localAbort()
+{
+ if (m_reply)
+ m_reply->abort();
+}
+
+void QtNetworkReplyThreadSafeProxy::localForwardData()
+{
+ if (m_reply->bytesAvailable()) {
+ QByteArray data = m_reply->read(m_reply->bytesAvailable());
+ emit dataReceived(data);
+ }
+}
+
+void QtNetworkReplyThreadSafeProxy::localSetForwardingDefered(bool forwardingDefered)
+{
+ if (m_forwardingDefered && !forwardingDefered)
+ localForwardData();
+ m_forwardingDefered = forwardingDefered;
+}
+
+void QtNetworkReplyThreadSafeProxy::localMirrorMembers()
+{
+ ASSERT(m_reply);
+ QMutexLocker lock(&m_mirroredMembersMutex);
+
+ m_contentDispositionHeader = m_reply->rawHeader("Content-Disposition");
+ m_contentLengthHeader = m_reply->header(QNetworkRequest::ContentLengthHeader).toLongLong();
+ m_contentTypeHeader = m_reply->header(QNetworkRequest::ContentTypeHeader).toString();
+ m_error = m_reply->error();
+ m_errorString = m_reply->errorString();
+ m_httpReasonPhrase = m_reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toByteArray();
+ m_httpStatusCode = m_reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
+ m_url = m_reply->url();
+ m_redirectionTarget = m_reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
+#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
+ m_rawHeaderPairs = m_reply->rawHeaderPairs();
+#else
+ m_rawHeaderPairs.clear();
+ foreach (const QByteArray& headerName, m_reply->rawHeaderList())
+ m_rawHeaderPairs.append(RawHeaderPair(headerName, m_reply->rawHeader(headerName)));
+#endif
+}
+
+void QtNetworkReplyThreadSafeProxy::localSetReply(QNetworkReply *reply)
+{
+ ASSERT(!m_reply);
+ m_reply = reply;
+ m_reply->setParent(0);
+ connect(m_reply, SIGNAL(readyRead()), this, SLOT(localForwardData()));
+ // Make sure localMirrorMembers() is called before the outward signal
+ connect(m_reply, SIGNAL(finished()), this, SLOT(localMirrorMembers()), Qt::DirectConnection);
+ connect(m_reply, SIGNAL(finished()), this, SIGNAL(finished()));
+ // Make sure localMirrorMembers() is called before the outward signal
+ connect(m_reply, SIGNAL(metaDataChanged()), this, SLOT(localMirrorMembers()), Qt::DirectConnection);
+ connect(m_reply, SIGNAL(metaDataChanged()), this, SIGNAL(metaDataChanged()));
+ connect(m_reply, SIGNAL(uploadProgress(qint64, qint64)), this, SIGNAL(uploadProgress(qint64, qint64)));
+}
+
+
+}
diff --git a/WebCore/platform/network/qt/QtNAMThreadSafeProxy.h b/WebCore/platform/network/qt/QtNAMThreadSafeProxy.h
new file mode 100644
index 0000000..3e0c189
--- /dev/null
+++ b/WebCore/platform/network/qt/QtNAMThreadSafeProxy.h
@@ -0,0 +1,186 @@
+/*
+ Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#ifndef QtNAMThreadSafeProxy_h
+#define QtNAMThreadSafeProxy_h
+
+#include <QFuture>
+#include <QMutex>
+#include <QNetworkCookie>
+#include <QNetworkReply>
+#include <QObject>
+
+class QNetworkAccessManager;
+class QNetworkRequest;
+class QUrl;
+
+namespace WebCore {
+
+class QtNAMThreadSafeProxy : public QObject {
+ Q_OBJECT
+public:
+ QtNAMThreadSafeProxy(QNetworkAccessManager *manager);
+
+ void setCookies(const QUrl& url, const QString& cookies)
+ {
+ emit localSetCookiesRequested(url, cookies);
+ }
+
+ QFuture<QList<QNetworkCookie> > cookiesForUrl(const QUrl& url)
+ {
+ QFutureInterface<QList<QNetworkCookie> > fi;
+ fi.reportStarted();
+ emit localCookiesForUrlRequested(fi, url);
+ return fi.future();
+ }
+
+ QFuture<bool> willLoadFromCache(const QUrl& url)
+ {
+ QFutureInterface<bool> fi;
+ fi.reportStarted();
+ emit localWillLoadFromCacheRequested(fi, url);
+ return fi.future();
+ }
+
+signals:
+ void localSetCookiesRequested(const QUrl& url, const QString& cookies);
+ void localCookiesForUrlRequested(QFutureInterface<QList<QNetworkCookie> > fi, const QUrl& url);
+ void localWillLoadFromCacheRequested(QFutureInterface<bool> fi, const QUrl& url);
+
+private slots:
+ void localSetCookies(const QUrl& url, const QString& cookies);
+ void localCookiesForUrl(QFutureInterface<QList<QNetworkCookie> > fi, const QUrl& url);
+ void localWillLoadFromCache(QFutureInterface<bool> fi, const QUrl& url);
+
+private:
+ QNetworkAccessManager* m_manager;
+};
+
+
+class QtNetworkReplyThreadSafeProxy : public QObject {
+ Q_OBJECT
+public:
+ typedef QPair<QByteArray, QByteArray> RawHeaderPair;
+ QtNetworkReplyThreadSafeProxy(QNetworkAccessManager *manager);
+ ~QtNetworkReplyThreadSafeProxy();
+ void abort()
+ {
+ emit localAbortRequested();
+ }
+ void setForwardingDefered(bool forwardingDefered)
+ {
+ emit localSetForwardingDeferedRequested(forwardingDefered);
+ }
+
+ QByteArray contentDispositionHeader() { QMutexLocker lock(&m_mirroredMembersMutex); return m_contentDispositionHeader; }
+ qlonglong contentLengthHeader() { QMutexLocker lock(&m_mirroredMembersMutex); return m_contentLengthHeader; }
+ QString contentTypeHeader() { QMutexLocker lock(&m_mirroredMembersMutex); return m_contentTypeHeader; }
+ QNetworkReply::NetworkError error() { QMutexLocker lock(&m_mirroredMembersMutex); return m_error; }
+ QString errorString() { QMutexLocker lock(&m_mirroredMembersMutex); return m_errorString; }
+ QByteArray httpReasonPhrase() { QMutexLocker lock(&m_mirroredMembersMutex); return m_httpReasonPhrase; }
+ int httpStatusCode() { QMutexLocker lock(&m_mirroredMembersMutex); return m_httpStatusCode; }
+ QUrl url() { QMutexLocker lock(&m_mirroredMembersMutex); return m_url; }
+ QUrl redirectionTarget() { QMutexLocker lock(&m_mirroredMembersMutex); return m_redirectionTarget; }
+ QList<RawHeaderPair> rawHeaderPairs() { QMutexLocker lock(&m_mirroredMembersMutex); return m_rawHeaderPairs; }
+
+ QNetworkReply* reply()
+ {
+ // Careful, acccessing the reply accross threads might be hazardous to your health
+ return m_reply;
+ }
+public:
+ void get(const QNetworkRequest &request)
+ {
+ emit localGetRequested(request);
+ }
+ void post(const QNetworkRequest &request, QIODevice* data)
+ {
+ emit localPostRequested(request, data);
+ }
+ void head(const QNetworkRequest &request)
+ {
+ emit localHeadRequested(request);
+ }
+ void put(const QNetworkRequest &request, QIODevice* data)
+ {
+ emit localPutRequested(request, data);
+ }
+ void deleteResource(const QNetworkRequest &request)
+ {
+ emit localDeleteResourceRequested(request);
+ }
+#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
+ void sendCustomRequest(const QNetworkRequest &request, const QByteArray& verb)
+ {
+ emit localCustomRequestRequested(request, verb);
+ }
+#endif
+
+signals:
+ void localGetRequested(const QNetworkRequest& request);
+ void localPostRequested(const QNetworkRequest& request, QIODevice* data);
+ void localHeadRequested(const QNetworkRequest& request);
+ void localPutRequested(const QNetworkRequest& request, QIODevice* data);
+ void localDeleteResourceRequested(const QNetworkRequest& request);
+ void localCustomRequestRequested(const QNetworkRequest& request, const QByteArray& verb);
+ void localAbortRequested();
+ void localSetForwardingDeferedRequested(bool forwardingDefered);
+
+ void finished();
+ void readyRead();
+ void metaDataChanged();
+ void uploadProgress(qint64 bytesSent, qint64 bytesTotal);
+ void dataReceived(const QByteArray &data);
+
+private slots:
+ void localGet(const QNetworkRequest& request);
+ void localPost(const QNetworkRequest& request, QIODevice* data);
+ void localHead(const QNetworkRequest& request);
+ void localPut(const QNetworkRequest& request, QIODevice* data);
+ void localDeleteResource(const QNetworkRequest& request);
+ void localCustomRequest(const QNetworkRequest& request, const QByteArray& verb);
+ void localAbort();
+ void localForwardData();
+ void localSetForwardingDefered(bool forwardingDefered);
+ void localMirrorMembers();
+
+private:
+ void localSetReply(QNetworkReply *reply);
+
+ QNetworkAccessManager *m_manager;
+ QNetworkReply *m_reply;
+ bool m_forwardingDefered;
+
+ // Mirrored members
+ QMutex m_mirroredMembersMutex;
+ QByteArray m_contentDispositionHeader;
+ qlonglong m_contentLengthHeader;
+ QString m_contentTypeHeader;
+ QNetworkReply::NetworkError m_error;
+ QString m_errorString;
+ QByteArray m_httpReasonPhrase;
+ int m_httpStatusCode;
+ QUrl m_url;
+ QUrl m_redirectionTarget;
+ QList<RawHeaderPair> m_rawHeaderPairs;
+};
+
+}
+
+
+#endif // QtNAMThreadSafeProxy_h
diff --git a/WebCore/platform/network/qt/ResourceHandleQt.cpp b/WebCore/platform/network/qt/ResourceHandleQt.cpp
index a5ac4c3..f40b828 100644
--- a/WebCore/platform/network/qt/ResourceHandleQt.cpp
+++ b/WebCore/platform/network/qt/ResourceHandleQt.cpp
@@ -35,6 +35,7 @@
#include "Frame.h"
#include "FrameNetworkingContext.h"
#include "FrameLoaderClientQt.h"
+#include "QtNAMThreadSafeProxy.h"
#include "NotImplemented.h"
#include "Page.h"
#include "QNetworkReplyHandler.h"
@@ -156,20 +157,13 @@ bool ResourceHandle::willLoadFromCache(ResourceRequest& request, Frame* frame)
if (!frame)
return false;
- QNetworkAccessManager* manager = 0;
- QAbstractNetworkCache* cache = 0;
if (frame->loader()->networkingContext()) {
- manager = frame->loader()->networkingContext()->networkAccessManager();
- cache = manager->cache();
- }
-
- if (!cache)
- return false;
-
- QNetworkCacheMetaData data = cache->metaData(request.url());
- if (data.isValid()) {
- request.setCachePolicy(ReturnCacheDataDontLoad);
- return true;
+ QNetworkAccessManager* manager = frame->loader()->networkingContext()->networkAccessManager();
+ QtNAMThreadSafeProxy managerProxy(manager);
+ if (managerProxy.willLoadFromCache(request.url())) {
+ request.setCachePolicy(ReturnCacheDataDontLoad);
+ return true;
+ }
}
return false;
diff --git a/WebCore/platform/network/soup/ResourceHandleSoup.cpp b/WebCore/platform/network/soup/ResourceHandleSoup.cpp
index c1933e3..a2440d3 100644
--- a/WebCore/platform/network/soup/ResourceHandleSoup.cpp
+++ b/WebCore/platform/network/soup/ResourceHandleSoup.cpp
@@ -492,7 +492,7 @@ static void sendRequestCallback(GObject* source, GAsyncResult* res, gpointer use
if (isTransportError || (error->domain == G_IO_ERROR)) {
SoupURI* uri = webkit_soup_request_get_uri(d->m_soupRequest.get());
GOwnPtr<char> uriStr(soup_uri_to_string(uri, false));
- gint errorCode = isTransportError ? soupMsg->status_code : error->code;
+ gint errorCode = isTransportError ? static_cast<gint>(soupMsg->status_code) : error->code;
const gchar* errorMsg = isTransportError ? soupMsg->reason_phrase : error->message;
const gchar* quarkStr = isTransportError ? g_quark_to_string(SOUP_HTTP_ERROR) : g_quark_to_string(G_IO_ERROR);
ResourceError resourceError(quarkStr, errorCode, uriStr.get(), String::fromUTF8(errorMsg));
@@ -508,8 +508,11 @@ static void sendRequestCallback(GObject* source, GAsyncResult* res, gpointer use
fillResponseFromMessage(soupMsg, &d->m_response);
client->didReceiveResponse(handle.get(), d->m_response);
- // WebCore might have cancelled the job in the while
- if (!d->m_cancelled && soupMsg->response_body->data)
+ // WebCore might have cancelled the job in the while. We
+ // must check for response_body->length and not
+ // response_body->data as libsoup always creates the
+ // SoupBuffer for the body even if the length is 0
+ if (!d->m_cancelled && soupMsg->response_body->length)
client->didReceiveData(handle.get(), soupMsg->response_body->data, soupMsg->response_body->length, true);
}
@@ -550,6 +553,9 @@ static void sendRequestCallback(GObject* source, GAsyncResult* res, gpointer use
}
}
+ if (d->m_defersLoading)
+ soup_session_pause_message(handle->defaultSession(), d->m_soupMessage.get());
+
g_input_stream_read_async(d->m_inputStream.get(), d->m_buffer, READ_BUFFER_SIZE,
G_PRIORITY_DEFAULT, d->m_cancellable.get(), readCallback, 0);
}
@@ -660,8 +666,11 @@ static bool startHttp(ResourceHandle* handle)
if (!soup_message_headers_get_one(soupMessage->request_headers, "Accept"))
soup_message_headers_append(soupMessage->request_headers, "Accept", "*/*");
- d->m_cancellable = adoptPlatformRef(g_cancellable_new());
- webkit_soup_request_send_async(d->m_soupRequest.get(), d->m_cancellable.get(), sendRequestCallback, 0);
+ // Send the request only if it's not been explicitely deferred.
+ if (!d->m_defersLoading) {
+ d->m_cancellable = adoptPlatformRef(g_cancellable_new());
+ webkit_soup_request_send_async(d->m_soupRequest.get(), d->m_cancellable.get(), sendRequestCallback, 0);
+ }
return true;
}
@@ -734,9 +743,28 @@ bool ResourceHandle::supportsBufferedData()
return false;
}
-void ResourceHandle::platformSetDefersLoading(bool)
+void ResourceHandle::platformSetDefersLoading(bool defersLoading)
{
- notImplemented();
+ // Initial implementation of this method was required for bug #44157.
+
+ if (d->m_cancelled)
+ return;
+
+ if (!defersLoading && !d->m_cancellable && d->m_soupRequest.get()) {
+ d->m_cancellable = adoptPlatformRef(g_cancellable_new());
+ webkit_soup_request_send_async(d->m_soupRequest.get(), d->m_cancellable.get(), sendRequestCallback, 0);
+ return;
+ }
+
+ // Only supported for http(s) transfers. Something similar would
+ // probably be needed for data transfers done with GIO.
+ if (!d->m_soupMessage)
+ return;
+
+ if (defersLoading)
+ soup_session_pause_message(defaultSession(), d->m_soupMessage.get());
+ else
+ soup_session_unpause_message(defaultSession(), d->m_soupMessage.get());
}
bool ResourceHandle::loadsBlocked()
@@ -758,7 +786,7 @@ void ResourceHandle::loadResourceSynchronously(NetworkingContext* context, const
// FIXME: we should use the ResourceHandle::create method here,
// but it makes us timeout in a couple of tests. See
// https://bugs.webkit.org/show_bug.cgi?id=41823
- RefPtr<ResourceHandle> handle = adoptRef(new ResourceHandle(request, &syncLoader, true, false));
+ RefPtr<ResourceHandle> handle = adoptRef(new ResourceHandle(request, &syncLoader, false /*defersLoading*/, false /*shouldContentSniff*/));
handle->start(context);
syncLoader.run();
diff --git a/WebCore/platform/network/soup/cache/soup-http-input-stream.c b/WebCore/platform/network/soup/cache/soup-http-input-stream.c
index dc95d6e..195c458 100644
--- a/WebCore/platform/network/soup/cache/soup-http-input-stream.c
+++ b/WebCore/platform/network/soup/cache/soup-http-input-stream.c
@@ -598,6 +598,7 @@ send_async_finished (GInputStream *stream)
g_error_free (error);
}
g_simple_async_result_complete (result);
+ g_object_unref (result);
}
static void
diff --git a/WebCore/platform/network/soup/cache/soup-request-http.c b/WebCore/platform/network/soup/cache/soup-request-http.c
index f3fe2ec..777fd72 100644
--- a/WebCore/platform/network/soup/cache/soup-request-http.c
+++ b/WebCore/platform/network/soup/cache/soup-request-http.c
@@ -188,6 +188,7 @@ typedef struct {
WebKitSoupRequestHTTP *http;
GAsyncReadyCallback callback;
gpointer user_data;
+ WebKitSoupHTTPInputStream *httpstream;
} SendAsyncHelper;
static void webkit_soup_request_http_send_async (WebKitSoupRequest *request,
@@ -199,45 +200,34 @@ static gboolean
send_async_cb (gpointer data)
{
GSimpleAsyncResult *simple;
- WebKitSoupHTTPInputStream *httpstream;
- SoupSession *session;
- WebKitSoupCache *cache;
SendAsyncHelper *helper = (SendAsyncHelper *)data;
+ const gchar *content_type;
- session = webkit_soup_request_get_session (WEBKIT_SOUP_REQUEST (helper->http));
- cache = (WebKitSoupCache *)soup_session_get_feature (session, WEBKIT_TYPE_SOUP_CACHE);
-
- httpstream = (WebKitSoupHTTPInputStream *)webkit_soup_cache_send_response (cache, SOUP_MESSAGE (helper->http->priv->msg));
-
- if (httpstream) {
- const gchar *content_type;
-
- simple = g_simple_async_result_new (G_OBJECT (helper->http),
- helper->callback, helper->user_data,
- webkit_soup_request_http_send_async);
- g_simple_async_result_set_op_res_gpointer (simple, httpstream, g_object_unref);
+ simple = g_simple_async_result_new (G_OBJECT (helper->http),
+ helper->callback, helper->user_data,
+ webkit_soup_request_http_send_async);
+ g_simple_async_result_set_op_res_gpointer (simple, helper->httpstream, g_object_unref);
- /* Update message status */
- soup_message_set_status (helper->http->priv->msg, SOUP_STATUS_OK);
+ /* Update message status */
+ soup_message_set_status (helper->http->priv->msg, SOUP_STATUS_OK);
- /* Issue signals */
- soup_message_got_headers (helper->http->priv->msg);
+ /* Issue signals */
+ soup_message_got_headers (helper->http->priv->msg);
- /* FIXME: Uncomment this when this becomes part of libsoup
- * if (!soup_message_disables_feature(helper->http->priv->msg, SOUP_TYPE_CONTENT_SNIFFER)) {
- * const gchar *content_type = soup_message_headers_get_content_type (helper->http->priv->msg->response_headers, NULL);
- * soup_message_content_sniffed (helper->http->priv->msg, content_type, NULL);
- * }
- */
- content_type = soup_message_headers_get_content_type (helper->http->priv->msg->response_headers, NULL);
- soup_message_content_sniffed (helper->http->priv->msg, content_type, NULL);
+ /* FIXME: Uncomment this when this becomes part of libsoup
+ * if (!soup_message_disables_feature(helper->http->priv->msg, SOUP_TYPE_CONTENT_SNIFFER)) {
+ * const gchar *content_type = soup_message_headers_get_content_type (helper->http->priv->msg->response_headers, NULL);
+ * soup_message_content_sniffed (helper->http->priv->msg, content_type, NULL);
+ * }
+ */
+ content_type = soup_message_headers_get_content_type (helper->http->priv->msg->response_headers, NULL);
+ soup_message_content_sniffed (helper->http->priv->msg, content_type, NULL);
- g_simple_async_result_complete (simple);
+ g_simple_async_result_complete (simple);
- soup_message_finished (helper->http->priv->msg);
+ soup_message_finished (helper->http->priv->msg);
- g_object_unref (simple);
- }
+ g_object_unref (simple);
g_object_unref (helper->http);
g_slice_free (SendAsyncHelper, helper);
@@ -265,17 +255,28 @@ webkit_soup_request_http_send_async (WebKitSoupRequest *request,
response = webkit_soup_cache_has_response (cache, http->priv->msg);
if (response == WEBKIT_SOUP_CACHE_RESPONSE_FRESH) {
- /* Do return the stream asynchronously as in
- the other cases. It's not enough to use
- g_simple_async_result_complete_in_idle as
- the signals must be also emitted
- asynchronously */
- SendAsyncHelper *helper = g_slice_new (SendAsyncHelper);
- helper->http = g_object_ref (http);
- helper->callback = callback;
- helper->user_data = user_data;
- g_timeout_add (0, send_async_cb, helper);
- return;
+ WebKitSoupHTTPInputStream *httpstream;
+
+ httpstream = (WebKitSoupHTTPInputStream *)
+ webkit_soup_cache_send_response (cache, SOUP_MESSAGE (http->priv->msg));
+
+ /* Cached resource file could have been deleted outside
+ */
+ if (httpstream) {
+ /* Do return the stream asynchronously as in
+ * the other cases. It's not enough to use
+ * g_simple_async_result_complete_in_idle as
+ * the signals must be also emitted
+ * asynchronously
+ */
+ SendAsyncHelper *helper = g_slice_new (SendAsyncHelper);
+ helper->http = g_object_ref (http);
+ helper->callback = callback;
+ helper->user_data = user_data;
+ helper->httpstream = httpstream;
+ g_timeout_add (0, send_async_cb, helper);
+ return;
+ }
} else if (response == WEBKIT_SOUP_CACHE_RESPONSE_NEEDS_VALIDATION) {
SoupMessage *conditional_msg;
ConditionalHelper *helper;
diff --git a/WebCore/platform/network/soup/cache/webkit/soup-cache.c b/WebCore/platform/network/soup/cache/webkit/soup-cache.c
index 4835750..b96428d 100644
--- a/WebCore/platform/network/soup/cache/webkit/soup-cache.c
+++ b/WebCore/platform/network/soup/cache/webkit/soup-cache.c
@@ -147,6 +147,8 @@ get_cacheability (WebKitSoupCache *cache, SoupMessage *msg)
soup_header_free_param_list (hash);
return WEBKIT_SOUP_CACHE_UNCACHEABLE;
}
+
+ soup_header_free_param_list (hash);
}
switch (msg->status_code) {
@@ -284,14 +286,12 @@ webkit_soup_cache_entry_set_freshness (WebKitSoupCacheEntry *entry, SoupMessage
{
const char *cache_control;
const char *expires, *date, *last_modified;
- GHashTable *hash;
-
- hash = NULL;
cache_control = soup_message_headers_get (entry->headers, "Cache-Control");
if (cache_control) {
const char *max_age, *s_maxage;
gint64 freshness_lifetime = 0;
+ GHashTable *hash;
WebKitSoupCachePrivate *priv = WEBKIT_SOUP_CACHE_GET_PRIVATE (cache);
hash = soup_header_parse_param_list (cache_control);
@@ -323,10 +323,9 @@ webkit_soup_cache_entry_set_freshness (WebKitSoupCacheEntry *entry, SoupMessage
soup_header_free_param_list (hash);
return;
}
- }
- if (hash != NULL)
soup_header_free_param_list (hash);
+ }
/* If the 'Expires' response header is present, use its value
* minus the value of the 'Date' response header
@@ -998,6 +997,7 @@ webkit_soup_cache_send_response (WebKitSoupCache *cache, SoupMessage *msg)
key = soup_message_get_cache_key (msg);
entry = g_hash_table_lookup (cache->priv->cache, key);
+ g_free (key);
g_return_val_if_fail (entry, NULL);
/* If we are told to send a response from cache any validation
@@ -1084,11 +1084,12 @@ webkit_soup_cache_init (WebKitSoupCache *cache)
}
static void
-remove_cache_item (gpointer key,
- gpointer value,
- WebKitSoupCache *cache)
+remove_cache_item (gpointer data,
+ gpointer user_data)
{
- WebKitSoupCacheEntry *entry = g_hash_table_lookup (cache->priv->cache, (const gchar *)key);
+ WebKitSoupCache *cache = (WebKitSoupCache *) user_data;
+ WebKitSoupCacheEntry *entry = (WebKitSoupCacheEntry *) data;
+
if (webkit_soup_cache_entry_remove (cache, entry))
webkit_soup_cache_entry_free (entry, FALSE);
}
@@ -1097,10 +1098,15 @@ static void
webkit_soup_cache_finalize (GObject *object)
{
WebKitSoupCachePrivate *priv;
+ GList *entries;
priv = WEBKIT_SOUP_CACHE (object)->priv;
- g_hash_table_foreach (priv->cache, (GHFunc)remove_cache_item, object);
+ // Cannot use g_hash_table_foreach as callbacks must not modify the hash table
+ entries = g_hash_table_get_values (priv->cache);
+ g_list_foreach (entries, remove_cache_item, object);
+ g_list_free (entries);
+
g_hash_table_destroy (priv->cache);
g_free (priv->cache_dir);
@@ -1257,7 +1263,6 @@ webkit_soup_cache_has_response (WebKitSoupCache *cache, SoupMessage *msg)
char *key;
WebKitSoupCacheEntry *entry;
const char *cache_control;
- GHashTable *hash;
gpointer value;
gboolean must_revalidate;
int max_age, max_stale, min_fresh;
@@ -1265,6 +1270,7 @@ webkit_soup_cache_has_response (WebKitSoupCache *cache, SoupMessage *msg)
key = soup_message_get_cache_key (msg);
entry = g_hash_table_lookup (cache->priv->cache, key);
+ g_free (key);
/* 1. The presented Request-URI and that of stored response
* match
@@ -1321,10 +1327,10 @@ webkit_soup_cache_has_response (WebKitSoupCache *cache, SoupMessage *msg)
cache_control = soup_message_headers_get (msg->request_headers, "Cache-Control");
if (cache_control) {
- hash = soup_header_parse_param_list (cache_control);
+ GHashTable *hash = soup_header_parse_param_list (cache_control);
if (g_hash_table_lookup_extended (hash, "no-store", NULL, NULL)) {
- g_hash_table_destroy (hash);
+ soup_header_free_param_list (hash);
return WEBKIT_SOUP_CACHE_RESPONSE_STALE;
}
@@ -1348,7 +1354,7 @@ webkit_soup_cache_has_response (WebKitSoupCache *cache, SoupMessage *msg)
if (value)
min_fresh = (int)MIN (g_ascii_strtoll (value, NULL, 10), G_MAXINT32);
- g_hash_table_destroy (hash);
+ soup_header_free_param_list (hash);
if (max_age != -1) {
guint current_age = webkit_soup_cache_entry_get_current_age (entry);
@@ -1449,11 +1455,12 @@ webkit_soup_cache_flush (WebKitSoupCache *cache)
}
static void
-clear_cache_item (gpointer key,
- gpointer value,
- WebKitSoupCache *cache)
+clear_cache_item (gpointer data,
+ gpointer user_data)
{
- WebKitSoupCacheEntry *entry = g_hash_table_lookup (cache->priv->cache, (const gchar *)key);
+ WebKitSoupCache *cache = (WebKitSoupCache *) user_data;
+ WebKitSoupCacheEntry *entry = (WebKitSoupCacheEntry *) data;
+
if (webkit_soup_cache_entry_remove (cache, entry))
webkit_soup_cache_entry_free (entry, TRUE);
}
@@ -1469,13 +1476,17 @@ void
webkit_soup_cache_clear (WebKitSoupCache *cache)
{
GHashTable *hash;
+ GList *entries;
g_return_if_fail (WEBKIT_IS_SOUP_CACHE (cache));
hash = cache->priv->cache;
g_return_if_fail (hash);
- g_hash_table_foreach (hash, (GHFunc)clear_cache_item, cache);
+ // Cannot use g_hash_table_foreach as callbacks must not modify the hash table
+ entries = g_hash_table_get_values (hash);
+ g_list_foreach (entries, clear_cache_item, cache);
+ g_list_free (entries);
}
SoupMessage *
@@ -1604,12 +1615,13 @@ webkit_soup_cache_load (WebKitSoupCache *cache)
filename = g_build_filename (priv->cache_dir, WEBKIT_SOUP_CACHE_FILE, NULL);
if (!g_file_get_contents (filename, &contents, &length, NULL)) {
g_free (filename);
+ g_free (contents);
return;
}
g_free (filename);
variant_format = g_variant_type_new (WEBKIT_SOUP_CACHE_ENTRIES_FORMAT);
- cache_variant = g_variant_new_from_data (variant_format, (const gchar *)contents, length, FALSE, NULL, NULL);
+ cache_variant = g_variant_new_from_data (variant_format, (const gchar *)contents, length, FALSE, g_free, contents);
g_variant_type_free (variant_format);
g_variant_get (cache_variant, WEBKIT_SOUP_CACHE_ENTRIES_FORMAT, &entries_iter);
diff --git a/WebCore/platform/qt/ClipboardQt.cpp b/WebCore/platform/qt/ClipboardQt.cpp
index 20cf62b..c14d362 100644
--- a/WebCore/platform/qt/ClipboardQt.cpp
+++ b/WebCore/platform/qt/ClipboardQt.cpp
@@ -2,6 +2,7 @@
* Copyright (C) 2007 Apple Inc. All rights reserved.
* Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
* Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2010 Sencha, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -204,8 +205,20 @@ HashSet<String> ClipboardQt::types() const
PassRefPtr<FileList> ClipboardQt::files() const
{
- notImplemented();
- return 0;
+ if (policy() != ClipboardReadable || !m_readableData->hasUrls())
+ return FileList::create();
+
+ RefPtr<FileList> fileList = FileList::create();
+ QList<QUrl> urls = m_readableData->urls();
+
+ for (int i = 0; i < urls.size(); i++) {
+ QUrl url = urls[i];
+ if (url.scheme() != QLatin1String("file"))
+ continue;
+ fileList->append(File::create(url.toLocalFile()));
+ }
+
+ return fileList.release();
}
void ClipboardQt::setDragImage(CachedImage* image, const IntPoint& point)
diff --git a/WebCore/platform/qt/ContextMenuQt.cpp b/WebCore/platform/qt/ContextMenuQt.cpp
index e3715c9..c877642 100644
--- a/WebCore/platform/qt/ContextMenuQt.cpp
+++ b/WebCore/platform/qt/ContextMenuQt.cpp
@@ -35,8 +35,7 @@
namespace WebCore {
-ContextMenu::ContextMenu(const HitTestResult& result)
- : m_hitTestResult(result)
+ContextMenu::ContextMenu()
{
}
diff --git a/WebCore/platform/qt/CookieJarQt.cpp b/WebCore/platform/qt/CookieJarQt.cpp
index 049ee0f..e5d36ba 100644
--- a/WebCore/platform/qt/CookieJarQt.cpp
+++ b/WebCore/platform/qt/CookieJarQt.cpp
@@ -31,6 +31,7 @@
#include "Cookie.h"
#include "Document.h"
#include "KURL.h"
+#include "QtNAMThreadSafeProxy.h"
#include "NetworkingContext.h"
#include "PlatformString.h"
@@ -43,7 +44,8 @@
namespace WebCore {
-static QNetworkCookieJar *cookieJar(const Document *document)
+
+static QNetworkAccessManager *networkAccessManager(const Document *document)
{
if (!document)
return 0;
@@ -53,38 +55,30 @@ static QNetworkCookieJar *cookieJar(const Document *document)
FrameLoader *loader = frame->loader();
if (!loader)
return 0;
- QNetworkAccessManager* manager = loader->networkingContext()->networkAccessManager();
- QNetworkCookieJar* jar = manager->cookieJar();
- return jar;
+ return loader->networkingContext()->networkAccessManager();
}
void setCookies(Document* document, const KURL& url, const String& value)
{
- QUrl u(url);
- QUrl p(document->firstPartyForCookies());
- QNetworkCookieJar* jar = cookieJar(document);
- if (!jar)
+ QNetworkAccessManager* manager = networkAccessManager(document);
+ if (!manager)
return;
- QList<QNetworkCookie> cookies = QNetworkCookie::parseCookies(QString(value).toAscii());
- QList<QNetworkCookie>::Iterator it = cookies.begin();
- while (it != cookies.end()) {
- if (it->isHttpOnly())
- it = cookies.erase(it);
- else
- ++it;
- }
- jar->setCookiesFromUrl(cookies, u);
+ // Create the manipulator on the heap to let it live until the
+ // async request is picked by the other thread's event loop.
+ QtNAMThreadSafeProxy* managerProxy = new QtNAMThreadSafeProxy(manager);
+ managerProxy->setCookies(url, value);
+ managerProxy->deleteLater();
}
String cookies(const Document* document, const KURL& url)
{
- QUrl u(url);
- QNetworkCookieJar* jar = cookieJar(document);
- if (!jar)
+ QNetworkAccessManager* manager = networkAccessManager(document);
+ if (!manager)
return String();
- QList<QNetworkCookie> cookies = jar->cookiesForUrl(u);
+ QtNAMThreadSafeProxy managerProxy(manager);
+ QList<QNetworkCookie> cookies = managerProxy.cookiesForUrl(url);
if (cookies.isEmpty())
return String();
@@ -101,12 +95,12 @@ String cookies(const Document* document, const KURL& url)
String cookieRequestHeaderFieldValue(const Document* document, const KURL &url)
{
- QUrl u(url);
- QNetworkCookieJar* jar = cookieJar(document);
- if (!jar)
+ QNetworkAccessManager* manager = networkAccessManager(document);
+ if (!manager)
return String();
- QList<QNetworkCookie> cookies = jar->cookiesForUrl(u);
+ QtNAMThreadSafeProxy managerProxy(manager);
+ QList<QNetworkCookie> cookies = managerProxy.cookiesForUrl(url);
if (cookies.isEmpty())
return String();
@@ -121,8 +115,7 @@ String cookieRequestHeaderFieldValue(const Document* document, const KURL &url)
bool cookiesEnabled(const Document* document)
{
- QNetworkCookieJar* jar = cookieJar(document);
- return (jar != 0);
+ return networkAccessManager(document);
}
bool getRawCookies(const Document*, const KURL&, Vector<Cookie>& rawCookies)
diff --git a/WebCore/platform/qt/FileSystemQt.cpp b/WebCore/platform/qt/FileSystemQt.cpp
index b384091..d88a967 100644
--- a/WebCore/platform/qt/FileSystemQt.cpp
+++ b/WebCore/platform/qt/FileSystemQt.cpp
@@ -3,6 +3,7 @@
* Copyright (C) 2007 Holger Hans Peter Freyther
* Copyright (C) 2008 Apple, Inc. All rights reserved.
* Copyright (C) 2008 Collabora, Ltd. All rights reserved.
+ * Copyright (C) 2010 Sencha, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -94,7 +95,7 @@ String pathGetFileName(const String& path)
String directoryName(const String& path)
{
- return String(QFileInfo(path).absolutePath());
+ return QFileInfo(path).absolutePath();
}
Vector<String> listDirectory(const String& path, const String& filter)
@@ -128,7 +129,6 @@ CString openTemporaryFile(const char* prefix, PlatformFileHandle& handle)
return CString();
}
-#if ENABLE(NETSCAPE_PLUGIN_METADATA_CACHE)
PlatformFileHandle openFile(const String& path, FileOpenMode mode)
{
QIODevice::OpenMode platformMode;
@@ -153,7 +153,6 @@ int readFromFile(PlatformFileHandle handle, char* data, int length)
return handle->read(data, length);
return 0;
}
-#endif
void closeFile(PlatformFileHandle& handle)
{
@@ -163,6 +162,34 @@ void closeFile(PlatformFileHandle& handle)
}
}
+long long seekFile(PlatformFileHandle handle, long long offset, FileSeekOrigin origin)
+{
+ if (handle) {
+ long long current = 0;
+
+ switch (origin) {
+ case SeekFromBeginning:
+ break;
+ case SeekFromCurrent:
+ current = handle->pos();
+ break;
+ case SeekFromEnd:
+ current = handle->size();
+ break;
+ }
+
+ // Add the offset to the current position and seek to the new position
+ // Return our new position if the seek is successful
+ current += offset;
+ if (handle->seek(current))
+ return current;
+ else
+ return -1;
+ }
+
+ return -1;
+}
+
int writeToFile(PlatformFileHandle handle, const char* data, int length)
{
if (handle && handle->exists() && handle->isWritable())
diff --git a/WebCore/platform/qt/GeolocationServiceQt.cpp b/WebCore/platform/qt/GeolocationServiceQt.cpp
index 3562eb9..f4379b2 100644
--- a/WebCore/platform/qt/GeolocationServiceQt.cpp
+++ b/WebCore/platform/qt/GeolocationServiceQt.cpp
@@ -83,7 +83,13 @@ void GeolocationServiceQt::positionUpdated(const QGeoPositionInfo &geoPosition)
RefPtr<Coordinates> coordinates = Coordinates::create(latitude, longitude, providesAltitude, altitude,
accuracy, providesAltitudeAccuracy, altitudeAccuracy,
providesHeading, heading, providesSpeed, speed);
- m_lastPosition = Geoposition::create(coordinates.release(), geoPosition.timestamp().toTime_t());
+
+#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
+ m_lastPosition = Geoposition::create(coordinates.release(), geoPosition.timestamp().toMSecsSinceEpoch());
+#else
+ QDateTime timestamp = geoPosition.timestamp();
+ m_lastPosition = Geoposition::create(coordinates.release(), (timestamp.toTime_t() * 1000.00) + timestamp.time().msec());
+#endif
positionChanged();
}
diff --git a/WebCore/platform/qt/PlatformScreenQt.cpp b/WebCore/platform/qt/PlatformScreenQt.cpp
index db34e21..4db8bd1 100644
--- a/WebCore/platform/qt/PlatformScreenQt.cpp
+++ b/WebCore/platform/qt/PlatformScreenQt.cpp
@@ -86,7 +86,7 @@ int screenDepthPerComponent(Widget* w)
bool screenIsMonochrome(Widget* w)
{
- return QApplication::desktop()->screen(screenNumber(w))->numColors() < 2;
+ return QApplication::desktop()->screen(screenNumber(w))->colorCount() == 2;
}
FloatRect screenRect(Widget* w)
diff --git a/WebCore/platform/qt/TemporaryLinkStubsQt.cpp b/WebCore/platform/qt/TemporaryLinkStubsQt.cpp
index d7b5104..a46b82c 100644
--- a/WebCore/platform/qt/TemporaryLinkStubsQt.cpp
+++ b/WebCore/platform/qt/TemporaryLinkStubsQt.cpp
@@ -62,7 +62,6 @@
#include "SystemTime.h"
#include "TextBoundaries.h"
#include "Widget.h"
-#include "loader.h"
#include <float.h>
#include <stdio.h>
diff --git a/WebCore/platform/text/BidiResolver.h b/WebCore/platform/text/BidiResolver.h
index 6018c3f..1f87115 100644
--- a/WebCore/platform/text/BidiResolver.h
+++ b/WebCore/platform/text/BidiResolver.h
@@ -314,13 +314,23 @@ void BidiResolver<Iterator, Run>::checkDirectionInLowerRaiseEmbeddingLevel()
using namespace WTF::Unicode;
ASSERT(m_status.eor != OtherNeutral || eor.atEnd());
- ASSERT(m_status.last != NonSpacingMark
- && m_status.last != BoundaryNeutral
- && m_status.last != RightToLeftEmbedding
- && m_status.last != LeftToRightEmbedding
- && m_status.last != RightToLeftOverride
- && m_status.last != LeftToRightOverride
- && m_status.last != PopDirectionalFormat);
+ // bidi.sor ... bidi.eor ... bidi.last eor; need to append the bidi.sor-bidi.eor run or extend it through bidi.last
+ // Bidi control characters are included into BidiRun, so last direction
+ // could be one of the bidi embeddings when there are nested embeddings.
+ // For example: "&#x202a;&#x202b;....."
+ ASSERT(m_status.last == EuropeanNumberSeparator
+ || m_status.last == EuropeanNumberTerminator
+ || m_status.last == CommonNumberSeparator
+ || m_status.last == BoundaryNeutral
+ || m_status.last == BlockSeparator
+ || m_status.last == SegmentSeparator
+ || m_status.last == WhiteSpaceNeutral
+ || m_status.last == OtherNeutral
+ || m_status.last == RightToLeftEmbedding
+ || m_status.last == LeftToRightEmbedding
+ || m_status.last == RightToLeftOverride
+ || m_status.last == LeftToRightOverride
+ || m_status.last == PopDirectionalFormat);
if (m_direction == OtherNeutral)
m_direction = m_status.lastStrong == LeftToRight ? LeftToRight : RightToLeft;
}
@@ -332,7 +342,6 @@ void BidiResolver<Iterator, Run>::lowerExplicitEmbeddingLevel(WTF::Unicode::Dire
if (!emptyRun && eor != last) {
checkDirectionInLowerRaiseEmbeddingLevel();
- // bidi.sor ... bidi.eor ... bidi.last eor; need to append the bidi.sor-bidi.eor run or extend it through bidi.last
if (from == LeftToRight) {
// bidi.sor ... bidi.eor ... bidi.last L
if (m_status.eor == EuropeanNumber) {
@@ -368,7 +377,6 @@ void BidiResolver<Iterator, Run>::raiseExplicitEmbeddingLevel(WTF::Unicode::Dire
if (!emptyRun && eor != last) {
checkDirectionInLowerRaiseEmbeddingLevel();
- // bidi.sor ... bidi.eor ... bidi.last eor; need to append the bidi.sor-bidi.eor run or extend it through bidi.last
if (to == LeftToRight) {
// bidi.sor ... bidi.eor ... bidi.last L
if (m_status.eor == EuropeanNumber) {
@@ -858,11 +866,6 @@ void BidiResolver<Iterator, Run>::createBidiRunsForLine(const Iterator& end, boo
break;
case NonSpacingMark:
case BoundaryNeutral:
- case RightToLeftEmbedding:
- case LeftToRightEmbedding:
- case RightToLeftOverride:
- case LeftToRightOverride:
- case PopDirectionalFormat:
// ignore these
break;
case EuropeanNumber:
diff --git a/WebCore/platform/text/CharacterNames.h b/WebCore/platform/text/CharacterNames.h
index 9f8f807..c4b496e 100644
--- a/WebCore/platform/text/CharacterNames.h
+++ b/WebCore/platform/text/CharacterNames.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 2009, 2010 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -32,13 +32,20 @@ namespace WebCore {
// Names here are taken from the Unicode standard.
-// Note, these are UChar constants, not UChar32, which makes them
+// Most of these are UChar constants, not UChar32, which makes them
// more convenient for WebCore code that mostly uses UTF-16.
+const UChar32 aegeanWordSeparatorLine = 0x10100;
+const UChar32 aegeanWordSeparatorDot = 0x10101;
+const UChar blackCircle = 0x25CF;
const UChar blackSquare = 0x25A0;
+const UChar blackUpPointingTriangle = 0x25B2;
const UChar bullet = 0x2022;
+const UChar bullseye = 0x25CE;
const UChar carriageReturn = 0x000D;
const UChar ethiopicPrefaceColon = 0x1366;
+const UChar ethiopicWordspace = 0x1361;
+const UChar fisheye = 0x25C9;
const UChar hebrewPunctuationGeresh = 0x05F3;
const UChar hebrewPunctuationGershayim = 0x05F4;
const UChar horizontalEllipsis = 0x2026;
@@ -63,9 +70,16 @@ const UChar rightSingleQuotationMark = 0x2019;
const UChar rightToLeftEmbed = 0x202B;
const UChar rightToLeftMark = 0x200F;
const UChar rightToLeftOverride = 0x202E;
+const UChar sesameDot = 0xFE45;
const UChar softHyphen = 0x00AD;
const UChar space = 0x0020;
+const UChar tibetanMarkIntersyllabicTsheg = 0x0F0B;
+const UChar tibetanMarkDelimiterTshegBstar = 0x0F0C;
+const UChar32 ugariticWordDivider = 0x1039F;
const UChar whiteBullet = 0x25E6;
+const UChar whiteCircle = 0x25CB;
+const UChar whiteSesameDot = 0xFE46;
+const UChar whiteUpPointingTriangle = 0x25B3;
const UChar yenSign = 0x00A5;
const UChar zeroWidthJoiner = 0x200D;
const UChar zeroWidthNonJoiner = 0x200C;
diff --git a/WebCore/platform/text/TextBoundaries.cpp b/WebCore/platform/text/TextBoundaries.cpp
index 8eaffca..fbb261b 100644
--- a/WebCore/platform/text/TextBoundaries.cpp
+++ b/WebCore/platform/text/TextBoundaries.cpp
@@ -36,6 +36,32 @@ using namespace Unicode;
namespace WebCore {
+int endOfFirstWordBoundaryContext(const UChar* characters, int length)
+{
+ for (int i = 0; i < length; ) {
+ int first = i;
+ UChar32 ch;
+ U16_NEXT(characters, i, length, ch);
+ if (!requiresContextForWordBoundary(ch))
+ return first;
+ }
+ return length;
+}
+
+int startOfLastWordBoundaryContext(const UChar* characters, int length)
+{
+ for (int i = length; i > 0; ) {
+ int last = i;
+ UChar32 ch;
+ U16_PREV(characters, 0, i, ch);
+ if (!requiresContextForWordBoundary(ch))
+ return last;
+ }
+ return 0;
+}
+
+#if !PLATFORM(BREWMP) && !PLATFORM(MAC) && !PLATFORM(QT)
+
int findNextWordFromIndex(const UChar* chars, int len, int position, bool forward)
{
TextBreakIterator* it = wordBreakIterator(chars, len);
@@ -76,4 +102,6 @@ void findWordBoundary(const UChar* chars, int len, int position, int* start, int
*start = textBreakPrevious(it);
}
+#endif // !PLATFORM(BREWMP) && !PLATFORM(MAC) && !PLATFORM(QT)
+
} // namespace WebCore
diff --git a/WebCore/platform/text/TextBoundaries.h b/WebCore/platform/text/TextBoundaries.h
index 7eb9cab..870ab62 100644
--- a/WebCore/platform/text/TextBoundaries.h
+++ b/WebCore/platform/text/TextBoundaries.h
@@ -35,6 +35,9 @@ namespace WebCore {
return WTF::Unicode::hasLineBreakingPropertyComplexContext(ch);
}
+ int endOfFirstWordBoundaryContext(const UChar* characters, int length);
+ int startOfLastWordBoundaryContext(const UChar* characters, int length);
+
void findWordBoundary(const UChar*, int len, int position, int* start, int* end);
int findNextWordFromIndex(const UChar*, int len, int position, bool forward);
diff --git a/WebCore/platform/text/TextCodecUTF16.cpp b/WebCore/platform/text/TextCodecUTF16.cpp
index 95f4dc4..e88e83b 100644
--- a/WebCore/platform/text/TextCodecUTF16.cpp
+++ b/WebCore/platform/text/TextCodecUTF16.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2006, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2004, 2006, 2008, 2010 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -117,8 +117,13 @@ String TextCodecUTF16::decode(const char* bytes, size_t length, bool, bool, bool
CString TextCodecUTF16::encode(const UChar* characters, size_t length, UnencodableHandling)
{
- if (length > numeric_limits<size_t>::max() / 2)
- CRASH();
+ // We need to be sure we can double the length without overflowing.
+ // Since the passed-in length is the length of an actual existing
+ // character buffer, each character is two bytes, and we know
+ // the buffer doesn't occupy the entire address space, we can
+ // assert here that doubling the length does not overflow size_t
+ // and there's no need for a runtime check.
+ ASSERT(length <= numeric_limits<size_t>::max() / 2);
char* bytes;
CString string = CString::newUninitialized(length * 2, bytes);
diff --git a/WebCore/platform/text/TextEncoding.cpp b/WebCore/platform/text/TextEncoding.cpp
index 58e691f..33313a0 100644
--- a/WebCore/platform/text/TextEncoding.cpp
+++ b/WebCore/platform/text/TextEncoding.cpp
@@ -40,19 +40,11 @@
#include "GOwnPtr.h"
#endif
#include <wtf/text/CString.h>
-#include <wtf/HashSet.h>
#include <wtf/OwnPtr.h>
#include <wtf/StdLibExtras.h>
namespace WebCore {
-static void addEncodingName(HashSet<const char*>& set, const char* name)
-{
- const char* atomicName = atomicCanonicalTextEncodingName(name);
- if (atomicName)
- set.add(atomicName);
-}
-
static const TextEncoding& UTF7Encoding()
{
static TextEncoding globalUTF7Encoding("UTF-7");
@@ -173,39 +165,12 @@ bool TextEncoding::usesVisualOrdering() const
bool TextEncoding::isJapanese() const
{
- if (noExtendedTextEncodingNameUsed())
- return false;
-
- DEFINE_STATIC_LOCAL(HashSet<const char*>, set, ());
- if (set.isEmpty()) {
- addEncodingName(set, "x-mac-japanese");
- addEncodingName(set, "cp932");
- addEncodingName(set, "JIS_X0201");
- addEncodingName(set, "JIS_X0208-1983");
- addEncodingName(set, "JIS_X0208-1990");
- addEncodingName(set, "JIS_X0212-1990");
- addEncodingName(set, "JIS_C6226-1978");
- addEncodingName(set, "Shift_JIS_X0213-2000");
- addEncodingName(set, "ISO-2022-JP");
- addEncodingName(set, "ISO-2022-JP-2");
- addEncodingName(set, "ISO-2022-JP-1");
- addEncodingName(set, "ISO-2022-JP-3");
- addEncodingName(set, "EUC-JP");
- addEncodingName(set, "Shift_JIS");
- }
- return m_name && set.contains(m_name);
+ return isJapaneseEncoding(m_name);
}
UChar TextEncoding::backslashAsCurrencySymbol() const
{
- if (noExtendedTextEncodingNameUsed())
- return '\\';
-
- // The text encodings below treat backslash as a currency symbol.
- // See http://blogs.msdn.com/michkap/archive/2005/09/17/469941.aspx for more information.
- static const char* const a = atomicCanonicalTextEncodingName("Shift_JIS_X0213-2000");
- static const char* const b = atomicCanonicalTextEncodingName("EUC-JP");
- return (m_name == a || m_name == b) ? 0x00A5 : '\\';
+ return shouldShowBackslashAsCurrencySymbolIn(m_name) ? 0x00A5 : '\\';
}
bool TextEncoding::isNonByteBasedEncoding() const
diff --git a/WebCore/platform/text/TextEncodingRegistry.cpp b/WebCore/platform/text/TextEncodingRegistry.cpp
index 6bf5552..c0c0255 100644
--- a/WebCore/platform/text/TextEncodingRegistry.cpp
+++ b/WebCore/platform/text/TextEncodingRegistry.cpp
@@ -36,6 +36,7 @@
#include <wtf/Assertions.h>
#include <wtf/HashFunctions.h>
#include <wtf/HashMap.h>
+#include <wtf/HashSet.h>
#include <wtf/StdLibExtras.h>
#include <wtf/StringExtras.h>
#include <wtf/Threading.h>
@@ -125,6 +126,8 @@ static Mutex& encodingRegistryMutex()
static TextEncodingNameMap* textEncodingNameMap;
static TextCodecMap* textCodecMap;
static bool didExtendTextCodecMaps;
+static HashSet<const char*>* japaneseEncodings;
+static HashSet<const char*>* nonBackslashEncodings;
static const char* const textEncodingNameBlacklist[] = {
"UTF-7"
@@ -249,6 +252,59 @@ static void buildBaseTextCodecMaps()
#endif
}
+static void addEncodingName(HashSet<const char*>* set, const char* name)
+{
+ // We must not use atomicCanonicalTextEncodingName() because this function is called in it.
+ const char* atomicName = textEncodingNameMap->get(name);
+ if (atomicName)
+ set->add(atomicName);
+}
+
+static void buildQuirksSets()
+{
+ // FIXME: Having isJapaneseEncoding() and shouldShowBackslashAsCurrencySymbolIn()
+ // and initializing the sets for them in TextEncodingRegistry.cpp look strange.
+
+ ASSERT(!japaneseEncodings);
+ ASSERT(!nonBackslashEncodings);
+
+ japaneseEncodings = new HashSet<const char*>();
+ addEncodingName(japaneseEncodings, "EUC-JP");
+ addEncodingName(japaneseEncodings, "ISO-2022-JP");
+ addEncodingName(japaneseEncodings, "ISO-2022-JP-1");
+ addEncodingName(japaneseEncodings, "ISO-2022-JP-2");
+ addEncodingName(japaneseEncodings, "ISO-2022-JP-3");
+ addEncodingName(japaneseEncodings, "JIS_C6226-1978");
+ addEncodingName(japaneseEncodings, "JIS_X0201");
+ addEncodingName(japaneseEncodings, "JIS_X0208-1983");
+ addEncodingName(japaneseEncodings, "JIS_X0208-1990");
+ addEncodingName(japaneseEncodings, "JIS_X0212-1990");
+ addEncodingName(japaneseEncodings, "Shift_JIS");
+ addEncodingName(japaneseEncodings, "Shift_JIS_X0213-2000");
+ addEncodingName(japaneseEncodings, "cp932");
+ addEncodingName(japaneseEncodings, "x-mac-japanese");
+
+ nonBackslashEncodings = new HashSet<const char*>();
+ // The text encodings below treat backslash as a currency symbol for IE compatibility.
+ // See http://blogs.msdn.com/michkap/archive/2005/09/17/469941.aspx for more information.
+ addEncodingName(nonBackslashEncodings, "x-mac-japanese");
+ addEncodingName(nonBackslashEncodings, "ISO-2022-JP");
+ addEncodingName(nonBackslashEncodings, "EUC-JP");
+ // Shift_JIS_X0213-2000 is not the same encoding as Shift_JIS on Mac. We need to register both of them.
+ addEncodingName(nonBackslashEncodings, "Shift_JIS");
+ addEncodingName(nonBackslashEncodings, "Shift_JIS_X0213-2000");
+}
+
+bool isJapaneseEncoding(const char* canonicalEncodingName)
+{
+ return canonicalEncodingName && japaneseEncodings && japaneseEncodings->contains(canonicalEncodingName);
+}
+
+bool shouldShowBackslashAsCurrencySymbolIn(const char* canonicalEncodingName)
+{
+ return canonicalEncodingName && nonBackslashEncodings && nonBackslashEncodings->contains(canonicalEncodingName);
+}
+
static void extendTextCodecMaps()
{
#if USE(ICU_UNICODE)
@@ -277,6 +333,7 @@ static void extendTextCodecMaps()
#endif
pruneBlacklistedCodecs();
+ buildQuirksSets();
}
PassOwnPtr<TextCodec> newTextCodec(const TextEncoding& encoding)
diff --git a/WebCore/platform/text/TextEncodingRegistry.h b/WebCore/platform/text/TextEncodingRegistry.h
index 81b7c4c..16844c6 100644
--- a/WebCore/platform/text/TextEncodingRegistry.h
+++ b/WebCore/platform/text/TextEncodingRegistry.h
@@ -39,12 +39,12 @@ namespace WebCore {
// Use TextEncoding::encode to encode, since it takes care of normalization.
PassOwnPtr<TextCodec> newTextCodec(const TextEncoding&);
- // Only TextEncoding should use this function directly.
+ // Only TextEncoding should use the following functions directly.
const char* atomicCanonicalTextEncodingName(const char* alias);
const char* atomicCanonicalTextEncodingName(const UChar* aliasCharacters, size_t aliasLength);
-
- // Only TextEncoding should use this function directly.
bool noExtendedTextEncodingNameUsed();
+ bool isJapaneseEncoding(const char* canonicalEncodingName);
+ bool shouldShowBackslashAsCurrencySymbolIn(const char* canonicalEncodingName);
#ifndef NDEBUG
void dumpTextEncodingNameMap();
diff --git a/WebCore/platform/text/brew/StringBrew.cpp b/WebCore/platform/text/brew/StringBrew.cpp
deleted file mode 100644
index 2da81e3..0000000
--- a/WebCore/platform/text/brew/StringBrew.cpp
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2010 Company 100, 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 COMPUTER, 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 COMPUTER, 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 "PlatformString.h"
-
-#include <AEEstd.h>
-
-namespace WTF {
-
-// String conversions
-String::String(const AECHAR* string)
-{
- // It is safe to cast AECHAR to UChar as both of them use 16 bits representation.
- const UChar* str = reinterpret_cast<const UChar*>(string);
- const size_t len = std_wstrlen(string);
-
- m_impl = StringImpl::create(str, len);
-}
-
-} // namespace WebCore
-
diff --git a/WebCore/platform/text/cf/HyphenationCF.cpp b/WebCore/platform/text/cf/HyphenationCF.cpp
index dbc11ae..3adacad 100644
--- a/WebCore/platform/text/cf/HyphenationCF.cpp
+++ b/WebCore/platform/text/cf/HyphenationCF.cpp
@@ -33,46 +33,16 @@
#include <wtf/ListHashSet.h>
#include <wtf/RetainPtr.h>
-#if PLATFORM(WIN)
-
-#include "SoftLinking.h"
-
-#ifdef DEBUG_ALL
-SOFT_LINK_DEBUG_LIBRARY(CoreFoundation)
-#else
-SOFT_LINK_LIBRARY(CoreFoundation)
-#endif
-
-SOFT_LINK_OPTIONAL(CoreFoundation, CFStringGetHyphenationLocationBeforeIndex, CFIndex, , (CFStringRef string, CFIndex location, CFRange limitRange, CFOptionFlags options, CFLocaleRef locale, UTF32Char *character))
-SOFT_LINK_OPTIONAL(CoreFoundation, CFStringIsHyphenationAvailableForLocale, Boolean, , (CFLocaleRef locale))
-
-static CFIndex wkCFStringGetHyphenationLocationBeforeIndex(CFStringRef string, CFIndex location, CFRange limitRange, CFOptionFlags options, CFLocaleRef locale, UTF32Char *character)
-{
- static CFStringGetHyphenationLocationBeforeIndexPtrType cfStringGetHyphenationLocationBeforeIndex = CFStringGetHyphenationLocationBeforeIndexPtr();
- if (!cfStringGetHyphenationLocationBeforeIndex)
- return kCFNotFound;
- return cfStringGetHyphenationLocationBeforeIndex(string, location, limitRange, options, locale, character);
-}
-
-static Boolean wkCFStringIsHyphenationAvailableForLocale(CFLocaleRef locale)
-{
- static CFStringIsHyphenationAvailableForLocalePtrType cfStringIsHyphenationAvailableForLocale = CFStringIsHyphenationAvailableForLocalePtr();
- return cfStringIsHyphenationAvailableForLocale && cfStringIsHyphenationAvailableForLocale(locale);
-}
-
-#define CFStringGetHyphenationLocationBeforeIndex wkCFStringGetHyphenationLocationBeforeIndex
-#define CFStringIsHyphenationAvailableForLocale wkCFStringIsHyphenationAvailableForLocale
-
-#endif // PLATFORM(WIN)
-
namespace WebCore {
+#if !PLATFORM(WIN) || (defined(MAC_OS_X_VERSION_10_7) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7)
+
template<>
RetainPtr<CFLocaleRef> AtomicStringKeyedMRUCache<RetainPtr<CFLocaleRef> >::createValueForNullKey()
{
- RetainPtr<CFStringRef> cfLocaleIdentifier(AdoptCF, CFStringCreateWithBytesNoCopy(kCFAllocatorDefault, reinterpret_cast<const UInt8*>(currentSearchLocaleID()), strlen(currentSearchLocaleID()), kCFStringEncodingASCII, false, kCFAllocatorNull));
- RetainPtr<CFLocaleRef> locale(AdoptCF, CFLocaleCreate(kCFAllocatorDefault, cfLocaleIdentifier.get()));
- return locale;
+ RetainPtr<CFLocaleRef> locale(AdoptCF, CFLocaleCopyCurrent());
+
+ return CFStringIsHyphenationAvailableForLocale(locale.get()) ? locale : 0;
}
template<>
@@ -80,7 +50,7 @@ RetainPtr<CFLocaleRef> AtomicStringKeyedMRUCache<RetainPtr<CFLocaleRef> >::creat
{
RetainPtr<CFStringRef> cfLocaleIdentifier(AdoptCF, localeIdentifier.createCFString());
RetainPtr<CFLocaleRef> locale(AdoptCF, CFLocaleCreate(kCFAllocatorDefault, cfLocaleIdentifier.get()));
-
+
return CFStringIsHyphenationAvailableForLocale(locale.get()) ? locale : 0;
}
@@ -106,6 +76,21 @@ size_t lastHyphenLocation(const UChar* characters, size_t length, size_t beforeI
return result == kCFNotFound ? 0 : result;
}
+#else
+
+bool canHyphenate(const AtomicString&)
+{
+ return false;
+}
+
+size_t lastHyphenLocation(const UChar*, size_t, size_t, const AtomicString&)
+{
+ ASSERT_NOT_REACHED();
+ return 0;
+}
+
+#endif // PLATFORM(WIN) && (!defined(MAC_OS_X_VERSION_10_7) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7)
+
} // namespace WebCore
#endif // !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
diff --git a/WebCore/platform/text/haiku/StringHaiku.cpp b/WebCore/platform/text/haiku/StringHaiku.cpp
deleted file mode 100644
index 96d6676..0000000
--- a/WebCore/platform/text/haiku/StringHaiku.cpp
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2007 Ryan Leavengood <leavengood@gmail.com>
- *
- * 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 COMPUTER, 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 COMPUTER, 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 "PlatformString.h"
-#include <wtf/text/CString.h>
-
-#include <String.h>
-
-namespace WTF {
-
-// String conversions
-String::String(const BString& string)
-{
- if (string.Length())
- m_impl = String::fromUTF8(string.String(), string.Length()).impl();
- else
- m_impl = StringImpl::empty();
-}
-
-String::operator BString() const
-{
- BString string;
- string.SetTo(utf8().data());
-
- return string;
-}
-
-} // namespace WebCore
-
diff --git a/WebCore/platform/text/wince/TextCodecWinCE.cpp b/WebCore/platform/text/wince/TextCodecWinCE.cpp
index da6d5a5..3532e74 100644
--- a/WebCore/platform/text/wince/TextCodecWinCE.cpp
+++ b/WebCore/platform/text/wince/TextCodecWinCE.cpp
@@ -333,8 +333,7 @@ String TextCodecWinCE::decode(const char* bytes, size_t length, bool flush, bool
result.append(L'?');
sawError = true;
if (stopOnError)
- return String(result.data(), result.size());
-
+ return String::adopt(result);
if (left == 1)
break;
@@ -351,7 +350,8 @@ String TextCodecWinCE::decode(const char* bytes, size_t length, bool flush, bool
}
} else
m_decodeBuffer.clear();
- return String(result.data(), result.size());
+
+ return String::adopt(result);
}
CString TextCodecWinCE::encode(const UChar* characters, size_t length, UnencodableHandling)
diff --git a/WebCore/platform/text/wx/StringWx.cpp b/WebCore/platform/text/wx/StringWx.cpp
deleted file mode 100644
index 7302edc..0000000
--- a/WebCore/platform/text/wx/StringWx.cpp
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2007 Vaclav Slavik, Kevin Ollivier <kevino@theolliviers.com>
- *
- * 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 COMPUTER, 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 COMPUTER, 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 "PlatformString.h"
-
-#include "unicode/ustring.h"
-#include <wtf/text/CString.h>
-
-#include <wx/defs.h>
-#include <wx/string.h>
-
-namespace WTF {
-
-// String conversions
-String::String(const wxString& wxstr)
-{
-#if !wxUSE_UNICODE
- #error "This code only works in Unicode build of wxWidgets"
-#endif
-
- // ICU's UChar is 16bit wide, UTF-16, and the code below counts on it, so
- // it would break if the definition changed:
- wxCOMPILE_TIME_ASSERT(sizeof(UChar) == 2, UCharSizeMustBe16Bit);
-
-#if SIZEOF_WCHAR_T == 2 // wchar_t==UChar
-
- const UChar* str = wxstr.wc_str();
- const size_t len = wxstr.length();
-
-#else // SIZEOF_WCHAR_T == 4
-
- // NB: we can't simply use wxstr.mb_str(wxMBConvUTF16()) here because
- // the number of characters in UTF-16 encoding of the string may differ
- // from the number of UTF-32 values and we can't get the length from
- // returned buffer:
-
-#if defined(wxUSE_UNICODE_UTF8) && wxUSE_UNICODE_UTF8
- // in wx3's UTF8 mode, wc_str() returns a buffer, not raw pointer
- wxWCharBuffer widestr(wxstr.wc_str());
-#else
- const wxChar *widestr = wxstr.wc_str();
-#endif
- const size_t widelen = wxstr.length();
-
- // allocate buffer for the UTF-16 string:
- wxMBConvUTF16 conv;
- const size_t utf16bufLen = conv.FromWChar(NULL, 0, widestr, widelen);
- wxCharBuffer utf16buf(utf16bufLen);
-
- // and convert wxString to UTF-16 (=UChar*):
- const UChar* str = (const UChar*)utf16buf.data();
- size_t len = conv.FromWChar(utf16buf.data(), utf16bufLen, widestr, widelen) / 2;
-
-#endif // SIZEOF_WCHAR_T == 4
-
- // conversion to UTF-16 or getting internal buffer isn't supposed to fail:
- wxASSERT_MSG(str != NULL, _T("failed string conversion?"));
-
- m_impl = StringImpl::create(str, len);
-}
-
-String::operator wxString() const
-{
- return wxString(utf8().data(), wxConvUTF8);
-}
-
-}
-
-// vim: ts=4 sw=4 et
diff --git a/WebCore/platform/win/ContextMenuItemWin.cpp b/WebCore/platform/win/ContextMenuItemWin.cpp
index 8d1c175..59aedcd 100644
--- a/WebCore/platform/win/ContextMenuItemWin.cpp
+++ b/WebCore/platform/win/ContextMenuItemWin.cpp
@@ -28,198 +28,66 @@
#include "ContextMenu.h"
-#include <wtf/text/CString.h>
-#include <windows.h>
-
-#if OS(WINCE)
-#ifndef MFS_DISABLED
-#define MFS_DISABLED MF_GRAYED
-#endif
-#ifndef MIIM_FTYPE
-#define MIIM_FTYPE MIIM_TYPE
-#endif
-#ifndef MIIM_STRING
-#define MIIM_STRING 0
-#endif
-#endif
-
namespace WebCore {
-ContextMenuItem::ContextMenuItem(LPMENUITEMINFO item)
- : m_platformDescription(item)
-{
-}
-
-ContextMenuItem::ContextMenuItem(ContextMenu* subMenu)
+ContextMenuItem::ContextMenuItem(const MENUITEMINFO& info)
{
- m_platformDescription = (LPMENUITEMINFO)malloc(sizeof(MENUITEMINFO));
- if (!m_platformDescription)
- return;
+ if (info.fMask & MIIM_FTYPE)
+ m_type = info.fType == MFT_SEPARATOR ? SeparatorType : ActionType;
+ else
+ m_type = SeparatorType;
- memset(m_platformDescription, 0, sizeof(MENUITEMINFO));
- m_platformDescription->cbSize = sizeof(MENUITEMINFO);
+ if (m_type == ActionType && info.fMask & MIIM_STRING)
+ m_title = String(info.dwTypeData, info.cch);
- m_platformDescription->wID = ContextMenuItemTagNoAction;
- if (subMenu) {
- m_platformDescription->fMask |= MIIM_SUBMENU;
- m_platformDescription->hSubMenu = subMenu->platformDescription();
+ if ((info.fMask & MIIM_SUBMENU) && info.hSubMenu) {
+ m_type = SubmenuType;
+ ContextMenu::getContextMenuItems(info.hSubMenu, m_subMenuItems);
}
-}
-
-ContextMenuItem::ContextMenuItem(ContextMenuItemType type, ContextMenuAction action, const String& title, ContextMenu* subMenu)
-{
- m_platformDescription = (LPMENUITEMINFO)malloc(sizeof(MENUITEMINFO));
- if (!m_platformDescription)
- return;
- memset(m_platformDescription, 0, sizeof(MENUITEMINFO));
- m_platformDescription->cbSize = sizeof(MENUITEMINFO);
- m_platformDescription->fMask = MIIM_FTYPE;
+ if (info.fMask & MIIM_ID)
+ m_action = static_cast<ContextMenuAction>(info.wID);
+ else
+ m_action = ContextMenuItemTagNoAction;
- if (type == SeparatorType) {
- m_platformDescription->fType = MFT_SEPARATOR;
- return;
+ if (info.fMask & MIIM_STATE) {
+ m_checked = info.fState & MFS_CHECKED;
+ m_enabled = !(info.fState & MFS_DISABLED);
+ } else {
+ m_checked = false;
+ m_enabled = false;
}
-
- if (subMenu) {
- m_platformDescription->fMask |= MIIM_STRING | MIIM_SUBMENU;
- m_platformDescription->hSubMenu = subMenu->platformDescription();
- } else
- m_platformDescription->fMask |= MIIM_STRING | MIIM_ID;
-
- m_platformDescription->fType = MFT_STRING;
- m_platformDescription->wID = action;
-
- String t = title;
- m_platformDescription->cch = t.length();
- m_platformDescription->dwTypeData = wcsdup(t.charactersWithNullTermination());
}
-ContextMenuItem::ContextMenuItem(ContextMenuItemType, ContextMenuAction, const String&, bool, bool)
+// ContextMenuItem::nativeMenuItem doesn't set the info.dwTypeData. This is
+// done to make the lifetime handling of the returned MENUITEMINFO easier on
+// callers. Callers can set dwTypeData themselves (and make their own decisions
+// about its lifetime) if they need it.
+MENUITEMINFO ContextMenuItem::nativeMenuItem() const
{
- // FIXME: Implement
-}
+ MENUITEMINFO info = {0};
+ info.cbSize = sizeof(MENUITEMINFO);
-ContextMenuItem::ContextMenuItem(ContextMenuAction, const String&, bool, bool, Vector<ContextMenuItem>&)
-{
- // FIXME: Implement
-}
-
-ContextMenuItem::~ContextMenuItem()
-{
- if (m_platformDescription) {
- if (m_platformDescription->fType == MFT_STRING)
- free(m_platformDescription->dwTypeData);
- free(m_platformDescription);
+ if (m_type == SeparatorType) {
+ info.fMask = MIIM_FTYPE;
+ info.fType = MFT_SEPARATOR;
+ return info;
}
-}
-
-LPMENUITEMINFO ContextMenuItem::releasePlatformDescription()
-{
- LPMENUITEMINFO info = m_platformDescription;
- m_platformDescription = 0;
- return info;
-}
-
-ContextMenuItemType ContextMenuItem::type() const
-{
- ContextMenuItemType type = ActionType;
- if (((m_platformDescription->fType & ~MFT_OWNERDRAW) == MFT_STRING) && m_platformDescription->hSubMenu)
- type = SubmenuType;
- else if (m_platformDescription->fType & MFT_SEPARATOR)
- type = SeparatorType;
-
- return type;
-}
-
-ContextMenuAction ContextMenuItem::action() const
-{
- return static_cast<ContextMenuAction>(m_platformDescription->wID);
-}
-
-String ContextMenuItem::title() const
-{
- return String(m_platformDescription->dwTypeData, wcslen(m_platformDescription->dwTypeData));
-}
-
-PlatformMenuDescription ContextMenuItem::platformSubMenu() const
-{
- return m_platformDescription->hSubMenu;
-}
-
-void ContextMenuItem::setType(ContextMenuItemType type)
-{
- if (type == SeparatorType)
- m_platformDescription->fType = MFT_SEPARATOR;
- else
- m_platformDescription->fType = MFT_STRING;
-}
-
-void ContextMenuItem::setAction(ContextMenuAction action)
-{
- m_platformDescription->wID = action;
-}
-
-void ContextMenuItem::setTitle(const String& title)
-{
- if (m_platformDescription->dwTypeData)
- free(m_platformDescription->dwTypeData);
-
- m_platformDescription->cch = title.length();
- String titleCopy = title;
- m_platformDescription->dwTypeData = wcsdup(titleCopy.charactersWithNullTermination());
-}
-
-void ContextMenuItem::setSubMenu(ContextMenu* subMenu)
-{
- if (subMenu->platformDescription() == m_platformDescription->hSubMenu)
- return;
-
- if (m_platformDescription->hSubMenu)
- ::DestroyMenu(m_platformDescription->hSubMenu);
- m_platformDescription->fMask |= MIIM_SUBMENU;
- m_platformDescription->hSubMenu = subMenu->releasePlatformDescription();
-}
+ info.fMask = MIIM_FTYPE | MIIM_ID | MIIM_STATE;
+ info.fType = MFT_STRING;
-void ContextMenuItem::setSubMenu(Vector<ContextMenuItem>&)
-{
- // FIXME: Implement
-}
+ info.wID = m_action;
-void ContextMenuItem::setChecked(bool checked)
-{
- m_platformDescription->fMask |= MIIM_STATE;
- if (checked) {
- m_platformDescription->fState &= ~MFS_UNCHECKED;
- m_platformDescription->fState |= MFS_CHECKED;
- } else {
- m_platformDescription->fState &= ~MFS_CHECKED;
- m_platformDescription->fState |= MFS_UNCHECKED;
+ if (m_type == SubmenuType) {
+ info.fMask |= MIIM_SUBMENU;
+ info.hSubMenu = ContextMenu::createNativeMenuFromItems(m_subMenuItems);
}
-}
-bool ContextMenuItem::checked() const
-{
- // FIXME - Implement
- return false;
-}
+ info.fState |= m_enabled ? MFS_ENABLED : MFS_DISABLED;
+ info.fState |= m_checked ? MFS_CHECKED : MFS_UNCHECKED;
-void ContextMenuItem::setEnabled(bool enabled)
-{
- m_platformDescription->fMask |= MIIM_STATE;
- if (enabled) {
- m_platformDescription->fState &= ~MFS_DISABLED;
- m_platformDescription->fState |= MFS_ENABLED;
- } else {
- m_platformDescription->fState &= ~MFS_ENABLED;
- m_platformDescription->fState |= MFS_DISABLED;
- }
-}
-
-bool ContextMenuItem::enabled() const
-{
- return !(m_platformDescription->fState & MFS_DISABLED);
+ return info;
}
}
diff --git a/WebCore/platform/win/ContextMenuWin.cpp b/WebCore/platform/win/ContextMenuWin.cpp
index 10443aa..24c355d 100644
--- a/WebCore/platform/win/ContextMenuWin.cpp
+++ b/WebCore/platform/win/ContextMenuWin.cpp
@@ -32,6 +32,7 @@
#include "Node.h"
#include <tchar.h>
#include <windows.h>
+#include <wtf/Vector.h>
#include <wtf/text/CString.h>
#ifndef MIIM_FTYPE
@@ -43,184 +44,67 @@
namespace WebCore {
-ContextMenu::ContextMenu(const HitTestResult& result)
- : m_hitTestResult(result)
- , m_platformDescription(0)
-#if OS(WINCE)
- , m_itemCount(0)
-#endif
+ContextMenu::ContextMenu(HMENU menu)
{
- setPlatformDescription(::CreatePopupMenu());
-}
-
-ContextMenu::ContextMenu(const HitTestResult& result, const PlatformMenuDescription menu)
- : m_hitTestResult(result)
- , m_platformDescription(0)
-#if OS(WINCE)
- , m_itemCount(0)
-#endif
-{
- setPlatformDescription(menu);
-}
-
-ContextMenu::~ContextMenu()
-{
- if (m_platformDescription)
- ::DestroyMenu(m_platformDescription);
-}
-
-unsigned ContextMenu::itemCount() const
-{
-#if OS(WINCE)
- return m_itemCount;
-#else
- if (!m_platformDescription)
- return 0;
-
- return ::GetMenuItemCount(m_platformDescription);
-#endif
+ getContextMenuItems(menu, m_items);
}
-#if OS(WINCE)
-static bool insertMenuItem(PlatformMenuDescription menu, unsigned int position, ContextMenuItem& item)
+void ContextMenu::getContextMenuItems(HMENU menu, Vector<ContextMenuItem>& items)
{
- UINT flags = MF_BYPOSITION;
- UINT newItem = 0;
- LPCWSTR title = 0;
-
- if (item.type() == SeparatorType)
- flags |= MF_SEPARATOR;
- else {
- flags |= MF_STRING;
- flags |= item.checked() ? MF_CHECKED : MF_UNCHECKED;
- flags |= item.enabled() ? MF_ENABLED : MF_GRAYED;
-
- PlatformMenuItemDescription description = item.releasePlatformDescription();
- title = description->dwTypeData;
- description->dwTypeData = 0;
-
- if (description->hSubMenu) {
- flags |= MF_POPUP;
- newItem = reinterpret_cast<UINT>(description->hSubMenu);
- description->hSubMenu = 0;
- } else
- newItem = description->wID;
-
- free(description);
- }
-
- return ::InsertMenuW(menu, position, flags, newItem, title);
-}
-#endif
-
-void ContextMenu::insertItem(unsigned int position, ContextMenuItem& item)
-{
- if (!m_platformDescription)
+ int count = ::GetMenuItemCount(menu);
+ if (count <= 0)
return;
- checkOrEnableIfNeeded(item);
+ for (int i = 0; i < count; ++i) {
+ MENUITEMINFO info = {0};
+ info.cbSize = sizeof(MENUITEMINFO);
+ info.fMask = MIIM_FTYPE | MIIM_ID | MIIM_STRING | MIIM_STATE | MIIM_SUBMENU;
-#if OS(WINCE)
- if (insertMenuItem(m_platformDescription, position, item))
- ++m_itemCount;
-#else
- ::InsertMenuItem(m_platformDescription, position, TRUE, item.releasePlatformDescription());
-#endif
-}
-
-void ContextMenu::appendItem(ContextMenuItem& item)
-{
- insertItem(itemCount(), item);
-}
+ if (!::GetMenuItemInfo(menu, i, TRUE, &info))
+ continue;
-static ContextMenuItem* contextMenuItemByIdOrPosition(HMENU menu, unsigned id, BOOL byPosition)
-{
- if (!menu)
- return 0;
- LPMENUITEMINFO info = static_cast<LPMENUITEMINFO>(malloc(sizeof(MENUITEMINFO)));
- if (!info)
- return 0;
-
- memset(info, 0, sizeof(MENUITEMINFO));
-
- info->cbSize = sizeof(MENUITEMINFO);
-
- // Setting MIIM_DATA which is useful for WebKit clients who store data in this member for their custom menu items.
- info->fMask = MIIM_FTYPE | MIIM_ID | MIIM_STRING | MIIM_DATA;
-
- if (!::GetMenuItemInfo(menu, id, byPosition, info)) {
- free(info);
- return 0;
- }
-
- if (info->fType & MFT_STRING) {
- LPTSTR buffer = static_cast<LPTSTR>(malloc(++info->cch * sizeof(TCHAR)));
- if (!buffer) {
- free(info);
- return 0;
+ if (info.fType == MFT_SEPARATOR) {
+ items.append(ContextMenuItem(SeparatorType, ContextMenuItemTagNoAction, String()));
+ continue;
}
- info->dwTypeData = buffer;
- ::GetMenuItemInfo(menu, id, byPosition, info);
- }
-
- return new ContextMenuItem(info);
-}
-ContextMenuItem* ContextMenu::itemWithAction(unsigned action)
-{
- return contextMenuItemByIdOrPosition(m_platformDescription, action, FALSE);
-}
+ int menuStringLength = info.cch + 1;
+ OwnArrayPtr<WCHAR> menuString(new WCHAR[menuStringLength]);
+ info.dwTypeData = menuString.get();
+ info.cch = menuStringLength;
-ContextMenuItem* ContextMenu::itemAtIndex(unsigned index, const PlatformMenuDescription platformDescription)
-{
- return contextMenuItemByIdOrPosition(platformDescription, index, TRUE);
+ if (::GetMenuItemInfo(menu, i, TRUE, &info))
+ items.append(ContextMenuItem(info));
+ }
}
-void ContextMenu::setPlatformDescription(HMENU menu)
+HMENU ContextMenu::createNativeMenuFromItems(const Vector<ContextMenuItem>& items)
{
- if (menu == m_platformDescription)
- return;
-
- if (m_platformDescription)
- ::DestroyMenu(m_platformDescription);
+ HMENU menu = ::CreatePopupMenu();
- m_platformDescription = menu;
- if (!m_platformDescription)
- return;
+ for (size_t i = 0; i < items.size(); ++i) {
+ const ContextMenuItem& item = items[i];
-#if !OS(WINCE)
- MENUINFO menuInfo = {0};
- menuInfo.cbSize = sizeof(MENUINFO);
- menuInfo.fMask = MIM_STYLE;
- ::GetMenuInfo(m_platformDescription, &menuInfo);
- menuInfo.fMask = MIM_STYLE;
- menuInfo.dwStyle |= MNS_NOTIFYBYPOS;
- ::SetMenuInfo(m_platformDescription, &menuInfo);
-#endif
-}
+ MENUITEMINFO menuItem = item.nativeMenuItem();
-HMENU ContextMenu::platformDescription() const
-{
- return m_platformDescription;
-}
+ // ContextMenuItem::nativeMenuItem doesn't set the title of the MENUITEMINFO to make the
+ // lifetime handling easier for callers.
+ String itemTitle = item.title();
+ if (item.type() != SeparatorType) {
+ menuItem.fMask |= MIIM_STRING;
+ menuItem.cch = itemTitle.length();
+ menuItem.dwTypeData = const_cast<LPWSTR>(itemTitle.charactersWithNullTermination());
+ }
-HMENU ContextMenu::releasePlatformDescription()
-{
- HMENU description = m_platformDescription;
- m_platformDescription = 0;
- return description;
-}
+ ::InsertMenuItem(menu, i, TRUE, &menuItem);
+ }
-Vector<ContextMenuItem> contextMenuItemVector(PlatformMenuDescription)
-{
- // FIXME - Implement
- return Vector<ContextMenuItem>();
+ return menu;
}
-PlatformMenuDescription platformMenuDescription(Vector<ContextMenuItem>& menuItemVector)
+HMENU ContextMenu::nativeMenu() const
{
- // FIXME - Implement
- return 0;
+ return createNativeMenuFromItems(m_items);
}
} // namespace WebCore
diff --git a/WebCore/platform/win/FileSystemWin.cpp b/WebCore/platform/win/FileSystemWin.cpp
index cef7196..5ee3b8e 100644
--- a/WebCore/platform/win/FileSystemWin.cpp
+++ b/WebCore/platform/win/FileSystemWin.cpp
@@ -134,10 +134,7 @@ String pathGetFileName(const String& path)
String directoryName(const String& path)
{
- String fileName = pathGetFileName(path);
- String dirName = String(path);
- dirName.truncate(dirName.length() - pathGetFileName(path).length());
- return dirName;
+ return path.left(path.length() - pathGetFileName(path).length());
}
static String bundleName()
diff --git a/WebCore/platform/wince/FileSystemWinCE.cpp b/WebCore/platform/wince/FileSystemWinCE.cpp
index 90b278e..49acf12 100644
--- a/WebCore/platform/wince/FileSystemWinCE.cpp
+++ b/WebCore/platform/wince/FileSystemWinCE.cpp
@@ -33,13 +33,26 @@
#include "NotImplemented.h"
#include "PlatformString.h"
-#include <wtf/text/CString.h>
-
-#include <windows.h>
#include <wincrypt.h>
+#include <windows.h>
+#include <wtf/text/CString.h>
namespace WebCore {
+static size_t reverseFindPathSeparator(const String& path, unsigned start = UINT_MAX)
+{
+ size_t positionSlash = path.reverseFind('/', start);
+ size_t positionBackslash = path.reverseFind('\\', start);
+
+ if (positionSlash == notFound)
+ return positionBackslash;
+
+ if (positionBackslash == notFound)
+ return positionSlash;
+
+ return std::max(positionSlash, positionBackslash);
+}
+
static bool getFileInfo(const String& path, BY_HANDLE_FILE_INFORMATION& fileInfo)
{
String filename = path;
@@ -133,14 +146,14 @@ CString fileSystemRepresentation(const String&)
bool makeAllDirectories(const String& path)
{
- int lastDivPos = std::max(path.reverseFind('/'), path.reverseFind('\\'));
- int endPos = path.length();
- if (lastDivPos == path.length() - 1) {
- endPos -= 1;
- lastDivPos = std::max(path.reverseFind('/', lastDivPos), path.reverseFind('\\', lastDivPos));
+ size_t lastDivPos = reverseFindPathSeparator(path);
+ unsigned endPos = path.length();
+ if (lastDivPos == endPos - 1) {
+ --endPos;
+ lastDivPos = reverseFindPathSeparator(path, lastDivPos);
}
- if (lastDivPos > 0) {
+ if (lastDivPos != notFound) {
if (!makeAllDirectories(path.substring(0, lastDivPos)))
return false;
}
@@ -160,13 +173,18 @@ String homeDirectoryPath()
String pathGetFileName(const String& path)
{
- return path.substring(std::max(path.reverseFind('/'), path.reverseFind('\\')) + 1);
+ size_t pos = reverseFindPathSeparator(path);
+ if (pos == notFound)
+ return path;
+ return path.substring(pos + 1);
}
String directoryName(const String& path)
{
- notImplemented();
- return String();
+ size_t pos = reverseFindPathSeparator(path);
+ if (pos == notFound)
+ return String();
+ return path.left(pos);
}
CString openTemporaryFile(const char*, PlatformFileHandle& handle)
diff --git a/WebCore/platform/wx/ContextMenuWx.cpp b/WebCore/platform/wx/ContextMenuWx.cpp
index b20d29e..a1bab37 100644
--- a/WebCore/platform/wx/ContextMenuWx.cpp
+++ b/WebCore/platform/wx/ContextMenuWx.cpp
@@ -42,7 +42,7 @@ ContextMenuItem* ContextMenu::itemWithId(int id)
return new ContextMenuItem(ActionType, s_itemActions.get(id), "");
}
-ContextMenu::ContextMenu(const HitTestResult& result) : m_hitTestResult(result)
+ContextMenu::ContextMenu()
{
m_platformDescription = new wxMenu(0);
}
@@ -57,8 +57,6 @@ void ContextMenu::appendItem(ContextMenuItem& item)
{
if (!m_platformDescription)
return;
-
- checkOrEnableIfNeeded(item);
PlatformMenuItemDescription itemDescription = item.releasePlatformDescription();
wxItemKind menuKindWx = ( itemDescription.type == CheckableActionType ) ? wxITEM_CHECK : wxITEM_NORMAL;
diff --git a/WebCore/platform/wx/LocalizedStringsWx.cpp b/WebCore/platform/wx/LocalizedStringsWx.cpp
index 3c90f6b..4b56394 100644
--- a/WebCore/platform/wx/LocalizedStringsWx.cpp
+++ b/WebCore/platform/wx/LocalizedStringsWx.cpp
@@ -47,7 +47,7 @@ String resetButtonDefaultLabel()
return String("Reset");
}
-String defaultLanguage()
+String platformDefaultLanguage()
{
return String("en");
}