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
WaveView::render (Rect const & area, Cairo::RefPtr<Cairo::Context> context) const
{
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();
+
/* pixel coordinates */
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 ();
- while ((end - start) > 1.0) {
+ while (end > start) {
/* Step through cache entries that end at or before our current position */
for (; cache != _cache.end(); ++cache) {
- if ((*cache)->pixel_start() <= start) {
+ if (image_to_window (self.x0, (*cache)->pixel_start()) <= start) {
break;
}
}
*/
CacheEntry* image = 0;
- const double BIG_IMAGE_SIZE = 32767.0;
+
+ /* Cairo limit, caused by its use of 16.16 fixed point */
+ const double BIG_IMAGE_SIZE = 32767.0;
if (cache == _cache.end ()) {
as possible, within the limits inherent in Cairo.
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 end_pixel = min (rend, max (end, BIG_IMAGE_SIZE));
+ double const region_end_pixel = image_to_window (self.x0, floor (_region->latest_possible_frame() / _samples_per_pixel));
+ double const end_pixel = min (region_end_pixel, start + BIG_IMAGE_SIZE);
- if ((end_pixel - start) < 1.0) {
- /* nothing more to draw */
- break;
- }
-
- cerr << "Create new cache entry to grow cache,"
- << " range is " << start << " .. " << end_pixel
- << endl;
+ cerr << "Need new image " << start << " .. " << end_pixel << " (region end = " << region_end_pixel << ")" << endl;
- CacheEntry* c = new CacheEntry (this, start, end_pixel);
+ if (end_pixel <= start) {
+ /* nothing more to draw */
+ image = 0;
+ } else {
- _cache.push_back (c);
- image = c;
+ CacheEntry* c = new CacheEntry (this, window_to_image (self.x0, start), window_to_image (self.x0, end_pixel));
+
+ _cache.push_back (c);
+ image = c;
+ }
- } else if ((*cache)->pixel_start() > start) {
+ } else if (image_to_window (self.x0, (*cache)->pixel_start()) > start) {
/* Case 2: we have a cache entry, but it begins after
* start, so we need another one for the missing section.
double end_pixel;
- if (end < (*cache)->pixel_start()) {
- double const rend = floor (_region->length() / _samples_per_pixel);
- end_pixel = min (rend, max (end, BIG_IMAGE_SIZE));
+ if (end > image_to_window (self.x0, (*cache)->pixel_start())) {
+ double const region_end_pixel = image_to_window (self.x0, floor (_region->length() / _samples_per_pixel));
+ end_pixel = min (region_end_pixel, max (image_to_window (self.x0, (*cache)->pixel_start()), start + BIG_IMAGE_SIZE));
} 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()
- << " range is " << start << " .. " << end_pixel
- << endl;
-
- CacheEntry* c = new CacheEntry (this, start, end_pixel);
+ cerr << "Need fill image " << start << " .. " << end_pixel << endl;
+
+ CacheEntry* c = new CacheEntry (this, window_to_image (self.x0, start), window_to_image (self.x0, end_pixel));
cache = _cache.insert (cache, c);
++cache;
} else {
- /* Case 3: we have a cache entry that will do at least some of what
- we have left, so render it.
+ /* Case 3: we have a cache entry that covers some of what
+ we have left to render
*/
+
image = *cache;
++cache;
+
+ cerr << "have image to " << image->pixel_end() << " win = " << image_to_window (self.x0, image->pixel_end()) << endl;
+ }
+
+ if (!image) {
+ break;
}
- double this_end = min (end, image->pixel_end ());
- double const image_origin = image->pixel_start ();
+ 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
cerr << "\t\tDraw image between "
<< start
<< image->pixel_start()
<< " .. "
<< image->pixel_end ()
+ << " WINDOW = "
+ << image_to_window (self.x0, image->pixel_start())
+ << " .. "
+ << image_to_window (self.x0, image->pixel_end())
<< endl;
#endif
- context->rectangle (start, draw.y0, this_end - start, _height);
- context->set_source (image->image(), self.x0 - image_origin, self.y0);
+ context->rectangle (start, draw.y0, this_end - start, draw.height());
+ context->set_source (image->image(), self.x0 + (start - image_origin), self.y0);
context->fill ();
start = this_end;