1 /* 2 * Copyright 2011 Google Inc. All Rights Reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.typography.font.sfntly.table.bitmap; 18 19 import com.google.typography.font.sfntly.data.ReadableFontData; 20 import com.google.typography.font.sfntly.data.WritableFontData; 21 22 /** 23 * @author Stuart Gill 24 * 25 */ 26 public class CompositeBitmapGlyph extends BitmapGlyph { 27 28 public static final class Component { 29 private final int glyphCode; 30 private int xOffset; 31 private int yOffset; 32 Component(int glyphCode, int xOffset, int yOffset)33 protected Component(int glyphCode, int xOffset, int yOffset) { 34 this.glyphCode = glyphCode; 35 this.xOffset = xOffset; 36 this.yOffset = yOffset; 37 } 38 glyphCode()39 public int glyphCode() { 40 return this.glyphCode; 41 } 42 xOffset()43 public int xOffset() { 44 return this.xOffset; 45 } 46 yOffset()47 public int yOffset() { 48 return this.yOffset; 49 } 50 51 @Override hashCode()52 public int hashCode() { 53 final int prime = 31; 54 int result = 1; 55 result = prime * result + glyphCode; 56 return result; 57 } 58 59 @Override equals(Object obj)60 public boolean equals(Object obj) { 61 if (this == obj) { 62 return true; 63 } 64 if (obj == null) { 65 return false; 66 } 67 if (!(obj instanceof Component)) { 68 return false; 69 } 70 Component other = (Component) obj; 71 if (glyphCode != other.glyphCode) { 72 return false; 73 } 74 return true; 75 } 76 } 77 78 private int numComponentsOffset; 79 private int componentArrayOffset; 80 CompositeBitmapGlyph(ReadableFontData data, int format)81 protected CompositeBitmapGlyph(ReadableFontData data, int format) { 82 super(data, format); 83 initialize(format); 84 } 85 86 /** 87 * Initializes the internal state from the data. 88 * 89 * @param format the glyph format 90 */ initialize(int format)91 private void initialize(int format) { 92 if (format == 8) { 93 this.numComponentsOffset = Offset.glyphFormat8_numComponents.offset; 94 this.componentArrayOffset = Offset.glyphFormat8_componentArray.offset; 95 } else if (format == 9) { 96 this.numComponentsOffset = Offset.glyphFormat9_numComponents.offset; 97 this.componentArrayOffset = Offset.glyphFormat9_componentArray.offset; 98 } else { 99 throw new IllegalStateException( 100 "Attempt to create a Composite Bitmap Glyph with a non-composite format."); 101 } 102 } 103 numComponents()104 public int numComponents() { 105 return this.data.readUShort(this.numComponentsOffset); 106 } 107 component(int componentNum)108 public Component component(int componentNum) { 109 int componentOffset = 110 this.componentArrayOffset + componentNum * Offset.ebdtComponentLength.offset; 111 return new Component( 112 this.data.readUShort(componentOffset + Offset.ebdtComponent_glyphCode.offset), 113 this.data.readChar(componentOffset + Offset.ebdtComponent_xOffset.offset), 114 this.data.readChar(componentOffset + Offset.ebdtComponent_yOffset.offset)); 115 } 116 117 public static class Builder extends BitmapGlyph.Builder<CompositeBitmapGlyph> { 118 Builder(WritableFontData data, int format)119 protected Builder(WritableFontData data, int format) { 120 super(data, format); 121 } 122 Builder(ReadableFontData data, int format)123 protected Builder(ReadableFontData data, int format) { 124 super(data, format); 125 } 126 127 @Override subBuildTable(ReadableFontData data)128 protected CompositeBitmapGlyph subBuildTable(ReadableFontData data) { 129 return new CompositeBitmapGlyph(data, this.format()); 130 } 131 } 132 } 133