예제 #1
0
PassRefPtr<BitmapContext> createBitmapContextFromWebView(bool, bool, bool, bool drawSelectionRect)
{
    Ewk_View_Smart_Data* smartData = static_cast<Ewk_View_Smart_Data*>(evas_object_smart_data_get(browser->mainView()));
    Ewk_View_Private_Data* privateData = static_cast<Ewk_View_Private_Data*>(smartData->_priv);
    const Evas_Object* mainFrame = browser->mainFrame();

    int x, y, width, height;
    if (!ewk_frame_visible_content_geometry_get(mainFrame, EINA_TRUE, &x, &y, &width, &height))
        return 0;

    RefPtr<cairo_surface_t> surface = adoptRef(cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height));
    RefPtr<cairo_t> context = adoptRef(cairo_create(surface.get()));

    const Eina_Rectangle rect = { x, y, width, height };
    if (!ewk_view_paint(privateData, context.get(), &rect))
        return 0;

    if (DumpRenderTreeSupportEfl::isTrackingRepaints(mainFrame)) {
        cairo_push_group(context.get());

        // Paint the gray mask over the original image.
        cairo_set_source_rgba(context.get(), 0, 0, 0, 0.66);
        cairo_paint(context.get());

        // Paint transparent rectangles over the mask to show the repainted regions.
        cairo_set_source_rgba(context.get(), 0, 0, 0, 0);
        cairo_set_operator(context.get(), CAIRO_OPERATOR_SOURCE);

        Eina_List* repaintRects = DumpRenderTreeSupportEfl::trackedRepaintRects(mainFrame);
        void* iter = 0;
        EINA_LIST_FREE(repaintRects, iter) {
            Eina_Rectangle* rect = static_cast<Eina_Rectangle*>(iter);

            cairo_rectangle(context.get(), rect->x, rect->y, rect->w, rect->h);
            cairo_fill(context.get());

            eina_rectangle_free(rect);
        }

        cairo_pop_group_to_source(context.get());
        cairo_paint(context.get());
    }
