Chromium文本选择放大镜

来源:互联网 发布:bim软件分类 编辑:程序博客网 时间:2024/06/05 18:21

前前后后做了大概两个月,实际时间应该只有一个多月把Chromium的文本选择进行了一系列的优化,包括

1. 文本选择的菜单

2. 文本选择在输入框中的优化,使得在handle移动时,输入框中的内容可以跟着移动。

3. 为文本选择添加放大镜。

关于前两点,基本代码都是JAVA层,内核层也有一些,这次不想多说,有时间把1,2整理一下。

今天主要是想总结一下放大镜的事情。

1. 为什么要做放大镜。

    主要是为了能够提高用户的体验,当字体比较小的时候,能够进行准确地选择。

2. 关键点

    放大镜的图来自哪里?

    关于这个图,我尝试过两种方案,

     方案一:是截取当前handle所在的坐标,截取可见区域的网页截图,具体可以

     total_scale 是你准备将源可见图放大的倍数。

     zoom_rect是想截取的区域(注意这个是未放大的区域)

     TransportDIB* transport_dib = NULL;

      {
       scoped_ptr<skia::PlatformCanvas> canvas(
             RenderProcess::current()->GetDrawingCanvas(&transport_dib,
                                                        gfx::Rect(canvas_size)));
         if (!canvas) {
           return;

         canvas->scale(total_scale / device_scale_factor_,
                       total_scale / device_scale_factor_);
         canvas->translate(-zoom_rect.x() * device_scale_factor_,
                           -zoom_rect.y() * device_scale_factor_);
 
         webwidget_->paint(
             canvas.get(),
             zoom_rect,          

             WebWidget::ForceSoftwareRenderingAndIgnoreGPUResidentContent);

       }

       SkBitmap zoom_bitmap;

       zoomed_bitmap.setConfig(SkBitmap::kARGB_8888_Config,
       zoom_rect.width()*total_scale, zoom_rect.height()*total_scale);
       zoomed_bitmap.setPixels(dib->memory());

 //之后注意释放

      RenderProcess::current()->ReleaseTransportDIB(transport_dib);

 //-------------------------------------------------------------------------------------------------------

这其实有一个问题,就是当Handle在可见区域内,但是handle附近的文本却部分不在可见区域内,这样截取的图必然是不完整的,虽然几率较小,总体上不影响体验,但本着精益求精的精神,又尝试了另一中方案。也就是如下的方案。

    方案二:使用FrameView的截图,这样不管索取的截图是否在可见区域内这都不影响,可以截取到FrameView中任意的位置。

    FrameView* view = frame()->view();

    // 这一句一定得要加上,如果不加可能会导致截图过程中断,导致截取图为空白。

   // 因为 ,frame()->view()->paintContents()执行时,如果发现needsLayout, 则返回。

    if (view->needsLayout())
        view->layout();

    PaintBehavior oldBehavior = view->paintBehavior();
    view->setPaintBehavior(oldBehavior | PaintBehaviorFlattenCompositingLayers);

    context.save();
    context.scale(WebCore::FloatSize(scaleX, scaleY));

    context.translate(-x, -y);
    IntRect pageRect(x, y, width, height);

    context.clip(pageRect);
    frame()->view()->paintContents(&context, pageRect);
    context.restore();

   view->setPaintBehavior(oldBehavior); 

   然后说一下几个参数:scaleX, scaleY: 是你最终的需要图的宽度,高度

                                       x, y, width, height: 是想要截取的图的坐标。(也就是当前网页中的坐标)

                                       确定方法是:首先确定在选择的文本在所在的frame中的坐标也就是contentsOffset,然后转化成windows, 可以使用函数

         zoom_rect = frame->view()->contentsToWindow(baseRect), 得到winowsRect, 注意没有结束,还得继续转化,

        WebSize webScrollOffset = mainFrame()->scrollOffset(); (得到mainFrame的scroll
        zoom_rect.move(webScrollOffset.width, webScrollOffset.height);

        这样就得到了最终所要截取的图的坐标。


当然在做放大镜过程中还有很多的其他点,过程虽然很艰辛,但都一一解决了,这里主要把关键的取图过程和大家分享一下,其实里边还有很过的细节,如TransportDIB的原理,下次认真研究后在分享一下。

   


        



      

 

      



   

0 0
原创粉丝点击