001: /*
002: *
003: *
004: * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: */
026: package com.sun.perseus.j2d;
027:
028: /**
029: * {@link com.sun.perseus.model.ModelNode ModelNode} are rendered into a
030: * {@link RenderGraphics RenderGraphics} which extends
031: * the <tt>RenderContext</tt> class. A <tt>RenderContext</tt> captures
032: * the current state of the properties used in painting operations. When a
033: * <tt>ModelNode</tt> tree is rendered, the <tt>RenderGraphics</tt>
034: * is passed down the tree to children nodes as they are painted. This
035: * provides the solution for computing CSS inherited values: if a
036: * <tt>ModelNode</tt> inherits one of its properties, it will simply use
037: * the one currently set in the <tt>RenderContext</tt>.
038: * <br />
039: * Initially (i.e., before any painting operation happens), the
040: * <tt>RenderContext</tt> holds values which correspond to the CSS 2 concept of
041: * <a href="http://www.w3.org/TR/REC-CSS2/about.html#q7">initial</a> values.
042: * <br />
043: * At any time during a rendering operation, the <tt>RenderContext</tt> holds
044: * values which correspond to the CSS 2
045: * <a href="http://www.w3.org/TR/REC-CSS2/cascade.html#computed-value">
046: * computed</a> values.
047: *
048: * Note that in addition to properties that correspond to CSS2 properties, the
049: * <tt>RenderContext</tt> also keeps an <tt>AffineTransform</tt> which is
050: * not a CSS2 property. The transform represents the current user space to
051: * device space transformation.
052: *
053: * @see com.sun.perseus.model.ModelNode
054: * @see com.sun.perseus.model.ElementNode#paint
055: *
056: * @version $Id: RenderContext.java,v 1.5 2006/04/21 06:35:38 st125089 Exp $
057: */
058: public class RenderContext implements TextRenderingProperties {
059: // =======================================================================
060: // Initial Property values used internally
061: // =======================================================================
062: /**
063: * Default stroke width
064: */
065: protected static int INITIAL_STROKE_WIDTH_IMPL = 1 << 16;
066:
067: /**
068: * Default miter limit
069: */
070: protected static int INITIAL_STROKE_MITER_LIMIT_IMPL = 4 << 16;
071:
072: /**
073: * Default dash array
074: */
075: protected static int[] INITIAL_STROKE_DASH_ARRAY_IMPL = null;
076:
077: /**
078: * Default dash offset
079: */
080: protected static int INITIAL_STROKE_DASH_OFFSET_IMPL = 0;
081:
082: // =======================================================================
083: // Constants used for packing and unpacking data in the pack member
084: // =======================================================================
085:
086: protected static final int FONT_STYLE_MASK = 0x60000000; /* 30-29 */
087: protected static final int FONT_WEIGHT_MASK = 0x1E000000; /* 28-27-26-25 */
088: protected static final int TEXT_ANCHOR_MASK = 0x01800000; /* 24-23 */
089: protected static final int STROKE_OPACITY_MASK = 0x007F8000; /* 22-21-20-19-18-17-16-15 */
090: protected static final int FILL_OPACITY_MASK = 0x00007F80; /* 14-13-12-11-10-09-08-07 */
091: protected static final int FILL_RULE_MASK = 0x00000040; /* 06 */
092: protected static final int STROKE_LINE_CAP_MASK = 0x00000030; /* 05-04 */
093: protected static final int STROKE_LINE_JOIN_MASK = 0x0000000C; /* 03-02 */
094: protected static final int VISIBILITY_MASK = 0x00000002; /* 01 */
095: protected static final int DISPLAY_MASK = 0x00000001; /* 00 */
096:
097: // =======================================================================
098: // Constants used for packing and unpacking data in the pack2 member
099: // =======================================================================
100: protected static final int OPACITY_MASK = 0x000000FF; /* 7-6-5-4-3-2-1-0 */
101:
102: protected static final int FONT_STYLE_NORMAL_IMPL = 0x00000000;
103: protected static final int FONT_STYLE_ITALIC_IMPL = 0x40000000;
104: protected static final int FONT_STYLE_OBLIQUE_IMPL = 0x60000000;
105:
106: protected static final int FONT_WEIGHT_100_IMPL = 0x00000000;
107: protected static final int FONT_WEIGHT_200_IMPL = 0x02000000;
108: protected static final int FONT_WEIGHT_300_IMPL = 0x04000000;
109: protected static final int FONT_WEIGHT_400_IMPL = 0x06000000;
110: protected static final int FONT_WEIGHT_500_IMPL = 0x08000000;
111: protected static final int FONT_WEIGHT_600_IMPL = 0x0A000000;
112: protected static final int FONT_WEIGHT_700_IMPL = 0x0C000000;
113: protected static final int FONT_WEIGHT_800_IMPL = 0x0E000000;
114: protected static final int FONT_WEIGHT_900_IMPL = 0x10000000;
115:
116: protected static final int TEXT_ANCHOR_MIDDLE_IMPL = 0x00000000;
117: protected static final int TEXT_ANCHOR_START_IMPL = 0x00800000;
118: protected static final int TEXT_ANCHOR_END_IMPL = 0x01000000;
119:
120: protected static final int CAP_BUTT_IMPL = 0x00000000;
121: protected static final int CAP_ROUND_IMPL = 0x00000010;
122: protected static final int CAP_SQUARE_IMPL = 0x00000020;
123:
124: protected static final int JOIN_MITER_IMPL = 0x00000000;
125: protected static final int JOIN_ROUND_IMPL = 0x00000004;
126: protected static final int JOIN_BEVEL_IMPL = 0x00000008;
127:
128: // =======================================================================
129: // Property values, some are packed.
130: // =======================================================================
131: /**
132: * Color used for fill operations
133: */
134: protected PaintServer fill = INITIAL_FILL;
135:
136: /**
137: * Color used for fill operations
138: */
139: protected PaintServer stroke = INITIAL_STROKE;
140:
141: /**
142: * Context Color. Corresponds to the concept of
143: * 'current color' in CSS
144: */
145: protected RGB color = INITIAL_COLOR;
146:
147: /**
148: * Controls the strokeDash pattern for stroke operations.
149: * If the array is null, a solid line is used
150: */
151: protected int[] strokeDashArray = INITIAL_STROKE_DASH_ARRAY_IMPL;
152:
153: /**
154: * Controls the width of the stroke. 15.16 format.
155: */
156: protected int strokeWidth = INITIAL_STROKE_WIDTH_IMPL;
157:
158: /**
159: * Controls the miter limit for stroke operations. 15.16 format.
160: */
161: protected int strokeMiterLimit = INITIAL_STROKE_MITER_LIMIT_IMPL;
162:
163: /**
164: * Controls the offset in the dash array for
165: * stroke operations. 15.16 format.
166: */
167: protected int strokeDashOffset = INITIAL_STROKE_DASH_OFFSET_IMPL;
168:
169: /**
170: * Controls the current font family. The font family is
171: * a list, which means that a set of fonts may be used
172: * to render a given text string. The fonts are queried in
173: * order to check which ones can render characters in the
174: * drawn text.
175: */
176: protected String[] fontFamily = INITIAL_FONT_FAMILY;
177:
178: /**
179: * Controls the current font size
180: */
181: protected float fontSize = INITIAL_FONT_SIZE;
182:
183: //
184: // Property pack
185: //
186: // fontStyle: 3 styles, 2 bits
187: // fontWeight: 9 weights, 4 bits
188: // textAnchor 3 values, 2 bits
189: // strokeOpacity: 8 bits [0-200]
190: // fillOpacity: 8 bits [0-200]
191: // fillRule: 1 bits
192: // strokeLineCap: 3 values, 2 bits
193: // strokeLineJoin 3 values, 2 bits
194: // visibility: 2 values, 1 bit
195: // display: 2 values, 1 bit
196: // Total: 31 bits
197: //
198: // Encoding:
199: //
200: // fontStyle: 30-29
201: // fontWeight: 28-27-26-25
202: // textAnchor: 24-23
203: // strokeOpacity: 22-21-20-19-18-17-16-15
204: // fillOpacity: 14-13-12-11-10-09-08-07
205: // fillRule: 06
206: // strokeLineCap: 05-04
207: // strokeLineJoin: 03-02
208: // visibility: 01
209: // display: 00
210: //
211: protected int pack = INITIAL_PACK;
212:
213: protected static final int INITIAL_FONT_STYLE_IMPL = FONT_STYLE_NORMAL_IMPL;
214: protected static final int INITIAL_FONT_WEIGHT_IMPL = FONT_WEIGHT_400_IMPL;
215: protected static final int INITIAL_TEXT_ANCHOR_IMPL = TEXT_ANCHOR_START_IMPL;
216: protected static final int INITIAL_STROKE_OPACITY_IMPL = 200 << 15;
217: protected static final int INITIAL_FILL_OPACITY_IMPL = 200 << 7;
218: protected static final int INITIAL_FILL_RULE_IMPL = 0;
219: protected static final int INITIAL_STROKE_LINE_CAP_IMPL = CAP_BUTT_IMPL;
220: protected static final int INITIAL_STROKE_LINE_JOIN_IMPL = JOIN_MITER_IMPL;
221: protected static final int INITIAL_VISIBILITY_IMPL = 0x2;
222: protected static final int INITIAL_DISPLAY_IMPL = 0x1;
223: protected static final int INITIAL_PACK = INITIAL_FONT_STYLE_IMPL
224: | INITIAL_FONT_WEIGHT_IMPL | INITIAL_TEXT_ANCHOR_IMPL
225: | INITIAL_STROKE_OPACITY_IMPL | INITIAL_FILL_OPACITY_IMPL
226: | INITIAL_FILL_RULE_IMPL | INITIAL_STROKE_LINE_CAP_IMPL
227: | INITIAL_STROKE_LINE_JOIN_IMPL | INITIAL_VISIBILITY_IMPL
228: | INITIAL_DISPLAY_IMPL;
229:
230: //
231: // Property pack2
232: //
233: // opacity: 8 bits [0-255]
234: // Total: 8 bits
235: //
236: // Encoding:
237: //
238: // opacity: 07-06-05-04-03-02-01-00
239: //
240: protected int pack2 = INITIAL_PACK2;
241:
242: protected static final int INITIAL_OPACITY_IMPL = 200;
243: protected static final int INITIAL_PACK2 = INITIAL_OPACITY_IMPL;
244:
245: /**
246: * Default constructor
247: */
248: public RenderContext() {
249: }
250:
251: /**
252: * Copy constructor
253: * @param rcs the <tt>RenderContext</tt> to copy values from. Should
254: * not be null.
255: */
256: public RenderContext(final RenderContext rcs) {
257: restore(rcs);
258: }
259:
260: /**
261: * @param rcs the <tt>RenderContext</tt> state to restore. Should
262: * not be null.
263: */
264: public void restore(final RenderContext rcs) {
265: this .fill = rcs.fill;
266: this .stroke = rcs.stroke;
267: this .color = rcs.color;
268: this .strokeDashArray = rcs.strokeDashArray;
269: this .strokeWidth = rcs.strokeWidth;
270: this .strokeMiterLimit = rcs.strokeMiterLimit;
271: this .strokeDashOffset = rcs.strokeDashOffset;
272: this .fontFamily = rcs.fontFamily;
273: this .fontSize = rcs.fontSize;
274: this .pack = rcs.pack;
275: this .pack2 = rcs.pack2;
276: }
277:
278: /**
279: * Resets context to initial values
280: */
281: public void reset() {
282: this .fill = INITIAL_FILL;
283: this .stroke = INITIAL_STROKE;
284: this .color = INITIAL_COLOR;
285: this .strokeDashArray = INITIAL_STROKE_DASH_ARRAY_IMPL;
286: this .strokeWidth = INITIAL_STROKE_WIDTH_IMPL;
287: this .strokeMiterLimit = INITIAL_STROKE_MITER_LIMIT_IMPL;
288: this .strokeDashOffset = INITIAL_STROKE_DASH_OFFSET_IMPL;
289: this .fontFamily = INITIAL_FONT_FAMILY;
290: this .fontSize = INITIAL_FONT_SIZE;
291: this .pack = INITIAL_PACK;
292: this .pack2 = INITIAL_PACK2;
293: }
294:
295: /**
296: * @param newFill the new value for the fill property
297: */
298: public void setFill(final PaintServer newFill) {
299: this .fill = newFill;
300: }
301:
302: /**
303: * @return the context's fill property value
304: */
305: public PaintServer getFill() {
306: return fill;
307: }
308:
309: /**
310: * @param newFillOpacity the new value for the fill opacity property. The
311: * input value is clamped to the [0, 1] range.
312: */
313: public void setFillOpacity(float newFillOpacity) {
314: if (newFillOpacity < 0) {
315: newFillOpacity = 0;
316: } else if (newFillOpacity > 1) {
317: newFillOpacity = 1;
318: }
319:
320: pack &= ~FILL_OPACITY_MASK;
321: pack |= ((((int) (newFillOpacity * 200)) << 7) & FILL_OPACITY_MASK);
322: }
323:
324: /**
325: * @return the context's fill opacity property value
326: */
327: public float getFillOpacity() {
328: return ((pack & FILL_OPACITY_MASK) >> 7) / 200.0f;
329: }
330:
331: /**
332: * @return the context's fill opacity property value
333: */
334: int getFillOpacityImpl() {
335: return (int) (((pack & FILL_OPACITY_MASK) >> 7) * 255f / 200f);
336: }
337:
338: /**
339: * @param newStroke the new value for the stroke property
340: */
341: public void setStroke(final PaintServer newStroke) {
342: this .stroke = newStroke;
343: }
344:
345: /**
346: * @return the context's stroke property value
347: */
348: public PaintServer getStroke() {
349: return stroke;
350: }
351:
352: /**
353: * @param newStrokeOpacity the new value for the stroke opacity property.
354: * The input value is clamped to the [0, 1] range.
355: */
356: public void setStrokeOpacity(float newStrokeOpacity) {
357: if (newStrokeOpacity < 0) {
358: newStrokeOpacity = 0;
359: } else if (newStrokeOpacity > 1) {
360: newStrokeOpacity = 1;
361: }
362:
363: pack &= ~STROKE_OPACITY_MASK;
364: pack |= ((((int) (newStrokeOpacity * 200)) << 15) & STROKE_OPACITY_MASK);
365: }
366:
367: /**
368: * @return the context's stroke opacity property value
369: */
370: public float getStrokeOpacity() {
371: return ((pack & STROKE_OPACITY_MASK) >> 15) / 200.0f;
372: }
373:
374: /**
375: * @return the context's stroke opacity property value
376: */
377: public int getStrokeOpacityImpl() {
378: return (int) (((pack & STROKE_OPACITY_MASK) >> 15) * 255f / 200f);
379: }
380:
381: /**
382: * @param newColor the new value for the color property
383: */
384: public void setColor(final RGB newColor) {
385: this .color = newColor;
386: }
387:
388: /**
389: * @return the context's color property value
390: */
391: public RGB getColor() {
392: return this .color;
393: }
394:
395: /**
396: * @param newFillRule the new value for the fill rule property
397: */
398: public void setFillRule(final int newFillRule) {
399: if (newFillRule == WIND_EVEN_ODD) {
400: pack |= FILL_RULE_MASK;
401: } else {
402: pack &= ~FILL_RULE_MASK;
403: }
404: }
405:
406: /**
407: * @return the context's fill rule property value
408: */
409: public int getFillRule() {
410: if ((pack & FILL_RULE_MASK) == FILL_RULE_MASK) {
411: return WIND_EVEN_ODD;
412: }
413: return WIND_NON_ZERO;
414: }
415:
416: /**
417: * @return the context's stroke dash array property value
418: */
419: public float[] getStrokeDashArray() {
420: if (strokeDashArray == null) {
421: return null;
422: }
423:
424: float[] sda = new float[strokeDashArray.length];
425: for (int i = 0; i < sda.length; i++) {
426: sda[i] = strokeDashArray[i] / 65536.0f;
427: }
428:
429: return sda;
430: }
431:
432: /**
433: * @param newStrokeDashArray the new stroke dash array property value
434: */
435: public void setStrokeDashArray(final float[] newStrokeDashArray) {
436: if (newStrokeDashArray == null) {
437: strokeDashArray = null;
438: } else {
439: strokeDashArray = new int[newStrokeDashArray.length];
440: for (int i = 0; i < strokeDashArray.length; i++) {
441: strokeDashArray[i] = (int) (newStrokeDashArray[i] * 65536);
442: }
443: }
444: }
445:
446: /**
447: * @return the context's stroke line cap property value
448: */
449: public int getStrokeLineCap() {
450: switch (pack & STROKE_LINE_CAP_MASK) {
451: case CAP_BUTT_IMPL:
452: return CAP_BUTT;
453: case CAP_ROUND_IMPL:
454: return CAP_ROUND;
455: default:
456: return CAP_SQUARE;
457: }
458: }
459:
460: /**
461: * @param newStrokeLineCap the new stroke line cap property value
462: */
463: public void setStrokeLineCap(final int newStrokeLineCap) {
464: // Clear stroke-linecap
465: pack &= ~STROKE_LINE_CAP_MASK;
466:
467: switch (newStrokeLineCap) {
468: case CAP_BUTT:
469: pack |= CAP_BUTT_IMPL;
470: break;
471: case CAP_ROUND:
472: pack |= CAP_ROUND_IMPL;
473: break;
474: default:
475: pack |= CAP_SQUARE_IMPL;
476: break;
477: }
478: }
479:
480: /**
481: * @return the context's stroke line join property value
482: */
483: public int getStrokeLineJoin() {
484: switch (pack & STROKE_LINE_JOIN_MASK) {
485: case JOIN_MITER_IMPL:
486: return JOIN_MITER;
487: case JOIN_ROUND_IMPL:
488: return JOIN_ROUND;
489: default:
490: return JOIN_BEVEL;
491: }
492: }
493:
494: /**
495: * @param newStrokeLineJoin the new stroke line join property value
496: */
497: public void setStrokeLineJoin(final int newStrokeLineJoin) {
498: // Clear stroke-linejoin
499: pack &= ~STROKE_LINE_JOIN_MASK;
500:
501: switch (newStrokeLineJoin) {
502: case JOIN_MITER:
503: pack |= JOIN_MITER_IMPL;
504: break;
505: case JOIN_ROUND:
506: pack |= JOIN_ROUND_IMPL;
507: break;
508: default:
509: pack |= JOIN_BEVEL_IMPL;
510: break;
511: }
512: }
513:
514: /**
515: * @return the context's stroke width property value
516: */
517: public float getStrokeWidth() {
518: return strokeWidth / 65536.0f;
519: }
520:
521: /**
522: * @param newStrokeWidth the new stroke width property value
523: */
524: public void setStrokeWidth(final float newStrokeWidth) {
525: strokeWidth = (int) (newStrokeWidth * 65536);
526: }
527:
528: /**
529: * @return the context's stroke miter limit property value
530: */
531: public float getStrokeMiterLimit() {
532: return strokeMiterLimit / 65536.0f;
533: }
534:
535: /**
536: * @param newStrokeMiterLimit the new stroke miter limit property value
537: */
538: public void setStrokeMiterLimit(final float newStrokeMiterLimit) {
539: strokeMiterLimit = (int) (newStrokeMiterLimit * 65536);
540: }
541:
542: /**
543: * @return the context's stroke dash offset property
544: */
545: public float getStrokeDashOffset() {
546: return strokeDashOffset / 65536.0f;
547: }
548:
549: /**
550: * @param newStrokeDashOffset the new stroke dash offset property value
551: */
552: public void setStrokeDashOffset(final float newStrokeDashOffset) {
553: strokeDashOffset = (int) (newStrokeDashOffset * 65536);
554: }
555:
556: /**
557: * @param newVisibility the new visibility property value
558: */
559: public void setVisibility(final boolean newVisibility) {
560: if (newVisibility) {
561: pack |= VISIBILITY_MASK;
562: } else {
563: pack &= ~VISIBILITY_MASK;
564: }
565: }
566:
567: /**
568: * @return the context's visibility
569: */
570: public boolean getVisibility() {
571: return ((pack & VISIBILITY_MASK) == VISIBILITY_MASK);
572: }
573:
574: /**
575: * @param newDisplay the new value for the display property
576: */
577: public void setDisplay(final boolean newDisplay) {
578: if (newDisplay) {
579: pack |= DISPLAY_MASK;
580: } else {
581: pack &= ~DISPLAY_MASK;
582: }
583: }
584:
585: /**
586: * @return the context' display property value
587: */
588: public boolean getDisplay() {
589: return ((pack & DISPLAY_MASK) == DISPLAY_MASK);
590: }
591:
592: /**
593: * @return the context's set of font families
594: */
595: public String[] getFontFamily() {
596: return fontFamily;
597: }
598:
599: /**
600: * @param newFontFamily the new set of font families to use for font
601: * matching.
602: */
603: public void setFontFamily(final String[] newFontFamily) {
604: this .fontFamily = newFontFamily;
605: }
606:
607: /**
608: * @return the context's font size property
609: */
610: public float getFontSize() {
611: return fontSize;
612: }
613:
614: /**
615: * @param newFontSize the new value for the font size property
616: */
617: public void setFontSize(final float newFontSize) {
618: this .fontSize = newFontSize;
619: }
620:
621: /**
622: * @return the context's font style property value
623: */
624: public int getFontStyle() {
625: switch (pack & FONT_STYLE_MASK) {
626: case FONT_STYLE_NORMAL_IMPL:
627: return FONT_STYLE_NORMAL;
628: case FONT_STYLE_ITALIC_IMPL:
629: return FONT_STYLE_ITALIC;
630: default:
631: return FONT_STYLE_OBLIQUE;
632: }
633: }
634:
635: /**
636: * @param newFontStyle the new value for the font style property
637: */
638: public void setFontStyle(final int newFontStyle) {
639: // Clear font-style.
640: pack &= ~FONT_STYLE_MASK;
641:
642: switch (newFontStyle) {
643: case FONT_STYLE_NORMAL:
644: pack |= FONT_STYLE_NORMAL_IMPL;
645: break;
646: case FONT_STYLE_ITALIC:
647: pack |= FONT_STYLE_ITALIC_IMPL;
648: break;
649: default:
650: pack |= FONT_STYLE_OBLIQUE_IMPL;
651: break;
652: }
653: }
654:
655: /**
656: * @return the current context's font weight property
657: */
658: public int getFontWeight() {
659: switch (pack & FONT_WEIGHT_MASK) {
660: case FONT_WEIGHT_100_IMPL:
661: return FONT_WEIGHT_100;
662: case FONT_WEIGHT_200_IMPL:
663: return FONT_WEIGHT_200;
664: case FONT_WEIGHT_300_IMPL:
665: return FONT_WEIGHT_300;
666: case FONT_WEIGHT_400_IMPL:
667: return FONT_WEIGHT_400;
668: case FONT_WEIGHT_500_IMPL:
669: return FONT_WEIGHT_500;
670: case FONT_WEIGHT_600_IMPL:
671: return FONT_WEIGHT_600;
672: case FONT_WEIGHT_700_IMPL:
673: return FONT_WEIGHT_700;
674: case FONT_WEIGHT_800_IMPL:
675: return FONT_WEIGHT_800;
676: default:
677: return FONT_WEIGHT_900;
678: }
679: }
680:
681: /**
682: * @param newFontWeight new font weight property value
683: */
684: public void setFontWeight(final int newFontWeight) {
685: // Clear font-weight
686: pack &= ~FONT_WEIGHT_MASK;
687:
688: switch (newFontWeight) {
689: case FONT_WEIGHT_100:
690: pack |= FONT_WEIGHT_100_IMPL;
691: break;
692: case FONT_WEIGHT_200:
693: pack |= FONT_WEIGHT_200_IMPL;
694: break;
695: case FONT_WEIGHT_300:
696: pack |= FONT_WEIGHT_300_IMPL;
697: break;
698: case FONT_WEIGHT_400:
699: pack |= FONT_WEIGHT_400_IMPL;
700: break;
701: case FONT_WEIGHT_500:
702: pack |= FONT_WEIGHT_500_IMPL;
703: break;
704: case FONT_WEIGHT_600:
705: pack |= FONT_WEIGHT_600_IMPL;
706: break;
707: case FONT_WEIGHT_700:
708: pack |= FONT_WEIGHT_700_IMPL;
709: break;
710: case FONT_WEIGHT_800:
711: pack |= FONT_WEIGHT_800_IMPL;
712: break;
713: default:
714: pack |= FONT_WEIGHT_900_IMPL;
715: break;
716: }
717: }
718:
719: /**
720: * @return the text anchor property
721: */
722: public int getTextAnchor() {
723: switch (pack & TEXT_ANCHOR_MASK) {
724: case TEXT_ANCHOR_START_IMPL:
725: return TEXT_ANCHOR_START;
726: case TEXT_ANCHOR_MIDDLE_IMPL:
727: return TEXT_ANCHOR_MIDDLE;
728: default:
729: return TEXT_ANCHOR_END;
730: }
731: }
732:
733: /**
734: * @param newTextAnchor the new text anchor property value
735: */
736: public void setTextAnchor(final int newTextAnchor) {
737: // Clear text-anchor.
738: pack &= ~TEXT_ANCHOR_MASK;
739:
740: switch (newTextAnchor) {
741: case TEXT_ANCHOR_START:
742: pack |= TEXT_ANCHOR_START_IMPL;
743: break;
744: case TEXT_ANCHOR_MIDDLE:
745: pack |= TEXT_ANCHOR_MIDDLE_IMPL;
746: break;
747: default:
748: pack |= TEXT_ANCHOR_END_IMPL;
749: break;
750: }
751: }
752:
753: /**
754: * @param newOpacity the new value for the opacity property. The
755: * input value is clamped to the [0, 1] range.
756: *
757: * @param newOpacity the new opacity value to set
758: */
759: public void setOpacity(float newOpacity) {
760: if (newOpacity < 0) {
761: newOpacity = 0;
762: } else if (newOpacity > 1) {
763: newOpacity = 1;
764: }
765:
766: pack2 &= ~OPACITY_MASK;
767: pack2 |= (((int) (newOpacity * 200)) & OPACITY_MASK);
768: }
769:
770: /**
771: * @return the context's opacity property value
772: */
773: public float getOpacity() {
774: return (pack2 & OPACITY_MASK) / 200.0f;
775: }
776:
777: /**
778: * @return the context's opacity property value
779: */
780: int getOpacityImpl() {
781: return (int) ((pack2 & OPACITY_MASK) * 255f / 200f);
782: }
783:
784: /**
785: * @return a copy of this <tt>RenderContext</tt>
786: */
787: public RenderContext save() {
788: return new RenderContext(this );
789: }
790:
791: /**
792: * Implemnetation: Handles negative strokeDashOffset
793: *
794: * @return a positive strokeDashOffset.
795: */
796: int computeStrokeDashOffset() {
797: if (strokeDashArray == null) {
798: // The stroke dash offset does not matter, simply return 0
799: return 0;
800: }
801:
802: if (strokeDashOffset >= 0) {
803: return strokeDashOffset;
804: }
805:
806: int length = 0;
807: for (int i = 0; i < strokeDashArray.length; i++) {
808: length += strokeDashArray[i];
809: }
810:
811: if (length <= 0) {
812: return 0;
813: }
814:
815: int sdo = strokeDashOffset;
816: while (sdo < 0) {
817: sdo += length;
818: }
819:
820: return sdo;
821: }
822: }
|