圆角控件 : 圆角 « GWT « Java

En
Java
1. 图形用户界面
2. 三维图形动画
3. 高级图形
4. 蚂蚁编译
5. Apache类库
6. 统计图
7. 
8. 集合数据结构
9. 数据类型
10. 数据库JDBC
11. 设计模式
12. 开发相关类
13. EJB3
14. 电子邮件
15. 事件
16. 文件输入输出
17. 游戏
18. 泛型
19. GWT
20. Hibernate
21. 本地化
22. J2EE平台
23. 基于J2ME
24. JDK-6
25. JNDI的LDAP
26. JPA
27. JSP技术
28. JSTL
29. 语言基础知识
30. 网络协议
31. PDF格式RTF格式
32. 映射
33. 常规表达式
34. 脚本
35. 安全
36. Servlets
37. Spring
38. Swing组件
39. 图形用户界面
40. SWT-JFace-Eclipse
41. 线程
42. 应用程序
43. Velocity
44. Web服务SOA
45. 可扩展标记语言
Java 教程
Java » GWT » 圆角屏幕截图 
圆角控件



// Copyright 2006 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.


// Known Issues:
//
// * Patterns are not implemented.
// * Radial gradient are not implemented. The VML version of these look very
//   different from the canvas one.
// * Clipping paths are not implemented.
// * Coordsize. The width and height attribute have higher priority than the
//   width and height style values which isn't correct.
// * Painting mode isn't implemented.
// * Canvas width/height should is using content-box by default. IE in
//   Quirks mode will draw the canvas using border-box. Either change your
//   doctype to HTML5
//   (http://www.whatwg.org/specs/web-apps/current-work/#the-doctype)
//   or use Box Sizing Behavior from WebFX
//   (http://webfx.eae.net/dhtml/boxsizing/boxsizing.html)
// * Optimize. There is always room for speed improvements.

