// Go down shadow layer tree and apply transformations for scrollable layers.
static void
TransformShadowTree(nsDisplayListBuilder* aBuilder, nsFrameLoader* aFrameLoader,
                    nsIFrame* aFrame, Layer* aLayer,
                    const ViewTransform& aTransform)
{
  ShadowLayer* shadow = aLayer->AsShadowLayer();
  shadow->SetShadowClipRect(aLayer->GetClipRect());
  shadow->SetShadowVisibleRegion(aLayer->GetVisibleRegion());

  const FrameMetrics* metrics = GetFrameMetrics(aLayer);

  gfx3DMatrix shadowTransform;
  ViewTransform layerTransform = aTransform;

  if (metrics && metrics->IsScrollable()) {
    const ViewID scrollId = metrics->mScrollId;
    const nsContentView* view =
      aFrameLoader->GetCurrentRemoteFrame()->GetContentView(scrollId);
    NS_ABORT_IF_FALSE(view, "Array of views should be consistent with layer tree");
    const gfx3DMatrix& currentTransform = aLayer->GetTransform();

    ViewTransform viewTransform = ComputeShadowTreeTransform(
      aFrame, aFrameLoader, metrics, view->GetViewConfig(),
      1 / (GetXScale(currentTransform)*layerTransform.mXScale),
      1 / (GetYScale(currentTransform)*layerTransform.mYScale)
    );

    // Apply the layer's own transform *before* the view transform
    shadowTransform = gfx3DMatrix(viewTransform) * currentTransform;

    if (metrics->IsRootScrollable()) {
      layerTransform.mTranslation = viewTransform.mTranslation;
      // Apply the root frame translation *before* we do the rest of the transforms.
      nsIntPoint rootFrameOffset = GetRootFrameOffset(aFrame, aBuilder);
      shadowTransform = shadowTransform *
          gfx3DMatrix::Translation(float(rootFrameOffset.x), float(rootFrameOffset.y), 0.0);
      layerTransform.mXScale *= GetXScale(currentTransform);
      layerTransform.mYScale *= GetYScale(currentTransform);
    }
  } else {
    shadowTransform = aLayer->GetTransform();
  }

  if (aLayer->GetIsFixedPosition() &&
      !aLayer->GetParent()->GetIsFixedPosition()) {
    ReverseTranslate(shadowTransform, layerTransform);
    const nsIntRect* clipRect = shadow->GetShadowClipRect();
    if (clipRect) {
      nsIntRect transformedClipRect(*clipRect);
      transformedClipRect.MoveBy(shadowTransform._41, shadowTransform._42);
      shadow->SetShadowClipRect(&transformedClipRect);
    }
  }

  shadow->SetShadowTransform(shadowTransform);
  for (Layer* child = aLayer->GetFirstChild();
       child; child = child->GetNextSibling()) {
    TransformShadowTree(aBuilder, aFrameLoader, aFrame, child, layerTransform);
  }
}
// Use shadow layer tree to build display list for the browser's frame.
static void
BuildListForLayer(Layer* aLayer,
                  nsFrameLoader* aRootFrameLoader,
                  const gfx3DMatrix& aTransform,
                  nsDisplayListBuilder* aBuilder,
                  nsDisplayList& aShadowTree,
                  nsIFrame* aSubdocFrame)
{
  const FrameMetrics* metrics = GetFrameMetrics(aLayer);

  gfx3DMatrix transform;

  if (metrics && metrics->IsScrollable()) {
    const ViewID scrollId = metrics->mScrollId;

    // We need to figure out the bounds of the scrollable region using the
    // shadow layer tree from the remote process. The metrics viewport is
    // defined based on all the transformations of its parent layers and
    // the scale of the current layer.

    // Calculate transform for this layer.
    nsContentView* view =
      aRootFrameLoader->GetCurrentRemoteFrame()->GetContentView(scrollId);
    // XXX why don't we include aLayer->GetTransform() in the inverse-scale here?
    // This seems wrong, but it doesn't seem to cause bugs!
    gfx3DMatrix applyTransform = ComputeShadowTreeTransform(
      aSubdocFrame, aRootFrameLoader, metrics, view->GetViewConfig(),
      1 / GetXScale(aTransform), 1 / GetYScale(aTransform));
    transform = applyTransform * aLayer->GetTransform() * aTransform;

    // As mentioned above, bounds calculation also depends on the scale
    // of this layer.
    gfx3DMatrix tmpTransform = aTransform;
    Scale(tmpTransform, GetXScale(applyTransform), GetYScale(applyTransform));

    // Calculate rect for this layer based on aTransform.
    nsRect bounds;
    {
      nscoord auPerDevPixel = aSubdocFrame->PresContext()->AppUnitsPerDevPixel();
      bounds = metrics->mViewport.ToAppUnits(auPerDevPixel);
      ApplyTransform(bounds, tmpTransform, auPerDevPixel);

    }

    aShadowTree.AppendToTop(
      new (aBuilder) nsDisplayRemoteShadow(aBuilder, aSubdocFrame, bounds, scrollId));

  } else {
    transform = aLayer->GetTransform() * aTransform;
  }

  for (Layer* child = aLayer->GetFirstChild(); child;
       child = child->GetNextSibling()) {
    BuildListForLayer(child, aRootFrameLoader, transform,
                      aBuilder, aShadowTree, aSubdocFrame);
  }
}
Esempio n. 3
0
// --------------------------------------------------------------
// Called by: GRPage, GRStaff, GRSystem
void
GDeviceWin32::OffsetOrigin( float x, float y )
{
//	const float prevX = mOriginX;
//	const float prevY = mOriginY;
	mOriginX += x;
	mOriginY += y;
	mWinOriginX += (x) * GetXScale(); // (JB) test
	mWinOriginY += (y) * GetYScale();
	::SetViewportOrgEx( mHDC, RInt( mWinOriginX ), RInt( mWinOriginY ), NULL );
}
// Recursively create a new array of scrollables, preserving any scrollables
// that are still in the layer tree.
//
// aXScale and aYScale are used to calculate any values that need to be in
// chrome-document CSS pixels and aren't part of the rendering loop, such as
// the initial scroll offset for a new view.
static void
BuildViewMap(ViewMap& oldContentViews, ViewMap& newContentViews,
             nsFrameLoader* aFrameLoader, Layer* aLayer,
             float aXScale = 1, float aYScale = 1)
{
  ContainerLayer* container = aLayer->AsContainerLayer();
  if (!container)
    return;
  const FrameMetrics metrics = container->GetFrameMetrics();
  const ViewID scrollId = metrics.mScrollId;
  const gfx3DMatrix transform = aLayer->GetTransform();
  aXScale *= GetXScale(transform);
  aYScale *= GetYScale(transform);

  if (metrics.IsScrollable()) {
    nscoord auPerDevPixel = aFrameLoader->GetPrimaryFrameOfOwningContent()
                                        ->PresContext()->AppUnitsPerDevPixel();
    nsContentView* view = FindViewForId(oldContentViews, scrollId);
    if (view) {
      // View already exists. Be sure to propagate scales for any values
      // that need to be calculated something in chrome-doc CSS pixels.
      ViewConfig config = view->GetViewConfig();
      aXScale *= config.mXScale;
      aYScale *= config.mYScale;
      view->mFrameLoader = aFrameLoader;
    } else {
      // View doesn't exist, so generate one. We start the view scroll offset at
      // the same position as the framemetric's scroll offset from the layer.
      // The default scale is 1, so no need to propagate scale down.
      ViewConfig config;
      config.mScrollOffset = nsPoint(
        NSIntPixelsToAppUnits(metrics.mViewportScrollOffset.x, auPerDevPixel) * aXScale,
        NSIntPixelsToAppUnits(metrics.mViewportScrollOffset.y, auPerDevPixel) * aYScale);
      view = new nsContentView(aFrameLoader, scrollId, config);
    }

    view->mViewportSize = nsSize(
      NSIntPixelsToAppUnits(metrics.mViewport.width, auPerDevPixel) * aXScale,
      NSIntPixelsToAppUnits(metrics.mViewport.height, auPerDevPixel) * aYScale);
    view->mContentSize = nsSize(
      NSIntPixelsToAppUnits(metrics.mContentSize.width, auPerDevPixel) * aXScale,
      NSIntPixelsToAppUnits(metrics.mContentSize.height, auPerDevPixel) * aYScale);

    newContentViews[scrollId] = view;
  }

  for (Layer* child = aLayer->GetFirstChild();
       child; child = child->GetNextSibling()) {
    BuildViewMap(oldContentViews, newContentViews, aFrameLoader, child,
                 aXScale, aYScale);
  }
}
Esempio n. 5
0
// --------------------------------------------------------------
void
GDeviceWin32::SetOrigin( float x, float y )
{
	const float prevX	= mOriginX;
	const float prevY	= mOriginY;
	mOriginX			= x;	// voir def dans VGDev.cpp
	mOriginY			= y;
	mWinOriginX += (x - prevX) * GetXScale(); // (JB) test
	mWinOriginY += (y - prevY) * GetYScale();
//	mWinOriginX += (x - prevX) ; // (JB) test
//	mWinOriginY += (y - prevY) ;
	::SetViewportOrgEx( mHDC, RInt( mWinOriginX ), RInt( mWinOriginY ), NULL );
}
Esempio n. 6
0
// --------------------------------------------------------------
bool GDeviceWin32::Win32ApplyTransform()
{
	const float xScale = GetXScale();
	const float yScale = GetYScale();
	float width, height, newWidth, newHeight;

	// - Original code, the standard way to calculate new size.
	width = (float)GetWidth();
	height = (float)GetHeight();
	newWidth = width * xScale;
	newHeight = height * yScale;

	// Win95 : Coordinates can't be larger than 16 bit.
	if( mMaximizeAxis || width > 32000 || height > 32000
						|| newWidth > 32000 || newHeight > 32000 )
	{
		// Then, use the largest extent possible, but under 32000
		if( xScale <= 1 ) {
			width = 32000;
			newWidth = width * xScale;
		} else {
			newWidth = 32000;
			width = newWidth / xScale;
		}

		if( yScale <= 1 ) {
			height = 32000;
			newHeight = height * yScale;
		} else {
			newHeight = 32000;
			height = newHeight / yScale;
		}
	}

	BOOL result;
	// OK for everything but print preview ->
	result = ::SetWindowExtEx( mHDC, RInt( width ), RInt( height ), NULL );
	result = ::SetViewportExtEx( mHDC, RInt( newWidth ), RInt( newHeight ), NULL );
	return true;
}
Esempio n. 7
0
/**
 * Attempts to initialize the graphical video display.  Returns 0 on
 * success, -1 on failure.
 */
