您的位置:首页 > 移动开发 > Android开发

Chromium文本选择放大镜

2014-05-08 11:04 351 查看
前前后后做了大概两个月,实际时间应该只有一个多月把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的原理,下次认真研究后在分享一下。

   

        

      

 

      

   
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android webkit chromium