// only add this code if we do not already have a canvas implementation
if (!window.CanvasRenderingContext2D) {

(function () {

  // alias some functions to make (compiled) code shorter
  var m = Math;
  var mr = m.round;
  var ms = m.sin;
  var mc = m.cos;

  // this is used for sub pixel precision
  var Z = 10;
  var Z2 = Z / 2;

  var G_vmlCanvasManager_ = {
    init: function (opt_doc) {
      var doc = opt_doc || document;
      if (/MSIE/.test(navigator.userAgent&& !window.opera) {
        var self = this;
        doc.attachEvent("onreadystatechange"function () {
          self.init_(doc);
        });
      }
    },

    init_: function (doc) {
      if (doc.readyState == "complete") {
        // create xmlns
        if (!doc.namespaces["g_vml_"]) {
          doc.namespaces.add("g_vml_""urn:schemas-microsoft-com:vml");
        }

        // setup default css
        var ss = doc.createStyleSheet();
        ss.cssText = "canvas{display:inline-block;overflow:hidden;" +
            // default size is 300x150 in Gecko and Opera
            "text-align:left;width:300px;height:150px}" +
            "g_vml_\\:*{behavior:url(#default#VML)}";

        // find all canvas elements
        var els = doc.getElementsByTagName("canvas");
        for (var i = 0; i < els.length; i++) {
          if (!els[i].getContext) {
            this.initElement(els[i]);
          }
        }
      }
    },

    fixElement_: function (el) {
      // in IE before version 5.5 we would need to add HTML: to the tag name
      // but we do not care about IE before version 6
      var outerHTML = el.outerHTML;

      var newEl = el.ownerDocument.createElement(outerHTML);
      // if the tag is still open IE has created the children as siblings and
      // it has also created a tag with the name "/FOO"
      if (outerHTML.slice(-2!= "/>") {
        var tagName = "/" + el.tagName;
        var ns;
        // remove content
        while ((ns = el.nextSibling&& ns.tagName != tagName) {
          ns.removeNode();
        }
        // remove the incorrect closing tag
        if (ns) {
          ns.removeNode();
        }
      }
      el.parentNode.replaceChild(newEl, el);
      return newEl;
    },

    /**
     * Public initializes a canvas element so that it can be used as canvas
     * element from now on. This is called automatically before the page is
     * loaded but if you are creating elements using createElement you need to
     * make sure this is called on the element.
     @param {HTMLElement} el The canvas element to initialize.
     @return {HTMLElement} the element that was created.
     */
    initElement: function (el) {
      el = this.fixElement_(el);
      el.getContext = function () {
        if (this.context_) {
          return this.context_;
        }
        return this.context_ = new CanvasRenderingContext2D_(this);
      };

      // do not use inline function because that will leak memory
      el.attachEvent('onpropertychange', onPropertyChange);
      el.attachEvent('onresize', onResize);

      var attrs = el.attributes;
      if (attrs.width && attrs.width.specified) {
        // TODO: use runtimeStyle and coordsize
        // el.getContext().setWidth_(attrs.width.nodeValue);
        el.style.width = attrs.width.nodeValue + "px";
      else {
        el.width = el.clientWidth;
      }
      if (attrs.height && attrs.height.specified) {
        // TODO: use runtimeStyle and coordsize
        // el.getContext().setHeight_(attrs.height.nodeValue);
        el.style.height = attrs.height.nodeValue + "px";
      else {
        el.height = el.clientHeight;
      }
      //el.getContext().setCoordsize_()
      return el;
    }
  };

  function onPropertyChange(e) {
    var el = e.srcElement;

    switch (e.propertyName) {
      case 'width':
        el.style.width = el.attributes.width.nodeValue + "px";
        el.getContext().clearRect();
        break;
      case 'height':
        el.style.height = el.attributes.height.nodeValue + "px";
        el.getContext().clearRect();
        break;
    }
  }

  function onResize(e) {
    var el = e.srcElement;
    if (el.firstChild) {
      el.firstChild.style.width =  el.clientWidth + 'px';
      el.firstChild.style.height = el.clientHeight + 'px';
    }
  }

  G_vmlCanvasManager_.init();

  // precompute "00" to "FF"
  var dec2hex = [];
  for (var i = 0; i < 16; i++) {
    for (var j = 0; j < 16; j++) {
      dec2hex[i * 16 + j= i.toString(16+ j.toString(16);
    }
  }

  function createMatrixIdentity() {
    return [
      [100],
      [010],
      [001]
    ];
  }

  function matrixMultiply(m1, m2) {
    var result = createMatrixIdentity();

    for (var x = 0; x < 3; x++) {
      for (var y = 0; y < 3; y++) {
        var sum = 0;

        for (var z = 0; z < 3; z++) {
          sum += m1[x][z* m2[z][y];
        }

        result[x][y= sum;
      }
    }
    return result;
  }

  function copyState(o1, o2) {
    o2.fillStyle     = o1.fillStyle;
    o2.lineCap       = o1.lineCap;
    o2.lineJoin      = o1.lineJoin;
    o2.lineWidth     = o1.lineWidth;
    o2.miterLimit    = o1.miterLimit;
    o2.shadowBlur    = o1.shadowBlur;
    o2.shadowColor   = o1.shadowColor;
    o2.shadowOffsetX = o1.shadowOffsetX;
    o2.shadowOffsetY = o1.shadowOffsetY;
    o2.strokeStyle   = o1.strokeStyle;
    o2.arcScaleX_    = o1.arcScaleX_;
    o2.arcScaleY_    = o1.arcScaleY_;
  }

  function processStyle(styleString) {
    var str, alpha = 1;

    styleString = String(styleString);
    if (styleString.substring(03== "rgb") {
      var start = styleString.indexOf("("3);
      var end = styleString.indexOf(")", start + 1);
      var guts = styleString.substring(start + 1end).split(",");

      str = "#";
      for (var i = 0; i < 3; i++) {
        str += dec2hex[Number(guts[i])];
      }

      if ((guts.length == 4&& (styleString.substr(31== "a")) {
        alpha = guts[3];
      }
    else {
      str = styleString;
    }

    return [str, alpha];
  }

  function processLineCap(lineCap) {
    switch (lineCap) {
      case "butt":
        return "flat";
      case "round":
        return "round";
      case "square":
      default:
        return "square";
    }
  }

  /**
   * This class implements CanvasRenderingContext2D interface as described by
   * the WHATWG.
   @param {HTMLElement} surfaceElement The element that the 2D context should
   * be associated with
   */
   function CanvasRenderingContext2D_(surfaceElement) {
    this.m_ = createMatrixIdentity();

    this.mStack_ = [];
    this.aStack_ = [];
    this.currentPath_ = [];

    // Canvas context properties
    this.strokeStyle = "#000";
    this.fillStyle = "#000";

    this.lineWidth = 1;
    this.lineJoin = "miter";
    this.lineCap = "butt";
    this.miterLimit = Z * 1;
    this.globalAlpha = 1;
    this.canvas = surfaceElement;

    var el = surfaceElement.ownerDocument.createElement('div');
    el.style.width =  surfaceElement.clientWidth + 'px';
    el.style.height = surfaceElement.clientHeight + 'px';
    el.style.overflow = 'hidden';
    el.style.position = 'absolute';
    surfaceElement.appendChild(el);

    this.element_ = el;
    this.arcScaleX_ = 1;
    this.arcScaleY_ = 1;
  };

  var contextPrototype = CanvasRenderingContext2D_.prototype;
  contextPrototype.clearRect = function() {
    this.element_.innerHTML = "";
    this.currentPath_ = [];
  };

  contextPrototype.beginPath = function() {
    // TODO: Branch current matrix so that save/restore has no effect
    //       as per safari docs.

    this.currentPath_ = [];
  };

  contextPrototype.moveTo = function(aX, aY) {
    this.currentPath_.push({type: "moveTo", x: aX, y: aY});
    this.currentX_ = aX;
    this.currentY_ = aY;
  };

  contextPrototype.lineTo = function(aX, aY) {
    this.currentPath_.push({type: "lineTo", x: aX, y: aY});
    this.currentX_ = aX;
    this.currentY_ = aY;
  };

  contextPrototype.bezierCurveTo = function(aCP1x, aCP1y,
                                            aCP2x, aCP2y,
                                            aX, aY) {
    this.currentPath_.push({type: "bezierCurveTo",
                           cp1x: aCP1x,
                           cp1y: aCP1y,
                           cp2x: aCP2x,
                           cp2y: aCP2y,
                           x: aX,
                           y: aY});
    this.currentX_ = aX;
    this.currentY_ = aY;
  };

  contextPrototype.quadraticCurveTo = function(aCPx, aCPy, aX, aY) {
    // the following is lifted almost directly from
    // http://developer.mozilla.org/en/docs/Canvas_tutorial:Drawing_shapes
    var cp1x = this.currentX_ + 2.0 3.0 (aCPx - this.currentX_);
    var cp1y = this.currentY_ + 2.0 3.0 (aCPy - this.currentY_);
    var cp2x = cp1x + (aX - this.currentX_3.0;
    var cp2y = cp1y + (aY - this.currentY_3.0;
    this.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, aX, aY);
  };

  contextPrototype.arc = function(aX, aY, aRadius,
                                  aStartAngle, aEndAngle, aClockwise) {
    aRadius *= Z;
    var arcType = aClockwise ? "at" "wa";

    var xStart = aX + (mc(aStartAngle* aRadius- Z2;
    var yStart = aY + (ms(aStartAngle* aRadius- Z2;

    var xEnd = aX + (mc(aEndAngle* aRadius- Z2;
    var yEnd = aY + (ms(aEndAngle* aRadius- Z2;

    // IE won't render arches drawn counter clockwise if xStart == xEnd.
    if (xStart == xEnd && !aClockwise) {
      xStart += 0.125// Offset xStart by 1/80 of a pixel. Use something
                       // that can be represented in binary
    }

    this.currentPath_.push({type: arcType,
                           x: aX,
                           y: aY,
                           radius: aRadius,
                           xStart: xStart,
                           yStart: yStart,
                           xEnd: xEnd,
                           yEnd: yEnd});

  };

  contextPrototype.rect = function(aX, aY, aWidth, aHeight) {
    this.moveTo(aX, aY);
    this.lineTo(aX + aWidth, aY);
    this.lineTo(aX + aWidth, aY + aHeight);
    this.lineTo(aX, aY + aHeight);
    this.closePath();
  };

  contextPrototype.strokeRect = function(aX, aY, aWidth, aHeight) {
    // Will destroy any existing path (same as FF behaviour)
    this.beginPath();
    this.moveTo(aX, aY);
    this.lineTo(aX + aWidth, aY);
    this.lineTo(aX + aWidth, aY + aHeight);
    this.lineTo(aX, aY + aHeight);
    this.closePath();
    this.stroke();
  };

  contextPrototype.fillRect = function(aX, aY, aWidth, aHeight) {
    // Will destroy any existing path (same as FF behaviour)
    this.beginPath();
    this.moveTo(aX, aY);
    this.lineTo(aX + aWidth, aY);
    this.lineTo(aX + aWidth, aY + aHeight);
    this.lineTo(aX, aY + aHeight);
    this.closePath();
    this.fill();
  };

  contextPrototype.createLinearGradient = function(aX0, aY0, aX1, aY1) {
    var gradient = new CanvasGradient_("gradient");
    return gradient;
  };

  contextPrototype.createRadialGradient = function(aX0, aY0,
                                                   aR0, aX1,
                                                   aY1, aR1) {
    var gradient = new CanvasGradient_("gradientradial");
    gradient.radius1_ = aR0;
    gradient.radius2_ = aR1;
    gradient.focus_.x = aX0;
    gradient.focus_.y = aY0;
    return gradient;
  };

  contextPrototype.drawImage = function (image, var_args) {
    var dx, dy, dw, dh, sx, sy, sw, sh;

    // to find the original width we overide the width and height
    var oldRuntimeWidth = image.runtimeStyle.width;
    var oldRuntimeHeight = image.runtimeStyle.height;
    image.runtimeStyle.width = 'auto';
    image.runtimeStyle.height = 'auto';

    // get the original size
    var w = image.width;
    var h = image.height;

    // and remove overides
    image.runtimeStyle.width = oldRuntimeWidth;
    image.runtimeStyle.height = oldRuntimeHeight;

    if (arguments.length == 3) {
      dx = arguments[1];
      dy = arguments[2];
      sx = sy = 0;
      sw = dw = w;
      sh = dh = h;
    else if (arguments.length == 5) {
      dx = arguments[1];
      dy = arguments[2];
      dw = arguments[3];
      dh = arguments[4];
      sx = sy = 0;
      sw = w;
      sh = h;
    else if (arguments.length == 9) {
      sx = arguments[1];
      sy = arguments[2];
      sw = arguments[3];
      sh = arguments[4];
      dx = arguments[5];
      dy = arguments[6];
      dw = arguments[7];
      dh = arguments[8];
    else {
      throw "Invalid number of arguments";
    }

    var d = this.getCoords_(dx, dy);

    var w2 = sw / 2;
    var h2 = sh / 2;

    var vmlStr = [];

    var W = 10;
    var H = 10;

    // For some reason that I've now forgotten, using divs didn't work
    vmlStr.push(' <g_vml_:group',
                ' coordsize="', Z * W, ',', Z * H, '"',
                ' coordorigin="0,0"' ,
                ' style="width:', W, ';height:', H, ';position:absolute;');

    // If filters are necessary (rotation exists), create them
    // filters are bog-slow, so only create them if abbsolutely necessary
    // The following check doesn't account for skews (which don't exist
    // in the canvas spec (yet) anyway.

    if (this.m_[0][0] != 1 || this.m_[0][1]) {
      var filter = [];

      // Note the 12/21 reversal
      filter.push("M11='", this.m_[0][0]"',",
                  "M12='"this.m_[1][0]"',",
                  "M21='"this.m_[0][1]"',",
                  "M22='"this.m_[1][1]"',",
                  "Dx='", mr(d.x / Z)"',",
                  "Dy='", mr(d.y / Z)"'");

      // Bounding box calculation (need to minimize displayed area so that
      // filters don't waste time on unused pixels.
      var max = d;
      var c2 = this.getCoords_(dx + dw, dy);
      var c3 = this.getCoords_(dx, dy + dh);
      var c4 = this.getCoords_(dx + dw, dy + dh);

      max.x = Math.max(max.x, c2.x, c3.x, c4.x);
      max.y = Math.max(max.y, c2.y, c3.y, c4.y);

      vmlStr.push("padding:0 ", mr(max.x / Z)"px ", mr(max.y / Z),
                  "px 0;filter:progid:DXImageTransform.Microsoft.Matrix(",
                  filter.join("")", sizingmethod='clip');")
    else {
      vmlStr.push("top:", mr(d.y / Z)"px;left:", mr(d.x / Z)"px;")
    }

    vmlStr.push(' ">' ,
                '<g_vml_:image src="', image.src, '"',
                ' style="width:', Z * dw, ';',
                ' height:', Z * dh, ';"',
                ' cropleft="', sx / w, '"',
                ' croptop="', sy / h, '"',
                ' cropright="', (w - sx - sw) / w, '"',
                ' cropbottom="', (h - sy - sh) / h, '"',
                ' />',
                '</g_vml_:group>');

    this.element_.insertAdjacentHTML("BeforeEnd",
                                    vmlStr.join(""));
  };

  contextPrototype.stroke = function(aFill) {
    var lineStr = [];
    var lineOpen = false;
    var a = processStyle(aFill ? this.fillStyle : this.strokeStyle);
    var color = a[0];
    var opacity = a[1this.globalAlpha;

    var W = 10;
    var H = 10;

    lineStr.push('<g_vml_:shape',
                 ' fillcolor="', color, '"',
                 ' filled="', Boolean(aFill), '"',
                 ' style="position:absolute;width:', W, ';height:', H, ';"',
                 ' coordorigin="0 0" coordsize="', Z * W, ' ', Z * H, '"',
                 ' stroked="', !aFill, '"',
                 ' strokeweight="', this.lineWidth, '"',
                 ' strokecolor="', color, '"',
                 ' path="');

    var newSeq = false;
    var min = {x: null, y: null};
    var max = {x: null, y: null};

    for (var i = 0; i < this.currentPath_.length; i++) {
      var p = this.currentPath_[i];

      if (p.type == "moveTo") {
        lineStr.push(" ");
        var c = this.getCoords_(p.x, p.y);
        lineStr.push(mr(c.x), ",", mr(c.y));
      } else if (p.type == "lineTo") {
        lineStr.push(" ");
        var c = this.getCoords_(p.x, p.y);
        lineStr.push(mr(c.x), ",", mr(c.y));
      } else if (p.type == "close") {
        lineStr.push(" ");
      } else if (p.type == "bezierCurveTo") {
        lineStr.push(" ");
        var c = this.getCoords_(p.x, p.y);
        var c1 = this.getCoords_(p.cp1x, p.cp1y);
        var c2 = this.getCoords_(p.cp2x, p.cp2y);
        lineStr.push(mr(c1.x), ",", mr(c1.y), ",",
                     mr(c2.x), ",", mr(c2.y), ",",
                     mr(c.x), ",", mr(c.y));
      } else if (p.type == "at" || p.type == "wa") {
        lineStr.push(" ", p.type, " ");
        var c  = this.getCoords_(p.x, p.y);
        var cStart = this.getCoords_(p.xStart, p.yStart);
        var cEnd = this.getCoords_(p.xEnd, p.yEnd);

        lineStr.push(mr(c.x - this.arcScaleX_ * p.radius), ",",
                     mr(c.y - this.arcScaleY_ * p.radius), " ",
                     mr(c.x + this.arcScaleX_ * p.radius), ",",
                     mr(c.y + this.arcScaleY_ * p.radius), " ",
                     mr(cStart.x), ",", mr(cStart.y), " ",
                     mr(cEnd.x), ",", mr(cEnd.y));
      }


      // TODO: Following is broken for curves due to
      //       move to proper paths.

      // Figure out dimensions so we can do gradient fills
      // properly
      if(c) {
        if (min.x == null || c.x < min.x) {
          min.x = c.x;
        }
        if (max.x == null || c.x > max.x) {
          max.x = c.x;
        }
        if (min.y == null || c.y < min.y) {
          min.y = c.y;
        }
        if (max.y == null || c.y > max.y) {
          max.y = c.y;
        }
      }
    }
    lineStr.push(' ">');

    if (typeof this.fillStyle == "object") {
      var focus = {x: "50%", y: "50%"};
      var width = (max.x - min.x);
      var height = (max.y - min.y);
      var dimension = (width > height? width : height;

      focus.x = mr((this.fillStyle.focus_.x / width100 50"%";
      focus.y = mr((this.fillStyle.focus_.y / height100 50"%";

      var colors = [];

      // inside radius (%)
      if (this.fillStyle.type_ == "gradientradial") {
        var inside = (this.fillStyle.radius1_ / dimension * 100);

        // percentage that outside radius exceeds inside radius
        var expansion = (this.fillStyle.radius2_ / dimension * 100- inside;
      else {
        var inside = 0;
        var expansion = 100;
      }

      var insidecolor = {offset: null, color: null};
      var outsidecolor = {offset: null, color: null};

      // We need to sort 'colors' by percentage, from 0 > 100 otherwise ie
      // won't interpret it correctly
      this.fillStyle.colors_.sort(function (cs1, cs2) {
        return cs1.offset - cs2.offset;
      });

      for (var i = 0; i < this.fillStyle.colors_.length; i++) {
        var fs = this.fillStyle.colors_[i];

        colors.push( (fs.offset * expansion+ inside, "% ", fs.color, ",");

        if (fs.offset > insidecolor.offset || insidecolor.offset == null) {
          insidecolor.offset = fs.offset;
          insidecolor.color = fs.color;
        }

        if (fs.offset < outsidecolor.offset || outsidecolor.offset == null) {
          outsidecolor.offset = fs.offset;
          outsidecolor.color = fs.color;
        }
      }
      colors.pop();

      lineStr.push('<g_vml_:fill',
                   ' color="', outsidecolor.color, '"',
                   ' color2="', insidecolor.color, '"',
                   ' type="', this.fillStyle.type_, '"',
                   ' focusposition="', focus.x, ', ', focus.y, '"',
                   ' colors="', colors.join(""), '"',
                   ' opacity="', opacity, '" />');
    else if (aFill) {
      lineStr.push('<g_vml_:fill color="', color, '" opacity="', opacity, '" />');
    else {
      lineStr.push(
        '<g_vml_:stroke',
        ' opacity="', opacity,'"',
        ' joinstyle="', this.lineJoin, '"',
        ' miterlimit="', this.miterLimit, '"',
        ' endcap="', processLineCap(this.lineCap) ,'"',
        ' weight="', this.lineWidth, 'px"',
        ' color="', color,'" />'
      );
    }

    lineStr.push("</g_vml_:shape>");

    this.element_.insertAdjacentHTML("beforeEnd", lineStr.join(""));

    this.currentPath_ = [];
  };

  contextPrototype.fill = function() {
    this.stroke(true);
  }

  contextPrototype.closePath = function() {
    this.currentPath_.push({type: "close"});
  };

  /**
   * @private
   */
  contextPrototype.getCoords_ = function(aX, aY) {
    return {
      x: Z * (aX * this.m_[0][0+ aY * this.m_[1][0this.m_[2][0]) - Z2,
      y: Z * (aX * this.m_[0][1+ aY * this.m_[1][1this.m_[2][1]) - Z2
    }
  };

  contextPrototype.save = function() {
    var o = {};
    copyState(this, o);
    this.aStack_.push(o);
    this.mStack_.push(this.m_);
    this.m_ = matrixMultiply(createMatrixIdentity()this.m_);
  };

  contextPrototype.restore = function() {
    copyState(this.aStack_.pop()this);
    this.m_ = this.mStack_.pop();
  };

  contextPrototype.translate = function(aX, aY) {
    var m1 = [
      [1,  0,  0],
      [0,  1,  0],
      [aX, aY, 1]
    ];

    this.m_ = matrixMultiply(m1, this.m_);
  };

  contextPrototype.rotate = function(aRot) {
    var c = mc(aRot);
    var s = ms(aRot);

    var m1 = [
      [c,  s, 0],
      [-s, c, 0],
      [0,  01]
    ];

    this.m_ = matrixMultiply(m1, this.m_);
  };

  contextPrototype.scale = function(aX, aY) {
    this.arcScaleX_ *= aX;
    this.arcScaleY_ *= aY;
    var m1 = [
      [aX, 0,  0],
      [0,  aY, 0],
      [0,  0,  1]
    ];

    this.m_ = matrixMultiply(m1, this.m_);
  };

  /******** STUBS ********/
  contextPrototype.clip = function() {
    // TODO: Implement
  };

  contextPrototype.arcTo = function() {
    // TODO: Implement
  };

  contextPrototype.createPattern = function() {
    return new CanvasPattern_;
  };

  // Gradient / Pattern Stubs
  function CanvasGradient_(aType) {
    this.type_ = aType;
    this.radius1_ = 0;
    this.radius2_ = 0;
    this.colors_ = [];
    this.focus_ = {x: 0, y: 0};
  }

  CanvasGradient_.prototype.addColorStop = function(aOffset, aColor) {
    aColor = processStyle(aColor);
    this.colors_.push({offset: 1-aOffset, color: aColor});
  };

  function CanvasPattern_() {}

  // set up externs
  G_vmlCanvasManager = G_vmlCanvasManager_;
  CanvasRenderingContext2D = CanvasRenderingContext2D_;
  CanvasGradient = CanvasGradient_;
  CanvasPattern = CanvasPattern_;

})();

// if
//////////////////////////////////////////////////////

First, include this code on your HTML host page:

<!--[if IE]><script src="js/excanvas.js" type="text/javascript"></script><![endif]--> 

//////////////////////////////////////////////////////

/* how to use it

final Canvas ctx = new Canvas(200, 200);
           
ctx.beginPath();
ctx.arc(75,75,50,0,(float)Math.PI*2,true); // Outer circle
ctx.moveTo(110,75);
ctx.arc(75,75,35,0,(float)Math.PI,false);   // Mouth (clockwise)
ctx.moveTo(65,65);
ctx.arc(60,65,5,0,(float)Math.PI*2,true);  // Left eye
ctx.moveTo(95,65);
ctx.arc(90,65,5,0,(float)Math.PI*2,true);  // Right eye
ctx.stroke();

*/
Canvas.java:

/*
Round Corners Widget for GWT
Copyright (C) 2006 Alexei Sokolov http://gwt.components.googlepages.com/

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

*/

package com.gwt.components.client;

import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Widget;

public class Canvas extends Widget {

    public static class DrawingStyle extends JavaScriptObject {
        protected DrawingStyle(int opaque) {
            super(opaque);
        }
    }

    public static class Gradient extends DrawingStyle {
        public Gradient(int opaque) {
            super(opaque);
        }

        protected static native void addColorStop(JavaScriptObject obj,
                float offset, String color/*-{
         obj.addColorStop(offset, color);
        }-*/;
    }

    public static class LinearGradient extends Gradient {
        public LinearGradient(int opaque) {
            super(opaque);
        }

        public LinearGradient addColorStop(float offset, String color) {
            Gradient.addColorStop(this, offset, color);
            return this;
        }
    }

    public static class RadialGradient extends Gradient {
        public RadialGradient(int opaque) {
            super(opaque);
        }

        public RadialGradient addColorStop(float offset, String color) {
            Gradient.addColorStop(this, offset, color);
            return this;
        }
    }

    public static class Pattern extends DrawingStyle {
        protected Pattern(int opaque) {
            super(opaque);
        }

    }

    private JavaScriptObject context;

    public Canvas(int width, int height) {
        setElement(DOM.createDiv());
        Element canvas = DOM.createElement("canvas");
        DOM.setAttribute(canvas, "width", String.valueOf(width));
        DOM.setAttribute(canvas, "height", String.valueOf(height));
        DOM.appendChild(getElement(), canvas);
        setStyleName("gwt-Canvas");

        init();

        setFillStyle("black");
        setStrokeColor("black");
    }

    public native static boolean isEmulation() /*-{
     return (typeof $wnd.G_vmlCanvasManager != "undefined");
    }-*/;

    protected native void init() /*-{
     var el = this.@com.google.gwt.user.client.ui.UIObject::getElement()().firstChild;
     if (typeof $wnd.G_vmlCanvasManager != "undefined") {
     
     var parent = el.parent;
     
     el = $wnd.G_vmlCanvasManager.fixElement_(el);
     el.getContext = function () {
     if (this.context_) {
     return this.context_;
     }
     return this.context_ = new $wnd.CanvasRenderingContext2D(el);
     };

     el.attachEvent("onpropertychange", function (e) {
     // we need to watch changes to width and height
     switch (e.propertyName) {
     case "width":
     case "height":
     // coord size changed?
     break;
     }
     });

     // if style.height is set

     var attrs = el.attributes;
     if (attrs.width && attrs.width.specified) {
     // TODO: use runtimeStyle and coordsize
     // el.getContext().setWidth_(attrs.width.nodeValue);
     el.style.width = attrs.width.nodeValue + "px";
     }
     if (attrs.height && attrs.height.specified) {
     // TODO: use runtimeStyle and coordsize
     // el.getContext().setHeight_(attrs.height.nodeValue);
     el.style.height = attrs.height.nodeValue + "px";
     }
     }
     this.@com.gwt.components.client.Canvas::context = el.getContext("2d");
    }-*/;

    public native void saveContext() /*-{
     this.@com.gwt.components.client.Canvas::context.save();
    }-*/;

    public native void restoreContext() /*-{
     this.@com.gwt.components.client.Canvas::context.restore();
    }-*/;

    public native void scale(float x, float y/*-{
     this.@com.gwt.components.client.Canvas::context.scale(x, y);   
    }-*/;

    public native void rotate(float angle)/*-{
     this.@com.gwt.components.client.Canvas::context.rotate(angle);   
    }-*/;

    public native void translate(float x, float y/*-{
     this.@com.gwt.components.client.Canvas::context.translate(x, y);   
    }-*/;

    public native void transform(float m11, float m12, float m21, float m22,
            float dx, float dy/*-{
     this.@com.gwt.components.client.Canvas::context.transform(
      m11, m12, m21, m22, dx, dy);   
    }-*/;

    public native void setTransform(float m11, float m12, float m21, float m22,
            float dx, float dy/*-{
     this.@com.gwt.components.client.Canvas::context.setTransform(
      m11, m12, m21, m22, dx, dy);   
    }-*/;

    public native float getGlobalAlpha() /*-{
     return this.@com.gwt.components.client.Canvas::context.globalAlpha;
    }-*/;

    public native void setGlobalAlpha(float alpha/*-{
     this.@com.gwt.components.client.Canvas::context.globalAlpha = alpha;
    }-*/;

    public native String getGlobalCompositeOperation() /*-{
     return this.@com.gwt.components.client.Canvas::context.globalCompositeOperation;
    }-*/;

    public native void setGlobalCompositeOperation(String operation/*-{
     this.@com.gwt.components.client.Canvas::context.globalCompositeOperation = 
      operation;
    }-*/;

    public native void setStrokeStyle(DrawingStyle style/*-{
     this.@com.gwt.components.client.Canvas::context.strokeStyle = style;
    }-*/;

    public native void setStrokeColor(String color/*-{
     this.@com.gwt.components.client.Canvas::context.strokeStyle = color;
    }-*/;

    public native void setFillStyle(DrawingStyle style/*-{
     this.@com.gwt.components.client.Canvas::context.fillStyle = style;
    }-*/;

    public native void setFillStyle(String style/*-{
     this.@com.gwt.components.client.Canvas::context.fillStyle = style;
    }-*/;

    public native LinearGradient createLinearGradient(float x0, float y0,
            float x1, float y1/*-{
     return this.@com.gwt.components.client.Canvas::context.createLinearGradient(
      x0, y0, x1, y1);   
    }-*/;

    public native RadialGradient createRadialGradient(float x0, float y0,
            float r0, float x1, float y1, float r1/*-{
     return this.@com.gwt.components.client.Canvas::context.createRadialGradient(
      x0, y0, r0, x1, y1, r1);   
    }-*/;

    public native Pattern createPattern(Image img, String repetition/*-{
     var elem = img.@com.google.gwt.user.client.ui.UIObject::getElement()();
     var ctx = this.@com.gwt.components.client.Canvas::context;
     if (ctx.createPattern)
     return ctx.createPattern(elem, repetition);
     return null;   
    }-*/;

    public native float getLineWidth() /*-{
     return this.@com.gwt.components.client.Canvas::context.lineWidth;
    }-*/;

    public native void setLineWidth(float lineWidth/*-{
     this.@com.gwt.components.client.Canvas::context.lineWidth = lineWidth;
    }-*/;

    public native String getLineCap() /*-{
     return this.@com.gwt.components.client.Canvas::context.lineCap;
    }-*/;

    public native void setLineCap(String lineCap/*-{
     this.@com.gwt.components.client.Canvas::context.lineCap = lineCap;
    }-*/;

    public native String getLineJoin() /*-{
     return this.@com.gwt.components.client.Canvas::context.lineJoin;
    }-*/;

    public native void setLineJoin(String lineJoin/*-{
     this.@com.gwt.components.client.Canvas::context.lineJoin = lineJoin;
    }-*/;

    public native float getMiterLimit() /*-{
     return this.@com.gwt.components.client.Canvas::context.miterLimit;
    }-*/;

    public native void setMiterLimit(float miterLimit/*-{
     this.@com.gwt.components.client.Canvas::context.miterLimit = miterLimit;
    }-*/;

    public native float getShadowOffsetX() /*-{
     return this.@com.gwt.components.client.Canvas::context.shadowOffsetX;
    }-*/;

    public native void setShadowOffsetX(float x/*-{
     this.@com.gwt.components.client.Canvas::context.shadowOffsetX = x;
    }-*/;

    public native float getShadowOffsetY() /*-{
     return this.@com.gwt.components.client.Canvas::context.shadowOffsetY;
    }-*/;

    public native void setShadowOffsetY(float y/*-{
     this.@com.gwt.components.client.Canvas::context.shadowOffsetY = y;
    }-*/;

    public native float getShadowBlur() /*-{
     return this.@com.gwt.components.client.Canvas::context.shadowBlur;
    }-*/;

    public native void setShadowBlur(float blur/*-{
     this.@com.gwt.components.client.Canvas::context.shadowBlur = blur;
    }-*/;

    public native String getShadowColor() /*-{
     return this.@com.gwt.components.client.Canvas::context.shadowColor;
    }-*/;

    public native void setShadowColor(String style/*-{
     this.@com.gwt.components.client.Canvas::context.shadowColor = style;
    }-*/;

    public native void clearRect(float x, float y, float w, float h/*-{
     var ctx = this.@com.gwt.components.client.Canvas::context;
     if (typeof $wnd.G_vmlCanvasManager != "undefined") {
     var el = this.@com.google.gwt.user.client.ui.UIObject::getElement()();
     if (el.currentStyle) {
     var color = el.currentStyle['background-color'];
     if (!color) {
     color = '#ffffff';
     }
     ctx.save();
     ctx.fillStyle = color;
     ctx.fillRect(x, y, w, h);
     ctx.restore();
     }
     } else {
     ctx.clearRect(x, y, w, h);
     }
    }-*/;

    public native void fillRect(float x, float y, float w, float h/*-{
     this.@com.gwt.components.client.Canvas::context.fillRect(x, y, w, h);
    }-*/;

    public native void strokeRect(float x, float y, float w, float h/*-{
     this.@com.gwt.components.client.Canvas::context.strokeRect(x, y, w, h);
    }-*/;

    public native void beginPath() /*-{
     this.@com.gwt.components.client.Canvas::context.beginPath();
    }-*/;

    public native void closePath() /*-{
     this.@com.gwt.components.client.Canvas::context.closePath();
    }-*/;

    public native void moveTo(float x, float y/*-{
     this.@com.gwt.components.client.Canvas::context.moveTo(x,y);
    }-*/;

    public native void lineTo(float x, float y/*-{
     this.@com.gwt.components.client.Canvas::context.lineTo(x,y);
    }-*/;

    public native void quadraticCurveTo(float cpx, float cpy, float x, float y/*-{
     this.@com.gwt.components.client.Canvas::context.quadraticCurveTo(cpx, cpy, x, y);
    }-*/;

    public native void bezierCurveTo(float cp1x, float cp1y, float cp2x,
            float cp2y, float x, float y/*-{
     this.@com.gwt.components.client.Canvas::context.bezierCurveTo(
      cp1x, cp1y, cp2x, cp2y, x, y);
    }-*/;

    public native void arcTo(float x1, float y1, float x2, float y2,
            float radius/*-{
     this.@com.gwt.components.client.Canvas::context.arcTo(x1, y1, x2, y2, radius);
    }-*/;

    public native void rect(float x, float y, float w, float h/*-{
     this.@com.gwt.components.client.Canvas::context.rect(x, y, w, h);
    }-*/;

    public native void arc(float x, float y, float radius, float startAngle,
            float endAngle, boolean anticlockwise/*-{
     this.@com.gwt.components.client.Canvas::context.arc(
      x, y, radius, startAngle, endAngle, anticlockwise);
    }-*/;

    public native void fill() /*-{
     this.@com.gwt.components.client.Canvas::context.fill();
    }-*/;

    public native void stroke() /*-{
     this.@com.gwt.components.client.Canvas::context.stroke();
    }-*/;

    public native void clip() /*-{
     this.@com.gwt.components.client.Canvas::context.clip();
    }-*/;

    public native boolean isPointInPath(float x, float y/*-{
     this.@com.gwt.components.client.Canvas::context.isPointInPath(x, y);
    }-*/;
}

/*
Canvas.css:

.gwt-Canvas {
    width:400px;
    height:400px;
    border: 1px solid black;
}
*/
           
       
Related examples in the same category
www.java2java.com | Contact Us
Copyright 2010 - 2030 Java Source and Support. All rights reserved.
All other trademarks are property of their respective owners.