25 #ifdef USE_IMAGEMAGICK 
   68     wave_color = 
Color((
unsigned char)0, (
unsigned char)123, (
unsigned char)255, (
unsigned char)255);
 
   93     parentTrackedObject = 
nullptr;
 
   94     parentClipObject = NULL;
 
  120     float rotate_angle = 0.0f;
 
  121     if (reader && reader->
info.
metadata.count(
"rotate") > 0) {
 
  123             rotate_angle = strtof(reader->
info.
metadata[
"rotate"].c_str(), 
nullptr);
 
  124         } 
catch (
const std::exception& e) {
 
  132     float w = 
static_cast<float>(reader->
info.
width);
 
  133     float h = 
static_cast<float>(reader->
info.
height);
 
  134     float rad = rotate_angle * M_PI / 180.0f;
 
  137     float new_width  = fabs(w * cos(rad)) + fabs(h * sin(rad));
 
  138     float new_height = fabs(w * sin(rad)) + fabs(h * cos(rad));
 
  142     float uniform_scale = std::min(w / new_width, h / new_height);
 
  150 Clip::Clip() : resampler(NULL), reader(NULL), allocated_reader(NULL), is_open(false)
 
  157 Clip::Clip(
ReaderBase* new_reader) : resampler(NULL), reader(new_reader), allocated_reader(NULL), is_open(false)
 
  176 Clip::Clip(std::string 
path) : resampler(NULL), reader(NULL), allocated_reader(NULL), is_open(false)
 
  182     std::string ext = get_file_extension(
path);
 
  183     std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower);
 
  186     if (ext==
"avi" || ext==
"mov" || ext==
"mkv" ||  ext==
"mpg" || ext==
"mpeg" || ext==
"mp3" || ext==
"mp4" || ext==
"mts" ||
 
  187         ext==
"ogg" || ext==
"wav" || ext==
"wmv" || ext==
"webm" || ext==
"vob" || ext==
"gif" || 
path.find(
"%") != std::string::npos)
 
  229         allocated_reader = reader;
 
  239     if (allocated_reader) {
 
  240         delete allocated_reader;
 
  241         allocated_reader = NULL;
 
  261     if (parentTimeline) {
 
  263         std::shared_ptr<openshot::TrackedObjectBase> trackedObject = parentTimeline->
GetTrackedObject(object_id);
 
  264         Clip* clipObject = parentTimeline->
GetClip(object_id);
 
  269             parentClipObject = NULL;
 
  271         else if (clipObject) {
 
  273             parentTrackedObject = 
nullptr;
 
  280     parentTrackedObject = trackedObject;
 
  285     parentClipObject = clipObject;
 
  293     bool is_same_reader = 
false;
 
  294     if (new_reader && allocated_reader) {
 
  295         if (new_reader->
Name() == 
"FrameMapper") {
 
  298             if (allocated_reader == clip_mapped_reader->
Reader()) {
 
  299                 is_same_reader = 
true;
 
  304     if (allocated_reader && !is_same_reader) {
 
  306         allocated_reader->
Close();
 
  307         delete allocated_reader;
 
  309         allocated_reader = NULL;
 
  331         throw ReaderClosed(
"No Reader has been initialized for this Clip.  Call Reader(*reader) before calling this method.");
 
  352         throw ReaderClosed(
"No Reader has been initialized for this Clip.  Call Reader(*reader) before calling this method.");
 
  358     if (is_open && reader) {
 
  383             throw ReaderClosed(
"No Reader has been initialized for this Clip.  Call Reader(*reader) before calling this method.");
 
  409     return GetFrame(NULL, clip_frame_number, NULL);
 
  414 std::shared_ptr<Frame> 
Clip::GetFrame(std::shared_ptr<openshot::Frame> background_frame, int64_t clip_frame_number)
 
  417     return GetFrame(background_frame, clip_frame_number, NULL);
 
  425         throw ReaderClosed(
"The Clip is closed.  Call Open() before calling this method.");
 
  430         std::shared_ptr<Frame> frame = NULL;
 
  433         frame = final_cache.
GetFrame(clip_frame_number);
 
  436             frame = GetOrCreateFrame(clip_frame_number);
 
  439             int64_t timeline_frame_number = clip_frame_number;
 
  440             QSize timeline_size(frame->GetWidth(), frame->GetHeight());
 
  441             if (background_frame) {
 
  443                 timeline_frame_number = background_frame->number;
 
  444                 timeline_size.setWidth(background_frame->GetWidth());
 
  445                 timeline_size.setHeight(background_frame->GetHeight());
 
  449             apply_timemapping(frame);
 
  452             apply_waveform(frame, timeline_size);
 
  455             apply_effects(frame, timeline_frame_number, options, 
true);
 
  458             apply_keyframes(frame, timeline_size);
 
  461             apply_effects(frame, timeline_frame_number, options, 
false);
 
  464             final_cache.
Add(frame);
 
  467         if (!background_frame) {
 
  469             background_frame = std::make_shared<Frame>(frame->number, frame->GetWidth(), frame->GetHeight(),
 
  470                                                        "#00000000",  frame->GetAudioSamplesCount(),
 
  471                                                        frame->GetAudioChannelsCount());
 
  475         apply_background(frame, background_frame);
 
  482         throw ReaderClosed(
"No Reader has been initialized for this Clip.  Call Reader(*reader) before calling this method.");
 
  489     for (
const auto& effect : effects) {
 
  490         if (effect->Id() == 
id) {
 
  499     if (!parentObjectId.empty() && (!parentClipObject && !parentTrackedObject)) {
 
  503     return parentClipObject;
 
  508     if (!parentObjectId.empty() && (!parentClipObject && !parentTrackedObject)) {
 
  512     return parentTrackedObject;
 
  516 std::string Clip::get_file_extension(std::string 
path)
 
  519     return path.substr(
path.find_last_of(
".") + 1);
 
  523 void Clip::apply_timemapping(std::shared_ptr<Frame> frame)
 
  528         throw ReaderClosed(
"No Reader has been initialized for this Clip.  Call Reader(*reader) before calling this method.");
 
  533         const std::lock_guard<std::recursive_mutex> lock(
getFrameMutex);
 
  535         int64_t clip_frame_number = frame->number;
 
  536         int64_t new_frame_number = adjust_frame_number_minimum(
time.
GetLong(clip_frame_number));
 
  552         int source_sample_count = round(target_sample_count * fabs(delta));
 
  558             location.
frame = new_frame_number;
 
  572             init_samples.clear();
 
  573             resampler->
SetBuffer(&init_samples, 1.0);
 
  581         if (source_sample_count <= 0) {
 
  583             frame->AddAudioSilence(target_sample_count);
 
  589         source_samples->clear();
 
  592         int remaining_samples = source_sample_count;
 
  594         while (remaining_samples > 0) {
 
  595             std::shared_ptr<Frame> source_frame = GetOrCreateFrame(location.
frame, 
false);
 
  596             int frame_sample_count = source_frame->GetAudioSamplesCount() - location.
sample_start;
 
  598             if (frame_sample_count == 0) {
 
  608             if (remaining_samples - frame_sample_count >= 0) {
 
  610                 for (
int channel = 0; channel < source_frame->GetAudioChannelsCount(); channel++) {
 
  611                     source_samples->addFrom(channel, source_pos, source_frame->GetAudioSamples(channel) + location.
sample_start, frame_sample_count, 1.0f);
 
  619                 remaining_samples -= frame_sample_count;
 
  620                 source_pos += frame_sample_count;
 
  624                 for (
int channel = 0; channel < source_frame->GetAudioChannelsCount(); channel++) {
 
  625                     source_samples->addFrom(channel, source_pos, source_frame->GetAudioSamples(channel) + location.
sample_start, remaining_samples, 1.0f);
 
  628                 remaining_samples = 0;
 
  629                 source_pos += remaining_samples;
 
  636         frame->AddAudioSilence(target_sample_count);
 
  638         if (source_sample_count != target_sample_count) {
 
  640             double resample_ratio = double(source_sample_count) / double(target_sample_count);
 
  641             resampler->
SetBuffer(source_samples, resample_ratio);
 
  649                 frame->AddAudio(
true, channel, 0, resampled_buffer->getReadPointer(channel, 0), std::min(resampled_buffer->getNumSamples(), target_sample_count), 1.0f);
 
  655                 frame->AddAudio(
true, channel, 0, source_samples->getReadPointer(channel, 0), target_sample_count, 1.0f);
 
  660         delete source_samples;
 
  668 int64_t Clip::adjust_frame_number_minimum(int64_t frame_number)
 
  671     if (frame_number < 1)
 
  679 std::shared_ptr<Frame> Clip::GetOrCreateFrame(int64_t number, 
bool enable_time)
 
  683         int64_t clip_frame_number = adjust_frame_number_minimum(number);
 
  687             clip_frame_number = adjust_frame_number_minimum(
time.
GetLong(clip_frame_number));
 
  692                 "Clip::GetOrCreateFrame (from reader)",
 
  693                 "number", number, 
"clip_frame_number", clip_frame_number);
 
  696         auto reader_frame = reader->
GetFrame(clip_frame_number);
 
  697         reader_frame->number = number; 
 
  704             auto reader_copy = std::make_shared<Frame>(*reader_frame.get());
 
  707                 reader_copy->AddColor(QColor(Qt::transparent));
 
  711                 reader_copy->AddAudioSilence(reader_copy->GetAudioSamplesCount());
 
  727         "Clip::GetOrCreateFrame (create blank)",
 
  729         "estimated_samples_in_frame", estimated_samples_in_frame);
 
  732     auto new_frame = std::make_shared<Frame>(
 
  734         "#000000", estimated_samples_in_frame, reader->
info.
channels);
 
  737     new_frame->AddAudioSilence(estimated_samples_in_frame);
 
  753     root[
"id"] = 
add_property_json(
"ID", 0.0, 
"string", 
Id(), NULL, -1, -1, 
true, requested_frame);
 
  754     root[
"position"] = 
add_property_json(
"Position", 
Position(), 
"float", 
"", NULL, 0, 30 * 60 * 60 * 48, 
false, requested_frame);
 
  756     root[
"start"] = 
add_property_json(
"Start", 
Start(), 
"float", 
"", NULL, 0, 30 * 60 * 60 * 48, 
false, requested_frame);
 
  757     root[
"end"] = 
add_property_json(
"End", 
End(), 
"float", 
"", NULL, 0, 30 * 60 * 60 * 48, 
false, requested_frame);
 
  758     root[
"duration"] = 
add_property_json(
"Duration", Duration(), 
"float", 
"", NULL, 0, 30 * 60 * 60 * 48, 
true, requested_frame);
 
  763     root[
"waveform"] = 
add_property_json(
"Waveform", waveform, 
"int", 
"", NULL, 0, 1, 
false, requested_frame);
 
  764     root[
"parentObjectId"] = 
add_property_json(
"Parent", 0.0, 
"string", parentObjectId, NULL, -1, -1, 
false, requested_frame);
 
  799     if (parentClipObject)
 
  804         double timeline_frame_number = requested_frame + clip_start_position - clip_start_frame;
 
  807         float parentObject_location_x = parentClipObject->
location_x.
GetValue(timeline_frame_number);
 
  808         float parentObject_location_y = parentClipObject->
location_y.
GetValue(timeline_frame_number);
 
  809         float parentObject_scale_x = parentClipObject->
scale_x.
GetValue(timeline_frame_number);
 
  810         float parentObject_scale_y = parentClipObject->
scale_y.
GetValue(timeline_frame_number);
 
  811         float parentObject_shear_x = parentClipObject->
shear_x.
GetValue(timeline_frame_number);
 
  812         float parentObject_shear_y = parentClipObject->
shear_y.
GetValue(timeline_frame_number);
 
  813         float parentObject_rotation = parentClipObject->
rotation.
GetValue(timeline_frame_number);
 
  816         root[
"location_x"] = 
add_property_json(
"Location X", parentObject_location_x, 
"float", 
"", &
location_x, -1.0, 1.0, 
false, requested_frame);
 
  817         root[
"location_y"] = 
add_property_json(
"Location Y", parentObject_location_y, 
"float", 
"", &
location_y, -1.0, 1.0, 
false, requested_frame);
 
  818         root[
"scale_x"] = 
add_property_json(
"Scale X", parentObject_scale_x, 
"float", 
"", &
scale_x, 0.0, 1.0, 
false, requested_frame);
 
  819         root[
"scale_y"] = 
add_property_json(
"Scale Y", parentObject_scale_y, 
"float", 
"", &
scale_y, 0.0, 1.0, 
false, requested_frame);
 
  820         root[
"rotation"] = 
add_property_json(
"Rotation", parentObject_rotation, 
"float", 
"", &
rotation, -360, 360, 
false, requested_frame);
 
  821         root[
"shear_x"] = 
add_property_json(
"Shear X", parentObject_shear_x, 
"float", 
"", &
shear_x, -1.0, 1.0, 
false, requested_frame);
 
  822         root[
"shear_y"] = 
add_property_json(
"Shear Y", parentObject_shear_y, 
"float", 
"", &
shear_y, -1.0, 1.0, 
false, requested_frame);
 
  862     return root.toStyledString();
 
  870     root[
"parentObjectId"] = parentObjectId;
 
  872     root[
"scale"] = 
scale;
 
  876     root[
"waveform"] = waveform;
 
  904     root[
"effects"] = Json::Value(Json::arrayValue);
 
  907     for (
auto existing_effect : effects)
 
  909         root[
"effects"].append(existing_effect->JsonValue());
 
  915         root[
"reader"] = Json::Value(Json::objectValue);
 
  931     catch (
const std::exception& e)
 
  934         throw InvalidJSON(
"JSON is invalid (missing keys or invalid data types)");
 
  945     if (!root[
"parentObjectId"].isNull()){
 
  946         parentObjectId = root[
"parentObjectId"].asString();
 
  947         if (parentObjectId.size() > 0 && parentObjectId != 
""){
 
  950             parentTrackedObject = 
nullptr;
 
  951             parentClipObject = NULL;
 
  954     if (!root[
"gravity"].isNull())
 
  956     if (!root[
"scale"].isNull())
 
  958     if (!root[
"anchor"].isNull())
 
  960     if (!root[
"display"].isNull())
 
  962     if (!root[
"mixing"].isNull())
 
  964     if (!root[
"waveform"].isNull())
 
  965         waveform = root[
"waveform"].asBool();
 
  966     if (!root[
"scale_x"].isNull())
 
  968     if (!root[
"scale_y"].isNull())
 
  970     if (!root[
"location_x"].isNull())
 
  972     if (!root[
"location_y"].isNull())
 
  974     if (!root[
"alpha"].isNull())
 
  976     if (!root[
"rotation"].isNull())
 
  978     if (!root[
"time"].isNull())
 
  980     if (!root[
"volume"].isNull())
 
  982     if (!root[
"wave_color"].isNull())
 
  984     if (!root[
"shear_x"].isNull())
 
  986     if (!root[
"shear_y"].isNull())
 
  988     if (!root[
"origin_x"].isNull())
 
  990     if (!root[
"origin_y"].isNull())
 
  992     if (!root[
"channel_filter"].isNull())
 
  994     if (!root[
"channel_mapping"].isNull())
 
  996     if (!root[
"has_audio"].isNull())
 
  998     if (!root[
"has_video"].isNull())
 
 1000     if (!root[
"perspective_c1_x"].isNull())
 
 1002     if (!root[
"perspective_c1_y"].isNull())
 
 1004     if (!root[
"perspective_c2_x"].isNull())
 
 1006     if (!root[
"perspective_c2_y"].isNull())
 
 1008     if (!root[
"perspective_c3_x"].isNull())
 
 1010     if (!root[
"perspective_c3_y"].isNull())
 
 1012     if (!root[
"perspective_c4_x"].isNull())
 
 1014     if (!root[
"perspective_c4_y"].isNull())
 
 1016     if (!root[
"effects"].isNull()) {
 
 1022         for (
const auto existing_effect : root[
"effects"]) {
 
 1024             if (existing_effect.isNull()) {
 
 1030             if (!existing_effect[
"type"].isNull()) {
 
 1033                 if ( (e = 
EffectInfo().CreateEffect(existing_effect[
"type"].asString()))) {
 
 1044     if (!root[
"reader"].isNull()) 
 
 1046         if (!root[
"reader"][
"type"].isNull()) 
 
 1049             bool already_open = 
false;
 
 1053                 already_open = reader->
IsOpen();
 
 1060             std::string type = root[
"reader"][
"type"].asString();
 
 1062             if (type == 
"FFmpegReader") {
 
 1068             } 
else if (type == 
"QtImageReader") {
 
 1074 #ifdef USE_IMAGEMAGICK 
 1075             } 
else if (type == 
"ImageReader") {
 
 1078                 reader = 
new ImageReader(root[
"reader"][
"path"].asString(), 
false);
 
 1081             } 
else if (type == 
"TextReader") {
 
 1088             } 
else if (type == 
"ChunkReader") {
 
 1094             } 
else if (type == 
"DummyReader") {
 
 1100             } 
else if (type == 
"Timeline") {
 
 1110                 allocated_reader = reader;
 
 1121     final_cache.
Clear();
 
 1125 void Clip::sort_effects()
 
 1138     effects.push_back(effect);
 
 1147         effect->ParentTimeline(parentTimeline);
 
 1154         if (parentTimeline){
 
 1156             effect->ParentTimeline(parentTimeline);
 
 1162                 std::shared_ptr<TrackedObjectBBox> trackedObjectBBox = std::static_pointer_cast<TrackedObjectBBox>(trackedObject.second);
 
 1165                 trackedObjectBBox->ParentClip(
this);
 
 1175     final_cache.
Clear();
 
 1181     effects.remove(effect);
 
 1184     final_cache.
Clear();
 
 1188 void Clip::apply_background(std::shared_ptr<openshot::Frame> frame, std::shared_ptr<openshot::Frame> background_frame) {
 
 1190     std::shared_ptr<QImage> background_canvas = background_frame->GetImage();
 
 1191     QPainter painter(background_canvas.get());
 
 1192     painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform | QPainter::TextAntialiasing, 
true);
 
 1195     painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
 
 1196     painter.drawImage(0, 0, *frame->GetImage());
 
 1200     frame->AddImage(background_canvas);
 
 1204 void Clip::apply_effects(std::shared_ptr<Frame> frame, int64_t timeline_frame_number, 
TimelineInfoStruct* options, 
bool before_keyframes)
 
 1206     for (
auto effect : effects)
 
 1209         if (effect->info.apply_before_clip && before_keyframes) {
 
 1210             effect->GetFrame(frame, frame->number);
 
 1211         } 
else if (!effect->info.apply_before_clip && !before_keyframes) {
 
 1212             effect->GetFrame(frame, frame->number);
 
 1216     if (
timeline != NULL && options != NULL) {
 
 1225 bool Clip::isNear(
double a, 
double b)
 
 1227     return fabs(a - b) < 0.000001;
 
 1231 void Clip::apply_keyframes(std::shared_ptr<Frame> frame, QSize timeline_size) {
 
 1233     if (!frame->has_image_data) {
 
 1239     std::shared_ptr<QImage> source_image = frame->GetImage();
 
 1240     std::shared_ptr<QImage> background_canvas = std::make_shared<QImage>(timeline_size.width(),
 
 1241                                                                          timeline_size.height(),
 
 1242                                                                          QImage::Format_RGBA8888_Premultiplied);
 
 1243     background_canvas->fill(QColor(Qt::transparent));
 
 1246     QTransform transform = get_transform(frame, background_canvas->width(), background_canvas->height());
 
 1249     QPainter painter(background_canvas.get());
 
 1250     painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform | QPainter::TextAntialiasing, 
true);
 
 1253     painter.setTransform(transform);
 
 1256     painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
 
 1257     painter.drawImage(0, 0, *source_image);
 
 1264             std::stringstream frame_number_str;
 
 1271                     frame_number_str << frame->number;
 
 1284             painter.setPen(QColor(
"#ffffff"));
 
 1285             painter.drawText(20, 20, QString(frame_number_str.str().c_str()));
 
 1291     frame->AddImage(background_canvas);
 
 1295 void Clip::apply_waveform(std::shared_ptr<Frame> frame, QSize timeline_size) {
 
 1303     std::shared_ptr<QImage> source_image = frame->GetImage();
 
 1307             "frame->number", frame->number,
 
 1308             "Waveform()", Waveform(),
 
 1309             "width", timeline_size.width(),
 
 1310             "height", timeline_size.height());
 
 1319     source_image = frame->GetWaveform(timeline_size.width(), timeline_size.height(), red, green, blue, 
alpha);
 
 1320     frame->AddImage(source_image);
 
 1324 QSize Clip::scale_size(QSize source_size, 
ScaleType source_scale, 
int target_width, 
int target_height) {
 
 1325     switch (source_scale)
 
 1328             source_size.scale(target_width, target_height, Qt::KeepAspectRatio);
 
 1332             source_size.scale(target_width, target_height, Qt::IgnoreAspectRatio);
 
 1336             source_size.scale(target_width, target_height, Qt::KeepAspectRatioByExpanding);;
 
 1345 QTransform Clip::get_transform(std::shared_ptr<Frame> frame, 
int width, 
int height)
 
 1348     std::shared_ptr<QImage> source_image = frame->GetImage();
 
 1356         unsigned char *pixels = source_image->bits();
 
 1359         for (
int pixel = 0, byte_index=0; pixel < source_image->width() * source_image->height(); pixel++, byte_index+=4)
 
 1363             pixels[byte_index + 0] *= alpha_value;
 
 1364             pixels[byte_index + 1] *= alpha_value;
 
 1365             pixels[byte_index + 2] *= alpha_value;
 
 1366             pixels[byte_index + 3] *= alpha_value;
 
 1371             "alpha_value", alpha_value,
 
 1372             "frame->number", frame->number);
 
 1376     QSize source_size = scale_size(source_image->size(), 
scale, width, height);
 
 1379     float parentObject_location_x = 0.0;
 
 1380     float parentObject_location_y = 0.0;
 
 1381     float parentObject_scale_x = 1.0;
 
 1382     float parentObject_scale_y = 1.0;
 
 1383     float parentObject_shear_x = 0.0;
 
 1384     float parentObject_shear_y = 0.0;
 
 1385     float parentObject_rotation = 0.0;
 
 1391         long parent_frame_number = frame->number + parent_start_offset;
 
 1394         parentObject_location_x = parentClipObject->
location_x.
GetValue(parent_frame_number);
 
 1395         parentObject_location_y = parentClipObject->
location_y.
GetValue(parent_frame_number);
 
 1396         parentObject_scale_x = parentClipObject->
scale_x.
GetValue(parent_frame_number);
 
 1397         parentObject_scale_y = parentClipObject->
scale_y.
GetValue(parent_frame_number);
 
 1398         parentObject_shear_x = parentClipObject->
shear_x.
GetValue(parent_frame_number);
 
 1399         parentObject_shear_y = parentClipObject->
shear_y.
GetValue(parent_frame_number);
 
 1400         parentObject_rotation = parentClipObject->
rotation.
GetValue(parent_frame_number);
 
 1406         Clip* parentClip = (
Clip*) parentTrackedObject->ParentClip();
 
 1411             long parent_frame_number = frame->number + parent_start_offset;
 
 1414             std::map<std::string, float> trackedObjectProperties = parentTrackedObject->GetBoxValues(parent_frame_number);
 
 1418                                            parentClip->
scale, width, height);
 
 1421             int trackedWidth = trackedObjectProperties[
"w"] * trackedObjectProperties[
"sx"] * parent_size.width() *
 
 1423             int trackedHeight = trackedObjectProperties[
"h"] * trackedObjectProperties[
"sy"] * parent_size.height() *
 
 1427             source_size = scale_size(source_size, 
scale, trackedWidth, trackedHeight);
 
 1430             parentObject_location_x = parentClip->
location_x.
GetValue(parent_frame_number) + ((trackedObjectProperties[
"cx"] - 0.5) * parentClip->
scale_x.
GetValue(parent_frame_number));
 
 1431             parentObject_location_y = parentClip->
location_y.
GetValue(parent_frame_number) + ((trackedObjectProperties[
"cy"] - 0.5) * parentClip->
scale_y.
GetValue(parent_frame_number));
 
 1432             parentObject_rotation = trackedObjectProperties[
"r"] + parentClip->
rotation.
GetValue(parent_frame_number);
 
 1445     if(parentObject_scale_x != 0.0 && parentObject_scale_y != 0.0){
 
 1446         sx*= parentObject_scale_x;
 
 1447         sy*= parentObject_scale_y;
 
 1450     float scaled_source_width = source_size.width() * sx;
 
 1451     float scaled_source_height = source_size.height() * sy;
 
 1459             x = (width - scaled_source_width) / 2.0; 
 
 1462             x = width - scaled_source_width; 
 
 1465             y = (height - scaled_source_height) / 2.0; 
 
 1468             x = (width - scaled_source_width) / 2.0; 
 
 1469             y = (height - scaled_source_height) / 2.0; 
 
 1472             x = width - scaled_source_width; 
 
 1473             y = (height - scaled_source_height) / 2.0; 
 
 1476             y = (height - scaled_source_height); 
 
 1479             x = (width - scaled_source_width) / 2.0; 
 
 1480             y = (height - scaled_source_height); 
 
 1483             x = width - scaled_source_width; 
 
 1484             y = (height - scaled_source_height); 
 
 1490         "Clip::get_transform (Gravity)",
 
 1491         "frame->number", frame->number,
 
 1492         "source_clip->gravity", 
gravity,
 
 1493         "scaled_source_width", scaled_source_width,
 
 1494         "scaled_source_height", scaled_source_height);
 
 1496     QTransform transform;
 
 1502     float shear_x_value = 
shear_x.
GetValue(frame->number) + parentObject_shear_x;
 
 1503     float shear_y_value = 
shear_y.
GetValue(frame->number) + parentObject_shear_y;
 
 1509         "Clip::get_transform (Build QTransform - if needed)",
 
 1510         "frame->number", frame->number,
 
 1513         "sx", sx, 
"sy", sy);
 
 1515     if (!isNear(x, 0) || !isNear(y, 0)) {
 
 1517         transform.translate(x, y);
 
 1519     if (!isNear(r, 0) || !isNear(shear_x_value, 0) || !isNear(shear_y_value, 0)) {
 
 1521         float origin_x_offset = (scaled_source_width * origin_x_value);
 
 1522         float origin_y_offset = (scaled_source_height * origin_y_value);
 
 1523         transform.translate(origin_x_offset, origin_y_offset);
 
 1524         transform.rotate(r);
 
 1525         transform.shear(shear_x_value, shear_y_value);
 
 1526         transform.translate(-origin_x_offset,-origin_y_offset);
 
 1529     float source_width_scale = (float(source_size.width()) / float(source_image->width())) * sx;
 
 1530     float source_height_scale = (float(source_size.height()) / float(source_image->height())) * sy;
 
 1531     if (!isNear(source_width_scale, 1.0) || !isNear(source_height_scale, 1.0)) {
 
 1532         transform.scale(source_width_scale, source_height_scale);
 
 1539 int64_t Clip::adjust_timeline_framenumber(int64_t clip_frame_number) {
 
 1556     int64_t frame_number = clip_frame_number + clip_start_position - clip_start_frame;
 
 1558     return frame_number;