mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-07 07:14:56 +01:00
inching pretty close to fully working waves now
This commit is contained in:
parent
79384aeb66
commit
f9d30cf41a
1 changed files with 67 additions and 35 deletions
|
|
@ -142,6 +142,18 @@ to_pixel_offset (frameoffset_t src_sample_start, double sample_offset, double sp
|
||||||
return llrintf ((sample_offset - src_sample_start) / spp);
|
return llrintf ((sample_offset - src_sample_start) / spp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline double
|
||||||
|
image_to_window (double wave_origin, double image_start)
|
||||||
|
{
|
||||||
|
return wave_origin + image_start;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline double
|
||||||
|
window_to_image (double wave_origin, double image_start)
|
||||||
|
{
|
||||||
|
return image_start - wave_origin;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
WaveView::render (Rect const & area, Cairo::RefPtr<Cairo::Context> context) const
|
WaveView::render (Rect const & area, Cairo::RefPtr<Cairo::Context> context) const
|
||||||
{
|
{
|
||||||
|
|
@ -158,23 +170,33 @@ WaveView::render (Rect const & area, Cairo::RefPtr<Cairo::Context> context) cons
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* we have a set of cached images that have precise pixel positions
|
||||||
|
* whose origin is 0,0 within our own rect. To convert these pixel
|
||||||
|
* positions so that they are useful when rendering, they need to
|
||||||
|
* be offset by the window position of our own origin. This is given
|
||||||
|
* by self.x0
|
||||||
|
*/
|
||||||
|
|
||||||
Rect draw = d.get();
|
Rect draw = d.get();
|
||||||
|
|
||||||
|
|
||||||
/* pixel coordinates */
|
/* pixel coordinates */
|
||||||
|
|
||||||
double start = floor (draw.x0);
|
double start = floor (draw.x0);
|
||||||
double const end = ceil (draw.x1);
|
double const end = ceil (draw.x1);
|
||||||
|
|
||||||
list<CacheEntry*>::iterator cache = _cache.begin ();
|
cerr << this << ' ' << name << " draw " << start << " .. " << end << endl;
|
||||||
|
|
||||||
|
list<CacheEntry*>::iterator cache;
|
||||||
|
|
||||||
cache = _cache.begin ();
|
cache = _cache.begin ();
|
||||||
|
|
||||||
while ((end - start) > 1.0) {
|
while (end > start) {
|
||||||
|
|
||||||
/* Step through cache entries that end at or before our current position */
|
/* Step through cache entries that end at or before our current position */
|
||||||
|
|
||||||
for (; cache != _cache.end(); ++cache) {
|
for (; cache != _cache.end(); ++cache) {
|
||||||
if ((*cache)->pixel_start() <= start) {
|
if (image_to_window (self.x0, (*cache)->pixel_start()) <= start) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -194,6 +216,8 @@ WaveView::render (Rect const & area, Cairo::RefPtr<Cairo::Context> context) cons
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CacheEntry* image = 0;
|
CacheEntry* image = 0;
|
||||||
|
|
||||||
|
/* Cairo limit, caused by its use of 16.16 fixed point */
|
||||||
const double BIG_IMAGE_SIZE = 32767.0;
|
const double BIG_IMAGE_SIZE = 32767.0;
|
||||||
|
|
||||||
if (cache == _cache.end ()) {
|
if (cache == _cache.end ()) {
|
||||||
|
|
@ -206,27 +230,26 @@ WaveView::render (Rect const & area, Cairo::RefPtr<Cairo::Context> context) cons
|
||||||
as possible, within the limits inherent in Cairo.
|
as possible, within the limits inherent in Cairo.
|
||||||
|
|
||||||
However, we don't want to try to make it larger than
|
However, we don't want to try to make it larger than
|
||||||
the region actually is, so clamp with that too.
|
the source could allow, so clamp with that too.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
double const rend = floor (_region->length() / _samples_per_pixel);
|
double const region_end_pixel = image_to_window (self.x0, floor (_region->latest_possible_frame() / _samples_per_pixel));
|
||||||
double const end_pixel = min (rend, max (end, BIG_IMAGE_SIZE));
|
double const end_pixel = min (region_end_pixel, start + BIG_IMAGE_SIZE);
|
||||||
|
|
||||||
if ((end_pixel - start) < 1.0) {
|
cerr << "Need new image " << start << " .. " << end_pixel << " (region end = " << region_end_pixel << ")" << endl;
|
||||||
|
|
||||||
|
if (end_pixel <= start) {
|
||||||
/* nothing more to draw */
|
/* nothing more to draw */
|
||||||
break;
|
image = 0;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
CacheEntry* c = new CacheEntry (this, window_to_image (self.x0, start), window_to_image (self.x0, end_pixel));
|
||||||
|
|
||||||
|
_cache.push_back (c);
|
||||||
|
image = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
cerr << "Create new cache entry to grow cache,"
|
} else if (image_to_window (self.x0, (*cache)->pixel_start()) > start) {
|
||||||
<< " range is " << start << " .. " << end_pixel
|
|
||||||
<< endl;
|
|
||||||
|
|
||||||
CacheEntry* c = new CacheEntry (this, start, end_pixel);
|
|
||||||
|
|
||||||
_cache.push_back (c);
|
|
||||||
image = c;
|
|
||||||
|
|
||||||
} else if ((*cache)->pixel_start() > start) {
|
|
||||||
|
|
||||||
/* Case 2: we have a cache entry, but it begins after
|
/* Case 2: we have a cache entry, but it begins after
|
||||||
* start, so we need another one for the missing section.
|
* start, so we need another one for the missing section.
|
||||||
|
|
@ -238,18 +261,16 @@ WaveView::render (Rect const & area, Cairo::RefPtr<Cairo::Context> context) cons
|
||||||
|
|
||||||
double end_pixel;
|
double end_pixel;
|
||||||
|
|
||||||
if (end < (*cache)->pixel_start()) {
|
if (end > image_to_window (self.x0, (*cache)->pixel_start())) {
|
||||||
double const rend = floor (_region->length() / _samples_per_pixel);
|
double const region_end_pixel = image_to_window (self.x0, floor (_region->length() / _samples_per_pixel));
|
||||||
end_pixel = min (rend, max (end, BIG_IMAGE_SIZE));
|
end_pixel = min (region_end_pixel, max (image_to_window (self.x0, (*cache)->pixel_start()), start + BIG_IMAGE_SIZE));
|
||||||
} else {
|
} else {
|
||||||
end_pixel = (*cache)->pixel_start();
|
end_pixel = image_to_window (self.x0, (*cache)->pixel_start());
|
||||||
}
|
}
|
||||||
|
|
||||||
cerr << "Create new cache entry to reach " << (*cache)->pixel_start()
|
cerr << "Need fill image " << start << " .. " << end_pixel << endl;
|
||||||
<< " range is " << start << " .. " << end_pixel
|
|
||||||
<< endl;
|
|
||||||
|
|
||||||
CacheEntry* c = new CacheEntry (this, start, end_pixel);
|
CacheEntry* c = new CacheEntry (this, window_to_image (self.x0, start), window_to_image (self.x0, end_pixel));
|
||||||
|
|
||||||
cache = _cache.insert (cache, c);
|
cache = _cache.insert (cache, c);
|
||||||
++cache;
|
++cache;
|
||||||
|
|
@ -257,16 +278,23 @@ WaveView::render (Rect const & area, Cairo::RefPtr<Cairo::Context> context) cons
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
/* Case 3: we have a cache entry that will do at least some of what
|
/* Case 3: we have a cache entry that covers some of what
|
||||||
we have left, so render it.
|
we have left to render
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
image = *cache;
|
image = *cache;
|
||||||
++cache;
|
++cache;
|
||||||
|
|
||||||
|
cerr << "have image to " << image->pixel_end() << " win = " << image_to_window (self.x0, image->pixel_end()) << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
double this_end = min (end, image->pixel_end ());
|
if (!image) {
|
||||||
double const image_origin = image->pixel_start ();
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
double this_end = min (end, image_to_window (self.x0, image->pixel_end ()));
|
||||||
|
double const image_origin = image_to_window (self.x0, image->pixel_start ());
|
||||||
#if 0
|
#if 0
|
||||||
cerr << "\t\tDraw image between "
|
cerr << "\t\tDraw image between "
|
||||||
<< start
|
<< start
|
||||||
|
|
@ -276,11 +304,15 @@ WaveView::render (Rect const & area, Cairo::RefPtr<Cairo::Context> context) cons
|
||||||
<< image->pixel_start()
|
<< image->pixel_start()
|
||||||
<< " .. "
|
<< " .. "
|
||||||
<< image->pixel_end ()
|
<< image->pixel_end ()
|
||||||
|
<< " WINDOW = "
|
||||||
|
<< image_to_window (self.x0, image->pixel_start())
|
||||||
|
<< " .. "
|
||||||
|
<< image_to_window (self.x0, image->pixel_end())
|
||||||
<< endl;
|
<< endl;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
context->rectangle (start, draw.y0, this_end - start, _height);
|
context->rectangle (start, draw.y0, this_end - start, draw.height());
|
||||||
context->set_source (image->image(), self.x0 - image_origin, self.y0);
|
context->set_source (image->image(), self.x0 + (start - image_origin), self.y0);
|
||||||
context->fill ();
|
context->fill ();
|
||||||
|
|
||||||
start = this_end;
|
start = this_end;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue