1 /*
   2  * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.javafx.font;
  27 
  28 import java.lang.ref.WeakReference;
  29 import java.util.concurrent.ConcurrentHashMap;
  30 import java.util.Map;
  31 
  32 import com.sun.javafx.geom.transform.BaseTransform;
  33 
  34 
  35 /*
  36  * Wraps a physical font and adds an appropriate fallback resource.
  37  */
  38 
  39 class PrismCompositeFontResource implements CompositeFontResource {
  40 
  41     private FontResource primaryResource;
  42     private FallbackResource fallbackResource; // is a composite too.
  43 
  44     PrismCompositeFontResource(FontResource primaryResource,
  45                              String lookupName) {
  46         // remind go through and make the typing better.
  47         if (!(primaryResource instanceof PrismFontFile)) {
  48             Thread.dumpStack();
  49             throw new IllegalStateException("wrong resource type");
  50         }
  51         if (lookupName != null) {
  52             PrismFontFactory factory = PrismFontFactory.getFontFactory();
  53             factory.compResourceMap.put(lookupName, this);
  54         }
  55         this.primaryResource = primaryResource;
  56         int aaMode = primaryResource.getDefaultAAMode();
  57         boolean bold = primaryResource.isBold();
  58         boolean italic = primaryResource.isItalic();
  59         fallbackResource =
  60               FallbackResource.getFallbackResource(bold, italic, aaMode);
  61     }
  62 
  63     public int getNumSlots() {
  64         return fallbackResource.getNumSlots()+1;
  65     }
  66 
  67     public int getSlotForFont(String fontName) {
  68         if (primaryResource.getFullName().equalsIgnoreCase(fontName)) {
  69             return 0;
  70         }
  71         return fallbackResource.getSlotForFont(fontName) + 1;
  72     }
  73 
  74     public FontResource getSlotResource(int slot) {
  75         if (slot == 0) {
  76             return primaryResource;
  77         } else {
  78             FontResource fb = fallbackResource.getSlotResource(slot-1);
  79             if (fb != null) {
  80                 return fb;
  81             } else {
  82                  return primaryResource;
  83             }
  84         }
  85     }
  86 
  87     public String getFullName() {
  88         return primaryResource.getFullName();
  89     }
  90 
  91     public String getPSName() {
  92         return primaryResource.getPSName();
  93     }
  94 
  95     public String getFamilyName() {
  96         return primaryResource.getFamilyName();
  97     }
  98 
  99     public String getStyleName() {
 100         return primaryResource.getStyleName();
 101     }
 102 
 103     public String getLocaleFullName() {
 104         return primaryResource.getLocaleFullName();
 105     }
 106 
 107     public String getLocaleFamilyName() {
 108         return primaryResource.getLocaleFamilyName();
 109     }
 110 
 111     public String getLocaleStyleName() {
 112         return primaryResource.getLocaleStyleName();
 113     }
 114 
 115     public String getFileName() {
 116         return primaryResource.getFileName();
 117     }
 118 
 119     public int getFeatures() {
 120         return primaryResource.getFeatures();
 121     }
 122 
 123     public Object getPeer() {
 124         return primaryResource.getPeer();
 125     }
 126 
 127     public void setPeer(Object peer) {
 128         throw new UnsupportedOperationException("Not supported");
 129     }
 130 
 131     public boolean isEmbeddedFont() {
 132         return primaryResource.isEmbeddedFont();
 133     }
 134 
 135     public boolean isBold() {
 136         return primaryResource.isBold();
 137     }
 138 
 139     public boolean isItalic() {
 140         return primaryResource.isItalic();
 141     }
 142 
 143     CompositeGlyphMapper mapper;
 144     public CharToGlyphMapper getGlyphMapper() {
 145         if (mapper == null) {
 146             mapper = new CompositeGlyphMapper(this);
 147         }
 148         return mapper;
 149     }
 150 
 151     public float[] getGlyphBoundingBox(int glyphCode,
 152                                 float size, float[] retArr) {
 153         int slot = (glyphCode >>> 24);
 154         int slotglyphCode = glyphCode & CompositeGlyphMapper.GLYPHMASK;
 155         FontResource slotResource = getSlotResource(slot);
 156         return slotResource.getGlyphBoundingBox(slotglyphCode, size, retArr);
 157     }
 158 
 159     public float getAdvance(int glyphCode, float size) {
 160         int slot = (glyphCode >>> 24);
 161         int slotglyphCode = glyphCode & CompositeGlyphMapper.GLYPHMASK;
 162         FontResource slotResource = getSlotResource(slot);
 163         return slotResource.getAdvance(slotglyphCode, size);
 164     }
 165 
 166     Map<FontStrikeDesc, WeakReference<FontStrike>> strikeMap =
 167         new ConcurrentHashMap<FontStrikeDesc, WeakReference<FontStrike>>();
 168 
 169     public Map<FontStrikeDesc, WeakReference<FontStrike>> getStrikeMap() {
 170         return strikeMap;
 171     }
 172 
 173     public int getDefaultAAMode() {
 174         return getSlotResource(0).getDefaultAAMode();
 175     }
 176 
 177     public FontStrike getStrike(float size, BaseTransform transform) {
 178         return getStrike(size, transform, getDefaultAAMode());
 179     }
 180 
 181     public FontStrike getStrike(float size, BaseTransform transform,
 182                                 int aaMode) {
 183         FontStrikeDesc desc = new FontStrikeDesc(size, transform, aaMode);
 184         WeakReference<FontStrike> ref = strikeMap.get(desc);
 185         CompositeStrike strike = null;
 186         if (ref != null) {
 187             strike = (CompositeStrike)ref.get();
 188         }
 189         if (strike == null) {
 190             strike = new CompositeStrike(this, size, transform, aaMode, desc);
 191             if (strike.disposer != null) {
 192                 ref = Disposer.addRecord(strike, strike.disposer);
 193             } else {
 194                 ref = new WeakReference<FontStrike>(strike);
 195             }
 196             strikeMap.put(desc, ref);
 197         }
 198         return strike;
 199     }
 200 
 201     @Override
 202     public boolean equals(Object obj) {
 203         if (obj == null) {
 204             return false;
 205         }
 206         if (!(obj instanceof PrismCompositeFontResource)) {
 207             return false;
 208         }
 209         final PrismCompositeFontResource other = (PrismCompositeFontResource)obj;
 210         return primaryResource.equals(other.primaryResource);
 211     }
 212 
 213     @Override
 214     public int hashCode() {
 215         return primaryResource.hashCode();
 216     }
 217 }