Import Cobalt 21.lts.5.304347
diff --git a/src/CONTRIBUTING.md b/src/CONTRIBUTING.md
index 71f6b83..332d6ab 100644
--- a/src/CONTRIBUTING.md
+++ b/src/CONTRIBUTING.md
@@ -53,7 +53,7 @@
1. Run `git clang-format HEAD~` to apply default C++ formatting rules,
followed by `git commit -a --amend` to squash any formatting changes
into your commit.
- 1. Run `git cl upload` to upload the review to
+ 1. Run `git push origin HEAD:refs/for/master` to upload the review to
[Cobalt's Gerrit instance](https://cobalt-review.googlesource.com/).
1. Someone from the maintainers team will review the code, putting up comments
on any things that need to change for submission.
@@ -62,4 +62,3 @@
1. If you do not need to make any more changes, a maintainer will integrate
the change into our private repository, and it will get pushed out to the
public repository after some time.
-
diff --git a/src/cobalt/build/build.id b/src/cobalt/build/build.id
index 87efaac..bd3b8b4 100644
--- a/src/cobalt/build/build.id
+++ b/src/cobalt/build/build.id
@@ -1 +1 @@
-302899
\ No newline at end of file
+304347
\ No newline at end of file
diff --git a/src/cobalt/build/save_build_id.py b/src/cobalt/build/save_build_id.py
index 014e80d..fc81ab9 100755
--- a/src/cobalt/build/save_build_id.py
+++ b/src/cobalt/build/save_build_id.py
@@ -63,7 +63,12 @@
return 0
if not options.build_id:
- options.build_id = gyp_utils.GetBuildNumber()
+ build_id_server_url = os.environ.get('BUILD_ID_SERVER_URL')
+ if build_id_server_url:
+ options.build_id = gyp_utils.GetBuildNumber(
+ version_server=build_id_server_url)
+ else:
+ options.build_id = gyp_utils.GetBuildNumber()
if not options.build_id:
logging.error('Unable to retrieve build id.')
diff --git a/src/cobalt/media/base/sbplayer_pipeline.cc b/src/cobalt/media/base/sbplayer_pipeline.cc
index 92979dd..a393489 100644
--- a/src/cobalt/media/base/sbplayer_pipeline.cc
+++ b/src/cobalt/media/base/sbplayer_pipeline.cc
@@ -852,11 +852,15 @@
task_runner_, source_url, window_, this, set_bounds_helper_.get(),
allow_resume_after_suspend_, *decode_to_texture_output_mode_,
on_encrypted_media_init_data_encountered_cb_, video_frame_provider_));
- SetPlaybackRateTask(playback_rate_);
- SetVolumeTask(volume_);
+ if (player_->IsValid()) {
+ SetPlaybackRateTask(playback_rate_);
+ SetVolumeTask(volume_);
+ } else {
+ player_.reset();
+ }
}
- if (player_->IsValid()) {
+ if (player_ && player_->IsValid()) {
base::Closure output_mode_change_cb;
{
base::AutoLock auto_lock(lock_);
@@ -867,7 +871,8 @@
return;
}
- player_.reset();
+ DLOG(ERROR) << "SbPlayerPipeline::CreateUrlPlayer failed: "
+ "player_->IsValid() is false.";
CallSeekCB(DECODER_ERROR_NOT_SUPPORTED);
}
@@ -937,33 +942,35 @@
set_bounds_helper_.get(), allow_resume_after_suspend_,
*decode_to_texture_output_mode_, video_frame_provider_,
max_video_capabilities_));
-
- if (!player_->IsValid()) {
+ if (player_->IsValid()) {
+ SetPlaybackRateTask(playback_rate_);
+ SetVolumeTask(volume_);
+ } else {
player_.reset();
- DLOG(ERROR) << "SbPlayerPipeline::CreatePlayer failed: "
- "player_->IsValid() is false.";
- CallSeekCB(DECODER_ERROR_NOT_SUPPORTED);
- return;
}
-
- SetPlaybackRateTask(playback_rate_);
- SetVolumeTask(volume_);
}
- base::Closure output_mode_change_cb;
- {
- base::AutoLock auto_lock(lock_);
- DCHECK(!output_mode_change_cb_.is_null());
- output_mode_change_cb = std::move(output_mode_change_cb_);
- }
- output_mode_change_cb.Run();
+ if (player_ && player_->IsValid()) {
+ base::Closure output_mode_change_cb;
+ {
+ base::AutoLock auto_lock(lock_);
+ DCHECK(!output_mode_change_cb_.is_null());
+ output_mode_change_cb = std::move(output_mode_change_cb_);
+ }
+ output_mode_change_cb.Run();
- if (audio_stream_) {
- UpdateDecoderConfig(audio_stream_);
+ if (audio_stream_) {
+ UpdateDecoderConfig(audio_stream_);
+ }
+ if (video_stream_) {
+ UpdateDecoderConfig(video_stream_);
+ }
+ return;
}
- if (video_stream_) {
- UpdateDecoderConfig(video_stream_);
- }
+
+ DLOG(ERROR) << "SbPlayerPipeline::CreatePlayer failed: "
+ "player_->IsValid() is false.";
+ CallSeekCB(DECODER_ERROR_NOT_SUPPORTED);
}
void SbPlayerPipeline::OnDemuxerInitialized(PipelineStatus status) {
@@ -1353,10 +1360,17 @@
if (player_) {
player_->Resume();
if (!player_->IsValid()) {
- player_.reset();
- DLOG(ERROR) << "SbPlayerPipeline::ResumeTask failed: "
- "player_->IsValid() is false.";
- CallSeekCB(DECODER_ERROR_NOT_SUPPORTED);
+ {
+ base::AutoLock auto_lock(lock_);
+ player_.reset();
+ }
+ // TODO: Determine if CallSeekCB() may be used here, as |seek_cb_| may be
+ // available if the app is suspended before a seek is completed.
+ if (!error_cb_.is_null()) {
+ ResetAndRunIfNotNull(&error_cb_, DECODER_ERROR_NOT_SUPPORTED,
+ "SbPlayerPipeline::ResumeTask failed: "
+ "player_->IsValid() is false.");
+ }
return;
}
}
diff --git a/src/cobalt/media/formats/mp4/box_definitions.cc b/src/cobalt/media/formats/mp4/box_definitions.cc
index 5d30892..2ff0303 100644
--- a/src/cobalt/media/formats/mp4/box_definitions.cc
+++ b/src/cobalt/media/formats/mp4/box_definitions.cc
@@ -1308,7 +1308,8 @@
reader->ReadChild(&decode_time) && reader->MaybeReadChildren(&runs) &&
reader->MaybeReadChild(&auxiliary_offset) &&
reader->MaybeReadChild(&auxiliary_size) &&
- reader->MaybeReadChild(&sdtp));
+ reader->MaybeReadChild(&sdtp) &&
+ reader->MaybeReadChild(&sample_encryption));
// There could be multiple SampleGroupDescription and SampleToGroup boxes with
// different grouping types. For common encryption, the relevant grouping type
diff --git a/src/cobalt/media/player/web_media_player_impl.cc b/src/cobalt/media/player/web_media_player_impl.cc
index d5cfa6f..c8ae297 100644
--- a/src/cobalt/media/player/web_media_player_impl.cc
+++ b/src/cobalt/media/player/web_media_player_impl.cc
@@ -231,7 +231,7 @@
UMA_HISTOGRAM_ENUMERATION("Media.URLScheme", URLScheme(url), kMaxURLScheme);
DLOG(INFO) << "Start URL playback";
- // Handle any volume changes that occured before load().
+ // Handle any volume changes that occurred before load().
SetVolume(GetClient()->Volume());
// TODO: Set networkState to WebMediaPlayer::kNetworkStateIdle on stop.
@@ -251,7 +251,7 @@
DLOG(INFO) << "Start MEDIASOURCE playback";
- // Handle any volume changes that occured before load().
+ // Handle any volume changes that occurred before load().
SetVolume(GetClient()->Volume());
SetNetworkState(WebMediaPlayer::kNetworkStateLoading);
@@ -278,7 +278,7 @@
UMA_HISTOGRAM_ENUMERATION("Media.URLScheme", URLScheme(url), kMaxURLScheme);
DLOG(INFO) << "Start PROGRESSIVE playback";
- // Handle any volume changes that occured before load().
+ // Handle any volume changes that occurred before load().
SetVolume(GetClient()->Volume());
SetNetworkState(WebMediaPlayer::kNetworkStateLoading);
@@ -307,9 +307,6 @@
TRACE_EVENT0("cobalt::media", "WebMediaPlayerImpl::Play");
DCHECK_EQ(main_loop_, base::MessageLoop::current());
-#if defined(__LB_ANDROID__)
- audio_focus_bridge_.RequestAudioFocus();
-#endif // defined(__LB_ANDROID__)
state_.paused = false;
pipeline_->SetPlaybackRate(state_.playback_rate);
@@ -319,9 +316,6 @@
void WebMediaPlayerImpl::Pause() {
DCHECK_EQ(main_loop_, base::MessageLoop::current());
-#if defined(__LB_ANDROID__)
- audio_focus_bridge_.AbandonAudioFocus();
-#endif // defined(__LB_ANDROID__)
state_.paused = true;
pipeline_->SetPlaybackRate(0.0f);
diff --git a/src/cobalt/media/player/web_media_player_impl.h b/src/cobalt/media/player/web_media_player_impl.h
index a1a51be..9aa48c1 100644
--- a/src/cobalt/media/player/web_media_player_impl.h
+++ b/src/cobalt/media/player/web_media_player_impl.h
@@ -313,10 +313,6 @@
std::unique_ptr<Demuxer> progressive_demuxer_;
std::unique_ptr<ChunkDemuxer> chunk_demuxer_;
-#if defined(__LB_ANDROID__)
- AudioFocusBridge audio_focus_bridge_;
-#endif // defined(__LB_ANDROID__)
-
// Suppresses calls to OnPipelineError() after destruction / shutdown has been
// started; prevents us from spuriously logging errors that are transient or
// unimportant.
diff --git a/src/cobalt/renderer/egl_and_gles.h b/src/cobalt/renderer/egl_and_gles.h
index 3dac4b2..6666f1b 100644
--- a/src/cobalt/renderer/egl_and_gles.h
+++ b/src/cobalt/renderer/egl_and_gles.h
@@ -50,6 +50,7 @@
#define GL_DCHECK_MAYBE_LOG(x)
#endif // defined(COBALT_EGL_AND_GLES_LOGGING)
+#if SB_DCHECK_ENABLED
#define EGL_DCHECK(x) \
do { \
EGL_DCHECK_MAYBE_LOG(x); \
@@ -64,6 +65,10 @@
SB_DCHECK(COBALT_GL_ERRNO == GL_NO_ERROR) \
<< #x << " exited with code: " << COBALT_GL_ERRNO; \
} while (false)
+#else
+#define EGL_DCHECK(x)
+#define GL_DCHECK(x)
+#endif // SB_DCHECK_ENABLED
#if SB_API_VERSION >= 11
namespace cobalt {
diff --git a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_circle_color_scale_threshold_2.glsl b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_circle_color_scale_threshold_2.glsl
index 1380682..1be401c 100644
--- a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_circle_color_scale_threshold_2.glsl
+++ b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_circle_color_scale_threshold_2.glsl
@@ -14,7 +14,7 @@
varying highp vec2 vTransformedCoords_0_Stage0;
mediump vec4 stage_Stage1_c0_c0_c0_c0(mediump vec4 _input) {
mediump vec4 _sample1099_c0_c0;
- mediump float t = vTransformedCoords_0_Stage0.x + 9.9999997473787516e-06;
+ mediump float t = vTransformedCoords_0_Stage0.x + 9.999999747378752e-06;
_sample1099_c0_c0 = vec4(t, 1.0, 0.0, 0.0);
return _sample1099_c0_c0;
}
diff --git a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_circle_color_scale_thresholds.glsl b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_circle_color_scale_thresholds.glsl
index 63ff1ed..11db997 100644
--- a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_circle_color_scale_thresholds.glsl
+++ b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_circle_color_scale_thresholds.glsl
@@ -19,7 +19,7 @@
varying highp vec2 vTransformedCoords_0_Stage0;
mediump vec4 stage_Stage1_c0_c0_c0_c0(mediump vec4 _input) {
mediump vec4 _sample1099_c0_c0;
- mediump float t = vTransformedCoords_0_Stage0.x + 9.9999997473787516e-06;
+ mediump float t = vTransformedCoords_0_Stage0.x + 9.999999747378752e-06;
_sample1099_c0_c0 = vec4(t, 1.0, 0.0, 0.0);
return _sample1099_c0_c0;
}
diff --git a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_coverage_scale_threshold_2.glsl b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_coverage_scale_threshold_2.glsl
index 9c5c1f3..e7447a2 100644
--- a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_coverage_scale_threshold_2.glsl
+++ b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_coverage_scale_threshold_2.glsl
@@ -14,7 +14,7 @@
varying mediump float vinCoverage_Stage0;
mediump vec4 stage_Stage1_c0_c0_c0_c0(mediump vec4 _input) {
mediump vec4 _sample1099_c0_c0;
- mediump float t = vTransformedCoords_0_Stage0.x + 9.9999997473787516e-06;
+ mediump float t = vTransformedCoords_0_Stage0.x + 9.999999747378752e-06;
_sample1099_c0_c0 = vec4(t, 1.0, 0.0, 0.0);
return _sample1099_c0_c0;
}
diff --git a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_coverage_scale_thresholds.glsl b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_coverage_scale_thresholds.glsl
index cbcba0c..7bf9ef3 100644
--- a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_coverage_scale_thresholds.glsl
+++ b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_coverage_scale_thresholds.glsl
@@ -19,7 +19,7 @@
varying highp float vcoverage_Stage0;
mediump vec4 stage_Stage1_c0_c0_c0_c0(mediump vec4 _input) {
mediump vec4 _sample1099_c0_c0;
- mediump float t = vTransformedCoords_0_Stage0.x + 9.9999997473787516e-06;
+ mediump float t = vTransformedCoords_0_Stage0.x + 9.999999747378752e-06;
_sample1099_c0_c0 = vec4(t, 1.0, 0.0, 0.0);
return _sample1099_c0_c0;
}
diff --git a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_coverage_scale_thresholds_2.glsl b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_coverage_scale_thresholds_2.glsl
index 083f5e4..e6a6613 100644
--- a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_coverage_scale_thresholds_2.glsl
+++ b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_coverage_scale_thresholds_2.glsl
@@ -14,7 +14,7 @@
varying highp float vcoverage_Stage0;
mediump vec4 stage_Stage1_c0_c0_c0_c0(mediump vec4 _input) {
mediump vec4 _sample1099_c0_c0;
- mediump float t = vTransformedCoords_0_Stage0.x + 9.9999997473787516e-06;
+ mediump float t = vTransformedCoords_0_Stage0.x + 9.999999747378752e-06;
_sample1099_c0_c0 = vec4(t, 1.0, 0.0, 0.0);
return _sample1099_c0_c0;
}
diff --git a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_coverage_scale_thresholds_3.glsl b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_coverage_scale_thresholds_3.glsl
index e737a75..a5049c7 100644
--- a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_coverage_scale_thresholds_3.glsl
+++ b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_coverage_scale_thresholds_3.glsl
@@ -21,7 +21,7 @@
varying mediump float vinCoverage_Stage0;
mediump vec4 stage_Stage1_c0_c0_c0_c0(mediump vec4 _input) {
mediump vec4 _sample1099_c0_c0;
- mediump float t = vTransformedCoords_0_Stage0.x + 9.9999997473787516e-06;
+ mediump float t = vTransformedCoords_0_Stage0.x + 9.999999747378752e-06;
_sample1099_c0_c0 = vec4(t, 1.0, 0.0, 0.0);
return _sample1099_c0_c0;
}
diff --git a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_decal_scaletranslate_texdom_texturew_threshold.glsl b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_decal_scaletranslate_texdom_texturew_threshold.glsl
index d3a03a4..e338bcf 100644
--- a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_decal_scaletranslate_texdom_texturew_threshold.glsl
+++ b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_decal_scaletranslate_texdom_texturew_threshold.glsl
@@ -18,7 +18,7 @@
varying highp vec2 vTransformedCoords_0_Stage0;
mediump vec4 stage_Stage1_c0_c0_c0_c0(mediump vec4 _input) {
mediump vec4 _sample1099_c0_c0;
- mediump float t = vTransformedCoords_0_Stage0.x + 9.9999997473787516e-06;
+ mediump float t = vTransformedCoords_0_Stage0.x + 9.999999747378752e-06;
_sample1099_c0_c0 = vec4(t, 1.0, 0.0, 0.0);
return _sample1099_c0_c0;
}
diff --git a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_quad_scale_threshold.glsl b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_quad_scale_threshold.glsl
index 5f2b1d3..667a564 100644
--- a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_quad_scale_threshold.glsl
+++ b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_quad_scale_threshold.glsl
@@ -15,7 +15,7 @@
varying highp vec2 vTransformedCoords_0_Stage0;
mediump vec4 stage_Stage1_c0_c0_c0_c0(mediump vec4 _input) {
mediump vec4 _sample1099_c0_c0;
- mediump float t = vTransformedCoords_0_Stage0.x + 9.9999997473787516e-06;
+ mediump float t = vTransformedCoords_0_Stage0.x + 9.999999747378752e-06;
_sample1099_c0_c0 = vec4(t, 1.0, 0.0, 0.0);
return _sample1099_c0_c0;
}
diff --git a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_quad_scale_threshold_2.glsl b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_quad_scale_threshold_2.glsl
index 084c066..35a3010 100644
--- a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_quad_scale_threshold_2.glsl
+++ b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_quad_scale_threshold_2.glsl
@@ -15,7 +15,7 @@
varying highp vec2 vTransformedCoords_0_Stage0;
mediump vec4 stage_Stage1_c0_c0_c0_c0(mediump vec4 _input) {
mediump vec4 _sample1099_c0_c0;
- mediump float t = vTransformedCoords_0_Stage0.x + 9.9999997473787516e-06;
+ mediump float t = vTransformedCoords_0_Stage0.x + 9.999999747378752e-06;
_sample1099_c0_c0 = vec4(t, 1.0, 0.0, 0.0);
return _sample1099_c0_c0;
}
diff --git a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_quad_scale_threshold_3.glsl b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_quad_scale_threshold_3.glsl
index cb27f80..1f47fae 100644
--- a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_quad_scale_threshold_3.glsl
+++ b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_quad_scale_threshold_3.glsl
@@ -15,7 +15,7 @@
varying highp vec2 vTransformedCoords_0_Stage0;
mediump vec4 stage_Stage1_c0_c0_c0_c0(mediump vec4 _input) {
mediump vec4 _sample1099_c0_c0;
- mediump float t = vTransformedCoords_0_Stage0.x + 9.9999997473787516e-06;
+ mediump float t = vTransformedCoords_0_Stage0.x + 9.999999747378752e-06;
_sample1099_c0_c0 = vec4(t, 1.0, 0.0, 0.0);
return _sample1099_c0_c0;
}
diff --git a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_quad_scale_thresholds.glsl b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_quad_scale_thresholds.glsl
index 1ba24f6..b7223a3 100644
--- a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_quad_scale_thresholds.glsl
+++ b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_quad_scale_thresholds.glsl
@@ -18,7 +18,7 @@
varying highp vec2 vTransformedCoords_0_Stage0;
mediump vec4 stage_Stage1_c0_c0_c0_c0(mediump vec4 _input) {
mediump vec4 _sample1099_c0_c0;
- mediump float t = vTransformedCoords_0_Stage0.x + 9.9999997473787516e-06;
+ mediump float t = vTransformedCoords_0_Stage0.x + 9.999999747378752e-06;
_sample1099_c0_c0 = vec4(t, 1.0, 0.0, 0.0);
return _sample1099_c0_c0;
}
diff --git a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_quad_scale_thresholds_2.glsl b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_quad_scale_thresholds_2.glsl
index da56a36..ba5cadd 100644
--- a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_quad_scale_thresholds_2.glsl
+++ b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_quad_scale_thresholds_2.glsl
@@ -20,7 +20,7 @@
varying highp vec2 vTransformedCoords_0_Stage0;
mediump vec4 stage_Stage1_c0_c0_c0_c0(mediump vec4 _input) {
mediump vec4 _sample1099_c0_c0;
- mediump float t = vTransformedCoords_0_Stage0.x + 9.9999997473787516e-06;
+ mediump float t = vTransformedCoords_0_Stage0.x + 9.999999747378752e-06;
_sample1099_c0_c0 = vec4(t, 1.0, 0.0, 0.0);
return _sample1099_c0_c0;
}
diff --git a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_scale_texindex_texturew_threshold.glsl b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_scale_texindex_texturew_threshold.glsl
index e2ec055..8bcc27a 100644
--- a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_scale_texindex_texturew_threshold.glsl
+++ b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_scale_texindex_texturew_threshold.glsl
@@ -16,7 +16,7 @@
varying highp vec2 vTransformedCoords_0_Stage0;
mediump vec4 stage_Stage1_c0_c0_c0_c0(mediump vec4 _input) {
mediump vec4 _sample1099_c0_c0;
- mediump float t = vTransformedCoords_0_Stage0.x + 9.9999997473787516e-06;
+ mediump float t = vTransformedCoords_0_Stage0.x + 9.999999747378752e-06;
_sample1099_c0_c0 = vec4(t, 1.0, 0.0, 0.0);
return _sample1099_c0_c0;
}
diff --git a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_scale_texindex_texturew_threshold_2.glsl b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_scale_texindex_texturew_threshold_2.glsl
index fe3a8ae..2ac7fcc 100644
--- a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_scale_texindex_texturew_threshold_2.glsl
+++ b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_scale_texindex_texturew_threshold_2.glsl
@@ -16,7 +16,7 @@
varying highp vec2 vTransformedCoords_0_Stage0;
mediump vec4 stage_Stage1_c0_c0_c0_c0(mediump vec4 _input) {
mediump vec4 _sample1099_c0_c0;
- mediump float t = vTransformedCoords_0_Stage0.x + 9.9999997473787516e-06;
+ mediump float t = vTransformedCoords_0_Stage0.x + 9.999999747378752e-06;
_sample1099_c0_c0 = vec4(t, 1.0, 0.0, 0.0);
return _sample1099_c0_c0;
}
diff --git a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_scale_texindex_texturew_threshold_3.glsl b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_scale_texindex_texturew_threshold_3.glsl
index f1bbe9d..1cb8137 100644
--- a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_scale_texindex_texturew_threshold_3.glsl
+++ b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_scale_texindex_texturew_threshold_3.glsl
@@ -16,7 +16,7 @@
varying highp vec2 vTransformedCoords_0_Stage0;
mediump vec4 stage_Stage1_c0_c0_c0_c0(mediump vec4 _input) {
mediump vec4 _sample1099_c0_c0;
- mediump float t = vTransformedCoords_0_Stage0.x + 9.9999997473787516e-06;
+ mediump float t = vTransformedCoords_0_Stage0.x + 9.999999747378752e-06;
_sample1099_c0_c0 = vec4(t, 1.0, 0.0, 0.0);
return _sample1099_c0_c0;
}
diff --git a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_scale_texindex_texturew_thresholds.glsl b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_scale_texindex_texturew_thresholds.glsl
index b073544..ba8e732 100644
--- a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_scale_texindex_texturew_thresholds.glsl
+++ b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_scale_texindex_texturew_thresholds.glsl
@@ -19,7 +19,7 @@
varying highp vec2 vTransformedCoords_0_Stage0;
mediump vec4 stage_Stage1_c0_c0_c0_c0(mediump vec4 _input) {
mediump vec4 _sample1099_c0_c0;
- mediump float t = vTransformedCoords_0_Stage0.x + 9.9999997473787516e-06;
+ mediump float t = vTransformedCoords_0_Stage0.x + 9.999999747378752e-06;
_sample1099_c0_c0 = vec4(t, 1.0, 0.0, 0.0);
return _sample1099_c0_c0;
}
diff --git a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_scale_threshold.glsl b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_scale_threshold.glsl
index 3657419..2cec90c 100644
--- a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_scale_threshold.glsl
+++ b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_scale_threshold.glsl
@@ -13,7 +13,7 @@
varying mediump vec4 vcolor_Stage0;
mediump vec4 stage_Stage1_c0_c0_c0_c0(mediump vec4 _input) {
mediump vec4 _sample1099_c0_c0;
- mediump float t = vTransformedCoords_0_Stage0.x + 9.9999997473787516e-06;
+ mediump float t = vTransformedCoords_0_Stage0.x + 9.999999747378752e-06;
_sample1099_c0_c0 = vec4(t, 1.0, 0.0, 0.0);
return _sample1099_c0_c0;
}
diff --git a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_scale_thresholds.glsl b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_scale_thresholds.glsl
index 6e1c100..7685597 100644
--- a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_scale_thresholds.glsl
+++ b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_scale_thresholds.glsl
@@ -18,7 +18,7 @@
varying highp vec2 vTransformedCoords_0_Stage0;
mediump vec4 stage_Stage1_c0_c0_c0_c0(mediump vec4 _input) {
mediump vec4 _sample1099_c0_c0;
- mediump float t = vTransformedCoords_0_Stage0.x + 9.9999997473787516e-06;
+ mediump float t = vTransformedCoords_0_Stage0.x + 9.999999747378752e-06;
_sample1099_c0_c0 = vec4(t, 1.0, 0.0, 0.0);
return _sample1099_c0_c0;
}
diff --git a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_scale_thresholds_2.glsl b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_scale_thresholds_2.glsl
index e055c58..a1f1060 100644
--- a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_scale_thresholds_2.glsl
+++ b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_bias_border_color_scale_thresholds_2.glsl
@@ -18,7 +18,7 @@
varying mediump vec4 vcolor_Stage0;
mediump vec4 stage_Stage1_c0_c0_c0_c0(mediump vec4 _input) {
mediump vec4 _sample1099_c0_c0;
- mediump float t = vTransformedCoords_0_Stage0.x + 9.9999997473787516e-06;
+ mediump float t = vTransformedCoords_0_Stage0.x + 9.999999747378752e-06;
_sample1099_c0_c0 = vec4(t, 1.0, 0.0, 0.0);
return _sample1099_c0_c0;
}
diff --git a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_border_color_coverage_texture.glsl b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_border_color_coverage_texture.glsl
index 224674d..07a5ac3 100644
--- a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_border_color_coverage_texture.glsl
+++ b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_border_color_coverage_texture.glsl
@@ -10,7 +10,7 @@
varying highp float vcoverage_Stage0;
mediump vec4 stage_Stage1_c0_c0_c0_c0(mediump vec4 _input) {
mediump vec4 _sample1099_c0_c0;
- mediump float t = vTransformedCoords_0_Stage0.x + 9.9999997473787516e-06;
+ mediump float t = vTransformedCoords_0_Stage0.x + 9.999999747378752e-06;
_sample1099_c0_c0 = vec4(t, 1.0, 0.0, 0.0);
return _sample1099_c0_c0;
}
diff --git a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_border_color_quad_texture.glsl b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_border_color_quad_texture.glsl
index 1ea6bd8..3c26f70 100644
--- a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_border_color_quad_texture.glsl
+++ b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_border_color_quad_texture.glsl
@@ -11,7 +11,7 @@
varying highp vec2 vTransformedCoords_0_Stage0;
mediump vec4 stage_Stage1_c0_c0_c0_c0(mediump vec4 _input) {
mediump vec4 _sample1099_c0_c0;
- mediump float t = vTransformedCoords_0_Stage0.x + 9.9999997473787516e-06;
+ mediump float t = vTransformedCoords_0_Stage0.x + 9.999999747378752e-06;
_sample1099_c0_c0 = vec4(t, 1.0, 0.0, 0.0);
return _sample1099_c0_c0;
}
diff --git a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_border_color_quad_texture_2.glsl b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_border_color_quad_texture_2.glsl
index d8c1e31..298ccc0 100644
--- a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_border_color_quad_texture_2.glsl
+++ b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_border_color_quad_texture_2.glsl
@@ -11,7 +11,7 @@
varying highp vec2 vTransformedCoords_0_Stage0;
mediump vec4 stage_Stage1_c0_c0_c0_c0(mediump vec4 _input) {
mediump vec4 _sample1099_c0_c0;
- mediump float t = vTransformedCoords_0_Stage0.x + 9.9999997473787516e-06;
+ mediump float t = vTransformedCoords_0_Stage0.x + 9.999999747378752e-06;
_sample1099_c0_c0 = vec4(t, 1.0, 0.0, 0.0);
return _sample1099_c0_c0;
}
diff --git a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_border_color_texindex_texturew.glsl b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_border_color_texindex_texturew.glsl
index 4e004af..92cba89 100644
--- a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_border_color_texindex_texturew.glsl
+++ b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_border_color_texindex_texturew.glsl
@@ -12,7 +12,7 @@
varying highp vec2 vTransformedCoords_0_Stage0;
mediump vec4 stage_Stage1_c0_c0_c0_c0(mediump vec4 _input) {
mediump vec4 _sample1099_c0_c0;
- mediump float t = vTransformedCoords_0_Stage0.x + 9.9999997473787516e-06;
+ mediump float t = vTransformedCoords_0_Stage0.x + 9.999999747378752e-06;
_sample1099_c0_c0 = vec4(t, 1.0, 0.0, 0.0);
return _sample1099_c0_c0;
}
diff --git a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_color_edges_texindex_texturew_2.glsl b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_color_edges_texindex_texturew_2.glsl
index e7cd090..fda3d24 100644
--- a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_color_edges_texindex_texturew_2.glsl
+++ b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_color_edges_texindex_texturew_2.glsl
@@ -21,9 +21,9 @@
{
texColor = texture2D(uTextureSampler_0_Stage0, uv).wwww;
}
- mediump float distance = 7.96875 * (texColor.x - 0.50196081399917603);
+ mediump float distance = 7.96875 * (texColor.x - 0.501960813999176);
mediump float afwidth;
- afwidth = abs(0.64999997615814209 * -dFdy(vIntTextureCoords_Stage0.y));
+ afwidth = abs(0.6499999761581421 * -dFdy(vIntTextureCoords_Stage0.y));
mediump float val = smoothstep(-afwidth, afwidth, distance);
outputCoverage_Stage0 = vec4(val);
}
diff --git a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_color_ellipse.glsl b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_color_ellipse.glsl
index ee26f8b..8b55db4 100644
--- a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_color_ellipse.glsl
+++ b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_color_ellipse.glsl
@@ -14,7 +14,7 @@
highp float test = dot(offset, offset) - 1.0;
highp vec2 grad = (2.0 * offset) * (vEllipseOffsets_Stage0.z * vEllipseRadii_Stage0.xy);
highp float grad_dot = dot(grad, grad);
- grad_dot = max(grad_dot, 6.1036000261083245e-05);
+ grad_dot = max(grad_dot, 6.103600026108325e-05);
highp float invlen = vEllipseOffsets_Stage0.z * inversesqrt(grad_dot);
highp float edgeAlpha = clamp(0.5 - test * invlen, 0.0, 1.0);
outputCoverage_Stage0 = vec4(edgeAlpha);
diff --git a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_color_ellipse_2.glsl b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_color_ellipse_2.glsl
index 0cb3d54..dd2801e 100644
--- a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_color_ellipse_2.glsl
+++ b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_color_ellipse_2.glsl
@@ -18,7 +18,7 @@
highp vec2 grad = vec2(vEllipseOffsets0_Stage0.x * duvdx.x + vEllipseOffsets0_Stage0.y * duvdx.y, vEllipseOffsets0_Stage0.x * duvdy.x + vEllipseOffsets0_Stage0.y * duvdy.y);
grad *= vEllipseOffsets0_Stage0.z;
highp float grad_dot = 4.0 * dot(grad, grad);
- grad_dot = max(grad_dot, 6.1036000261083245e-05);
+ grad_dot = max(grad_dot, 6.103600026108325e-05);
highp float invlen = inversesqrt(grad_dot);
invlen *= vEllipseOffsets0_Stage0.z;
highp float edgeAlpha = clamp(0.5 - test * invlen, 0.0, 1.0);
@@ -29,7 +29,7 @@
grad = vec2(vEllipseOffsets1_Stage0.x * duvdx.x + vEllipseOffsets1_Stage0.y * duvdx.y, vEllipseOffsets1_Stage0.x * duvdy.x + vEllipseOffsets1_Stage0.y * duvdy.y);
grad *= vEllipseOffsets0_Stage0.z;
grad_dot = 4.0 * dot(grad, grad);
- grad_dot = max(grad_dot, 6.1036000261083245e-05);
+ grad_dot = max(grad_dot, 6.103600026108325e-05);
invlen = inversesqrt(grad_dot);
invlen *= vEllipseOffsets0_Stage0.z;
edgeAlpha *= clamp(0.5 + test * invlen, 0.0, 1.0);
diff --git a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_color_ellipse_3.glsl b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_color_ellipse_3.glsl
index 6148054..ff7654e 100644
--- a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_color_ellipse_3.glsl
+++ b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_color_ellipse_3.glsl
@@ -18,7 +18,7 @@
highp vec2 grad = vec2(vEllipseOffsets0_Stage0.x * duvdx.x + vEllipseOffsets0_Stage0.y * duvdx.y, vEllipseOffsets0_Stage0.x * duvdy.x + vEllipseOffsets0_Stage0.y * duvdy.y);
grad *= vEllipseOffsets0_Stage0.z;
highp float grad_dot = 4.0 * dot(grad, grad);
- grad_dot = max(grad_dot, 6.1036000261083245e-05);
+ grad_dot = max(grad_dot, 6.103600026108325e-05);
highp float invlen = inversesqrt(grad_dot);
invlen *= vEllipseOffsets0_Stage0.z;
highp float edgeAlpha = clamp(0.5 - test * invlen, 0.0, 1.0);
diff --git a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_color_ellipse_scale_texture.glsl b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_color_ellipse_scale_texture.glsl
index 0b4a811..4676e51 100644
--- a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_color_ellipse_scale_texture.glsl
+++ b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_color_ellipse_scale_texture.glsl
@@ -27,7 +27,7 @@
highp float implicit = dot(Z, d) - 1.0;
highp float grad_dot = 4.0 * dot(Z, Z);
{
- grad_dot = max(grad_dot, 6.1036000261083245e-05);
+ grad_dot = max(grad_dot, 6.103600026108325e-05);
}
highp float approx_dist = implicit * inversesqrt(grad_dot);
{
diff --git a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_color_texindex_texturew.glsl b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_color_texindex_texturew.glsl
index 53a0a74..32a6af2 100644
--- a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_color_texindex_texturew.glsl
+++ b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_color_texindex_texturew.glsl
@@ -18,9 +18,9 @@
{
texColor = texture2D(uTextureSampler_0_Stage0, uv).wwww;
}
- mediump float distance = 7.96875 * (texColor.x - 0.50196081399917603);
+ mediump float distance = 7.96875 * (texColor.x - 0.501960813999176);
mediump float afwidth;
- afwidth = abs(0.64999997615814209 * -dFdy(vIntTextureCoords_Stage0.y));
+ afwidth = abs(0.6499999761581421 * -dFdy(vIntTextureCoords_Stage0.y));
mediump float val = smoothstep(-afwidth, afwidth, distance);
outputCoverage_Stage0 = vec4(val);
}
diff --git a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_color_texindex_texturew_2.glsl b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_color_texindex_texturew_2.glsl
index 1b61907..7c4db08 100644
--- a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_color_texindex_texturew_2.glsl
+++ b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_color_texindex_texturew_2.glsl
@@ -18,9 +18,9 @@
{
texColor = texture2D(uTextureSampler_0_Stage0, uv).wwww;
}
- mediump float distance = 7.96875 * (texColor.x - 0.50196081399917603);
+ mediump float distance = 7.96875 * (texColor.x - 0.501960813999176);
mediump float afwidth;
- afwidth = abs(0.64999997615814209 * -dFdy(vIntTextureCoords_Stage0.y));
+ afwidth = abs(0.6499999761581421 * -dFdy(vIntTextureCoords_Stage0.y));
mediump float val = smoothstep(-afwidth, afwidth, distance);
outputCoverage_Stage0 = vec4(val);
}
diff --git a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_color_texindex_texturew_3.glsl b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_color_texindex_texturew_3.glsl
index f4db076..421494c 100644
--- a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_color_texindex_texturew_3.glsl
+++ b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_color_texindex_texturew_3.glsl
@@ -18,19 +18,19 @@
{
texColor = texture2D(uTextureSampler_0_Stage0, uv).wwww;
}
- mediump float distance = 7.96875 * (texColor.x - 0.50196081399917603);
+ mediump float distance = 7.96875 * (texColor.x - 0.501960813999176);
mediump float afwidth;
mediump vec2 dist_grad = vec2(dFdx(distance), -dFdy(distance));
mediump float dg_len2 = dot(dist_grad, dist_grad);
- if (dg_len2 < 9.9999997473787516e-05) {
- dist_grad = vec2(0.70709997415542603, 0.70709997415542603);
+ if (dg_len2 < 9.999999747378752e-05) {
+ dist_grad = vec2(0.707099974155426, 0.707099974155426);
} else {
dist_grad = dist_grad * inversesqrt(dg_len2);
}
mediump vec2 Jdx = dFdx(vIntTextureCoords_Stage0);
mediump vec2 Jdy = -dFdy(vIntTextureCoords_Stage0);
mediump vec2 grad = vec2(dist_grad.x * Jdx.x + dist_grad.y * Jdy.x, dist_grad.x * Jdx.y + dist_grad.y * Jdy.y);
- afwidth = 0.64999997615814209 * length(grad);
+ afwidth = 0.6499999761581421 * length(grad);
mediump float val = smoothstep(-afwidth, afwidth, distance);
outputCoverage_Stage0 = vec4(val);
}
diff --git a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_color_texindex_texturew_4.glsl b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_color_texindex_texturew_4.glsl
index 20eef11..663553b 100644
--- a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_color_texindex_texturew_4.glsl
+++ b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_color_texindex_texturew_4.glsl
@@ -18,10 +18,10 @@
{
texColor = texture2D(uTextureSampler_0_Stage0, uv).wwww;
}
- mediump float distance = 7.96875 * (texColor.x - 0.50196081399917603);
+ mediump float distance = 7.96875 * (texColor.x - 0.501960813999176);
mediump float afwidth;
mediump float st_grad_len = length(-dFdy(vIntTextureCoords_Stage0));
- afwidth = abs(0.64999997615814209 * st_grad_len);
+ afwidth = abs(0.6499999761581421 * st_grad_len);
mediump float val = smoothstep(-afwidth, afwidth, distance);
outputCoverage_Stage0 = vec4(val);
}
diff --git a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_color_texindex_texturew_5.glsl b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_color_texindex_texturew_5.glsl
index ac92c03..80cd4a3 100644
--- a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_color_texindex_texturew_5.glsl
+++ b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_color_texindex_texturew_5.glsl
@@ -18,10 +18,10 @@
{
texColor = texture2D(uTextureSampler_0_Stage0, uv).wwww;
}
- mediump float distance = 7.96875 * (texColor.x - 0.50196081399917603);
+ mediump float distance = 7.96875 * (texColor.x - 0.501960813999176);
mediump float afwidth;
mediump float st_grad_len = length(-dFdy(vIntTextureCoords_Stage0));
- afwidth = abs(0.64999997615814209 * st_grad_len);
+ afwidth = abs(0.6499999761581421 * st_grad_len);
mediump float val = smoothstep(-afwidth, afwidth, distance);
outputCoverage_Stage0 = vec4(val);
}
diff --git a/src/cobalt/renderer/rasterizer/egl/textured_mesh_renderer.cc b/src/cobalt/renderer/rasterizer/egl/textured_mesh_renderer.cc
index ac3cb80..3c20715 100644
--- a/src/cobalt/renderer/rasterizer/egl/textured_mesh_renderer.cc
+++ b/src/cobalt/renderer/rasterizer/egl/textured_mesh_renderer.cc
@@ -20,6 +20,7 @@
#include <string>
#include <vector>
+#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "cobalt/extension/graphics.h"
#include "cobalt/math/size.h"
@@ -364,28 +365,31 @@
graphics_extension->GetMapToMeshColorAdjustments(&color_adjustment)) {
// Setup vectors for the color adjustments. Ensure they use dot for decimal
// point regardless of locale.
- std::stringstream buffer;
- buffer.imbue(std::locale::classic());
- buffer << " vec4 scale0 = vec4(" << color_adjustment.rgba0_scale[0] << ","
- << color_adjustment.rgba0_scale[1] << ","
- << color_adjustment.rgba0_scale[2] << ","
- << color_adjustment.rgba0_scale[3] << ");";
- buffer << " vec4 scale1 = vec4(" << color_adjustment.rgba1_scale[0] << ","
- << color_adjustment.rgba1_scale[1] << ","
- << color_adjustment.rgba1_scale[2] << ","
- << color_adjustment.rgba1_scale[3] << ");";
- buffer << " vec4 scale2 = vec4(" << color_adjustment.rgba2_scale[0] << ","
- << color_adjustment.rgba2_scale[1] << ","
- << color_adjustment.rgba2_scale[2] << ","
- << color_adjustment.rgba2_scale[3] << ");";
- buffer << " vec4 scale3 = vec4(" << color_adjustment.rgba3_scale[0] << ","
- << color_adjustment.rgba3_scale[1] << ","
- << color_adjustment.rgba3_scale[2] << ","
- << color_adjustment.rgba3_scale[3] << ");";
+ std::string buffer;
+ buffer = " vec4 scale0 = vec4(" +
+ base::NumberToString(color_adjustment.rgba0_scale[0]) + "," +
+ base::NumberToString(color_adjustment.rgba0_scale[1]) + "," +
+ base::NumberToString(color_adjustment.rgba0_scale[2]) + "," +
+ base::NumberToString(color_adjustment.rgba0_scale[3]) + ");" +
+ " vec4 scale1 = vec4(" +
+ base::NumberToString(color_adjustment.rgba1_scale[0]) + "," +
+ base::NumberToString(color_adjustment.rgba1_scale[1]) + "," +
+ base::NumberToString(color_adjustment.rgba1_scale[2]) + "," +
+ base::NumberToString(color_adjustment.rgba1_scale[3]) + ");" +
+ " vec4 scale2 = vec4(" +
+ base::NumberToString(color_adjustment.rgba2_scale[0]) + "," +
+ base::NumberToString(color_adjustment.rgba2_scale[1]) + "," +
+ base::NumberToString(color_adjustment.rgba2_scale[2]) + "," +
+ base::NumberToString(color_adjustment.rgba2_scale[3]) + ");" +
+ " vec4 scale3 = vec4(" +
+ base::NumberToString(color_adjustment.rgba3_scale[0]) + "," +
+ base::NumberToString(color_adjustment.rgba3_scale[1]) + "," +
+ base::NumberToString(color_adjustment.rgba3_scale[2]) + "," +
+ base::NumberToString(color_adjustment.rgba3_scale[3]) + ");";
blit_fragment_shader_source +=
" vec4 color2 = color * color;"
" vec4 color3 = color2 * color;" +
- buffer.str() +
+ buffer +
" color = scale0 + scale1*color + scale2*color2 + scale3*color3;"
" gl_FragColor = clamp(color, vec4(0.0), vec4(1.0));"
"}";
diff --git a/src/cobalt/renderer/rasterizer/skia/skia/skia.gyp b/src/cobalt/renderer/rasterizer/skia/skia/skia.gyp
index dfefca6..5fe1b23 100644
--- a/src/cobalt/renderer/rasterizer/skia/skia/skia.gyp
+++ b/src/cobalt/renderer/rasterizer/skia/skia/skia.gyp
@@ -28,6 +28,7 @@
'target_name': 'skia_library',
'type': 'static_library',
'dependencies': [
+ '<(DEPTH)/base/base.gyp:base',
'skia_library_no_asan',
],
'includes': [
@@ -65,7 +66,6 @@
'target_name': 'filter_fuzz_stub',
'type': 'executable',
'dependencies': [
- '<(DEPTH)/base/base.gyp:base',
'skia',
],
'sources': [
diff --git a/src/cobalt/site/docs/contributors/index.md b/src/cobalt/site/docs/contributors/index.md
index ea93cc6..77811fa 100644
--- a/src/cobalt/site/docs/contributors/index.md
+++ b/src/cobalt/site/docs/contributors/index.md
@@ -52,7 +52,7 @@
* Ensure you or your company have signed the appropriate CLA as discussed
in the [Before You Contribute](#before-you-contribute) section above.
* Rebase your changes down into a single git commit.
-* Run `git cl upload` to upload the review to
+* Run `git push origin HEAD:refs/for/master` to upload the review to
[Cobalt's Gerrit instance](https://cobalt-review.googlesource.com/).
* Someone from the maintainers team reviews the code, adding comments on
any things that need to change before the code can be submitted.
diff --git a/src/cobalt/updater/network_fetcher.cc b/src/cobalt/updater/network_fetcher.cc
index fb7ea98..1dfbc7c 100644
--- a/src/cobalt/updater/network_fetcher.cc
+++ b/src/cobalt/updater/network_fetcher.cc
@@ -129,6 +129,13 @@
url_fetcher_->Start();
}
+void NetworkFetcher::CancelDownloadToFile() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+ SB_LOG(INFO) << "Canceling DownloadToFile";
+ url_fetcher_.reset();
+}
+
void NetworkFetcher::OnURLFetchResponseStarted(const net::URLFetcher* source) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
std::move(response_started_callback_)
diff --git a/src/cobalt/updater/network_fetcher.h b/src/cobalt/updater/network_fetcher.h
index 1ff2675..17b8909 100644
--- a/src/cobalt/updater/network_fetcher.h
+++ b/src/cobalt/updater/network_fetcher.h
@@ -69,6 +69,7 @@
ProgressCallback progress_callback,
DownloadToFileCompleteCallback
download_to_file_complete_callback) override;
+ void CancelDownloadToFile() override;
// net::URLFetcherDelegate interface.
void OnURLFetchResponseStarted(const net::URLFetcher* source) override;
diff --git a/src/cobalt/updater/updater_module.cc b/src/cobalt/updater/updater_module.cc
index 8f5663f..3941cb6 100644
--- a/src/cobalt/updater/updater_module.cc
+++ b/src/cobalt/updater/updater_module.cc
@@ -174,6 +174,7 @@
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
update_client_->RemoveObserver(updater_observer_.get());
updater_observer_.reset();
+ update_client_->Stop();
update_client_ = nullptr;
if (updater_configurator_ != nullptr) {
diff --git a/src/cobalt/version.h b/src/cobalt/version.h
index 9e20fe2..e014a72 100644
--- a/src/cobalt/version.h
+++ b/src/cobalt/version.h
@@ -35,6 +35,6 @@
// release is cut.
//.
-#define COBALT_VERSION "21.lts.4"
+#define COBALT_VERSION "21.lts.5"
#endif // COBALT_VERSION_H_
diff --git a/src/cobalt/webdriver/protocol/moveto.cc b/src/cobalt/webdriver/protocol/moveto.cc
index a8a10f9..d9eb35e 100644
--- a/src/cobalt/webdriver/protocol/moveto.cc
+++ b/src/cobalt/webdriver/protocol/moveto.cc
@@ -12,10 +12,11 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#include "cobalt/webdriver/protocol/moveto.h"
+
#include <memory>
#include <string>
-
-#include "cobalt/webdriver/protocol/moveto.h"
+#include <utility>
namespace cobalt {
namespace webdriver {
@@ -43,7 +44,7 @@
}
base::Optional<Moveto> Moveto::FromValue(const base::Value* value) {
- const base::DictionaryValue* dictionary_value;
+ const base::DictionaryValue* dictionary_value = nullptr;
if (!value->GetAsDictionary(&dictionary_value)) {
return base::nullopt;
}
@@ -53,6 +54,12 @@
if (dictionary_value->GetString(kElementKey, &element_id) &&
!element_id.empty()) {
element = ElementId(element_id);
+ } else {
+ const base::Value* element_value =
+ value->FindKeyOfType(kElementKey, base::Value::Type::DICTIONARY);
+ if (element_value) {
+ element = ElementId::FromValue(element_value);
+ }
}
int xoffset_value = 0;
diff --git a/src/cobalt/webdriver/testdata/simple_test.py b/src/cobalt/webdriver/testdata/simple_test.py
index d2cea99..bf532b0 100755
--- a/src/cobalt/webdriver/testdata/simple_test.py
+++ b/src/cobalt/webdriver/testdata/simple_test.py
@@ -29,6 +29,37 @@
POST = 'POST'
DELETE = 'DELETE'
+# WebDriver Response Status Codes:
+# https://github.com/SeleniumHQ/selenium/wiki/JsonWireProtocol#Response-Status-Codes
+
+RESPONSE_STATUS_CODES = {
+ 0: 'Success',
+ 6: 'No Such Driver',
+ 7: 'No Such Element',
+ 8: 'No Such Frame',
+ 9: 'Unknown Command',
+ 10: 'Stale Element Reference',
+ 11: 'Element Not Visible',
+ 12: 'Invalid Element State',
+ 13: 'Unknown Error',
+ 15: 'Element Is Not Selectable',
+ 17: 'JavaScript Error',
+ 19: 'XPath Lookup Error',
+ 21: 'Timeout',
+ 23: 'No Such Window',
+ 24: 'Invalid Cookie Domain',
+ 25: 'Unable To Set Cookie',
+ 26: 'Unexpected Alert Open',
+ 27: 'No Alert Open Error',
+ 28: 'Script Timeout',
+ 29: 'Invalid Element Coordinates',
+ 30: 'IME Not Available',
+ 31: 'IME Engine Activation Failed',
+ 32: 'Invalid Selector',
+ 33: 'Session Not Created Exception',
+ 34: 'Move Target Out Of Bounds'
+}
+
def Request(request_type, path='', parameters=None):
"""Perform a WebDriver JSON Wire Protocol Request.
@@ -54,8 +85,11 @@
if request.status_code == 200:
return result
else:
- print '*** Error %d: %s' % (request.status_code, result['value']['message']
- if isinstance(result, dict) else result)
+ print('*** Error %d %s: \"%s\"' %
+ (request.status_code, RESPONSE_STATUS_CODES[result['status']]
+ if isinstance(result, dict) else 'unknown',
+ result['value']['message'] if isinstance(result, dict) else result))
+ print('*** Error %d: %s' % (request.status_code, result))
return None
@@ -82,8 +116,9 @@
request_type,
path=None,
parameters=None):
- return SessionRequest(session_id, request_type, 'element/%s/%s' %
- (element_id[u'ELEMENT'], path), parameters)
+ return SessionRequest(session_id, request_type,
+ 'element/%s/%s' % (element_id[u'ELEMENT'], path),
+ parameters)
def GetSessionID():
@@ -129,6 +164,20 @@
f.close()
+def GetElementScreenShot(session_id, element_id, filename):
+ """Retrieve a Screenshot.
+
+ Args:
+ session_id: Value for ':sessionId' for the request
+ filename: The filename to write the PNG screenshot to
+ """
+ request = ElementRequest(session_id, element_id, GET, 'screenshot')
+ if request:
+ with open(filename, 'w') as f:
+ f.write(binascii.a2b_base64(request['value']))
+ f.close()
+
+
def GetActiveElement(session_id):
return SessionRequest(session_id, POST, 'element/active')['value']
@@ -171,32 +220,97 @@
def ElementFind(session_id, using, value):
- return SessionRequest(session_id, POST, 'element',
- {u'using': using,
- u'value': value})['value']
+ result = SessionRequest(session_id, POST, 'element', {
+ u'using': using,
+ u'value': value
+ })
+ return None if result is None else result['value']
def MouseTest():
# Do a simple test that hovers the mouse to the right from the active
# element, then clicks on the element of class 'trending'.
session_id = GetSessionID()
- active_element = GetActiveElement(session_id)
- print 'active_element : %s' % active_element
+ try:
+ active_element = GetActiveElement(session_id)
+ print('active_element : %s' % active_element)
- for xoffset in range(0, 1900, 20):
- print 'Moveto: %s' % Moveto(session_id, active_element, xoffset, 200)
- time.sleep(0.05)
+ for xoffset in range(0, 1900, 20):
+ print('Moveto: %s' % Moveto(session_id, active_element, xoffset, 200))
+ time.sleep(0.05)
- trending_element = ElementFind(session_id, 'class name', 'trending')
- print 'trending_element : %s' % trending_element
+ selected_element = ElementFind(session_id, 'class name',
+ 'ytlr-tile-renderer--focused')
+ print('selected_element : %s' % selected_element)
- print 'ElementClick: %s' % ElementClick(session_id, trending_element, 0)
+ print('ElementClick: %s' % ElementClick(session_id, selected_element, 0))
+
+ except KeyboardInterrupt:
+ print('Bye')
DeleteSession(session_id)
+def ElementScreenShotTest():
+ # Do a simple test that hovers the mouse to the right from the active
+ # element, then clicks on the element of class 'trending'.
+ session_id = GetSessionID()
+ try:
+ selected_element = ElementFind(session_id, 'class name',
+ 'ytlr-tile-renderer--focused')
+ print('Selected List element : %s' % selected_element)
+
+ # Write screenshots for the selected element, until interrupted.
+ while True:
+ selected_element = ElementFind(session_id, 'class name',
+ 'ytlr-tile-renderer--focused')
+ print('Selected List element : %s' % selected_element)
+ if selected_element is not None:
+ print('GetElementScreenShot: %s' % GetElementScreenShot(
+ session_id, selected_element,
+ 'element-' + selected_element['ELEMENT'] + '.png'))
+
+ except KeyboardInterrupt:
+ print('Bye')
+
+ DeleteSession(session_id)
+
+
+def ElementUniqueTest():
+ # Do a simple test that keeps running as long as the element IDs stay the
+ # same.
+ session_id = GetSessionID()
+ try:
+ initial_active_element = GetActiveElement(session_id)
+ print('initial active_element : %s' % initial_active_element)
+
+ initial_selected_element = ElementFind(session_id, 'class name',
+ 'ytlr-tile-renderer--focused')
+ print('Selected List element : %s' % initial_selected_element)
+ while True:
+ active_element = GetActiveElement(session_id)
+ print('active_element : %s' % active_element)
+
+ if initial_active_element != active_element:
+ break
+
+ selected_element = ElementFind(session_id, 'class name',
+ 'ytlr-tile-renderer--focused')
+ print('Selected List element : %s' % selected_element)
+
+ if initial_selected_element != selected_element:
+ break
+
+ time.sleep(1)
+
+ except KeyboardInterrupt:
+ print('Bye')
+
+
def main():
MouseTest()
+ ElementScreenShotTest()
+ # ElementUniqueTest()
if __name__ == '__main__':
diff --git a/src/cobalt/webdriver/window_driver.cc b/src/cobalt/webdriver/window_driver.cc
index 483b6d2..1cb4432 100644
--- a/src/cobalt/webdriver/window_driver.cc
+++ b/src/cobalt/webdriver/window_driver.cc
@@ -399,6 +399,14 @@
protocol::ElementId WindowDriver::ElementToId(
const scoped_refptr<dom::Element>& element) {
DCHECK_EQ(base::MessageLoop::current()->task_runner(), window_task_runner_);
+ for (auto i : element_drivers_) {
+ // Note: The element_task_runner_ is the same as the window_task_runner_.
+ auto weak_element = i.second->GetWeakElement();
+ if (element == weak_element) {
+ return i.second->element_id();
+ }
+ }
+
return CreateNewElementDriver(base::AsWeakPtr(element.get()));
}
diff --git a/src/components/update_client/component.cc b/src/components/update_client/component.cc
index 3e23074..21a74f0 100644
--- a/src/components/update_client/component.cc
+++ b/src/components/update_client/component.cc
@@ -300,6 +300,13 @@
base::BindOnce(&Component::ChangeState, base::Unretained(this)));
}
+#if defined(STARBOARD)
+void Component::Cancel() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ state_->Cancel();
+}
+#endif
+
void Component::ChangeState(std::unique_ptr<State> next_state) {
DCHECK(thread_checker_.CalledOnValidThread());
@@ -532,6 +539,14 @@
DoHandle();
}
+#if defined(STARBOARD)
+void Component::State::Cancel() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ // Further work may be needed to ensure cancelation during any state results
+ // in a clear result and no memory leaks.
+}
+#endif
+
void Component::State::TransitionState(std::unique_ptr<State> next_state) {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(next_state);
@@ -726,6 +741,13 @@
DCHECK(thread_checker_.CalledOnValidThread());
}
+#if defined(STARBOARD)
+void Component::StateDownloadingDiff::Cancel() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ crx_downloader_->CancelDownload();
+}
+#endif
+
void Component::StateDownloadingDiff::DoHandle() {
DCHECK(thread_checker_.CalledOnValidThread());
@@ -800,6 +822,13 @@
DCHECK(thread_checker_.CalledOnValidThread());
}
+#if defined(STARBOARD)
+void Component::StateDownloading::Cancel() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ crx_downloader_->CancelDownload();
+}
+#endif
+
void Component::StateDownloading::DoHandle() {
DCHECK(thread_checker_.CalledOnValidThread());
diff --git a/src/components/update_client/component.h b/src/components/update_client/component.h
index 0f9b973..229e80e 100644
--- a/src/components/update_client/component.h
+++ b/src/components/update_client/component.h
@@ -55,6 +55,12 @@
// to the next component state before |callback_handle_complete_| is invoked.
void Handle(CallbackHandleComplete callback_handle_complete);
+#if defined(STARBOARD)
+ // Stops update progress for the component and may clean resources used in its
+ // current state.
+ void Cancel();
+#endif
+
CrxUpdateItem GetCrxUpdateItem() const;
// Sets the uninstall state for this component.
@@ -156,6 +162,11 @@
// by the outer component, after the current state is fully handled.
void Handle(CallbackNextState callback);
+#if defined(STARBOARD)
+ // Stops update progress and may clean resources used in the current state.
+ virtual void Cancel();
+#endif
+
ComponentState state() const { return state_; }
protected:
@@ -247,6 +258,9 @@
public:
explicit StateDownloadingDiff(Component* component);
~StateDownloadingDiff() override;
+#if defined(STARBOARD)
+ void Cancel() override;
+#endif
private:
// State overrides.
@@ -270,6 +284,9 @@
public:
explicit StateDownloading(Component* component);
~StateDownloading() override;
+#if defined(STARBOARD)
+ void Cancel() override;
+#endif
private:
// State overrides.
diff --git a/src/components/update_client/crx_downloader.cc b/src/components/update_client/crx_downloader.cc
index bac3857..1e347d6 100644
--- a/src/components/update_client/crx_downloader.cc
+++ b/src/components/update_client/crx_downloader.cc
@@ -120,6 +120,12 @@
DoStartDownload(*current_url_);
}
+#if defined(STARBOARD)
+void CrxDownloader::CancelDownload() {
+ DoCancelDownload();
+}
+#endif
+
void CrxDownloader::OnDownloadComplete(
bool is_handled,
const Result& result,
diff --git a/src/components/update_client/crx_downloader.h b/src/components/update_client/crx_downloader.h
index 3b46799..2db575a 100644
--- a/src/components/update_client/crx_downloader.h
+++ b/src/components/update_client/crx_downloader.h
@@ -122,6 +122,10 @@
const std::string& expected_hash,
DownloadCallback download_callback);
+#if defined(STARBOARD)
+ void CancelDownload();
+#endif
+
const std::vector<DownloadMetrics> download_metrics() const;
protected:
@@ -151,6 +155,9 @@
private:
virtual void DoStartDownload(const GURL& url) = 0;
+#if defined(STARBOARD)
+ virtual void DoCancelDownload() = 0;
+#endif
void VerifyResponse(bool is_handled,
Result result,
diff --git a/src/components/update_client/network.h b/src/components/update_client/network.h
index daed162..dec108f 100644
--- a/src/components/update_client/network.h
+++ b/src/components/update_client/network.h
@@ -63,6 +63,9 @@
ResponseStartedCallback response_started_callback,
ProgressCallback progress_callback,
DownloadToFileCompleteCallback download_to_file_complete_callback) = 0;
+#if defined(STARBOARD)
+ virtual void CancelDownloadToFile() = 0;
+#endif
protected:
NetworkFetcher() = default;
diff --git a/src/components/update_client/task_update.cc b/src/components/update_client/task_update.cc
index ab445b5..0129e4c 100644
--- a/src/components/update_client/task_update.cc
+++ b/src/components/update_client/task_update.cc
@@ -36,13 +36,25 @@
return;
}
+#if defined(STARBOARD)
+ update_engine_->Update(is_foreground_, ids_, std::move(crx_data_callback_),
+ base::BindOnce(&TaskUpdate::TaskComplete, this),
+ cancelation_closure_);
+#else
update_engine_->Update(is_foreground_, ids_, std::move(crx_data_callback_),
base::BindOnce(&TaskUpdate::TaskComplete, this));
+#endif
}
void TaskUpdate::Cancel() {
DCHECK(thread_checker_.CalledOnValidThread());
+#if defined(STARBOARD)
+ if (cancelation_closure_) { // The engine's picked up the task.
+ std::move(cancelation_closure_).Run();
+ }
+#endif
+
TaskComplete(Error::UPDATE_CANCELED);
}
diff --git a/src/components/update_client/task_update.h b/src/components/update_client/task_update.h
index 4df796b..74c0a6a 100644
--- a/src/components/update_client/task_update.h
+++ b/src/components/update_client/task_update.h
@@ -57,6 +57,9 @@
const std::vector<std::string> ids_;
UpdateClient::CrxDataCallback crx_data_callback_;
Callback callback_;
+#if defined(STARBOARD)
+ base::OnceClosure cancelation_closure_;
+#endif
DISALLOW_COPY_AND_ASSIGN(TaskUpdate);
};
diff --git a/src/components/update_client/update_client.cc b/src/components/update_client/update_client.cc
index 369c6d3..6ce65bf 100644
--- a/src/components/update_client/update_client.cc
+++ b/src/components/update_client/update_client.cc
@@ -201,6 +201,16 @@
is_stopped_ = true;
+ // Cancel the pending tasks. These tasks are safe to cancel and delete since
+ // they have not picked up by the update engine, and not shared with any
+ // task runner yet.
+ while (!task_queue_.empty()) {
+ auto task = task_queue_.front();
+ task_queue_.pop_front();
+ task->Cancel();
+ }
+
+#if !defined(STARBOARD)
// In the current implementation it is sufficient to cancel the pending
// tasks only. The tasks that are run by the update engine will stop
// making progress naturally, as the main task runner stops running task
@@ -210,15 +220,15 @@
// area, to cancel the running tasks by canceling the current action update.
// This behavior would be expected, correct, and result in no resource leaks
// in all cases, in shutdown or not.
- //
- // Cancel the pending tasks. These tasks are safe to cancel and delete since
- // they have not picked up by the update engine, and not shared with any
- // task runner yet.
- while (!task_queue_.empty()) {
- auto task = task_queue_.front();
- task_queue_.pop_front();
+#else
+ // For Cobalt it's not sufficient to just let the tasks already picked up by
+ // the update engine stop naturally, as this can result in resource leaks and
+ // crashes. These tasks are also canceled so that any necessary cleanup can be
+ // done.
+ for (auto task : tasks_) {
task->Cancel();
}
+#endif
}
void UpdateClientImpl::SendUninstallPing(const std::string& id,
diff --git a/src/components/update_client/update_engine.cc b/src/components/update_client/update_engine.cc
index a6d6920..29c260b 100644
--- a/src/components/update_client/update_engine.cc
+++ b/src/components/update_client/update_engine.cc
@@ -72,10 +72,19 @@
DCHECK(thread_checker_.CalledOnValidThread());
}
+#if !defined(STARBOARD)
void UpdateEngine::Update(bool is_foreground,
const std::vector<std::string>& ids,
UpdateClient::CrxDataCallback crx_data_callback,
Callback callback) {
+#else
+void UpdateEngine::Update(bool is_foreground,
+ const std::vector<std::string>& ids,
+ UpdateClient::CrxDataCallback crx_data_callback,
+ Callback callback,
+ base::OnceClosure& cancelation_closure) {
+
+#endif
DCHECK(thread_checker_.CalledOnValidThread());
if (ids.empty()) {
@@ -100,6 +109,10 @@
config_, is_foreground, ids, std::move(crx_data_callback),
notify_observers_callback_, std::move(callback), crx_downloader_factory_);
DCHECK(!update_context->session_id.empty());
+#if defined(STARBOARD)
+ cancelation_closure = base::BindOnce(&UpdateEngine::Cancel, this,
+ update_context->session_id, ids);
+#endif
const auto result = update_contexts_.insert(
std::make_pair(update_context->session_id, update_context));
@@ -405,6 +418,17 @@
now < throttle_updates_until_;
}
+#if defined(STARBOARD)
+void UpdateEngine::Cancel(const std::string& update_context_session_id,
+ const std::vector<std::string>& crx_component_ids) {
+ const auto& context = update_contexts_.at(update_context_session_id);
+ for (const auto& crx_component_id : crx_component_ids) {
+ auto& component = context->components.at(crx_component_id);
+ component->Cancel();
+ }
+}
+#endif
+
void UpdateEngine::SendUninstallPing(const std::string& id,
const base::Version& version,
int reason,
diff --git a/src/components/update_client/update_engine.h b/src/components/update_client/update_engine.h
index 9601873..4384fa8 100644
--- a/src/components/update_client/update_engine.h
+++ b/src/components/update_client/update_engine.h
@@ -56,10 +56,20 @@
// is not found.
bool GetUpdateState(const std::string& id, CrxUpdateItem* update_state);
+#if !defined(STARBOARD)
void Update(bool is_foreground,
const std::vector<std::string>& ids,
UpdateClient::CrxDataCallback crx_data_callback,
Callback update_callback);
+#else
+ // |cancelation_closure| is populated with a closure that can be run to cancel
+ // the update requested by the caller.
+ void Update(bool is_foreground,
+ const std::vector<std::string>& ids,
+ UpdateClient::CrxDataCallback crx_data_callback,
+ Callback update_callback,
+ base::OnceClosure& cancelation_closure);
+#endif
void SendUninstallPing(const std::string& id,
const base::Version& version,
@@ -96,6 +106,14 @@
// occurs too soon.
bool IsThrottled(bool is_foreground) const;
+#if defined(STARBOARD)
+ // Cancels updates currently handled by the engine for each component
+ // identified by one of |crx_component_ids| for the update context identified
+ // by the |update_context_session_id|.
+ void Cancel(const std::string& update_context_session_id,
+ const std::vector<std::string>& crx_component_ids);
+#endif
+
base::ThreadChecker thread_checker_;
scoped_refptr<Configurator> config_;
UpdateChecker::Factory update_checker_factory_;
diff --git a/src/components/update_client/url_fetcher_downloader.cc b/src/components/update_client/url_fetcher_downloader.cc
index f94b010..f940e2e 100644
--- a/src/components/update_client/url_fetcher_downloader.cc
+++ b/src/components/update_client/url_fetcher_downloader.cc
@@ -144,6 +144,13 @@
#endif
}
+#if defined(STARBOARD)
+void UrlFetcherDownloader::DoCancelDownload() {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ network_fetcher_->CancelDownloadToFile();
+}
+#endif
+
void UrlFetcherDownloader::CreateDownloadDir() {
base::CreateNewTempDirectory(FILE_PATH_LITERAL("chrome_url_fetcher_"),
&download_dir_);
diff --git a/src/components/update_client/url_fetcher_downloader.h b/src/components/update_client/url_fetcher_downloader.h
index fc32732..ea7f29d 100644
--- a/src/components/update_client/url_fetcher_downloader.h
+++ b/src/components/update_client/url_fetcher_downloader.h
@@ -42,6 +42,9 @@
private:
// Overrides for CrxDownloader.
void DoStartDownload(const GURL& url) override;
+#if defined(STARBOARD)
+ void DoCancelDownload() override;
+#endif
void CreateDownloadDir();
void StartURLFetch(const GURL& url);
diff --git a/src/docker/linux/base/build/Dockerfile b/src/docker/linux/base/build/Dockerfile
index 545908d..8d60ad9 100644
--- a/src/docker/linux/base/build/Dockerfile
+++ b/src/docker/linux/base/build/Dockerfile
@@ -2,10 +2,15 @@
FROM ${FROM_IMAGE:-cobalt-base}
# === Get Nodejs pinned LTS version via NVM
+ARG NVM_SHA256SUM="f068e17dacb88f73302790cc076956c7a0d459ce9b01df842ff3e75744f9e2fe /tmp/install.sh"
+ARG NVM_URL="https://cobalt.googlesource.com/third_party/nvm/+/refs/tags/v0.35.3/install.sh?format=TEXT"
ENV NVM_DIR /root/.nvm
ENV NODE_VERSION 12.17.0
-RUN curl --silent -o- https://raw.githubusercontent.com/creationix/nvm/v0.35.3/install.sh | bash
+RUN curl --silent -o- ${NVM_URL} \
+ | base64 -d > /tmp/install.sh \
+ && echo ${NVM_SHA256SUM} | sha256sum --check \
+ && . /tmp/install.sh
RUN . $NVM_DIR/nvm.sh \
&& nvm install --lts \
diff --git a/src/requirements.txt b/src/requirements.txt
index e9215ea..b666306 100644
--- a/src/requirements.txt
+++ b/src/requirements.txt
@@ -2,3 +2,4 @@
pre-commit==2.6.0
pylint==2.6.0
yapf==0.30.0
+requests==2.25.1
diff --git a/src/starboard/android/apk/build.id b/src/starboard/android/apk/build.id
deleted file mode 100644
index 772184d..0000000
--- a/src/starboard/android/apk/build.id
+++ /dev/null
@@ -1 +0,0 @@
-302879
\ No newline at end of file
diff --git a/src/starboard/build/collect_deploy_content.gypi b/src/starboard/build/collect_deploy_content.gypi
index 6bee14a..a9a5064 100644
--- a/src/starboard/build/collect_deploy_content.gypi
+++ b/src/starboard/build/collect_deploy_content.gypi
@@ -46,6 +46,11 @@
'collect_deploy_content_extra_args': [ '--use_absolute_symlinks' ],
}
}],
+ ['cobalt_docker_build == 1 and host_os == "win"', {
+ 'variables': {
+ 'collect_deploy_content_extra_args': [ '--copy_override' ],
+ }
+ }],
],
'actions': [{
'action_name': 'collect_deploy_content',
diff --git a/src/starboard/build/collect_deploy_content.py b/src/starboard/build/collect_deploy_content.py
index 8d3fffd..49bf9af 100644
--- a/src/starboard/build/collect_deploy_content.py
+++ b/src/starboard/build/collect_deploy_content.py
@@ -17,6 +17,7 @@
import argparse
import logging
import os
+import shutil
import sys
import _env # pylint: disable=unused-import
@@ -39,6 +40,21 @@
port_symlink.Rmtree(path)
+def _CopyTree(src_path, dst_path):
+ """
+ Copy tree with a safeguard for windows long path (>260).
+ On Windows Python is facing long path limitation, for more details see
+ https://bugs.python.org/issue27730
+ """
+ if os.sep == r'\\':
+ prefix = r'\\\\?\\'
+ if prefix not in src_path:
+ src_path = prefix + src_path
+ if prefix not in dst_path:
+ dst_path = prefix + dst_path
+ shutil.copytree(src_path, dst_path)
+
+
def main(argv):
parser = argparse.ArgumentParser()
parser.add_argument(
@@ -59,6 +75,11 @@
metavar='subdirs',
nargs='*',
help='subdirectories within both the input and output directories')
+ parser.add_argument(
+ '--copy_override',
+ action='store_true',
+ help='Overrides the behavior of collect_deploy_content to copy files, '
+ 'instead of symlinking them.')
options = parser.parse_args(argv[1:])
if os.environ.get(_SHOULD_LOG_ENV_KEY, None) == '1':
@@ -107,7 +128,9 @@
msg += ' path points to an unknown type'
logging.error(msg)
- if options.use_absolute_symlinks:
+ if options.copy_override:
+ _CopyTree(src_path, dst_path)
+ elif options.use_absolute_symlinks:
port_symlink.MakeSymLink(
target_path=os.path.abspath(src_path),
link_path=os.path.abspath(dst_path))
diff --git a/src/starboard/common/log.h b/src/starboard/common/log.h
index f1ec6b9..596dbc6 100644
--- a/src/starboard/common/log.h
+++ b/src/starboard/common/log.h
@@ -168,8 +168,10 @@
#if SB_LOGGING_IS_OFFICIAL_BUILD || \
(defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON))
#define SB_DCHECK(condition) SB_EAT_STREAM_PARAMETERS
+#define SB_DCHECK_ENABLED 0
#else
#define SB_DCHECK(condition) SB_CHECK(condition)
+#define SB_DCHECK_ENABLED 1
#endif
#define SB_DLOG(severity) SB_DLOG_IF(severity, SB_DLOG_IS_ON(severity))
@@ -224,8 +226,10 @@
#if SB_LOGGING_IS_OFFICIAL_BUILD
#define SB_NOTIMPLEMENTED()
#define SB_DCHECK(condition)
+#define SB_DCHECK_ENABLED 0
#else
#define SB_DCHECK(condition) SB_CHECK(condition)
+#define SB_DCHECK_ENABLED 1
#define SB_NOTIMPLEMENTED() \
do { \
static int count = 0; \
diff --git a/src/starboard/linux/shared/gyp_configuration.py b/src/starboard/linux/shared/gyp_configuration.py
index b8f0949..4e4a96c 100644
--- a/src/starboard/linux/shared/gyp_configuration.py
+++ b/src/starboard/linux/shared/gyp_configuration.py
@@ -121,3 +121,10 @@
'VideoDecoderTests/VideoDecoderTest.*Invalid*',
],
}
+ # Conditionally disables tests that require ipv6
+ if os.getenv('IPV6_AVAILABLE', 1) == '0':
+ __FILTERED_TESTS['nplb'] = [
+ 'SbSocketAddressTypes/SbSocketGetInterfaceAddressTest.SunnyDayDestination/1',
+ 'SbSocketAddressTypes/SbSocketGetInterfaceAddressTest.SunnyDaySourceForDestination/1',
+ 'SbSocketAddressTypes/SbSocketGetInterfaceAddressTest.SunnyDaySourceNotLoopback/1',
+ ]
diff --git a/src/starboard/nplb/nplb_evergreen_compat_tests/crashpad_config_test.cc b/src/starboard/nplb/nplb_evergreen_compat_tests/crashpad_config_test.cc
new file mode 100644
index 0000000..ca4ee47
--- /dev/null
+++ b/src/starboard/nplb/nplb_evergreen_compat_tests/crashpad_config_test.cc
@@ -0,0 +1,61 @@
+// Copyright 2021 The Cobalt Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <string>
+#include <vector>
+
+#include "cobalt/extension/crash_handler.h"
+#include "starboard/nplb/nplb_evergreen_compat_tests/checks.h"
+#include "starboard/system.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+#if SB_IS(EVERGREEN_COMPATIBLE)
+
+namespace starboard {
+namespace nplb {
+namespace nplb_evergreen_compat_tests {
+
+namespace {
+
+class CrashpadConfigTest : public ::testing::Test {
+ protected:
+ CrashpadConfigTest() {}
+ ~CrashpadConfigTest() {}
+};
+
+TEST_F(CrashpadConfigTest, VerifyUploadCert) {
+ std::vector<char> buffer(kSbFileMaxPath);
+ ASSERT_TRUE(SbSystemGetPath(kSbSystemPathContentDirectory, buffer.data(),
+ buffer.size()));
+
+ std::string cert_location(buffer.data());
+ cert_location.append(std::string(kSbFileSepString) + "app" +
+ kSbFileSepString + "cobalt" + kSbFileSepString +
+ "content" + kSbFileSepString + "ssl" + kSbFileSepString +
+ "certs");
+ ASSERT_TRUE(SbFileExists(cert_location.c_str()));
+}
+
+TEST_F(CrashpadConfigTest, VerifyCrashHandlerExtension) {
+ auto crash_handler_extension =
+ SbSystemGetExtension(kCobaltExtensionCrashHandlerName);
+ ASSERT_TRUE(crash_handler_extension != nullptr);
+}
+
+} // namespace
+} // namespace nplb_evergreen_compat_tests
+} // namespace nplb
+} // namespace starboard
+
+#endif // SB_IS(EVERGREEN_COMPATIBLE)
diff --git a/src/starboard/nplb/nplb_evergreen_compat_tests/nplb_evergreen_compat_tests.gyp b/src/starboard/nplb/nplb_evergreen_compat_tests/nplb_evergreen_compat_tests.gyp
index 4e292f8..1f2b9a73 100644
--- a/src/starboard/nplb/nplb_evergreen_compat_tests/nplb_evergreen_compat_tests.gyp
+++ b/src/starboard/nplb/nplb_evergreen_compat_tests/nplb_evergreen_compat_tests.gyp
@@ -19,6 +19,7 @@
'type': '<(gtest_target_type)',
'sources': [
'checks.h',
+ 'crashpad_config_test.cc',
'executable_memory_test.cc',
'fonts_test.cc',
'sabi_test.cc',
diff --git a/src/third_party/crashpad/handler/handler.gyp b/src/third_party/crashpad/handler/handler.gyp
index effe9e1..1275a4d 100644
--- a/src/third_party/crashpad/handler/handler.gyp
+++ b/src/third_party/crashpad/handler/handler.gyp
@@ -89,8 +89,21 @@
'sources': [
'main.cc',
],
-
'conditions': [
+ # Help platforms cross compiled on linux to reduce
+ # the memory footprint of crashpad_handler by eliminating
+ # unused code and unused shared libraries.
+ # The flags assume gcc/clang toolchain.
+ ['host_os=="linux"', {
+ 'cflags': [
+ '-ffunction-sections',
+ '-fdata-sections',
+ ],
+ 'ldflags': [
+ '-Wl,--as-needed',
+ '-Wl,-gc-sections',
+ ],
+ }],
['OS=="win"', {
'msvs_settings': {
'VCLinkerTool': {
diff --git a/src/third_party/freetype2/src/tools/Jamfile b/src/third_party/freetype2/src/tools/Jamfile
new file mode 100644
index 0000000..475161e
--- /dev/null
+++ b/src/third_party/freetype2/src/tools/Jamfile
@@ -0,0 +1,5 @@
+# Jamfile for src/tools
+#
+SubDir FT2_TOP src tools ;
+
+Main apinames : apinames.c ;
diff --git a/src/third_party/freetype2/src/tools/afblue.pl b/src/third_party/freetype2/src/tools/afblue.pl
new file mode 100644
index 0000000..bbc4f47
--- /dev/null
+++ b/src/third_party/freetype2/src/tools/afblue.pl
@@ -0,0 +1,551 @@
+#! /usr/bin/perl -w
+# -*- Perl -*-
+#
+# afblue.pl
+#
+# Process a blue zone character data file.
+#
+# Copyright (C) 2013-2020 by
+# David Turner, Robert Wilhelm, and Werner Lemberg.
+#
+# This file is part of the FreeType project, and may only be used,
+# modified, and distributed under the terms of the FreeType project
+# license, LICENSE.TXT. By continuing to use, modify, or distribute
+# this file you indicate that you have read the license and
+# understand and accept it fully.
+
+use strict;
+use warnings;
+use English '-no_match_vars';
+use open ':std', ':encoding(UTF-8)';
+
+
+my $prog = $PROGRAM_NAME;
+$prog =~ s| .* / ||x; # Remove path.
+
+die "usage: $prog datafile < infile > outfile\n" if $#ARGV != 0;
+
+
+my $datafile = $ARGV[0];
+
+my %diversions; # The extracted and massaged data from `datafile'.
+my @else_stack; # Booleans to track else-clauses.
+my @name_stack; # Stack of integers used for names of aux. variables.
+
+my $curr_enum; # Name of the current enumeration.
+my $curr_array; # Name of the current array.
+my $curr_max; # Name of the current maximum value.
+
+my $curr_enum_element; # Name of the current enumeration element.
+my $curr_offset; # The offset relative to current aux. variable.
+my $curr_elem_size; # The number of non-space characters in the current string or
+ # the number of elements in the current block.
+
+my $have_sections = 0; # Boolean; set if start of a section has been seen.
+my $have_strings; # Boolean; set if current section contains strings.
+my $have_blocks; # Boolean; set if current section contains blocks.
+
+my $have_enum_element; # Boolean; set if we have an enumeration element.
+my $in_string; # Boolean; set if a string has been parsed.
+
+my $num_sections = 0; # Number of sections seen so far.
+
+my $last_aux; # Name of last auxiliary variable.
+
+
+# Regular expressions.
+
+# [<ws>] <enum_name> <ws> <array_name> <ws> <max_name> [<ws>] ':' [<ws>] '\n'
+my $section_re = qr/ ^ \s* (\S+) \s+ (\S+) \s+ (\S+) \s* : \s* $ /x;
+
+# [<ws>] <enum_element_name> [<ws>] '\n'
+my $enum_element_re = qr/ ^ \s* ( [A-Za-z0-9_]+ ) \s* $ /x;
+
+# '#' <preprocessor directive> '\n'
+my $preprocessor_re = qr/ ^ \# /x;
+
+# [<ws>] '/' '/' <comment> '\n'
+my $comment_re = qr| ^ \s* // |x;
+
+# empty line
+my $whitespace_only_re = qr/ ^ \s* $ /x;
+
+# [<ws>] '"' <string> '"' [<ws>] '\n' (<string> doesn't contain newlines)
+my $string_re = qr/ ^ \s*
+ " ( (?> (?: (?> [^"\\]+ ) | \\. )* ) ) "
+ \s* $ /x;
+
+# [<ws>] '{' <block> '}' [<ws>] '\n' (<block> can contain newlines)
+my $block_start_re = qr/ ^ \s* \{ /x;
+
+# We need the capturing group for `split' to make it return the separator
+# tokens (i.e., the opening and closing brace) also.
+my $brace_re = qr/ ( [{}] ) /x;
+
+
+sub Warn
+{
+ my $message = shift;
+ warn "$datafile:$INPUT_LINE_NUMBER: warning: $message\n";
+}
+
+
+sub Die
+{
+ my $message = shift;
+ die "$datafile:$INPUT_LINE_NUMBER: error: $message\n";
+}
+
+
+my $warned_before = 0;
+
+sub warn_before
+{
+ Warn("data before first section gets ignored") unless $warned_before;
+ $warned_before = 1;
+}
+
+
+sub strip_newline
+{
+ chomp;
+ s/ \x0D $ //x;
+}
+
+
+sub end_curr_string
+{
+ # Append final null byte to string.
+ if ($have_strings)
+ {
+ push @{$diversions{$curr_array}}, " '\\0',\n" if $in_string;
+
+ $curr_offset++;
+ $in_string = 0;
+ }
+}
+
+
+sub update_max_elem_size
+{
+ if ($curr_elem_size)
+ {
+ my $max = pop @{$diversions{$curr_max}};
+ $max = $curr_elem_size if $curr_elem_size > $max;
+ push @{$diversions{$curr_max}}, $max;
+ }
+}
+
+
+sub convert_non_ascii_char
+{
+ # A UTF-8 character outside of the printable ASCII range, with possibly a
+ # leading backslash character.
+ my $s = shift;
+
+ # Here we count characters, not bytes.
+ $curr_elem_size += length $s;
+
+ utf8::encode($s);
+ $s = uc unpack 'H*', $s;
+
+ $curr_offset += $s =~ s/\G(..)/'\\x$1', /sg;
+
+ return $s;
+}
+
+
+sub convert_ascii_chars
+{
+ # A series of ASCII characters in the printable range.
+ my $s = shift;
+
+ # We reduce multiple space characters to a single one.
+ $s =~ s/ +/ /g;
+
+ # Count all non-space characters. Note that `()' applies a list context
+ # to the capture that is used to count the elements.
+ $curr_elem_size += () = $s =~ /[^ ]/g;
+
+ $curr_offset += $s =~ s/\G(.)/'$1', /g;
+
+ return $s;
+}
+
+
+sub convert_literal
+{
+ my $s = shift;
+ my $orig = $s;
+
+ # ASCII printables and space
+ my $safe_re = '\x20-\x7E';
+ # ASCII printables and space, no backslash
+ my $safe_no_backslash_re = '\x20-\x5B\x5D-\x7E';
+
+ $s =~ s{
+ (?: \\? ( [^$safe_re] )
+ | ( (?: [$safe_no_backslash_re]
+ | \\ [$safe_re] )+ ) )
+ }
+ {
+ defined($1) ? convert_non_ascii_char($1)
+ : convert_ascii_chars($2)
+ }egx;
+
+ # We assume that `$orig' doesn't contain `*/'
+ return $s . " /* $orig */";
+}
+
+
+sub aux_name
+{
+ return "af_blue_" . $num_sections. "_" . join('_', @name_stack);
+}
+
+
+sub aux_name_next
+{
+ $name_stack[$#name_stack]++;
+ my $name = aux_name();
+ $name_stack[$#name_stack]--;
+
+ return $name;
+}
+
+
+sub enum_val_string
+{
+ # Build string that holds code to save the current offset in an
+ # enumeration element.
+ my $aux = shift;
+
+ my $add = ($last_aux eq "af_blue_" . $num_sections . "_0" )
+ ? ""
+ : "$last_aux + ";
+
+ return " $aux = $add$curr_offset,\n";
+}
+
+
+
+# Process data file.
+
+open(DATA, $datafile) || die "$prog: can't open \`$datafile': $OS_ERROR\n";
+
+while (<DATA>)
+{
+ strip_newline();
+
+ next if /$comment_re/;
+ next if /$whitespace_only_re/;
+
+ if (/$section_re/)
+ {
+ Warn("previous section is empty") if ($have_sections
+ && !$have_strings
+ && !$have_blocks);
+
+ end_curr_string();
+ update_max_elem_size();
+
+ # Save captured groups from `section_re'.
+ $curr_enum = $1;
+ $curr_array = $2;
+ $curr_max = $3;
+
+ $curr_enum_element = "";
+ $curr_offset = 0;
+
+ Warn("overwriting already defined enumeration \`$curr_enum'")
+ if exists($diversions{$curr_enum});
+ Warn("overwriting already defined array \`$curr_array'")
+ if exists($diversions{$curr_array});
+ Warn("overwriting already defined maximum value \`$curr_max'")
+ if exists($diversions{$curr_max});
+
+ $diversions{$curr_enum} = [];
+ $diversions{$curr_array} = [];
+ $diversions{$curr_max} = [];
+
+ push @{$diversions{$curr_max}}, 0;
+
+ @name_stack = ();
+ push @name_stack, 0;
+
+ $have_sections = 1;
+ $have_strings = 0;
+ $have_blocks = 0;
+
+ $have_enum_element = 0;
+ $in_string = 0;
+
+ $num_sections++;
+ $curr_elem_size = 0;
+
+ $last_aux = aux_name();
+
+ next;
+ }
+
+ if (/$preprocessor_re/)
+ {
+ if ($have_sections)
+ {
+ # Having preprocessor conditionals complicates the computation of
+ # correct offset values. We have to introduce auxiliary enumeration
+ # elements with the name `af_blue_<s>_<n1>_<n2>_...' that store
+ # offsets to be used in conditional clauses. `<s>' is the number of
+ # sections seen so far, `<n1>' is the number of `#if' and `#endif'
+ # conditionals seen so far in the topmost level, `<n2>' the number of
+ # `#if' and `#endif' conditionals seen so far one level deeper, etc.
+ # As a consequence, uneven values are used within a clause, and even
+ # values after a clause, since the C standard doesn't allow the
+ # redefinition of an enumeration value. For example, the name
+ # `af_blue_5_1_6' is used to construct enumeration values in the fifth
+ # section after the third (second-level) if-clause within the first
+ # (top-level) if-clause. After the first top-level clause has
+ # finished, `af_blue_5_2' is used. The current offset is then
+ # relative to the value stored in the current auxiliary element.
+
+ if (/ ^ \# \s* if /x)
+ {
+ push @else_stack, 0;
+
+ $name_stack[$#name_stack]++;
+
+ push @{$diversions{$curr_enum}}, enum_val_string(aux_name());
+ $last_aux = aux_name();
+
+ push @name_stack, 0;
+
+ $curr_offset = 0;
+ }
+ elsif (/ ^ \# \s* elif /x)
+ {
+ Die("unbalanced #elif") unless @else_stack;
+
+ pop @name_stack;
+
+ push @{$diversions{$curr_enum}}, enum_val_string(aux_name_next());
+ $last_aux = aux_name();
+
+ push @name_stack, 0;
+
+ $curr_offset = 0;
+ }
+ elsif (/ ^ \# \s* else /x)
+ {
+ my $prev_else = pop @else_stack;
+ Die("unbalanced #else") unless defined($prev_else);
+ Die("#else already seen") if $prev_else;
+ push @else_stack, 1;
+
+ pop @name_stack;
+
+ push @{$diversions{$curr_enum}}, enum_val_string(aux_name_next());
+ $last_aux = aux_name();
+
+ push @name_stack, 0;
+
+ $curr_offset = 0;
+ }
+ elsif (/ ^ (\# \s*) endif /x)
+ {
+ my $prev_else = pop @else_stack;
+ Die("unbalanced #endif") unless defined($prev_else);
+
+ pop @name_stack;
+
+ # If there is no else-clause for an if-clause, we add one. This is
+ # necessary to have correct offsets.
+ if (!$prev_else)
+ {
+ # Use amount of whitespace from `endif'.
+ push @{$diversions{$curr_enum}}, enum_val_string(aux_name_next())
+ . $1 . "else\n";
+ $last_aux = aux_name();
+
+ $curr_offset = 0;
+ }
+
+ $name_stack[$#name_stack]++;
+
+ push @{$diversions{$curr_enum}}, enum_val_string(aux_name());
+ $last_aux = aux_name();
+
+ $curr_offset = 0;
+ }
+
+ # Handle (probably continued) preprocessor lines.
+ CONTINUED_LOOP:
+ {
+ do
+ {
+ strip_newline();
+
+ push @{$diversions{$curr_enum}}, $ARG . "\n";
+ push @{$diversions{$curr_array}}, $ARG . "\n";
+
+ last CONTINUED_LOOP unless / \\ $ /x;
+
+ } while (<DATA>);
+ }
+ }
+ else
+ {
+ warn_before();
+ }
+
+ next;
+ }
+
+ if (/$enum_element_re/)
+ {
+ end_curr_string();
+ update_max_elem_size();
+
+ $curr_enum_element = $1;
+ $have_enum_element = 1;
+ $curr_elem_size = 0;
+
+ next;
+ }
+
+ if (/$string_re/)
+ {
+ if ($have_sections)
+ {
+ Die("strings and blocks can't be mixed in a section") if $have_blocks;
+
+ # Save captured group from `string_re'.
+ my $string = $1;
+
+ if ($have_enum_element)
+ {
+ push @{$diversions{$curr_enum}}, enum_val_string($curr_enum_element);
+ $have_enum_element = 0;
+ }
+
+ $string = convert_literal($string);
+
+ push @{$diversions{$curr_array}}, " $string\n";
+
+ $have_strings = 1;
+ $in_string = 1;
+ }
+ else
+ {
+ warn_before();
+ }
+
+ next;
+ }
+
+ if (/$block_start_re/)
+ {
+ if ($have_sections)
+ {
+ Die("strings and blocks can't be mixed in a section") if $have_strings;
+
+ my $depth = 0;
+ my $block = "";
+ my $block_end = 0;
+
+ # Count braces while getting the block.
+ BRACE_LOOP:
+ {
+ do
+ {
+ strip_newline();
+
+ foreach my $substring (split(/$brace_re/))
+ {
+ if ($block_end)
+ {
+ Die("invalid data after last matching closing brace")
+ if $substring !~ /$whitespace_only_re/;
+ }
+
+ $block .= $substring;
+
+ if ($substring eq '{')
+ {
+ $depth++;
+ }
+ elsif ($substring eq '}')
+ {
+ $depth--;
+
+ $block_end = 1 if $depth == 0;
+ }
+ }
+
+ # If we are here, we have run out of substrings, so get next line
+ # or exit.
+ last BRACE_LOOP if $block_end;
+
+ $block .= "\n";
+
+ } while (<DATA>);
+ }
+
+ if ($have_enum_element)
+ {
+ push @{$diversions{$curr_enum}}, enum_val_string($curr_enum_element);
+ $have_enum_element = 0;
+ }
+
+ push @{$diversions{$curr_array}}, $block . ",\n";
+
+ $curr_offset++;
+ $curr_elem_size++;
+
+ $have_blocks = 1;
+ }
+ else
+ {
+ warn_before();
+ }
+
+ next;
+ }
+
+ # Garbage. We weren't able to parse the data.
+ Die("syntax error");
+}
+
+# Finalize data.
+end_curr_string();
+update_max_elem_size();
+
+
+# Filter stdin to stdout, replacing `@...@' templates.
+
+sub emit_diversion
+{
+ my $diversion_name = shift;
+ return (exists($diversions{$1})) ? "@{$diversions{$1}}"
+ : "@" . $diversion_name . "@";
+}
+
+
+$LIST_SEPARATOR = '';
+
+my $s1 = "This file has been generated by the Perl script \`$prog',";
+my $s1len = length $s1;
+my $s2 = "using data from file \`$datafile'.";
+my $s2len = length $s2;
+my $slen = ($s1len > $s2len) ? $s1len : $s2len;
+
+print "/* " . $s1 . " " x ($slen - $s1len) . " */\n"
+ . "/* " . $s2 . " " x ($slen - $s2len) . " */\n"
+ . "\n";
+
+while (<STDIN>)
+{
+ s/ @ ( [A-Za-z0-9_]+? ) @ / emit_diversion($1) /egx;
+ print;
+}
+
+# EOF
diff --git a/src/third_party/freetype2/src/tools/apinames.c b/src/third_party/freetype2/src/tools/apinames.c
new file mode 100644
index 0000000..aeecf88
--- /dev/null
+++ b/src/third_party/freetype2/src/tools/apinames.c
@@ -0,0 +1,514 @@
+/*
+ * This little program is used to parse the FreeType headers and
+ * find the declaration of all public APIs. This is easy, because
+ * they all look like the following:
+ *
+ * FT_EXPORT( return_type )
+ * function_name( function arguments );
+ *
+ * You must pass the list of header files as arguments. Wildcards are
+ * accepted if you are using GCC for compilation (and probably by
+ * other compilers too).
+ *
+ * Author: FreeType team, 2005-2019
+ *
+ * This code is explicitly placed into the public domain.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#define PROGRAM_NAME "apinames"
+#define PROGRAM_VERSION "0.3"
+
+#define LINEBUFF_SIZE 1024
+
+
+typedef enum OutputFormat_
+{
+ OUTPUT_LIST = 0, /* output the list of names, one per line */
+ OUTPUT_WINDOWS_DEF, /* output a Windows .DEF file for Visual C++ or Mingw */
+ OUTPUT_BORLAND_DEF, /* output a Windows .DEF file for Borland C++ */
+ OUTPUT_WATCOM_LBC, /* output a Watcom Linker Command File */
+ OUTPUT_NETWARE_IMP, /* output a NetWare ImportFile */
+ OUTPUT_GNU_VERMAP /* output a version map for GNU or Solaris linker */
+
+} OutputFormat;
+
+
+static void
+panic( const char* message )
+{
+ fprintf( stderr, "PANIC: %s\n", message );
+ exit(2);
+}
+
+
+typedef struct NameRec_
+{
+ char* name;
+ unsigned int hash;
+
+} NameRec, *Name;
+
+
+static Name the_names;
+static int num_names;
+static int max_names;
+
+
+static void
+names_add( const char* name,
+ const char* end )
+{
+ unsigned int h;
+ int nn, len;
+ Name nm;
+
+
+ if ( end <= name )
+ return;
+
+ /* compute hash value */
+ len = (int)( end - name );
+ h = 0;
+
+ for ( nn = 0; nn < len; nn++ )
+ h = h * 33 + name[nn];
+
+ /* check for an pre-existing name */
+ for ( nn = 0; nn < num_names; nn++ )
+ {
+ nm = the_names + nn;
+
+ if ( (int)nm->hash == h &&
+ memcmp( name, nm->name, len ) == 0 &&
+ nm->name[len] == 0 )
+ return;
+ }
+
+ /* add new name */
+ if ( num_names >= max_names )
+ {
+ max_names += ( max_names >> 1 ) + 4;
+ the_names = (NameRec*)realloc( the_names,
+ sizeof ( the_names[0] ) * max_names );
+ if ( !the_names )
+ panic( "not enough memory" );
+ }
+ nm = &the_names[num_names++];
+
+ nm->hash = h;
+ nm->name = (char*)malloc( len + 1 );
+ if ( !nm->name )
+ panic( "not enough memory" );
+
+ memcpy( nm->name, name, len );
+ nm->name[len] = 0;
+}
+
+
+static int
+name_compare( const void* name1,
+ const void* name2 )
+{
+ Name n1 = (Name)name1;
+ Name n2 = (Name)name2;
+
+ return strcmp( n1->name, n2->name );
+}
+
+
+static void
+names_sort( void )
+{
+ qsort( the_names, (size_t)num_names,
+ sizeof ( the_names[0] ), name_compare );
+}
+
+
+static void
+names_dump( FILE* out,
+ OutputFormat format,
+ const char* dll_name )
+{
+ int nn;
+
+
+ switch ( format )
+ {
+ case OUTPUT_WINDOWS_DEF:
+ if ( dll_name )
+ fprintf( out, "LIBRARY %s\n", dll_name );
+
+ fprintf( out, "DESCRIPTION FreeType 2 DLL\n" );
+ fprintf( out, "EXPORTS\n" );
+
+ for ( nn = 0; nn < num_names; nn++ )
+ fprintf( out, " %s\n", the_names[nn].name );
+
+ break;
+
+ case OUTPUT_BORLAND_DEF:
+ if ( dll_name )
+ fprintf( out, "LIBRARY %s\n", dll_name );
+
+ fprintf( out, "DESCRIPTION FreeType 2 DLL\n" );
+ fprintf( out, "EXPORTS\n" );
+
+ for ( nn = 0; nn < num_names; nn++ )
+ fprintf( out, " _%s\n", the_names[nn].name );
+
+ break;
+
+ case OUTPUT_WATCOM_LBC:
+ {
+ const char* dot;
+ char temp[512];
+
+
+ if ( !dll_name )
+ {
+ fprintf( stderr,
+ "you must provide a DLL name with the -d option!\n" );
+ exit( 4 );
+ }
+
+ /* we must omit the `.dll' suffix from the library name */
+ dot = strchr( dll_name, '.' );
+ if ( dot )
+ {
+ int len = dot - dll_name;
+
+
+ if ( len > (int)( sizeof ( temp ) - 1 ) )
+ len = sizeof ( temp ) - 1;
+
+ memcpy( temp, dll_name, len );
+ temp[len] = 0;
+
+ dll_name = (const char*)temp;
+ }
+
+ for ( nn = 0; nn < num_names; nn++ )
+ fprintf( out, "++_%s.%s.%s\n",
+ the_names[nn].name, dll_name, the_names[nn].name );
+ }
+
+ break;
+
+ case OUTPUT_NETWARE_IMP:
+ if ( dll_name )
+ fprintf( out, " (%s)\n", dll_name );
+
+ for ( nn = 0; nn < num_names - 1; nn++ )
+ fprintf( out, " %s,\n", the_names[nn].name );
+ fprintf( out, " %s\n", the_names[num_names - 1].name );
+
+ break;
+
+ case OUTPUT_GNU_VERMAP:
+ fprintf( out, "{\n\tglobal:\n" );
+
+ for ( nn = 0; nn < num_names; nn++ )
+ fprintf( out, "\t\t%s;\n", the_names[nn].name );
+
+ fprintf( out, "\tlocal:\n\t\t*;\n};\n" );
+
+ break;
+
+ default: /* LIST */
+ for ( nn = 0; nn < num_names; nn++ )
+ fprintf( out, "%s\n", the_names[nn].name );
+
+ break;
+ }
+}
+
+
+/* states of the line parser */
+
+typedef enum State_
+{
+ STATE_START = 0, /* waiting for FT_EXPORT keyword and return type */
+ STATE_TYPE /* type was read, waiting for function name */
+
+} State;
+
+
+static int
+read_header_file( FILE* file,
+ int verbose )
+{
+ static char buff[LINEBUFF_SIZE + 1];
+ State state = STATE_START;
+
+
+ while ( !feof( file ) )
+ {
+ char* p;
+
+
+ if ( !fgets( buff, LINEBUFF_SIZE, file ) )
+ break;
+
+ p = buff;
+
+ /* skip leading whitespace */
+ while ( *p && ( *p == ' ' || *p == '\\' ) )
+ p++;
+
+ /* skip empty lines */
+ if ( *p == '\n' || *p == '\r' )
+ continue;
+
+ switch ( state )
+ {
+ case STATE_START:
+ if ( memcmp( p, "FT_EXPORT(", 10 ) != 0 )
+ break;
+
+ p += 10;
+ for (;;)
+ {
+ if ( *p == 0 || *p == '\n' || *p == '\r' )
+ goto NextLine;
+
+ if ( *p == ')' )
+ {
+ p++;
+ break;
+ }
+
+ p++;
+ }
+
+ state = STATE_TYPE;
+
+ /*
+ * Sometimes, the name is just after `FT_EXPORT(...)', so skip
+ * whitespace and fall-through if we find an alphanumeric character.
+ */
+ while ( *p == ' ' || *p == '\t' )
+ p++;
+
+ if ( !isalpha( *p ) )
+ break;
+
+ /* fall-through */
+
+ case STATE_TYPE:
+ {
+ char* name = p;
+
+
+ while ( isalnum( *p ) || *p == '_' )
+ p++;
+
+ if ( p > name )
+ {
+ if ( verbose )
+ fprintf( stderr, ">>> %.*s\n", (int)( p - name ), name );
+
+ names_add( name, p );
+ }
+
+ state = STATE_START;
+ }
+
+ break;
+
+ default:
+ ;
+ }
+
+NextLine:
+ ;
+ } /* end of while loop */
+
+ return 0;
+}
+
+
+static void
+usage( void )
+{
+ static const char* const format =
+ "%s %s: extract FreeType API names from header files\n"
+ "\n"
+ "This program extracts the list of public FreeType API functions.\n"
+ "It receives a list of header files as an argument and\n"
+ "generates a sorted list of unique identifiers in various formats.\n"
+ "\n"
+ "usage: %s header1 [options] [header2 ...]\n"
+ "\n"
+ "options: - parse the contents of stdin, ignore arguments\n"
+ " -v verbose mode, output sent to standard error\n"
+ " -oFILE write output to FILE instead of standard output\n"
+ " -dNAME indicate DLL file name, 'freetype.dll' by default\n"
+ " -w output .DEF file for Visual C++ and Mingw\n"
+ " -wB output .DEF file for Borland C++\n"
+ " -wW output Watcom Linker Response File\n"
+ " -wN output NetWare Import File\n"
+ " -wL output version map for GNU or Solaris linker\n"
+ "\n";
+
+ fprintf( stderr,
+ format,
+ PROGRAM_NAME,
+ PROGRAM_VERSION,
+ PROGRAM_NAME );
+
+ exit( 1 );
+}
+
+
+int
+main( int argc,
+ const char* const* argv )
+{
+ int from_stdin = 0;
+ int verbose = 0;
+ OutputFormat format = OUTPUT_LIST; /* the default */
+ FILE* out = stdout;
+ const char* library_name = NULL;
+
+
+ if ( argc < 2 )
+ usage();
+
+ /* `-' used as a single argument means read source file from stdin */
+ while ( argc > 1 && argv[1][0] == '-' )
+ {
+ const char* arg = argv[1];
+
+
+ switch ( arg[1] )
+ {
+ case 'v':
+ verbose = 1;
+
+ break;
+
+ case 'o':
+ if ( arg[2] == 0 )
+ {
+ if ( argc < 2 )
+ usage();
+
+ arg = argv[2];
+ argv++;
+ argc--;
+ }
+ else
+ arg += 2;
+
+ out = fopen( arg, "wt" );
+ if ( !out )
+ {
+ fprintf( stderr, "could not open '%s' for writing\n", arg );
+ exit( 3 );
+ }
+
+ break;
+
+ case 'd':
+ if ( arg[2] == 0 )
+ {
+ if ( argc < 2 )
+ usage();
+
+ arg = argv[2];
+ argv++;
+ argc--;
+ }
+ else
+ arg += 2;
+
+ library_name = arg;
+
+ break;
+
+ case 'w':
+ format = OUTPUT_WINDOWS_DEF;
+
+ switch ( arg[2] )
+ {
+ case 'B':
+ format = OUTPUT_BORLAND_DEF;
+ break;
+
+ case 'W':
+ format = OUTPUT_WATCOM_LBC;
+ break;
+
+ case 'N':
+ format = OUTPUT_NETWARE_IMP;
+ break;
+
+ case 'L':
+ format = OUTPUT_GNU_VERMAP;
+ break;
+
+ case 0:
+ break;
+
+ default:
+ usage();
+ }
+
+ break;
+
+ case 0:
+ from_stdin = 1;
+
+ break;
+
+ default:
+ usage();
+ }
+
+ argc--;
+ argv++;
+
+ } /* end of while loop */
+
+ if ( from_stdin )
+ read_header_file( stdin, verbose );
+ else
+ {
+ for ( --argc, argv++; argc > 0; argc--, argv++ )
+ {
+ FILE* file = fopen( argv[0], "rb" );
+
+
+ if ( !file )
+ fprintf( stderr, "unable to open '%s'\n", argv[0] );
+ else
+ {
+ if ( verbose )
+ fprintf( stderr, "opening '%s'\n", argv[0] );
+
+ read_header_file( file, verbose );
+ fclose( file );
+ }
+ }
+ }
+
+ if ( num_names == 0 )
+ panic( "could not find exported functions\n" );
+
+ names_sort();
+ names_dump( out, format, library_name );
+
+ if ( out != stdout )
+ fclose( out );
+
+ return 0;
+}
+
+
+/* END */
diff --git a/src/third_party/freetype2/src/tools/ftrandom/Makefile b/src/third_party/freetype2/src/tools/ftrandom/Makefile
new file mode 100644
index 0000000..24dc49c
--- /dev/null
+++ b/src/third_party/freetype2/src/tools/ftrandom/Makefile
@@ -0,0 +1,45 @@
+# TOP_DIR and OBJ_DIR should be set by the user to the right directories,
+# if necessary.
+
+TOP_DIR ?= ../../..
+OBJ_DIR ?= $(TOP_DIR)/objs
+
+
+# The setup below is for gcc on a Unix-like platform,
+# where FreeType has been set up to create a static library
+# (which is the default).
+
+VPATH = $(OBJ_DIR) \
+ $(OBJ_DIR)/.libs
+
+SRC_DIR = $(TOP_DIR)/src/tools/ftrandom
+
+CC = gcc
+WFLAGS = -Wmissing-prototypes \
+ -Wunused \
+ -Wimplicit \
+ -Wreturn-type \
+ -Wparentheses \
+ -pedantic \
+ -Wformat \
+ -Wchar-subscripts \
+ -Wsequence-point
+CFLAGS = $(WFLAGS) \
+ -g
+INCLUDES = -I $(TOP_DIR)/include
+LDFLAGS =
+LIBS = -lm \
+ -lz \
+ -lpng \
+ -lbz2 \
+ -lharfbuzz
+
+all: $(OBJ_DIR)/ftrandom
+
+$(OBJ_DIR)/ftrandom.o: $(SRC_DIR)/ftrandom.c
+ $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $<
+
+$(OBJ_DIR)/ftrandom: $(OBJ_DIR)/ftrandom.o libfreetype.a
+ $(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
+
+# EOF
diff --git a/src/third_party/freetype2/src/tools/ftrandom/README b/src/third_party/freetype2/src/tools/ftrandom/README
new file mode 100644
index 0000000..7c61086
--- /dev/null
+++ b/src/third_party/freetype2/src/tools/ftrandom/README
@@ -0,0 +1,69 @@
+ftrandom
+========
+
+This program expects a set of directories containing good fonts, and a set
+of extensions of fonts to be tested. It will randomly pick a font, copy it,
+introduce an error and then test it.
+
+The FreeType tests are quite basic; for each erroneous font ftrandom
+
+ . forks off a new tester,
+ . initializes the library,
+ . opens each font in the file,
+ . loads each glyph,
+ . optionally reviews the contours of the glyph,
+ . optionally rasterizes the glyph, and
+ . closes the face.
+
+If a tester takes longer than 20 seconds, ftrandom saves the erroneous font
+and continues. If the tester exits normally or with an error, then the
+superstructure removes the test font and continues.
+
+
+Command line options
+--------------------
+
+ --all Test every font in the directory(ies) no matter
+ what its extension.
+ --check-outlines Call `FT_Outline_Decompose' on each glyph.
+ --dir <dir> Append <dir> to the list of directories to search
+ for good fonts. No recursive search.
+ --error-count <cnt> Introduce <cnt> single-byte errors into the
+ erroneous fonts (default: 1).
+ --error-fraction <frac> Multiply the file size of the font by <frac> and
+ introduce that many errors into the erroneous
+ font file. <frac> should be in the range [0;1]
+ (default: 0.0).
+ --ext <ext> Add <ext> to the set of font types tested.
+ --help Print out this list of options.
+ --nohints Specify FT_LOAD_NO_HINTING when loading glyphs.
+ --rasterize Call `FT_Render_Glyph' as well as loading it.
+ --result <dir> This is the directory in which test files are
+ placed.
+ --test <file> Run a single test on a pre-generated testcase.
+ This is done in the current process so it can be
+ debugged more easily.
+
+The default font extensions tested by ftrandom are
+
+ .ttf .otf .ttc .cid .pfb .pfa .bdf .pcf .pfr .fon .otb .cff
+
+The default font directory is controlled by the macro `GOOD_FONTS_DIR' in
+the source code (and can be thus specified during compilation); its default
+value is
+
+ /usr/local/share/fonts
+
+The default result directory is `results' (in the current directory).
+
+
+Compilation
+-----------
+
+Two possible solutions.
+
+. Run ftrandom within a debugging tool like `valgrind' to catch various
+ memory issues.
+
+. Compile FreeType with sanitizer flags as provided by gcc or clang, for
+ example, then link it with ftrandom.
diff --git a/src/third_party/freetype2/src/tools/ftrandom/ftrandom.c b/src/third_party/freetype2/src/tools/ftrandom/ftrandom.c
new file mode 100644
index 0000000..ab5cfc9
--- /dev/null
+++ b/src/third_party/freetype2/src/tools/ftrandom/ftrandom.c
@@ -0,0 +1,720 @@
+/* Copyright (C) 2005, 2007, 2008, 2013 by George Williams */
+/*
+ * 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.
+
+ * The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+/* modified by Werner Lemberg <wl@gnu.org> */
+/* This file is now part of the FreeType library */
+
+
+#define _XOPEN_SOURCE 500 /* for `kill', `strdup', `random', and `srandom' */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <signal.h>
+#include <time.h>
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_OUTLINE_H
+
+#define true 1
+#define false 0
+#define forever for (;;)
+
+
+ static int check_outlines = false;
+ static int nohints = false;
+ static int rasterize = false;
+ static char* results_dir = "results";
+
+#define GOOD_FONTS_DIR "/usr/local/share/fonts"
+
+ static char* default_dir_list[] =
+ {
+ GOOD_FONTS_DIR,
+ NULL
+ };
+
+ static char* default_ext_list[] =
+ {
+ "ttf",
+ "otf",
+ "ttc",
+ "cid",
+ "pfb",
+ "pfa",
+ "bdf",
+ "pcf",
+ "pfr",
+ "fon",
+ "otb",
+ "cff",
+ NULL
+ };
+
+ static unsigned int error_count = 1;
+ static double error_fraction = 0.0;
+
+ static FT_F26Dot6 font_size = 12 * 64;
+
+ static struct fontlist
+ {
+ char* name;
+ long len;
+ unsigned int isbinary: 1;
+ unsigned int isascii: 1;
+ unsigned int ishex: 1;
+
+ } *fontlist;
+
+ static unsigned int fcnt;
+
+
+ static int
+ FT_MoveTo( const FT_Vector *to,
+ void *user )
+ {
+ FT_UNUSED( to );
+ FT_UNUSED( user );
+
+ return 0;
+ }
+
+
+ static int
+ FT_LineTo( const FT_Vector *to,
+ void *user )
+ {
+ FT_UNUSED( to );
+ FT_UNUSED( user );
+
+ return 0;
+ }
+
+
+ static int
+ FT_ConicTo( const FT_Vector *_cp,
+ const FT_Vector *to,
+ void *user )
+ {
+ FT_UNUSED( _cp );
+ FT_UNUSED( to );
+ FT_UNUSED( user );
+
+ return 0;
+ }
+
+
+ static int
+ FT_CubicTo( const FT_Vector *cp1,
+ const FT_Vector *cp2,
+ const FT_Vector *to,
+ void *user )
+ {
+ FT_UNUSED( cp1 );
+ FT_UNUSED( cp2 );
+ FT_UNUSED( to );
+ FT_UNUSED( user );
+
+ return 0;
+ }
+
+
+ static FT_Outline_Funcs outlinefuncs =
+ {
+ FT_MoveTo,
+ FT_LineTo,
+ FT_ConicTo,
+ FT_CubicTo,
+ 0, 0 /* No shift, no delta */
+ };
+
+
+ static void
+ TestFace( FT_Face face )
+ {
+ unsigned int gid;
+ int load_flags = FT_LOAD_DEFAULT;
+
+
+ if ( check_outlines &&
+ FT_IS_SCALABLE( face ) )
+ load_flags = FT_LOAD_NO_BITMAP;
+
+ if ( nohints )
+ load_flags |= FT_LOAD_NO_HINTING;
+
+ FT_Set_Char_Size( face, 0, font_size, 72, 72 );
+
+ for ( gid = 0; gid < face->num_glyphs; gid++ )
+ {
+ if ( check_outlines &&
+ FT_IS_SCALABLE( face ) )
+ {
+ if ( !FT_Load_Glyph( face, gid, load_flags ) )
+ FT_Outline_Decompose( &face->glyph->outline, &outlinefuncs, NULL );
+ }
+ else
+ FT_Load_Glyph( face, gid, load_flags );
+
+ if ( rasterize )
+ FT_Render_Glyph( face->glyph, ft_render_mode_normal );
+ }
+
+ FT_Done_Face( face );
+ }
+
+
+ static void
+ ExecuteTest( char* testfont )
+ {
+ FT_Library context;
+ FT_Face face;
+
+
+ if ( FT_Init_FreeType( &context ) )
+ {
+ fprintf( stderr, "Can't initialize FreeType.\n" );
+ exit( 1 );
+ }
+
+ if ( FT_New_Face( context, testfont, 0, &face ) )
+ {
+ /* The font is erroneous, so if this fails that's ok. */
+ exit( 0 );
+ }
+
+ if ( face->num_faces == 1 )
+ TestFace( face );
+ else
+ {
+ long i, num;
+
+
+ num = face->num_faces;
+ FT_Done_Face( face );
+
+ for ( i = 0; i < num; i++ )
+ {
+ if ( !FT_New_Face( context, testfont, i, &face ) )
+ TestFace( face );
+ }
+ }
+
+ FT_Done_FreeType( context );
+
+ exit( 0 );
+ }
+
+
+ static int
+ extmatch( char* filename,
+ char** extensions )
+ {
+ int i;
+ char* pt;
+
+
+ if ( !extensions )
+ return true;
+
+ pt = strrchr( filename, '.' );
+ if ( !pt )
+ return false;
+ if ( pt < strrchr( filename, '/' ) )
+ return false;
+
+ for ( i = 0; extensions[i] != NULL; i++ )
+ if ( strcasecmp( pt + 1, extensions[i] ) == 0 ||
+ strcasecmp( pt, extensions[i] ) == 0 )
+ return true;
+
+ return false;
+ }
+
+
+ static void
+ figurefiletype( struct fontlist* item )
+ {
+ FILE* foo;
+
+
+ item->isbinary = item->isascii = item->ishex = false;
+
+ foo = fopen( item->name, "rb" );
+ if ( foo )
+ {
+ /* Try to guess the file type from the first few characters... */
+ int ch1 = getc( foo );
+ int ch2 = getc( foo );
+ int ch3 = getc( foo );
+ int ch4 = getc( foo );
+
+
+ fclose( foo );
+
+ if ( ( ch1 == 0 && ch2 == 1 && ch3 == 0 && ch4 == 0 ) ||
+ ( ch1 == 'O' && ch2 == 'T' && ch3 == 'T' && ch4 == 'O' ) ||
+ ( ch1 == 't' && ch2 == 'r' && ch3 == 'u' && ch4 == 'e' ) ||
+ ( ch1 == 't' && ch2 == 't' && ch3 == 'c' && ch4 == 'f' ) )
+ {
+ /* ttf, otf, ttc files */
+ item->isbinary = true;
+ }
+ else if ( ch1 == 0x80 && ch2 == '\01' )
+ {
+ /* PFB header */
+ item->isbinary = true;
+ }
+ else if ( ch1 == '%' && ch2 == '!' )
+ {
+ /* Random PostScript */
+ if ( strstr( item->name, ".pfa" ) ||
+ strstr( item->name, ".PFA" ) )
+ item->ishex = true;
+ else
+ item->isascii = true;
+ }
+ else if ( ch1 == 1 && ch2 == 0 && ch3 == 4 )
+ {
+ /* Bare CFF */
+ item->isbinary = true;
+ }
+ else if ( ch1 == 'S' && ch2 == 'T' && ch3 == 'A' && ch4 == 'R' )
+ {
+ /* BDF */
+ item->ishex = true;
+ }
+ else if ( ch1 == 'P' && ch2 == 'F' && ch3 == 'R' && ch4 == '0' )
+ {
+ /* PFR */
+ item->isbinary = true;
+ }
+ else if ( ( ch1 == '\1' && ch2 == 'f' && ch3 == 'c' && ch4 == 'p' ) ||
+ ( ch1 == 'M' && ch2 == 'Z' ) )
+ {
+ /* Windows FON */
+ item->isbinary = true;
+ }
+ else
+ {
+ fprintf( stderr,
+ "Can't recognize file type of `%s', assuming binary\n",
+ item->name );
+ item->isbinary = true;
+ }
+ }
+ else
+ {
+ fprintf( stderr, "Can't open `%s' for typing the file.\n",
+ item->name );
+ item->isbinary = true;
+ }
+ }
+
+
+ static void
+ FindFonts( char** fontdirs,
+ char** extensions )
+ {
+ int i;
+ unsigned int max;
+ char buffer[1025];
+ struct stat statb;
+
+
+ max = 0;
+ fcnt = 0;
+
+ for ( i = 0; fontdirs[i] != NULL; i++ )
+ {
+ DIR* examples;
+ struct dirent* ent;
+
+
+ examples = opendir( fontdirs[i] );
+ if ( !examples )
+ {
+ fprintf( stderr,
+ "Can't open example font directory `%s'\n",
+ fontdirs[i] );
+ exit( 1 );
+ }
+
+ while ( ( ent = readdir( examples ) ) != NULL )
+ {
+ snprintf( buffer, sizeof ( buffer ),
+ "%s/%s", fontdirs[i], ent->d_name );
+ if ( stat( buffer, &statb ) == -1 || S_ISDIR( statb.st_mode ) )
+ continue;
+ if ( !extensions || extmatch( buffer, extensions ) )
+ {
+ if ( fcnt >= max )
+ {
+ max += 100;
+ fontlist = realloc( fontlist, max * sizeof ( struct fontlist ) );
+ if ( !fontlist )
+ {
+ fprintf( stderr, "Can't allocate memory\n" );
+ exit( 1 );
+ }
+ }
+
+ fontlist[fcnt].name = strdup( buffer );
+ fontlist[fcnt].len = statb.st_size;
+
+ figurefiletype( &fontlist[fcnt] );
+ fcnt++;
+ }
+ }
+
+ closedir( examples );
+ }
+
+ if ( fcnt == 0 )
+ {
+ fprintf( stderr, "Can't find matching font files.\n" );
+ exit( 1 );
+ }
+
+ fontlist[fcnt].name = NULL;
+ }
+
+
+ static unsigned int
+ getErrorCnt( struct fontlist* item )
+ {
+ if ( error_count == 0 && error_fraction == 0.0 )
+ return 0;
+
+ return error_count + (unsigned int)( error_fraction * item->len );
+ }
+
+
+ static int
+ getRandom( int low,
+ int high )
+ {
+ if ( low - high < 0x10000L )
+ return low + ( ( random() >> 8 ) % ( high + 1 - low ) );
+
+ return low + ( random() % ( high + 1 - low ) );
+ }
+
+
+ static int
+ copyfont( struct fontlist* item,
+ char* newfont )
+ {
+ static char buffer[8096];
+ FILE *good, *newf;
+ size_t len;
+ unsigned int i, err_cnt;
+
+
+ good = fopen( item->name, "r" );
+ if ( !good )
+ {
+ fprintf( stderr, "Can't open `%s'\n", item->name );
+ return false;
+ }
+
+ newf = fopen( newfont, "w+" );
+ if ( !newf )
+ {
+ fprintf( stderr, "Can't create temporary output file `%s'\n",
+ newfont );
+ exit( 1 );
+ }
+
+ while ( ( len = fread( buffer, 1, sizeof ( buffer ), good ) ) > 0 )
+ fwrite( buffer, 1, len, newf );
+
+ fclose( good );
+
+ err_cnt = getErrorCnt( item );
+ for ( i = 0; i < err_cnt; i++ )
+ {
+ fseek( newf, getRandom( 0, (int)( item->len - 1 ) ), SEEK_SET );
+
+ if ( item->isbinary )
+ putc( getRandom( 0, 0xFF ), newf );
+ else if ( item->isascii )
+ putc( getRandom( 0x20, 0x7E ), newf );
+ else
+ {
+ int hex = getRandom( 0, 15 );
+
+
+ if ( hex < 10 )
+ hex += '0';
+ else
+ hex += 'A' - 10;
+
+ putc( hex, newf );
+ }
+ }
+
+ if ( ferror( newf ) )
+ {
+ fclose( newf );
+ unlink( newfont );
+ return false;
+ }
+
+ fclose( newf );
+
+ return true;
+ }
+
+
+ static int child_pid;
+
+ static void
+ abort_test( int sig )
+ {
+ FT_UNUSED( sig );
+
+ /* If a time-out happens, then kill the child */
+ kill( child_pid, SIGFPE );
+ write( 2, "Timeout... ", 11 );
+ }
+
+
+ static void
+ do_test( void )
+ {
+ int i = getRandom( 0, (int)( fcnt - 1 ) );
+ static int test_num = 0;
+ char buffer[1024];
+
+
+ sprintf( buffer, "%s/test%d", results_dir, test_num++ );
+
+ if ( copyfont ( &fontlist[i], buffer ) )
+ {
+ signal( SIGALRM, abort_test );
+ /* Anything that takes more than 20 seconds */
+ /* to parse and/or rasterize is an error. */
+ alarm( 20 );
+ if ( ( child_pid = fork() ) == 0 )
+ ExecuteTest( buffer );
+ else if ( child_pid != -1 )
+ {
+ int status;
+
+
+ waitpid( child_pid, &status, 0 );
+ alarm( 0 );
+ if ( WIFSIGNALED ( status ) )
+ printf( "Error found in file `%s'\n", buffer );
+ else
+ unlink( buffer );
+ }
+ else
+ {
+ fprintf( stderr, "Can't fork test case.\n" );
+ exit( 1 );
+ }
+ alarm( 0 );
+ }
+ }
+
+
+ static void
+ usage( FILE* out,
+ char* name )
+ {
+ char** d = default_dir_list;
+ char** e = default_ext_list;
+
+
+ fprintf( out, "%s [options] -- Generate random erroneous fonts\n"
+ " and attempt to parse them with FreeType.\n\n", name );
+
+ fprintf( out, " --all All non-directory files are assumed to be fonts.\n" );
+ fprintf( out, " --check-outlines Make sure we can parse the outlines of each glyph.\n" );
+ fprintf( out, " --dir <path> Append <path> to list of font search directories\n"
+ " (no recursive search).\n" );
+ fprintf( out, " --error-count <cnt> Introduce <cnt> single byte errors into each font\n"
+ " (default: 1)\n" );
+ fprintf( out, " --error-fraction <frac> Introduce <frac>*filesize single byte errors\n"
+ " into each font (default: 0.0).\n" );
+ fprintf( out, " --ext <ext> Add <ext> to list of extensions indicating fonts.\n" );
+ fprintf( out, " --help Print this.\n" );
+ fprintf( out, " --nohints Turn off hinting.\n" );
+ fprintf( out, " --rasterize Attempt to rasterize each glyph.\n" );
+ fprintf( out, " --results <path> Place the created test fonts into <path>\n"
+ " (default: `results')\n" );
+ fprintf( out, " --size <float> Use the given font size for the tests.\n" );
+ fprintf( out, " --test <file> Run a single test on an already existing file.\n" );
+ fprintf( out, "\n" );
+
+ fprintf( out, "Default font extensions:\n" );
+ fprintf( out, " " );
+ while ( *e )
+ fprintf( out, " .%s", *e++ );
+ fprintf( out, "\n" );
+
+ fprintf( out, "Default font directories:\n" );
+ fprintf( out, " " );
+ while ( *d )
+ fprintf( out, " %s", *d++ );
+ fprintf( out, "\n" );
+ }
+
+
+ int
+ main( int argc,
+ char** argv )
+ {
+ char **dirs, **exts;
+ int dcnt = 0, ecnt = 0, rset = false, allexts = false;
+ int i;
+ time_t now;
+ char* testfile = NULL;
+
+
+ dirs = calloc( (size_t)( argc + 1 ), sizeof ( char ** ) );
+ exts = calloc( (size_t)( argc + 1 ), sizeof ( char ** ) );
+
+ for ( i = 1; i < argc; i++ )
+ {
+ char* pt = argv[i];
+ char* end;
+
+
+ if ( pt[0] == '-' && pt[1] == '-' )
+ pt++;
+
+ if ( strcmp( pt, "-all" ) == 0 )
+ allexts = true;
+ else if ( strcmp( pt, "-check-outlines" ) == 0 )
+ check_outlines = true;
+ else if ( strcmp( pt, "-dir" ) == 0 )
+ dirs[dcnt++] = argv[++i];
+ else if ( strcmp( pt, "-error-count" ) == 0 )
+ {
+ if ( !rset )
+ error_fraction = 0.0;
+ rset = true;
+ error_count = (unsigned int)strtoul( argv[++i], &end, 10 );
+ if ( *end != '\0' )
+ {
+ fprintf( stderr, "Bad value for error-count: %s\n", argv[i] );
+ exit( 1 );
+ }
+ }
+ else if ( strcmp( pt, "-error-fraction" ) == 0 )
+ {
+ if ( !rset )
+ error_count = 0;
+ rset = true;
+ error_fraction = strtod( argv[++i], &end );
+ if ( *end != '\0' )
+ {
+ fprintf( stderr, "Bad value for error-fraction: %s\n", argv[i] );
+ exit( 1 );
+ }
+ if ( error_fraction < 0.0 || error_fraction > 1.0 )
+ {
+ fprintf( stderr, "error-fraction must be in the range [0;1]\n" );
+ exit( 1 );
+ }
+ }
+ else if ( strcmp( pt, "-ext" ) == 0 )
+ exts[ecnt++] = argv[++i];
+ else if ( strcmp( pt, "-help" ) == 0 )
+ {
+ usage( stdout, argv[0] );
+ exit( 0 );
+ }
+ else if ( strcmp( pt, "-nohints" ) == 0 )
+ nohints = true;
+ else if ( strcmp( pt, "-rasterize" ) == 0 )
+ rasterize = true;
+ else if ( strcmp( pt, "-results" ) == 0 )
+ results_dir = argv[++i];
+ else if ( strcmp( pt, "-size" ) == 0 )
+ {
+ font_size = (FT_F26Dot6)( strtod( argv[++i], &end ) * 64 );
+ if ( *end != '\0' || font_size < 64 )
+ {
+ fprintf( stderr, "Bad value for size: %s\n", argv[i] );
+ exit( 1 );
+ }
+ }
+ else if ( strcmp( pt, "-test" ) == 0 )
+ testfile = argv[++i];
+ else
+ {
+ usage( stderr, argv[0] );
+ exit( 1 );
+ }
+ }
+
+ if ( allexts )
+ {
+ free( exts );
+ exts = NULL;
+ }
+ else if ( ecnt == 0 )
+ {
+ free( exts );
+ exts = default_ext_list;
+ }
+
+ if ( dcnt == 0 )
+ {
+ free( dirs );
+ dirs = default_dir_list;
+ }
+
+ if ( testfile )
+ ExecuteTest( testfile ); /* This should never return */
+
+ time( &now );
+ srandom( (unsigned int)now );
+
+ FindFonts( dirs, exts );
+ mkdir( results_dir, 0755 );
+
+ forever
+ do_test();
+
+ return 0;
+ }
+
+
+/* EOF */
diff --git a/src/third_party/freetype2/src/tools/no-copyright b/src/third_party/freetype2/src/tools/no-copyright
new file mode 100644
index 0000000..d639aa4
--- /dev/null
+++ b/src/third_party/freetype2/src/tools/no-copyright
@@ -0,0 +1,65 @@
+# Files that don't get a copyright, or which are taken from elsewhere.
+#
+# All lines in this file are patterns, including the comment lines; this
+# means that e.g. `FTL.TXT' matches all files that have this string in
+# the file name (including the path relative to the current directory,
+# always starting with `./').
+#
+# Don't put empty lines into this file!
+#
+.gitignore
+#
+builds/unix/pkg.m4
+#
+docs/FTL.TXT
+docs/GPLv2.TXT
+#
+include/freetype/internal/fthash.h
+#
+src/base/fthash.c
+src/base/md5.c
+src/base/md5.h
+#
+src/bdf/bdf.c
+src/bdf/bdf.h
+src/bdf/bdfdrivr.c
+src/bdf/bdfdrivr.h
+src/bdf/bdferror.h
+src/bdf/bdflib.c
+src/bdf/module.mk
+src/bdf/README
+src/bdf/rules.mk
+#
+src/pcf/module.mk
+src/pcf/pcf.c
+src/pcf/pcf.h
+src/pcf/pcfdrivr.c
+src/pcf/pcfdrivr.h
+src/pcf/pcferror.h
+src/pcf/pcfread.c
+src/pcf/pcfread.h
+src/pcf/pcfutil.c
+src/pcf/pcfutil.h
+src/pcf/README
+src/pcf/rules.mk
+#
+src/gzip/adler32.c
+src/gzip/infblock.c
+src/gzip/infblock.h
+src/gzip/infcodes.c
+src/gzip/infcodes.h
+src/gzip/inffixed.h
+src/gzip/inflate.c
+src/gzip/inftrees.c
+src/gzip/inftrees.h
+src/gzip/infutil.c
+src/gzip/infutil.h
+src/gzip/zconf.h
+src/gzip/zlib.h
+src/gzip/zutil.c
+src/gzip/zutil.h
+#
+src/tools/apinames.c
+src/tools/ftrandom/ftrandom.c
+#
+# EOF
diff --git a/src/third_party/freetype2/src/tools/test_afm.c b/src/third_party/freetype2/src/tools/test_afm.c
new file mode 100644
index 0000000..8de619b
--- /dev/null
+++ b/src/third_party/freetype2/src/tools/test_afm.c
@@ -0,0 +1,157 @@
+/*
+ * gcc -DFT2_BUILD_LIBRARY -I../../include -o test_afm test_afm.c \
+ * -L../../objs/.libs -lfreetype -lz -static
+ */
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_INTERNAL_STREAM_H
+#include FT_INTERNAL_POSTSCRIPT_AUX_H
+
+ void dump_fontinfo( AFM_FontInfo fi )
+ {
+ FT_UInt i;
+
+
+ printf( "This AFM is for %sCID font.\n\n",
+ ( fi->IsCIDFont ) ? "" : "non-" );
+
+ printf( "FontBBox: %.2f %.2f %.2f %.2f\n", fi->FontBBox.xMin / 65536.,
+ fi->FontBBox.yMin / 65536.,
+ fi->FontBBox.xMax / 65536.,
+ fi->FontBBox.yMax / 65536. );
+ printf( "Ascender: %.2f\n", fi->Ascender / 65536. );
+ printf( "Descender: %.2f\n\n", fi->Descender / 65536. );
+
+ if ( fi->NumTrackKern )
+ printf( "There are %d sets of track kernings:\n",
+ fi->NumTrackKern );
+ else
+ printf( "There is no track kerning.\n" );
+
+ for ( i = 0; i < fi->NumTrackKern; i++ )
+ {
+ AFM_TrackKern tk = fi->TrackKerns + i;
+
+
+ printf( "\t%2d: %5.2f %5.2f %5.2f %5.2f\n", tk->degree,
+ tk->min_ptsize / 65536.,
+ tk->min_kern / 65536.,
+ tk->max_ptsize / 65536.,
+ tk->max_kern / 65536. );
+ }
+
+ printf( "\n" );
+
+ if ( fi->NumKernPair )
+ printf( "There are %d kerning pairs:\n",
+ fi->NumKernPair );
+ else
+ printf( "There is no kerning pair.\n" );
+
+ for ( i = 0; i < fi->NumKernPair; i++ )
+ {
+ AFM_KernPair kp = fi->KernPairs + i;
+
+
+ printf( "\t%3d + %3d => (%4d, %4d)\n", kp->index1,
+ kp->index2,
+ kp->x,
+ kp->y );
+ }
+
+ }
+
+ int
+ dummy_get_index( const char* name,
+ FT_Offset len,
+ void* user_data )
+ {
+ if ( len )
+ return name[0];
+ else
+ return 0;
+ }
+
+ FT_Error
+ parse_afm( FT_Library library,
+ FT_Stream stream,
+ AFM_FontInfo fi )
+ {
+ PSAux_Service psaux;
+ AFM_ParserRec parser;
+ FT_Error error = FT_Err_Ok;
+
+
+ psaux = (PSAux_Service)FT_Get_Module_Interface( library, "psaux" );
+ if ( !psaux || !psaux->afm_parser_funcs )
+ return -1;
+
+ error = FT_Stream_EnterFrame( stream, stream->size );
+ if ( error )
+ return error;
+
+ error = psaux->afm_parser_funcs->init( &parser,
+ library->memory,
+ stream->cursor,
+ stream->limit );
+ if ( error )
+ return error;
+
+ parser.FontInfo = fi;
+ parser.get_index = dummy_get_index;
+
+ error = psaux->afm_parser_funcs->parse( &parser );
+
+ psaux->afm_parser_funcs->done( &parser );
+
+ return error;
+ }
+
+
+ int main( int argc,
+ char** argv )
+ {
+ FT_Library library;
+ FT_StreamRec stream;
+ FT_Error error = FT_Err_Ok;
+ AFM_FontInfoRec fi;
+
+
+ if ( argc < 2 )
+ return FT_ERR( Invalid_Argument );
+
+ error = FT_Init_FreeType( &library );
+ if ( error )
+ return error;
+
+ FT_ZERO( &stream );
+ error = FT_Stream_Open( &stream, argv[1] );
+ if ( error )
+ goto Exit;
+ stream.memory = library->memory;
+
+ FT_ZERO( &fi );
+ error = parse_afm( library, &stream, &fi );
+
+ if ( !error )
+ {
+ FT_Memory memory = library->memory;
+
+
+ dump_fontinfo( &fi );
+
+ if ( fi.KernPairs )
+ FT_FREE( fi.KernPairs );
+ if ( fi.TrackKerns )
+ FT_FREE( fi.TrackKerns );
+ }
+ else
+ printf( "parse error\n" );
+
+ FT_Stream_Close( &stream );
+
+ Exit:
+ FT_Done_FreeType( library );
+
+ return error;
+ }
diff --git a/src/third_party/freetype2/src/tools/test_bbox.c b/src/third_party/freetype2/src/tools/test_bbox.c
new file mode 100644
index 0000000..64b82c3
--- /dev/null
+++ b/src/third_party/freetype2/src/tools/test_bbox.c
@@ -0,0 +1,188 @@
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_BBOX_H
+
+
+#include <time.h> /* for clock() */
+
+/* SunOS 4.1.* does not define CLOCKS_PER_SEC, so include <sys/param.h> */
+/* to get the HZ macro which is the equivalent. */
+#if defined(__sun__) && !defined(SVR4) && !defined(__SVR4)
+#include <sys/param.h>
+#define CLOCKS_PER_SEC HZ
+#endif
+
+ static long
+ get_time( void )
+ {
+ return clock() * 10000L / CLOCKS_PER_SEC;
+ }
+
+
+
+
+ /* test bbox computations */
+
+#define XSCALE 65536
+#define XX(x) ((FT_Pos)(x*XSCALE))
+#define XVEC(x,y) { XX(x), XX(y) }
+#define XVAL(x) ((x)/(1.0*XSCALE))
+
+ /* dummy outline #1 */
+ static FT_Vector dummy_vec_1[4] =
+ {
+#if 1
+ XVEC( 408.9111, 535.3164 ),
+ XVEC( 455.8887, 634.396 ),
+ XVEC( -37.8765, 786.2207 ),
+ XVEC( 164.6074, 535.3164 )
+#else
+ { (FT_Int32)0x0198E93DL , (FT_Int32)0x021750FFL }, /* 408.9111, 535.3164 */
+ { (FT_Int32)0x01C7E312L , (FT_Int32)0x027A6560L }, /* 455.8887, 634.3960 */
+ { (FT_Int32)0xFFDA1F9EL , (FT_Int32)0x0312387FL }, /* -37.8765, 786.2207 */
+ { (FT_Int32)0x00A49B7EL , (FT_Int32)0x021750FFL } /* 164.6074, 535.3164 */
+#endif
+ };
+
+ static char dummy_tag_1[4] =
+ {
+ FT_CURVE_TAG_ON,
+ FT_CURVE_TAG_CUBIC,
+ FT_CURVE_TAG_CUBIC,
+ FT_CURVE_TAG_ON
+ };
+
+ static short dummy_contour_1[1] =
+ {
+ 3
+ };
+
+ static FT_Outline dummy_outline_1 =
+ {
+ 1,
+ 4,
+ dummy_vec_1,
+ dummy_tag_1,
+ dummy_contour_1,
+ 0
+ };
+
+
+ /* dummy outline #2 */
+ static FT_Vector dummy_vec_2[4] =
+ {
+ XVEC( 100.0, 100.0 ),
+ XVEC( 100.0, 200.0 ),
+ XVEC( 200.0, 200.0 ),
+ XVEC( 200.0, 133.0 )
+ };
+
+ static FT_Outline dummy_outline_2 =
+ {
+ 1,
+ 4,
+ dummy_vec_2,
+ dummy_tag_1,
+ dummy_contour_1,
+ 0
+ };
+
+
+ /* dummy outline #3 with bbox of [0 100 128 128] precisely */
+ static FT_Vector dummy_vec_3[4] =
+ {
+ XVEC( 100.0, 127.0 ),
+ XVEC( 200.0, 127.0 ),
+ XVEC( 0.0, 136.0 ),
+ XVEC( 0.0, 100.0 )
+ };
+
+ static FT_Outline dummy_outline_3 =
+ {
+ 1,
+ 4,
+ dummy_vec_3,
+ dummy_tag_1,
+ dummy_contour_1,
+ 0
+ };
+
+
+ static void
+ dump_outline( FT_Outline* outline )
+ {
+ FT_BBox bbox;
+
+ /* compute and display cbox */
+ FT_Outline_Get_CBox( outline, &bbox );
+ printf( "cbox = [%.2f %.2f %.2f %.2f]\n",
+ XVAL( bbox.xMin ),
+ XVAL( bbox.yMin ),
+ XVAL( bbox.xMax ),
+ XVAL( bbox.yMax ) );
+
+ /* compute and display bbox */
+ FT_Outline_Get_BBox( outline, &bbox );
+ printf( "bbox = [%.2f %.2f %.2f %.2f]\n",
+ XVAL( bbox.xMin ),
+ XVAL( bbox.yMin ),
+ XVAL( bbox.xMax ),
+ XVAL( bbox.yMax ) );
+ }
+
+
+
+ static void
+ profile_outline( FT_Outline* outline,
+ long repeat )
+ {
+ FT_BBox bbox;
+ long count;
+ long time0;
+
+ time0 = get_time();
+ for ( count = repeat; count > 0; count-- )
+ FT_Outline_Get_CBox( outline, &bbox );
+
+ time0 = get_time() - time0;
+ printf( "time = %6.3f cbox = [%8.4f %8.4f %8.4f %8.4f]\n",
+ ((double)time0/10000.0),
+ XVAL( bbox.xMin ),
+ XVAL( bbox.yMin ),
+ XVAL( bbox.xMax ),
+ XVAL( bbox.yMax ) );
+ printf( "cbox_hex = [%08X %08X %08X %08X]\n",
+ bbox.xMin, bbox.yMin, bbox.xMax, bbox.yMax );
+
+
+ time0 = get_time();
+ for ( count = repeat; count > 0; count-- )
+ FT_Outline_Get_BBox( outline, &bbox );
+
+ time0 = get_time() - time0;
+ printf( "time = %6.3f bbox = [%8.4f %8.4f %8.4f %8.4f]\n",
+ ((double)time0/10000.0),
+ XVAL( bbox.xMin ),
+ XVAL( bbox.yMin ),
+ XVAL( bbox.xMax ),
+ XVAL( bbox.yMax ) );
+ printf( "bbox_hex = [%08X %08X %08X %08X]\n",
+ bbox.xMin, bbox.yMin, bbox.xMax, bbox.yMax );
+ }
+
+#define REPEAT 1000000L
+
+ int main( int argc, char** argv )
+ {
+ printf( "outline #1\n" );
+ profile_outline( &dummy_outline_1, REPEAT );
+
+ printf( "outline #2\n" );
+ profile_outline( &dummy_outline_2, REPEAT );
+
+ printf( "outline #3\n" );
+ profile_outline( &dummy_outline_3, REPEAT );
+
+ return 0;
+ }
+
diff --git a/src/third_party/freetype2/src/tools/test_trig.c b/src/third_party/freetype2/src/tools/test_trig.c
new file mode 100644
index 0000000..99ac1cf
--- /dev/null
+++ b/src/third_party/freetype2/src/tools/test_trig.c
@@ -0,0 +1,258 @@
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_TRIGONOMETRY_H
+
+#include <math.h>
+#include <stdio.h>
+
+#define PI 3.14159265358979323846
+#define SPI (PI/FT_ANGLE_PI)
+
+/* the precision in 16.16 fixed-point checks. Expect between 2 and 5 */
+/* noise LSB bits during operations, due to rounding errors.. */
+#define THRESHOLD 64
+
+ static error = 0;
+
+ static void
+ test_cos( void )
+ {
+ int i;
+
+
+ for ( i = 0; i < FT_ANGLE_2PI; i += 0x10000L )
+ {
+ FT_Fixed f1, f2;
+ double d2;
+
+
+ f1 = FT_Cos(i);
+ d2 = cos( i*SPI );
+ f2 = (FT_Fixed)(d2*65536.0);
+
+ if ( abs( f2-f1 ) > THRESHOLD )
+ {
+ error = 1;
+ printf( "FT_Cos[%3d] = %.7f cos[%3d] = %.7f\n",
+ (i >> 16), f1/65536.0, (i >> 16), d2 );
+ }
+ }
+ }
+
+
+ static void
+ test_sin( void )
+ {
+ int i;
+
+
+ for ( i = 0; i < FT_ANGLE_2PI; i += 0x10000L )
+ {
+ FT_Fixed f1, f2;
+ double d2;
+
+
+ f1 = FT_Sin(i);
+ d2 = sin( i*SPI );
+ f2 = (FT_Fixed)(d2*65536.0);
+
+ if ( abs( f2-f1 ) > THRESHOLD )
+ {
+ error = 1;
+ printf( "FT_Sin[%3d] = %.7f sin[%3d] = %.7f\n",
+ (i >> 16), f1/65536.0, (i >> 16), d2 );
+ }
+ }
+ }
+
+
+ static void
+ test_tan( void )
+ {
+ int i;
+
+
+ for ( i = 0; i < FT_ANGLE_PI2 - 0x2000000L; i += 0x10000L )
+ {
+ FT_Fixed f1, f2;
+ double d2;
+
+
+ f1 = FT_Tan(i);
+ d2 = tan( i*SPI );
+ f2 = (FT_Fixed)(d2*65536.0);
+
+ if ( abs( f2-f1 ) > THRESHOLD )
+ {
+ error = 1;
+ printf( "FT_Tan[%3d] = %.7f tan[%3d] = %.7f\n",
+ (i >> 16), f1/65536.0, (i >> 16), d2 );
+ }
+ }
+ }
+
+
+ static void
+ test_atan2( void )
+ {
+ int i;
+
+
+ for ( i = 0; i < FT_ANGLE_2PI; i += 0x10000L )
+ {
+ FT_Fixed c2, s2;
+ double l, a, c1, s1;
+ int j;
+
+
+ l = 5.0;
+ a = i*SPI;
+
+ c1 = l * cos(a);
+ s1 = l * sin(a);
+
+ c2 = (FT_Fixed)(c1*65536.0);
+ s2 = (FT_Fixed)(s1*65536.0);
+
+ j = FT_Atan2( c2, s2 );
+ if ( j < 0 )
+ j += FT_ANGLE_2PI;
+
+ if ( abs( i - j ) > 1 )
+ {
+ printf( "FT_Atan2( %.7f, %.7f ) = %.5f, atan = %.5f\n",
+ c2/65536.0, s2/65536.0, j/65536.0, i/65536.0 );
+ }
+ }
+ }
+
+
+ static void
+ test_unit( void )
+ {
+ int i;
+
+
+ for ( i = 0; i < FT_ANGLE_2PI; i += 0x10000L )
+ {
+ FT_Vector v;
+ double a, c1, s1;
+ FT_Fixed c2, s2;
+
+
+ FT_Vector_Unit( &v, i );
+ a = ( i*SPI );
+ c1 = cos(a);
+ s1 = sin(a);
+ c2 = (FT_Fixed)(c1*65536.0);
+ s2 = (FT_Fixed)(s1*65536.0);
+
+ if ( abs( v.x-c2 ) > THRESHOLD ||
+ abs( v.y-s2 ) > THRESHOLD )
+ {
+ error = 1;
+ printf( "FT_Vector_Unit[%3d] = ( %.7f, %.7f ) vec = ( %.7f, %.7f )\n",
+ (i >> 16),
+ v.x/65536.0, v.y/65536.0,
+ c1, s1 );
+ }
+ }
+ }
+
+
+ static void
+ test_length( void )
+ {
+ int i;
+
+
+ for ( i = 0; i < FT_ANGLE_2PI; i += 0x10000L )
+ {
+ FT_Vector v;
+ FT_Fixed l, l2;
+
+
+ l = (FT_Fixed)(500.0*65536.0);
+ v.x = (FT_Fixed)( l * cos( i*SPI ) );
+ v.y = (FT_Fixed)( l * sin( i*SPI ) );
+ l2 = FT_Vector_Length( &v );
+
+ if ( abs( l2-l ) > THRESHOLD )
+ {
+ error = 1;
+ printf( "FT_Length( %.7f, %.7f ) = %.5f, length = %.5f\n",
+ v.x/65536.0, v.y/65536.0, l2/65536.0, l/65536.0 );
+ }
+ }
+ }
+
+
+ static void
+ test_rotate( void )
+ {
+ int rotate;
+
+
+ for ( rotate = 0; rotate < FT_ANGLE_2PI; rotate += 0x10000L )
+ {
+ double ra, cra, sra;
+ int i;
+
+
+ ra = rotate*SPI;
+ cra = cos( ra );
+ sra = sin( ra );
+
+ for ( i = 0; i < FT_ANGLE_2PI; i += 0x10000L )
+ {
+ FT_Fixed c2, s2, c4, s4;
+ FT_Vector v;
+ double l, a, c1, s1, c3, s3;
+
+
+ l = 500.0;
+ a = i*SPI;
+
+ c1 = l * cos(a);
+ s1 = l * sin(a);
+
+ v.x = c2 = (FT_Fixed)(c1*65536.0);
+ v.y = s2 = (FT_Fixed)(s1*65536.0);
+
+ FT_Vector_Rotate( &v, rotate );
+
+ c3 = c1 * cra - s1 * sra;
+ s3 = c1 * sra + s1 * cra;
+
+ c4 = (FT_Fixed)(c3*65536.0);
+ s4 = (FT_Fixed)(s3*65536.0);
+
+ if ( abs( c4 - v.x ) > THRESHOLD ||
+ abs( s4 - v.y ) > THRESHOLD )
+ {
+ error = 1;
+ printf( "FT_Rotate( (%.7f,%.7f), %.5f ) = ( %.7f, %.7f ), rot = ( %.7f, %.7f )\n",
+ c1, s1, ra,
+ c2/65536.0, s2/65536.0,
+ c4/65536.0, s4/65536.0 );
+ }
+ }
+ }
+ }
+
+
+ int main( void )
+ {
+ test_cos();
+ test_sin();
+ test_tan();
+ test_atan2();
+ test_unit();
+ test_length();
+ test_rotate();
+
+ if (!error)
+ printf( "trigonometry test ok !\n" );
+
+ return !error;
+ }
diff --git a/src/third_party/freetype2/src/tools/update-copyright b/src/third_party/freetype2/src/tools/update-copyright
new file mode 100755
index 0000000..4a8bf9b
--- /dev/null
+++ b/src/third_party/freetype2/src/tools/update-copyright
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+# Run the `update-copyright-year' script on all files in the git repository,
+# taking care of exceptions stored in file `no-copyright'.
+
+topdir=`git rev-parse --show-toplevel`
+toolsdir=$topdir/src/tools
+
+git ls-files --full-name $topdir \
+| sed 's|^|../../|' \
+| grep -vFf $toolsdir/no-copyright \
+| xargs $toolsdir/update-copyright-year
+
+# EOF
diff --git a/src/third_party/freetype2/src/tools/update-copyright-year b/src/third_party/freetype2/src/tools/update-copyright-year
new file mode 100755
index 0000000..c659bba
--- /dev/null
+++ b/src/third_party/freetype2/src/tools/update-copyright-year
@@ -0,0 +1,138 @@
+eval '(exit $?0)' && eval 'exec perl -wS -i "$0" ${1+"$@"}'
+ & eval 'exec perl -wS -i "$0" $argv:q'
+ if 0;
+
+# Copyright (C) 2015-2020 by
+# Werner Lemberg.
+#
+# This file is part of the FreeType project, and may only be used, modified,
+# and distributed under the terms of the FreeType project license,
+# LICENSE.TXT. By continuing to use, modify, or distribute this file you
+# indicate that you have read the license and understand and accept it
+# fully.
+
+# [Note: This script is expected to be called by the shell, which in turn
+# calls perl automatically. The nifty start-up code above is based on
+# gnulib's `update-copyright' script; it is a more portable replacement for
+# the shebang, using the first `perl' program in the shell's path instead.]
+
+# Usage:
+#
+# update-copyright-year file1 [file2 ...]
+
+
+# This script handles copyright entries like
+#
+# Copyright 2000 by
+# foobar
+#
+# or
+#
+# /* Copyright 2000, 2001, 2004-2007 by */
+# /* foobar */
+#
+# and replaces them uniformly with
+#
+# Copyright 2000-2015
+# foobar
+#
+# and
+#
+# /* Copyright 2000-2015 by */
+# /* foobar */
+#
+# (assuming that the current year is 2015). As can be seen, the line length
+# is retained if there is non-whitespace after the word `by' on the same
+# line.
+
+use strict;
+
+
+my (undef, undef, undef,
+ undef, undef, $year,
+ undef, undef, undef) = localtime(time);
+$year += 1900;
+
+my $replaced = 0;
+
+
+# Loop over all input files; option `-i' (issued at the very beginning of
+# this script) makes perl edit them in-place.
+while (<>)
+{
+ # Only handle the first copyright notice in a file.
+ if (!$replaced)
+ {
+ # First try: Search multiple copyright years.
+ s {
+ (?<begin>.*)
+ Copyright
+ (?<space1>(\ +
+ | \ +\(C\)\ +))
+ (?<first>[12][0-9][0-9][0-9])
+ (?<middle>.+)
+ (?<last>[12][0-9][0-9][0-9])
+ (?<space2>\ +)
+ by
+ (?<space3>\ *)
+ (?<end>.*)
+ }
+ {
+ # Fill line to the same length (if appropriate); we skip the middle
+ # part but insert `(C)', three spaces, and `-'.
+ my $space = length($+{space1}) - 1
+ + length($+{middle}) - 1
+ + length($+{space2}) - 1
+ + length($+{space3})
+ - (length("(C)") + 1);
+
+ print "$+{begin}";
+ print "Copyright\ (C)\ $+{first}-$year\ by";
+ print ' ' x $space if length($+{end});
+ print "$+{end}\n";
+ $replaced = 1;
+ }ex
+ ||
+ # Second try: Search a single copyright year.
+ s {
+ (?<begin>.*)
+ Copyright
+ (?<space1>(\ +
+ | \ +\(C\)\ +))
+ (?<first>[12][0-9][0-9][0-9])
+ (?<space2>\ +)
+ by
+ (?<space3>\ *)
+ (?<end>.*)
+ }
+ {
+ # Fill line to the same length (if appropriate); we insert three
+ # spaces, a `-', and the current year.
+ my $space = length($+{space1}) - 1
+ + length($+{space2}) - 1
+ + length($+{space3})
+ - (length($year) + 1);
+
+ print "$+{begin}";
+ print "Copyright\ (C)\ $+{first}-$year\ by";
+ # If $space is negative this inserts nothing.
+ print ' ' x $space if length($+{end});
+ print "$+{end}\n";
+ $replaced = 1;
+ }ex
+ ||
+ # Otherwise print line unaltered.
+ print;
+ }
+ else
+ {
+ print;
+ }
+}
+continue
+{
+ # Reset $replaced before processing the next file.
+ $replaced = 0 if eof;
+}
+
+# EOF
diff --git a/src/third_party/inspector_protocol/crdtp/json_platform.cc b/src/third_party/inspector_protocol/crdtp/json_platform.cc
index 59c8deb..21e26ce 100644
--- a/src/third_party/inspector_protocol/crdtp/json_platform.cc
+++ b/src/third_party/inspector_protocol/crdtp/json_platform.cc
@@ -16,6 +16,9 @@
namespace json {
namespace platform {
bool StrToD(const char* str, double* result) {
+#if SB_IS(EVERGREEN)
+#error "The std::locale::classic() is not supported for Evergreen. Please use base::StringToDouble()."
+#endif
std::istringstream is(str);
is.imbue(std::locale::classic());
is >> *result;
@@ -23,6 +26,9 @@
}
std::string DToStr(double value) {
+#if SB_IS(EVERGREEN)
+#error "The std::locale::classic() is not supported for Evergreen. Please use base::NumberToString()."
+#endif
std::stringstream ss;
ss.imbue(std::locale::classic());
ss << value;
diff --git a/src/third_party/libevent/evdns.c b/src/third_party/libevent/evdns.c
index 05fe594..d72fdaa 100644
--- a/src/third_party/libevent/evdns.c
+++ b/src/third_party/libevent/evdns.c
@@ -783,7 +783,6 @@
for(;;) {
u8 label_len;
- if (j >= length) return -1;
GET8(label_len);
if (!label_len) break;
if (label_len & 0xc0) {
@@ -804,6 +803,7 @@
*cp++ = '.';
}
if (cp + label_len >= end) return -1;
+ if (j + label_len > length) return -1;
memcpy(cp, packet + j, label_len);
cp += label_len;
j += label_len;
diff --git a/src/third_party/libxml/src/entities.c b/src/third_party/libxml/src/entities.c
index ea54cc3..4b41fe9 100644
--- a/src/third_party/libxml/src/entities.c
+++ b/src/third_party/libxml/src/entities.c
@@ -667,11 +667,25 @@
} else {
/*
* We assume we have UTF-8 input.
+ * It must match either:
+ * 110xxxxx 10xxxxxx
+ * 1110xxxx 10xxxxxx 10xxxxxx
+ * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+ * That is:
+ * cur[0] is 11xxxxxx
+ * cur[1] is 10xxxxxx
+ * cur[2] is 10xxxxxx if cur[0] is 111xxxxx
+ * cur[3] is 10xxxxxx if cur[0] is 1111xxxx
+ * cur[0] is not 11111xxx
*/
char buf[11], *ptr;
int val = 0, l = 1;
- if (*cur < 0xC0) {
+ if (((cur[0] & 0xC0) != 0xC0) ||
+ ((cur[1] & 0xC0) != 0x80) ||
+ (((cur[0] & 0xE0) == 0xE0) && ((cur[2] & 0xC0) != 0x80)) ||
+ (((cur[0] & 0xF0) == 0xF0) && ((cur[3] & 0xC0) != 0x80)) ||
+ (((cur[0] & 0xF8) == 0xF8))) {
xmlEntitiesErr(XML_CHECK_NOT_UTF8,
"xmlEncodeEntities: input not UTF-8");
if (doc != NULL)
diff --git a/src/third_party/skia/src/sksl/SkSLString.cpp b/src/third_party/skia/src/sksl/SkSLString.cpp
index 433744a..c8124da 100644
--- a/src/third_party/skia/src/sksl/SkSLString.cpp
+++ b/src/third_party/skia/src/sksl/SkSLString.cpp
@@ -15,6 +15,8 @@
#include <sstream>
#include <string>
+#include "base/strings/string_number_conversions.h"
+
#if defined(STARBOARD)
#include "starboard/client_porting/poem/stdio_leaks_poem.h"
#include "starboard/client_porting/poem/stdlib_poem.h"
@@ -229,6 +231,24 @@
}
String to_string(double value) {
+#if defined(STARBOARD)
+ std::string s = base::NumberToString(value);
+ bool needsDotZero = true;
+ for (int i = s.size() - 1; i >= 0; --i) {
+ char c = s[i];
+ if (c == '.' || c == 'e') {
+ needsDotZero = false;
+ break;
+ }
+ }
+ if (needsDotZero) {
+ s += ".0";
+ }
+ if (s.size() > 0 && s[0] == '.') {
+ s = "0" + s;
+ }
+ return String(s.c_str());
+#else
std::stringstream buffer;
buffer.imbue(std::locale::classic());
buffer.precision(17);
@@ -246,6 +266,7 @@
buffer << ".0";
}
return String(buffer.str().c_str());
+#endif
}
SKSL_INT stoi(const String& s) {
@@ -258,6 +279,12 @@
}
SKSL_FLOAT stod(const String& s) {
+#if defined(STARBOARD)
+ double d;
+ bool res= base::StringToDouble(s.c_str(), &d);
+ SkASSERT(res);
+ return d;
+#else
double result;
std::string str(s.c_str(), s.size());
std::stringstream buffer(str);
@@ -265,6 +292,7 @@
buffer >> result;
SkASSERT(!buffer.fail());
return result;
+#endif
}
long stol(const String& s) {
diff --git a/src/tools/__init__.py b/src/tools/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/tools/__init__.py
diff --git a/src/tools/download_from_gcs.py b/src/tools/download_from_gcs.py
index fc7c8ee..9c79dfb 100755
--- a/src/tools/download_from_gcs.py
+++ b/src/tools/download_from_gcs.py
@@ -56,7 +56,13 @@
url = '{}/{}/{}'.format(_BASE_GCS_URL, bucket, sha1)
context = create_default_context()
- res = urllib.urlopen(url, context=context) if context else urllib.urlopen(url)
+ try:
+ res = urllib.urlopen(url, context=context) if context else urllib.urlopen(url)
+ except urllib.URLError:
+ from ssl import _create_unverified_context
+ context = _create_unverified_context()
+ res = urllib.urlopen(url, context=context) if context else urllib.urlopen(url)
+
if not res:
logging.error('Could not reach %s', url)
return None
diff --git a/src/tools/gyp/pylib/gyp/MSVSVersion.py b/src/tools/gyp/pylib/gyp/MSVSVersion.py
index 0dacf85..cae2c88 100644
--- a/src/tools/gyp/pylib/gyp/MSVSVersion.py
+++ b/src/tools/gyp/pylib/gyp/MSVSVersion.py
@@ -324,10 +324,13 @@
if not os.path.exists(path):
path = r'C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE'
path = _ConvertToCygpath(path)
- full_path = os.path.join(path, 'devenv.exe')
- if os.path.exists(full_path) and version in version_to_year:
+ devenv_path = os.path.join(path, 'devenv.exe')
+ devenv_ini_path = os.path.join(path, 'devenv.isolation.ini')
+ if (os.path.exists(devenv_path) or os.path.exists(devenv_ini_path)) and version in version_to_year:
versions.append(_CreateVersion(version_to_year[version],
os.path.join(path, '..', '..')))
+ else:
+ print('_DetectVisualStudioVersion() did not find Visual Studio 2017 (v15.0)')
continue
# Old method of searching for which VS version is installed
# We don't use the 2010-encouraged-way because we also want to get the
diff --git a/src/tools/gyp/pylib/gyp/msvs_emulation.py b/src/tools/gyp/pylib/gyp/msvs_emulation.py
index 068ad1e..3951c19 100755
--- a/src/tools/gyp/pylib/gyp/msvs_emulation.py
+++ b/src/tools/gyp/pylib/gyp/msvs_emulation.py
@@ -747,6 +747,7 @@
'cell_.*',
'sn_.*',
'sce_.*',
+ 'is_docker',
)
env = {}
for line in output_of_set.splitlines():
diff --git a/src/tools/imagediff/image_diff.cc b/src/tools/imagediff/image_diff.cc
deleted file mode 100644
index 19d5df9..0000000
--- a/src/tools/imagediff/image_diff.cc
+++ /dev/null
@@ -1,382 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// This file input format is based loosely on
-// Tools/DumpRenderTree/ImageDiff.m
-
-// The exact format of this tool's output to stdout is important, to match
-// what the run-webkit-tests script expects.
-
-#include <algorithm>
-#include <vector>
-#include <string>
-#include <iostream>
-
-#include "base/basictypes.h"
-#include "base/command_line.h"
-#include "base/file_path.h"
-#include "base/file_util.h"
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/process_util.h"
-#include "base/string_util.h"
-#include "base/utf_string_conversions.h"
-#include "ui/gfx/codec/png_codec.h"
-#include "ui/gfx/size.h"
-
-#if defined(OS_WIN)
-#include "windows.h"
-#endif
-
-// Causes the app to remain open, waiting for pairs of filenames on stdin.
-// The caller is then responsible for terminating this app.
-static const char kOptionPollStdin[] = "use-stdin";
-static const char kOptionGenerateDiff[] = "diff";
-
-// Return codes used by this utility.
-static const int kStatusSame = 0;
-static const int kStatusDifferent = 1;
-static const int kStatusError = 2;
-
-// Color codes.
-static const uint32 RGBA_RED = 0x000000ff;
-static const uint32 RGBA_ALPHA = 0xff000000;
-
-class Image {
- public:
- Image() : w_(0), h_(0) {
- }
-
- Image(const Image& image)
- : w_(image.w_),
- h_(image.h_),
- data_(image.data_) {
- }
-
- bool has_image() const {
- return w_ > 0 && h_ > 0;
- }
-
- int w() const {
- return w_;
- }
-
- int h() const {
- return h_;
- }
-
- const unsigned char* data() const {
- return &data_.front();
- }
-
- // Creates the image from stdin with the given data length. On success, it
- // will return true. On failure, no other methods should be accessed.
- bool CreateFromStdin(size_t byte_length) {
- if (byte_length == 0)
- return false;
-
- scoped_array<unsigned char> source(new unsigned char[byte_length]);
- if (fread(source.get(), 1, byte_length, stdin) != byte_length)
- return false;
-
- if (!gfx::PNGCodec::Decode(source.get(), byte_length,
- gfx::PNGCodec::FORMAT_RGBA,
- &data_, &w_, &h_)) {
- Clear();
- return false;
- }
- return true;
- }
-
- // Creates the image from the given filename on disk, and returns true on
- // success.
- bool CreateFromFilename(const FilePath& path) {
- FILE* f = file_util::OpenFile(path, "rb");
- if (!f)
- return false;
-
- std::vector<unsigned char> compressed;
- const int buf_size = 1024;
- unsigned char buf[buf_size];
- size_t num_read = 0;
- while ((num_read = fread(buf, 1, buf_size, f)) > 0) {
- compressed.insert(compressed.end(), buf, buf + num_read);
- }
-
- file_util::CloseFile(f);
-
- if (!gfx::PNGCodec::Decode(&compressed[0], compressed.size(),
- gfx::PNGCodec::FORMAT_RGBA, &data_, &w_, &h_)) {
- Clear();
- return false;
- }
- return true;
- }
-
- void Clear() {
- w_ = h_ = 0;
- data_.clear();
- }
-
- // Returns the RGBA value of the pixel at the given location
- uint32 pixel_at(int x, int y) const {
- DCHECK(x >= 0 && x < w_);
- DCHECK(y >= 0 && y < h_);
- return *reinterpret_cast<const uint32*>(&(data_[(y * w_ + x) * 4]));
- }
-
- void set_pixel_at(int x, int y, uint32 color) const {
- DCHECK(x >= 0 && x < w_);
- DCHECK(y >= 0 && y < h_);
- void* addr = &const_cast<unsigned char*>(&data_.front())[(y * w_ + x) * 4];
- *reinterpret_cast<uint32*>(addr) = color;
- }
-
- private:
- // pixel dimensions of the image
- int w_, h_;
-
- std::vector<unsigned char> data_;
-};
-
-float PercentageDifferent(const Image& baseline, const Image& actual) {
- int w = std::min(baseline.w(), actual.w());
- int h = std::min(baseline.h(), actual.h());
-
- // compute pixels different in the overlap
- int pixels_different = 0;
- for (int y = 0; y < h; y++) {
- for (int x = 0; x < w; x++) {
- if (baseline.pixel_at(x, y) != actual.pixel_at(x, y))
- pixels_different++;
- }
- }
-
- // count pixels that are a difference in size as also being different
- int max_w = std::max(baseline.w(), actual.w());
- int max_h = std::max(baseline.h(), actual.h());
-
- // ...pixels off the right side, but not including the lower right corner
- pixels_different += (max_w - w) * h;
-
- // ...pixels along the bottom, including the lower right corner
- pixels_different += (max_h - h) * max_w;
-
- // Like the WebKit ImageDiff tool, we define percentage different in terms
- // of the size of the 'actual' bitmap.
- float total_pixels = static_cast<float>(actual.w()) *
- static_cast<float>(actual.h());
- if (total_pixels == 0)
- return 100.0f; // when the bitmap is empty, they are 100% different
- return static_cast<float>(pixels_different) / total_pixels * 100;
-}
-
-void PrintHelp() {
- fprintf(stderr,
- "Usage:\n"
- " image_diff <compare file> <reference file>\n"
- " Compares two files on disk, returning 0 when they are the same\n"
- " image_diff --use-stdin\n"
- " Stays open reading pairs of filenames from stdin, comparing them,\n"
- " and sending 0 to stdout when they are the same\n"
- " image_diff --diff <compare file> <reference file> <output file>\n"
- " Compares two files on disk, outputs an image that visualizes the"
- " difference to <output file>\n");
- /* For unfinished webkit-like-mode (see below)
- "\n"
- " image_diff -s\n"
- " Reads stream input from stdin, should be EXACTLY of the format\n"
- " \"Content-length: <byte length> <data>Content-length: ...\n"
- " it will take as many file pairs as given, and will compare them as\n"
- " (cmp_file, reference_file) pairs\n");
- */
-}
-
-int CompareImages(const FilePath& file1, const FilePath& file2) {
- Image actual_image;
- Image baseline_image;
-
- if (!actual_image.CreateFromFilename(file1)) {
- fprintf(stderr, "image_diff: Unable to open file \"%" PRFilePath "\"\n",
- file1.value().c_str());
- return kStatusError;
- }
- if (!baseline_image.CreateFromFilename(file2)) {
- fprintf(stderr, "image_diff: Unable to open file \"%" PRFilePath "\"\n",
- file2.value().c_str());
- return kStatusError;
- }
-
- float percent = PercentageDifferent(actual_image, baseline_image);
- if (percent > 0.0) {
- // failure: The WebKit version also writes the difference image to
- // stdout, which seems excessive for our needs.
- printf("diff: %01.2f%% failed\n", percent);
- return kStatusDifferent;
- }
-
- // success
- printf("diff: %01.2f%% passed\n", percent);
- return kStatusSame;
-
-/* Untested mode that acts like WebKit's image comparator. I wrote this but
- decided it's too complicated. We may use it in the future if it looks useful
-
- char buffer[2048];
- while (fgets(buffer, sizeof(buffer), stdin)) {
-
- if (strncmp("Content-length: ", buffer, 16) == 0) {
- char* context;
- strtok_s(buffer, " ", &context);
- int image_size = strtol(strtok_s(NULL, " ", &context), NULL, 10);
-
- bool success = false;
- if (image_size > 0 && actual_image.has_image() == 0) {
- if (!actual_image.CreateFromStdin(image_size)) {
- fputs("Error, input image can't be decoded.\n", stderr);
- return 1;
- }
- } else if (image_size > 0 && baseline_image.has_image() == 0) {
- if (!baseline_image.CreateFromStdin(image_size)) {
- fputs("Error, baseline image can't be decoded.\n", stderr);
- return 1;
- }
- } else {
- fputs("Error, image size must be specified.\n", stderr);
- return 1;
- }
- }
-
- if (actual_image.has_image() && baseline_image.has_image()) {
- float percent = PercentageDifferent(actual_image, baseline_image);
- if (percent > 0.0) {
- // failure: The WebKit version also writes the difference image to
- // stdout, which seems excessive for our needs.
- printf("diff: %01.2f%% failed\n", percent);
- } else {
- // success
- printf("diff: %01.2f%% passed\n", percent);
- }
- actual_image.Clear();
- baseline_image.Clear();
- }
-
- fflush(stdout);
- }
-*/
-}
-
-bool CreateImageDiff(const Image& image1, const Image& image2, Image* out) {
- int w = std::min(image1.w(), image2.w());
- int h = std::min(image1.h(), image2.h());
- *out = Image(image1);
- bool same = (image1.w() == image2.w()) && (image1.h() == image2.h());
-
- // TODO(estade): do something with the extra pixels if the image sizes
- // are different.
- for (int y = 0; y < h; y++) {
- for (int x = 0; x < w; x++) {
- uint32 base_pixel = image1.pixel_at(x, y);
- if (base_pixel != image2.pixel_at(x, y)) {
- // Set differing pixels red.
- out->set_pixel_at(x, y, RGBA_RED | RGBA_ALPHA);
- same = false;
- } else {
- // Set same pixels as faded.
- uint32 alpha = base_pixel & RGBA_ALPHA;
- uint32 new_pixel = base_pixel - ((alpha / 2) & RGBA_ALPHA);
- out->set_pixel_at(x, y, new_pixel);
- }
- }
- }
-
- return same;
-}
-
-int DiffImages(const FilePath& file1, const FilePath& file2,
- const FilePath& out_file) {
- Image actual_image;
- Image baseline_image;
-
- if (!actual_image.CreateFromFilename(file1)) {
- fprintf(stderr, "image_diff: Unable to open file \"%" PRFilePath "\"\n",
- file1.value().c_str());
- return kStatusError;
- }
- if (!baseline_image.CreateFromFilename(file2)) {
- fprintf(stderr, "image_diff: Unable to open file \"%" PRFilePath "\"\n",
- file2.value().c_str());
- return kStatusError;
- }
-
- Image diff_image;
- bool same = CreateImageDiff(baseline_image, actual_image, &diff_image);
- if (same)
- return kStatusSame;
-
- std::vector<unsigned char> png_encoding;
- gfx::PNGCodec::Encode(diff_image.data(), gfx::PNGCodec::FORMAT_RGBA,
- gfx::Size(diff_image.w(), diff_image.h()),
- diff_image.w() * 4, false,
- std::vector<gfx::PNGCodec::Comment>(), &png_encoding);
- if (file_util::WriteFile(out_file,
- reinterpret_cast<char*>(&png_encoding.front()), png_encoding.size()) < 0)
- return kStatusError;
-
- return kStatusDifferent;
-}
-
-// It isn't strictly correct to only support ASCII paths, but this
-// program reads paths on stdin and the program that spawns it outputs
-// paths as non-wide strings anyway.
-FilePath FilePathFromASCII(const std::string& str) {
-#if defined(OS_WIN)
- return FilePath(ASCIIToWide(str));
-#else
- return FilePath(str);
-#endif
-}
-
-int main(int argc, const char* argv[]) {
- base::EnableTerminationOnHeapCorruption();
- CommandLine::Init(argc, argv);
- const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess();
- if (parsed_command_line.HasSwitch(kOptionPollStdin)) {
- // Watch stdin for filenames.
- std::string stdin_buffer;
- FilePath filename1;
- while (std::getline(std::cin, stdin_buffer)) {
- if (stdin_buffer.empty())
- continue;
-
- if (!filename1.empty()) {
- // CompareImages writes results to stdout unless an error occurred.
- FilePath filename2 = FilePathFromASCII(stdin_buffer);
- if (CompareImages(filename1, filename2) == kStatusError)
- printf("error\n");
- fflush(stdout);
- filename1 = FilePath();
- } else {
- // Save the first filename in another buffer and wait for the second
- // filename to arrive via stdin.
- filename1 = FilePathFromASCII(stdin_buffer);
- }
- }
- return 0;
- }
-
- const CommandLine::StringVector& args = parsed_command_line.GetArgs();
- if (parsed_command_line.HasSwitch(kOptionGenerateDiff)) {
- if (args.size() == 3) {
- return DiffImages(FilePath(args[0]),
- FilePath(args[1]),
- FilePath(args[2]));
- }
- } else if (args.size() == 2) {
- return CompareImages(FilePath(args[0]), FilePath(args[1]));
- }
-
- PrintHelp();
- return kStatusError;
-}
diff --git a/src/tools/imagediff/image_diff.gyp b/src/tools/imagediff/image_diff.gyp
deleted file mode 100644
index 6d4a620..0000000
--- a/src/tools/imagediff/image_diff.gyp
+++ /dev/null
@@ -1,22 +0,0 @@
-# Copyright (c) 2009 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-{
- 'variables': {
- 'chromium_code': 1,
- },
- 'targets' : [
- {
- 'target_name': 'image_diff',
- 'type': 'executable',
- 'dependencies': [
- '../../base/base.gyp:base',
- '../../ui/ui.gyp:ui',
- ],
- 'sources': [
- 'image_diff.cc',
- ],
- },
- ],
-}
diff --git a/src/v8/regress-1051017.js b/src/v8/regress-1051017.js
new file mode 100644
index 0000000..142b563
--- /dev/null
+++ b/src/v8/regress-1051017.js
@@ -0,0 +1,48 @@
+// Copyright 2020 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax
+
+
+function foo1() {
+ var x = -Infinity;
+ var i = 0;
+ for (; i < 1; i += x) {
+ if (i == -Infinity) x = +Infinity;
+ }
+ return i;
+}
+
+%PrepareFunctionForOptimization(foo1);
+assertEquals(NaN, foo1());
+assertEquals(NaN, foo1());
+%OptimizeFunctionOnNextCall(foo1);
+assertEquals(NaN, foo1());
+
+
+function foo2() {
+ var i = -Infinity;
+ for (; i <= 42; i += Infinity) { }
+ return i;
+}
+
+%PrepareFunctionForOptimization(foo2);
+assertEquals(NaN, foo2());
+assertEquals(NaN, foo2());
+%OptimizeFunctionOnNextCall(foo2);
+assertEquals(NaN, foo2());
+
+
+function foo3(b) {
+ var k = 0;
+ let str = b ? "42" : "0";
+ for (var i = str; i < 1 && k++ < 1; i -= 0) { }
+ return i;
+}
+
+%PrepareFunctionForOptimization(foo3);
+assertEquals(0, foo3());
+assertEquals(0, foo3());
+%OptimizeFunctionOnNextCall(foo3);
+assertEquals(0, foo3());
diff --git a/src/v8/src/compiler/js-create-lowering.cc b/src/v8/src/compiler/js-create-lowering.cc
index 4e69db6..fe60eaa 100644
--- a/src/v8/src/compiler/js-create-lowering.cc
+++ b/src/v8/src/compiler/js-create-lowering.cc
@@ -667,6 +667,9 @@
length_type.Max() <= kElementLoopUnrollLimit &&
length_type.Min() == length_type.Max()) {
int capacity = static_cast<int>(length_type.Max());
+ // Replace length with a constant in order to protect against a potential
+ // typer bug leading to length > capacity.
+ length = jsgraph()->Constant(capacity);
return ReduceNewArray(node, length, capacity, *initial_map, elements_kind,
allocation, slack_tracking_prediction);
}
diff --git a/src/v8/src/compiler/typer.cc b/src/v8/src/compiler/typer.cc
index ae1590a..956f0ec 100644
--- a/src/v8/src/compiler/typer.cc
+++ b/src/v8/src/compiler/typer.cc
@@ -211,6 +211,9 @@
Type TypeConstant(Handle<Object> value);
+ bool InductionVariablePhiTypeIsPrefixedPoint(
+ InductionVariable* induction_var);
+
private:
Typer* typer_;
LoopVariableOptimizer* induction_vars_;
@@ -251,7 +254,8 @@
using BinaryTyperFun = Type (*)(Type, Type, Typer* t);
Type TypeUnaryOp(Node* node, UnaryTyperFun);
- Type TypeBinaryOp(Node* node, BinaryTyperFun);
+ inline Type TypeBinaryOp(Node* node, BinaryTyperFun);
+ inline Type TypeBinaryOp(Type left, Type right, BinaryTyperFun);
static Type BinaryNumberOpTyper(Type lhs, Type rhs, Typer* t,
BinaryTyperFun f);
@@ -299,7 +303,21 @@
SIMPLIFIED_SPECULATIVE_NUMBER_BINOP_LIST(DECLARE_METHOD)
SIMPLIFIED_SPECULATIVE_BIGINT_BINOP_LIST(DECLARE_METHOD)
#undef DECLARE_METHOD
-
+#define DECLARE_METHOD(Name) \
+ inline Type Type##Name(Type left, Type right) { \
+ return TypeBinaryOp(left, right, Name##Typer); \
+ }
+ JS_SIMPLE_BINOP_LIST(DECLARE_METHOD)
+#undef DECLARE_METHOD
+#define DECLARE_METHOD(Name) \
+ inline Type Type##Name(Type left, Type right) { \
+ return TypeBinaryOp(left, right, Name); \
+ }
+ SIMPLIFIED_NUMBER_BINOP_LIST(DECLARE_METHOD)
+ SIMPLIFIED_BIGINT_BINOP_LIST(DECLARE_METHOD)
+ SIMPLIFIED_SPECULATIVE_NUMBER_BINOP_LIST(DECLARE_METHOD)
+ SIMPLIFIED_SPECULATIVE_BIGINT_BINOP_LIST(DECLARE_METHOD)
+#undef DECLARE_METHOD
static Type ObjectIsArrayBufferView(Type, Typer*);
static Type ObjectIsBigInt(Type, Typer*);
static Type ObjectIsCallable(Type, Typer*);
@@ -430,6 +448,14 @@
graph_reducer.ReduceGraph();
if (induction_vars != nullptr) {
+ // Validate the types computed by TypeInductionVariablePhi.
+ for (auto entry : induction_vars->induction_variables()) {
+ InductionVariable* induction_var = entry.second;
+ if (induction_var->phi()->opcode() == IrOpcode::kInductionVariablePhi) {
+ CHECK(visitor.InductionVariablePhiTypeIsPrefixedPoint(induction_var));
+ }
+ }
+
induction_vars->ChangeToPhisAndInsertGuards();
}
}
@@ -466,6 +492,10 @@
Type Typer::Visitor::TypeBinaryOp(Node* node, BinaryTyperFun f) {
Type left = Operand(node, 0);
Type right = Operand(node, 1);
+ return TypeBinaryOp(left, right, f);
+}
+
+Type Typer::Visitor::TypeBinaryOp(Type left, Type right, BinaryTyperFun f) {
return left.IsNone() || right.IsNone() ? Type::None()
: f(left, right, typer_);
}
@@ -843,15 +873,23 @@
Type initial_type = Operand(node, 0);
Type increment_type = Operand(node, 2);
- // We only handle integer induction variables (otherwise ranges
- // do not apply and we cannot do anything).
- if (!initial_type.Is(typer_->cache_->kInteger) ||
- !increment_type.Is(typer_->cache_->kInteger)) {
- // Fallback to normal phi typing, but ensure monotonicity.
- // (Unfortunately, without baking in the previous type, monotonicity might
- // be violated because we might not yet have retyped the incrementing
- // operation even though the increment's type might been already reflected
- // in the induction variable phi.)
+ // Fallback to normal phi typing in a variety of cases:
+ // - when the induction variable is not initially of type Integer, because we
+ // want to work with ranges in the algorithm below.
+ // - when the increment is zero, because in that case normal phi typing will
+ // generally yield a more precise type.
+ // - when the induction variable can become NaN (through addition/subtraction
+ // of opposing infinities), because the code below can't handle that case.
+ if (initial_type.IsNone() ||
+ increment_type.Is(typer_->cache_->kSingletonZero) ||
+ !initial_type.Is(typer_->cache_->kInteger) ||
+ !increment_type.Is(typer_->cache_->kInteger) ||
+ increment_type.Min() == -V8_INFINITY ||
+ increment_type.Max() == +V8_INFINITY) {
+ // Unfortunately, without baking in the previous type, monotonicity might be
+ // violated because we might not yet have retyped the incrementing operation
+ // even though the increment's type might been already reflected in the
+ // induction variable phi.
Type type = NodeProperties::IsTyped(node) ? NodeProperties::GetType(node)
: Type::None();
for (int i = 0; i < arity; ++i) {
@@ -859,18 +897,10 @@
}
return type;
}
- // If we do not have enough type information for the initial value or
- // the increment, just return the initial value's type.
- if (initial_type.IsNone() ||
- increment_type.Is(typer_->cache_->kSingletonZero)) {
- return initial_type;
- }
- // Now process the bounds.
auto res = induction_vars_->induction_variables().find(node->id());
- DCHECK(res != induction_vars_->induction_variables().end());
+ DCHECK_NE(res, induction_vars_->induction_variables().end());
InductionVariable* induction_var = res->second;
-
InductionVariable::ArithmeticType arithmetic_type = induction_var->Type();
double min = -V8_INFINITY;
@@ -882,13 +912,13 @@
increment_min = increment_type.Min();
increment_max = increment_type.Max();
} else {
- DCHECK_EQ(InductionVariable::ArithmeticType::kSubtraction, arithmetic_type);
+ DCHECK_EQ(arithmetic_type, InductionVariable::ArithmeticType::kSubtraction);
increment_min = -increment_type.Max();
increment_max = -increment_type.Min();
}
if (increment_min >= 0) {
- // increasing sequence
+ // Increasing sequence.
min = initial_type.Min();
for (auto bound : induction_var->upper_bounds()) {
Type bound_type = TypeOrNone(bound.bound);
@@ -908,7 +938,7 @@
// The upper bound must be at least the initial value's upper bound.
max = std::max(max, initial_type.Max());
} else if (increment_max <= 0) {
- // decreasing sequence
+ // Decreasing sequence.
max = initial_type.Max();
for (auto bound : induction_var->lower_bounds()) {
Type bound_type = TypeOrNone(bound.bound);
@@ -928,9 +958,11 @@
// The lower bound must be at most the initial value's lower bound.
min = std::min(min, initial_type.Min());
} else {
- // Shortcut: If the increment can be both positive and negative,
- // the variable can go arbitrarily far, so just return integer.
- return typer_->cache_->kInteger;
+ // If the increment can be both positive and negative, the variable can go
+ // arbitrarily far. Use the maximal range in that case. Note that this may
+ // be less precise than what ordinary typing would produce.
+ min = -V8_INFINITY;
+ max = +V8_INFINITY;
}
#ifndef V8_OS_STARBOARD
if (FLAG_trace_turbo_loop) {
@@ -945,9 +977,68 @@
<< ")\n";
}
#endif
+
return Type::Range(min, max, typer_->zone());
}
+bool Typer::Visitor::InductionVariablePhiTypeIsPrefixedPoint(
+ InductionVariable* induction_var) {
+ Node* node = induction_var->phi();
+ DCHECK_EQ(node->opcode(), IrOpcode::kInductionVariablePhi);
+ Type type = NodeProperties::GetType(node);
+ Type initial_type = Operand(node, 0);
+ Node* arith = node->InputAt(1);
+ Type increment_type = Operand(node, 2);
+
+ // Intersect {type} with useful bounds.
+ for (auto bound : induction_var->upper_bounds()) {
+ Type bound_type = TypeOrNone(bound.bound);
+ if (!bound_type.Is(typer_->cache_->kInteger)) continue;
+ if (!bound_type.IsNone()) {
+ bound_type = Type::Range(
+ -V8_INFINITY,
+ bound_type.Max() - (bound.kind == InductionVariable::kStrict),
+ zone());
+ }
+ type = Type::Intersect(type, bound_type, typer_->zone());
+ }
+ for (auto bound : induction_var->lower_bounds()) {
+ Type bound_type = TypeOrNone(bound.bound);
+ if (!bound_type.Is(typer_->cache_->kInteger)) continue;
+ if (!bound_type.IsNone()) {
+ bound_type = Type::Range(
+ bound_type.Min() + (bound.kind == InductionVariable::kStrict),
+ +V8_INFINITY, typer_->zone());
+ }
+ type = Type::Intersect(type, bound_type, typer_->zone());
+ }
+
+ // Apply ordinary typing to the "increment" operation.
+ // clang-format off
+ switch (arith->opcode()) {
+#define CASE(x) \
+ case IrOpcode::k##x: \
+ type = Type##x(type, increment_type); \
+ break;
+ CASE(JSAdd)
+ CASE(JSSubtract)
+ CASE(NumberAdd)
+ CASE(NumberSubtract)
+ CASE(SpeculativeNumberAdd)
+ CASE(SpeculativeNumberSubtract)
+ CASE(SpeculativeSafeIntegerAdd)
+ CASE(SpeculativeSafeIntegerSubtract)
+#undef CASE
+ default:
+ UNREACHABLE();
+ }
+ // clang-format on
+
+ type = Type::Union(initial_type, type, typer_->zone());
+
+ return type.Is(NodeProperties::GetType(node));
+}
+
Type Typer::Visitor::TypeEffectPhi(Node* node) { UNREACHABLE(); }
Type Typer::Visitor::TypeLoopExit(Node* node) { UNREACHABLE(); }