sge::opengl::vf::client_state_combiner::~client_state_combiner() { apply_difference( old_states_.normal_states(), new_states_.normal_states(), sge::opengl::enable_client_state, sge::opengl::disable_client_state ); apply_difference( old_states_.texture_states(), new_states_.texture_states(), std::bind( sge::opengl::vf::enable_texcoords, std::ref( log_ ), std::ref( context_ ), std::placeholders::_1 ), std::bind( sge::opengl::vf::disable_texcoords, std::ref( log_ ), std::ref( context_ ), std::placeholders::_1 ) ); apply_difference( old_states_.attribute_states(), new_states_.attribute_states(), std::bind( sge::opengl::vf::enable_vertex_attrib_array, std::ref( attribute_context_ ), std::placeholders::_1 ), std::bind( sge::opengl::vf::disable_vertex_attrib_array, std::ref( attribute_context_ ), std::placeholders::_1 ) ); vf_context_.state( new_states_ ); }
char* UndoStackItem::get_data() { // Find latest key buffer UndoStackItem *current = this; while(current && !current->key) current = PREVIOUS; if(!current) { printf("UndoStackItem::get_data: no key buffer found!\n"); return 0; } // This is the key buffer if(current == this) { char *result = new char[data_size]; memcpy(result, data, data_size); return result; } // Get key buffer char *current_data = current->get_data(); int current_size = current->get_size(); current = NEXT; while(current) { // Do incremental updates int new_size; char *new_data = (char*)apply_difference((unsigned char*)current_data, current_size, (unsigned char*)current->get_incremental_data(), current->get_incremental_size(), &new_size); delete [] current_data; if(current == this) return new_data; else { current_data = new_data; current_size = new_size; current = NEXT; } } // Never hit this object. delete [] current_data; printf("UndoStackItem::get_data: lost starting object!\n"); return 0; }
void UndoStackItem::set_data(char *data) { delete [] this->data; this->data = 0; this->data_size = 0; // Search for key buffer within interval int need_key = 1; UndoStackItem *current = this; this->key = 0; for(int i = 0; i < UNDO_KEY_INTERVAL && current; i++) { if(current->key && current->has_data()) { need_key = 0; break; } else current = PREVIOUS; } int new_size = strlen(data) + 1; if(!need_key) { // Reconstruct previous data for difference char *prev_buffer = previous->get_data(); int prev_size = prev_buffer ? strlen(prev_buffer) + 1 : 0; // Timer timer; // timer.update(); // printf("UndoStackItem::set_data 1\n"); this->data = (char*)get_difference_fast((unsigned char*)prev_buffer, prev_size, (unsigned char*)data, new_size, &this->data_size, 0); //printf("UndoStackItem::set_data 2 %lld\n", timer.get_difference()); // Testing // FILE *test1 = fopen("/tmp/undo1", "w"); // fwrite(prev_buffer, prev_size, 1, test1); // fclose(test1); // FILE *test2 = fopen("/tmp/undo2", "w"); // fwrite(data, new_size, 1, test2); // fclose(test2); // FILE *test3 = fopen("/tmp/undo2.diff", "w"); // fwrite(this->data, this->data_size, 1, test3); // fclose(test3); // //printf("UndoStackItem::set_data 3 %d %d\n", new_size, this->data_size); // Diff was bigger than original. // Happens if a lot of tiny changes happened and the record headers // took more space than the changes. if(this->data_size > new_size) { delete [] this->data; this->data_size = 0; need_key = 1; } else { // Reconstruct current data from difference int test_size; char *test_buffer = (char*)apply_difference((unsigned char*)prev_buffer, prev_size, (unsigned char*)this->data, this->data_size, &test_size); if(test_size != new_size || memcmp(test_buffer, data, test_size)) { // FILE *test1 = fopen("/tmp/undo1", "w"); // fwrite(prev_buffer, prev_size, 1, test1); // fclose(test1); // FILE *test2 = fopen("/tmp/undo2", "w"); // fwrite(data, new_size, 1, test2); // fclose(test2); // FILE *test3 = fopen("/tmp/undo2.diff", "w"); // fwrite(this->data, this->data_size, 1, test3); // fclose(test3); // FILE *test4 = fopen("/tmp/undo3", "w"); // fwrite(test_buffer, test_size, 1, test4); // fclose(test4); printf("UndoStackItem::set_data: incremental undo failed!\n"); need_key = 1; delete [] this->data; this->data_size = 0; this->data = 0; } delete [] test_buffer; } delete [] prev_buffer; } if(need_key) { this->key = 1; this->data_size = new_size; this->data = new char[this->data_size]; memcpy(this->data, data, this->data_size); } return; }