int
InitVideo(FCEUGI *gi)
{
	// XXX soules - const?  is this necessary?
	const SDL_VideoInfo *vinf;
	int error, flags = 0;
	int doublebuf, xstretch, ystretch, xres, yres, show_fps;

	FCEUI_printf("Initializing video...");

	// load the relevant configuration variables
	g_config->getOption("SDL.Fullscreen", &s_fullscreen);
	g_config->getOption("SDL.DoubleBuffering", &doublebuf);
#ifdef OPENGL
	g_config->getOption("SDL.OpenGL", &s_useOpenGL);
#endif
	g_config->getOption("SDL.SpecialFilter", &s_sponge);
	g_config->getOption("SDL.XStretch", &xstretch);
	g_config->getOption("SDL.YStretch", &ystretch);
	g_config->getOption("SDL.LastXRes", &xres);
	g_config->getOption("SDL.LastYRes", &yres);
	g_config->getOption("SDL.ClipSides", &s_clipSides);
	g_config->getOption("SDL.NoFrame", &noframe);
	g_config->getOption("SDL.ShowFPS", &show_fps);

	// check the starting, ending, and total scan lines
	FCEUI_GetCurrentVidSystem(&s_srendline, &s_erendline);
	s_tlines = s_erendline - s_srendline + 1;

	// check if we should auto-set x/y resolution

    // check for OpenGL and set the global flags
#if OPENGL
	if(s_useOpenGL && !s_sponge) {
		flags = SDL_OPENGL;
	}
#endif

	// initialize the SDL video subsystem if it is not already active
	if(!SDL_WasInit(SDL_INIT_VIDEO)) {
		error = SDL_InitSubSystem(SDL_INIT_VIDEO);
		if(error) {
			FCEUD_PrintError(SDL_GetError());
			return -1;
		}
	}
	s_inited = 1;

	// shows the cursor within the display window
	SDL_ShowCursor(1);

	// determine if we can allocate the display on the video card
	vinf = SDL_GetVideoInfo();
	if(vinf->hw_available) {
		flags |= SDL_HWSURFACE;
	}
    
	// get the monitor's current resolution if we do not already have it
	if(s_nativeWidth < 0) {
		s_nativeWidth = vinf->current_w;
	}
	if(s_nativeHeight < 0) {
		s_nativeHeight = vinf->current_h;
	}

	// check to see if we are showing FPS
	FCEUI_SetShowFPS(show_fps);
    
	// check if we are rendering fullscreen
	if(s_fullscreen) {
		int no_cursor;
		g_config->getOption("SDL.NoFullscreenCursor", &no_cursor);
		flags |= SDL_FULLSCREEN;
		SDL_ShowCursor(!no_cursor);
	}
	else {
		SDL_ShowCursor(1);
	}
    
	if(noframe) {
		flags |= SDL_NOFRAME;
	}

	// gives the SDL exclusive palette control... ensures the requested colors
	// flags |= SDL_HWPALETTE;

	// enable double buffering if requested and we have hardware support
#ifdef OPENGL
	if(s_useOpenGL) {
		FCEU_printf("Initializing with OpenGL (Disable with '--opengl 0').\n");
		if(doublebuf) {
			 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
		}
	} else
#endif
		if(doublebuf && (flags & SDL_HWSURFACE)) {
			flags |= SDL_DOUBLEBUF;
		}

	if(s_fullscreen) {
		int desbpp, autoscale;
		g_config->getOption("SDL.BitsPerPixel", &desbpp);
		g_config->getOption("SDL.AutoScale", &autoscale);
		if (autoscale)
		{
			double auto_xscale = GetXScale(xres);
			double auto_yscale = GetYScale(yres);
			double native_ratio = ((double)NWIDTH) / s_tlines;
			double screen_ratio = ((double)xres) / yres;
			int keep_ratio;
            
			g_config->getOption("SDL.KeepRatio", &keep_ratio);
            
			// Try to choose resolution
			if (screen_ratio < native_ratio)
			{
				// The screen is narrower than the original. Maximizing width will not clip
				auto_xscale = auto_yscale = GetXScale(xres);
				if (keep_ratio) 
					auto_yscale = GetYScale(yres);
			}
			else
			{
				auto_yscale = auto_xscale = GetYScale(yres);
				if (keep_ratio) 
					auto_xscale = GetXScale(xres);
			}
			s_exs = auto_xscale;
			s_eys = auto_yscale;
		}
		else
		{
			g_config->getOption("SDL.XScale", &s_exs);
			g_config->getOption("SDL.YScale", &s_eys);
		}
		g_config->getOption("SDL.SpecialFX", &s_eefx);

#ifdef OPENGL
		if(!s_useOpenGL) {
			s_exs = (int)s_exs;
			s_eys = (int)s_eys;
		} else {
			desbpp = 0;
		}
        
		// -Video Modes Tag-
		if(s_sponge) {
			if(s_sponge == 4 || s_sponge == 5) {
				s_exs = s_eys = 3;
			} else {
				s_exs = s_eys = 2;
			}
			s_eefx = 0;
			if(s_sponge == 1 || s_sponge == 4) {
				desbpp = 32;
			}
		}

		if((s_useOpenGL && !xstretch) || !s_useOpenGL)
#endif
			if(xres < (NWIDTH * s_exs) || s_exs <= 0.01) {
				FCEUD_PrintError("xscale out of bounds.");
				KillVideo();
				return -1;
			}

#ifdef OPENGL
		if((s_useOpenGL && !ystretch) || !s_useOpenGL)
#endif
			if(yres < s_tlines * s_eys || s_eys <= 0.01) {
				FCEUD_PrintError("yscale out of bounds.");
				KillVideo();
				return -1;
			}

#ifdef OPENGL
		s_screen = SDL_SetVideoMode(s_useOpenGL ? s_nativeWidth : xres,
									s_useOpenGL ? s_nativeHeight : yres,
									desbpp, flags);
#else
		s_screen = SDL_SetVideoMode(xres, yres, desbpp, flags);
#endif

		if(!s_screen) {
			FCEUD_PrintError(SDL_GetError());
			return -1;
		}
	} else {
		int desbpp;
		g_config->getOption("SDL.BitsPerPixel", &desbpp);

		g_config->getOption("SDL.XScale", &s_exs);
		g_config->getOption("SDL.YScale", &s_eys);
		g_config->getOption("SDL.SpecialFX", &s_eefx);
        
		// -Video Modes Tag-
		if(s_sponge) {
			if(s_sponge >= 4) {
				s_exs = s_eys = 3;
			} else {
				s_exs = s_eys = 2;
			}
			s_eefx = 0;
		}

#ifdef OPENGL
		if(!s_useOpenGL) {
			s_exs = (int)s_exs;
			s_eys = (int)s_eys;
		}
		if(s_exs <= 0.01) {
			FCEUD_PrintError("xscale out of bounds.");
			KillVideo();
			return -1;
		}
		if(s_eys <= 0.01) {
			FCEUD_PrintError("yscale out of bounds.");
			KillVideo();
			return -1;
		}
		if(s_sponge && s_useOpenGL) {
			FCEUD_PrintError("scalers not compatible with openGL mode.");
			KillVideo();
			return -1;
		}
#endif

#if defined(_GTK) && defined(SDL_VIDEO_DRIVER_X11)
		if(noGui == 0)
		{
			while (gtk_events_pending())
				gtk_main_iteration_do(FALSE);
        
			char SDL_windowhack[128];
			sprintf(SDL_windowhack, "SDL_WINDOWID=%u", (unsigned int)GDK_WINDOW_XID(gtk_widget_get_window(evbox)));
			SDL_putenv(SDL_windowhack);
        
			// init SDL video
			if (SDL_WasInit(SDL_INIT_VIDEO))
				SDL_QuitSubSystem(SDL_INIT_VIDEO);
			if ( SDL_InitSubSystem(SDL_INIT_VIDEO) < 0 )
			{
				fprintf(stderr, "Couldn't init SDL video: %s\n", SDL_GetError());
				gtk_main_quit();
			}
		}
#endif
        
		s_screen = SDL_SetVideoMode((int)(NWIDTH * s_exs),
								(int)(s_tlines * s_eys),
								desbpp, flags);
		if(!s_screen) {
			FCEUD_PrintError(SDL_GetError());
			return -1;
		}

#ifdef _GTK
		if(noGui == 0)
		{
			GtkRequisition req;
			gtk_widget_size_request(GTK_WIDGET(MainWindow), &req);
			gtk_window_resize(GTK_WINDOW(MainWindow), req.width, req.height);
		 }
#endif
		 }
	s_curbpp = s_screen->format->BitsPerPixel;
	if(!s_screen) {
		FCEUD_PrintError(SDL_GetError());
		KillVideo();
		return -1;
	}

#if 0
	// XXX soules - this would be creating a surface on the video
    //              card, but was commented out for some reason...
    s_BlitBuf = SDL_CreateRGBSurface(SDL_HWSURFACE, 256, 240,
                                     s_screen->format->BitsPerPixel,
                                     s_screen->format->Rmask,
                                     s_screen->format->Gmask,
                                     s_screen->format->Bmask, 0);
#endif

	FCEU_printf(" Video Mode: %d x %d x %d bpp %s\n",
				s_screen->w, s_screen->h, s_screen->format->BitsPerPixel,
				s_fullscreen ? "full screen" : "");

	if(s_curbpp != 8 && s_curbpp != 16 && s_curbpp != 24 && s_curbpp != 32) {
		FCEU_printf("  Sorry, %dbpp modes are not supported by FCE Ultra.  Supported bit depths are 8bpp, 16bpp, and 32bpp.\n", s_curbpp);
		KillVideo();
		return -1;
	}

	// if the game being run has a name, set it as the window name
	if(gi)
	{
		if(gi->name) {
			SDL_WM_SetCaption((const char *)gi->name, (const char *)gi->name);
		} else {
			SDL_WM_SetCaption(FCEU_NAME_AND_VERSION,"FCE Ultra");
		}
	}

	// create the surface for displaying graphical messages
#ifdef LSB_FIRST
	s_IconSurface = SDL_CreateRGBSurfaceFrom((void *)fceu_playicon.pixel_data,
											32, 32, 24, 32 * 3,
											0xFF, 0xFF00, 0xFF0000, 0x00);
#else
	s_IconSurface = SDL_CreateRGBSurfaceFrom((void *)fceu_playicon.pixel_data,
											32, 32, 24, 32 * 3,
											0xFF0000, 0xFF00, 0xFF, 0x00);
#endif
	SDL_WM_SetIcon(s_IconSurface,0);
	s_paletterefresh = 1;

	// XXX soules - can't SDL do this for us?
	 // if using more than 8bpp, initialize the conversion routines
	if(s_curbpp > 8) {
	InitBlitToHigh(s_curbpp >> 3,
						s_screen->format->Rmask,
						s_screen->format->Gmask,
						s_screen->format->Bmask,
						s_eefx, s_sponge, 0);
#ifdef OPENGL
		if(s_useOpenGL) 
		{
			int openGLip;
			g_config->getOption("SDL.OpenGLip", &openGLip);

			if(!InitOpenGL(NOFFSET, 256 - (s_clipSides ? 8 : 0),
						s_srendline, s_erendline + 1,
						s_exs, s_eys, s_eefx,
						openGLip, xstretch, ystretch, s_screen)) 
			{
				FCEUD_PrintError("Error initializing OpenGL.");
				KillVideo();
				return -1;
			}
		}
#endif
	}
// Recursively create a new array of scrollables, preserving any scrollables
// that are still in the layer tree.
//
// aXScale and aYScale are used to calculate any values that need to be in
// chrome-document CSS pixels and aren't part of the rendering loop, such as
// the initial scroll offset for a new view.
static void
BuildViewMap(ViewMap& oldContentViews, ViewMap& newContentViews,
             nsFrameLoader* aFrameLoader, Layer* aLayer,
             float aXScale = 1, float aYScale = 1,
             float aAccConfigXScale = 1, float aAccConfigYScale = 1)
{
  ContainerLayer* container = aLayer->AsContainerLayer();
  if (!container)
    return;
  const FrameMetrics metrics = container->GetFrameMetrics();
  const ViewID scrollId = metrics.mScrollId;
  const gfx3DMatrix transform = aLayer->GetTransform();
  aXScale *= GetXScale(transform);
  aYScale *= GetYScale(transform);

  if (metrics.IsScrollable()) {
    nscoord auPerDevPixel = aFrameLoader->GetPrimaryFrameOfOwningContent()
                                        ->PresContext()->AppUnitsPerDevPixel();
    nsContentView* view = FindViewForId(oldContentViews, scrollId);
    if (view) {
      // View already exists. Be sure to propagate scales for any values
      // that need to be calculated something in chrome-doc CSS pixels.
      ViewConfig config = view->GetViewConfig();
      aXScale *= config.mXScale;
      aYScale *= config.mYScale;
      view->mFrameLoader = aFrameLoader;
      // If scale has changed, then we should update
      // current scroll offset to new scaled value
      if (aAccConfigXScale != view->mParentScaleX ||
          aAccConfigYScale != view->mParentScaleY) {
        float xscroll = 0, yscroll = 0;
        view->GetScrollX(&xscroll);
        view->GetScrollY(&yscroll);
        xscroll = xscroll * (aAccConfigXScale / view->mParentScaleX);
        yscroll = yscroll * (aAccConfigYScale / view->mParentScaleY);
        view->ScrollTo(xscroll, yscroll);
        view->mParentScaleX = aAccConfigXScale;
        view->mParentScaleY = aAccConfigYScale;
      }
      // Collect only config scale values for scroll compensation
      aAccConfigXScale *= config.mXScale;
      aAccConfigYScale *= config.mYScale;
    } else {
      // View doesn't exist, so generate one. We start the view scroll offset at
      // the same position as the framemetric's scroll offset from the layer.
      // The default scale is 1, so no need to propagate scale down.
      ViewConfig config;
      config.mScrollOffset = nsPoint(
        NSIntPixelsToAppUnits(metrics.mViewportScrollOffset.x, auPerDevPixel) * aXScale,
        NSIntPixelsToAppUnits(metrics.mViewportScrollOffset.y, auPerDevPixel) * aYScale);
      view = new nsContentView(aFrameLoader, scrollId, config);
      view->mParentScaleX = aAccConfigXScale;
      view->mParentScaleY = aAccConfigYScale;
    }

    view->mViewportSize = nsSize(
      NSIntPixelsToAppUnits(metrics.mViewport.width, auPerDevPixel) * aXScale,
      NSIntPixelsToAppUnits(metrics.mViewport.height, auPerDevPixel) * aYScale);
    view->mContentSize = nsSize(
      nsPresContext::CSSPixelsToAppUnits(metrics.mCSSContentSize.width) * aXScale,
      nsPresContext::CSSPixelsToAppUnits(metrics.mCSSContentSize.height) * aYScale);

    newContentViews[scrollId] = view;
  }

  for (Layer* child = aLayer->GetFirstChild();
       child; child = child->GetNextSibling()) {
    BuildViewMap(oldContentViews, newContentViews, aFrameLoader, child,
                 aXScale, aYScale, aAccConfigXScale, aAccConfigYScale);
  }
}