예제 #2
0
/* calculates one good zoom level to fit given hit test result */
static float
_view_zoom_fits_hit(View_Smart_Data *sd, const Ewk_Hit_Test *hit_test)
{
   Evas_Coord x, y; /* hit test point */
   Evas_Coord bx, by, bw, bh, bw1, bw2, bh1, bh2; /* bounding box */
   Evas_Coord vx, vy, vw, vh, vw1, vw2, vh1, vh2; /* visible content */
   Evas_Coord cw, ch;
   float zx, zy, z, old_zoom, zx1, zx2, zy1, zy2;

   if (!hit_test)
      return 0.0;

   old_zoom = ewk_frame_page_zoom_get(sd->base.main_frame);

   /* save some typing */
   x = hit_test->x;
   y = hit_test->y;

   bx = hit_test->bounding_box.x;
   by = hit_test->bounding_box.y;
   bw = hit_test->bounding_box.w;
   bh = hit_test->bounding_box.h;

   if ((bw <= 0) || (bh <= 0))
      return 0.0;

   ewk_frame_visible_content_geometry_get
      (sd->base.main_frame, EINA_FALSE, &vx, &vy, &vw, &vh);
   if ((vw <= 0) || (vh <= 0))
      return 0.0;

   ewk_frame_contents_size_get(sd->base.main_frame, &cw, &ch);
   if ((cw <= 0) || (ch <= 0))
      return 0.0;

   /* split width of left and right parts from hit test position */
   bw1 = x - bx;
   bw2 = bw - bw1;

   /* split height of top and bottom parts from hit test position */
   bh1 = y - by;
   bh2 = bh - bh1;

   /* split size of viewport as well. We'll use this as the available space */
   vw1 = x - vx;
   vw2 = vw - vw1;

   vh1 = y - vy;
   vh2 = vh - vh1;

   /* check if we can add padding around those sizes, "adding" if possible
    * (we actually subtract as adding a pad is removing available space)
    */
   if (vw1 > ZOOM_AUTO_PADDING)
      vw1 -= ZOOM_AUTO_PADDING;

   if (vw2 > ZOOM_AUTO_PADDING)
      vw2 -= ZOOM_AUTO_PADDING;

   if (vh1 > ZOOM_AUTO_PADDING)
      vh1 -= ZOOM_AUTO_PADDING;

   if (vh2 > ZOOM_AUTO_PADDING)
      vh2 -= ZOOM_AUTO_PADDING;

   /* check individual zoom to fit each part */
   zx1 = (bw1 > 0) ? (vw1 / (float)bw1) : 0.0;
   zx2 = (bw2 > 0) ? (vw2 / (float)bw2) : 0.0;

   zy1 = (bh1 > 0) ? (vh1 / (float)bh1) : 0.0;
   zy2 = (bh2 > 0) ? (vh2 / (float)bh2) : 0.0;

   if ((zx1 >= ZOOM_AUTO_MIN_DIFFERENCE) && (zx2 >= ZOOM_AUTO_MIN_DIFFERENCE))
      zx = (zx1 < zx2) ? zx1 : zx2;
   else if (zx1 >= ZOOM_AUTO_MIN_DIFFERENCE)
      zx = zx1;
   else
      zx = zx2;

   if ((zy1 >= ZOOM_AUTO_MIN_DIFFERENCE) && (zy2 >= ZOOM_AUTO_MIN_DIFFERENCE))
      zy = (zy1 < zy2) ? zy1 : zy2;
   else if (zy1 >= ZOOM_AUTO_MIN_DIFFERENCE)
      zy = zy1;
   else
      zy = zy2;

   if ((zx >= ZOOM_AUTO_MIN_DIFFERENCE) && (zy >= ZOOM_AUTO_MIN_DIFFERENCE))
      z = (zx < zy) ? zx : zy;
   else if (zx >= ZOOM_AUTO_MIN_DIFFERENCE)
      z = zx;
   else
      z = zy;

   /* zoom will make contents be smaller than viewport, limit it */
   if (((int)(z * old_zoom * cw) < vw) || ((int)(z * old_zoom * ch) < vh))
     {
        float ac = cw / (float)ch;
        float av = vw / (float)vh;

        if (ac < av)
           z = vw / (float)cw;
        else
           z = vh / (float)ch;
     }

#if 0
   /* debug */
   printf(">>> fit: center=%3d,%3d   box=%3d,%3d+%3dx%3d\n"
          "    x:  %3d = %3d + %3d,  %3d = %3d + %3d,  %2.4f  %2.4f  -> %2.4f\n"
          "    y:  %3d = %3d + %3d,  %3d = %3d + %3d,  %2.4f  %2.4f  -> %2.4f\n"
          "    final: %2.4f   %2.4f (old=%0.3f, difference=%0.3f)\n"
          "    contents: %4dx%4d  -> %4dx%4d\n"
          "\n",
          x, y, bx, by, bw, bh,
          bw, bw1, bw2, vw, vw1, vw2, zx1, zx2, zx,
          bh, bh1, bh2, vh, vh1, vh2, zy1, zy2, zy,
          z, old_zoom * z, old_zoom, fabs(old_zoom - z),
          cw, ch, (int)(z * old_zoom * cw), (int)(z * old_zoom * ch));
#endif

   z *= old_zoom;

   if (z < ZOOM_AUTO_MIN)
      z = ZOOM_AUTO_MIN;
   else if (z > ZOOM_AUTO_MAX)
      z = ZOOM_AUTO_MAX;

   if (fabs(old_zoom - z) < ZOOM_AUTO_MIN_DIFFERENCE)
      return 0.0;

   return z;
}
예제 #3
0
static Eina_Bool _ewk_view_tiled_smart_pre_render_start(Ewk_View_Smart_Data* smartData)
{
    int contentWidth, contentHeight;
    ewk_frame_contents_size_get(smartData->main_frame, &contentWidth, &contentHeight);

    int viewX, viewY, viewWidth, viewHeight;
    ewk_frame_visible_content_geometry_get(smartData->main_frame, false, &viewX, &viewY, &viewWidth, &viewHeight);

    if (viewWidth <= 0 || viewHeight <= 0 || contentWidth <= 0 || contentHeight <= 0)
        return false;

    if (viewWidth >= contentWidth && viewHeight >= contentHeight)
        return false;

    int previousViewX, previousViewY;
    previousViewX = smartData->previousView.x;
    previousViewY = smartData->previousView.y;

    if (previousViewX < 0 || previousViewX > contentWidth || previousViewY < 0 || previousViewY > contentHeight)
        previousViewX = previousViewY = 0;

    float currentViewZoom = ewk_view_zoom_get(smartData->self);

    // pre-render works when two conditions are met.
    // zoom has been changed.
    // and the view has been moved more than tile size.
    if (abs(previousViewX - viewX) < defaultTileWidth
        && abs(previousViewY - viewY) < defaultTileHeigth
        && smartData->previousView.zoom == currentViewZoom) {
        return false;
    }

    // store previous view position and zoom.
    smartData->previousView.x = viewX;
    smartData->previousView.y = viewY;
    smartData->previousView.zoom = currentViewZoom;

    // cancelling previous pre-rendering list if exists.
    ewk_view_pre_render_cancel(smartData->self);

    Ewk_Tile_Unused_Cache* tileUnusedCache = ewk_view_tiled_unused_cache_get(smartData->self);
    int maxMemory = ewk_tile_unused_cache_max_get(tileUnusedCache);
    if (maxMemory <= viewWidth * viewHeight * EWK_ARGB_BYTES_SIZE)
        return false;

    Eina_Rectangle viewRect = {viewX, viewY, viewWidth, viewHeight};
    Eina_Rectangle contentRect = {0, 0, contentWidth, contentHeight};

    // get a base render rect.
    const int contentMemory = contentWidth * contentHeight * EWK_ARGB_BYTES_SIZE;

    // get render rect's width and height.
    Eina_Rectangle renderRect;
    if (maxMemory > contentMemory)
        renderRect = contentRect;
    else {
        // Make a base rectangle as big as possible with using maxMemory.
        // and then reshape the base rectangle to fit to contents.
        const int baseSize = static_cast<int>(sqrt(maxMemory / 4.0f));
        const float widthRate = (viewRect.w + (defaultTileWidth * 2)) / static_cast<float>(baseSize);
        const float heightRate = baseSize / static_cast<float>(contentHeight);
        const float rectRate = std::max(widthRate, heightRate);

        renderRect.w = static_cast<int>(baseSize * rectRate);
        renderRect.h = static_cast<int>(baseSize / rectRate);
        renderRect.x = viewRect.x + (viewRect.w / 2) - (renderRect.w / 2);
        renderRect.y = viewRect.y + (viewRect.h / 2) - (renderRect.h / 2);

        // reposition of renderRect, if the renderRect overlapped the content rect, this code moves the renderRect inside the content rect.
        int collisionSide = _ewk_view_tiled_rect_collision_check(renderRect, contentRect);
        if (collisionSide > 0)
            _ewk_view_tiled_rect_collision_resolve(collisionSide, &renderRect, contentRect);

        // check abnormal render rect
        if (renderRect.x < 0)
            renderRect.x = 0;
        if (renderRect.y < 0)
            renderRect.y = 0;
        if (renderRect.w > contentWidth)
            renderRect.w = contentWidth;
        if (renderRect.h > contentHeight)
            renderRect.h = contentHeight;
    }

    // enqueue tiles into tiled backing store in spiral order.
    ewk_tiled_backing_store_pre_render_spiral_queue(smartData->backing_store, &viewRect, &renderRect, maxMemory, currentViewZoom);

    return true;
}