| 1 | /* |
|---|
| 2 | * Copyright (c) 2000, 2001 Yuki Sawada |
|---|
| 3 | * All rights reserved. |
|---|
| 4 | * |
|---|
| 5 | * Redistribution and use in source and binary forms, with or without |
|---|
| 6 | * modification, are permitted provided that the following conditions |
|---|
| 7 | * are met: |
|---|
| 8 | * 1. Redistributions of source code must retain the above copyright |
|---|
| 9 | * notice, this list of conditions and the following disclaimer. |
|---|
| 10 | * 2. Redistributions in binary form must reproduce the above copyright |
|---|
| 11 | * notice, this list of conditions and the following disclaimer in the |
|---|
| 12 | * documentation and/or other materials provided with the distribution. |
|---|
| 13 | * 3. The name of the author may not be used to endorse or promote products |
|---|
| 14 | * derived from this software without specific prior written permission. |
|---|
| 15 | * |
|---|
| 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
|---|
| 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
|---|
| 18 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
|---|
| 19 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
|---|
| 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
|---|
| 21 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
|---|
| 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
|---|
| 23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|---|
| 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
|---|
| 25 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|---|
| 26 | */ |
|---|
| 27 | |
|---|
| 28 | #include <stdlib.h> |
|---|
| 29 | #include <stdio.h> |
|---|
| 30 | #include "font.h" |
|---|
| 31 | #include "font_peer.h" |
|---|
| 32 | #include <map> |
|---|
| 33 | #include <string> |
|---|
| 34 | #include <iostream> |
|---|
| 35 | |
|---|
| 36 | namespace XKFont { |
|---|
| 37 | |
|---|
| 38 | class Cache : public std::map<unsigned int, Glyph*> { |
|---|
| 39 | public: |
|---|
| 40 | Cache() {} |
|---|
| 41 | ~Cache() { |
|---|
| 42 | iterator it; |
|---|
| 43 | for (it = begin(); it != end(); it++) |
|---|
| 44 | delete (it->second); |
|---|
| 45 | } |
|---|
| 46 | }; |
|---|
| 47 | |
|---|
| 48 | Face::Face(const char *name_orig, int index, int hsize, int vsize) |
|---|
| 49 | { |
|---|
| 50 | cache = new Cache; |
|---|
| 51 | |
|---|
| 52 | /* name: ';' åºåãã§è€æ°æå®å¯èœ */ |
|---|
| 53 | char* name = new char[strlen(name_orig)+1]; |
|---|
| 54 | while(*name_orig != 0) { |
|---|
| 55 | const char* next_name = strchr(name_orig, ';'); |
|---|
| 56 | if (next_name) { |
|---|
| 57 | strncpy(name, name_orig, next_name - name_orig); |
|---|
| 58 | name[next_name-name_orig] = 0; |
|---|
| 59 | name_orig = next_name + 1; |
|---|
| 60 | } else { |
|---|
| 61 | strcpy(name, name_orig); |
|---|
| 62 | name_orig += strlen(name_orig); |
|---|
| 63 | } |
|---|
| 64 | if (strstr(name, "fn.dat")) { |
|---|
| 65 | peer.push_back(new PeerFn(name, index, hsize, vsize)); |
|---|
| 66 | } else if (strstr(name, ".ttf") || strstr(name, ".ttc")) { |
|---|
| 67 | peer.push_back(new PeerFt2(name, index, hsize, vsize)); |
|---|
| 68 | #if USE_X11 |
|---|
| 69 | } else { |
|---|
| 70 | peer.push_back(new PeerX11(name, index, hsize, vsize)); |
|---|
| 71 | #endif |
|---|
| 72 | } |
|---|
| 73 | } |
|---|
| 74 | delete[] name; |
|---|
| 75 | return; |
|---|
| 76 | } |
|---|
| 77 | |
|---|
| 78 | Face::~Face() { |
|---|
| 79 | delete cache; |
|---|
| 80 | } |
|---|
| 81 | |
|---|
| 82 | Glyph* Face::GlyphLoad(unsigned int code) { |
|---|
| 83 | if (cache->count(code)) |
|---|
| 84 | return (*cache)[code]; |
|---|
| 85 | |
|---|
| 86 | Glyph* g = new Glyph; |
|---|
| 87 | iterator it; |
|---|
| 88 | for (it=peer.begin(); it != peer.end(); it++) { |
|---|
| 89 | if ( (*it)->GlyphCreate(code, g)) break; |
|---|
| 90 | } |
|---|
| 91 | if (it == peer.end()) { |
|---|
| 92 | fprintf(stderr,"Cannot find glyph, code %04x\n",code); |
|---|
| 93 | g->bitmap_left = 0; |
|---|
| 94 | g->bitmap_top = 0; |
|---|
| 95 | g->bitmap.width = 0; |
|---|
| 96 | g->bitmap.rows = 0; |
|---|
| 97 | g->bitmap.buffer = new unsigned char[1]; |
|---|
| 98 | g->bitmap.buffer[0] = 0; |
|---|
| 99 | g->advance.x = 0; |
|---|
| 100 | g->advance.y = 0; |
|---|
| 101 | } |
|---|
| 102 | (*cache)[code] = g; |
|---|
| 103 | return g; |
|---|
| 104 | } |
|---|
| 105 | |
|---|
| 106 | class FontImpl { |
|---|
| 107 | public: |
|---|
| 108 | std::map<int, Face*> cache; |
|---|
| 109 | std::string fontname; |
|---|
| 110 | int size; |
|---|
| 111 | ~FontImpl(); |
|---|
| 112 | }; |
|---|
| 113 | |
|---|
| 114 | FontImpl::~FontImpl() { |
|---|
| 115 | std::map<int,Face*>::iterator it; |
|---|
| 116 | for (it=cache.begin(); it!=cache.end(); it++) delete it->second; |
|---|
| 117 | } |
|---|
| 118 | |
|---|
| 119 | Font::Font(const char* name, int size) { |
|---|
| 120 | pimpl = new FontImpl; |
|---|
| 121 | pimpl->fontname = name; |
|---|
| 122 | pimpl->size = size; |
|---|
| 123 | vsize = size; |
|---|
| 124 | }; |
|---|
| 125 | |
|---|
| 126 | Font::~Font() { |
|---|
| 127 | delete pimpl; |
|---|
| 128 | } |
|---|
| 129 | |
|---|
| 130 | Face* Font::FaceLoad(double scale) { |
|---|
| 131 | std::map<int, Face*>& cache = pimpl->cache; |
|---|
| 132 | int size = int(scale * pimpl->size); |
|---|
| 133 | if (cache.find(size) != cache.end()) return cache[size]; |
|---|
| 134 | try { |
|---|
| 135 | Face* face = new Face(pimpl->fontname.c_str(), 0, size, size); |
|---|
| 136 | cache[size] = face; |
|---|
| 137 | return face; |
|---|
| 138 | } catch(...) { |
|---|
| 139 | std::cerr << "Cannot create font face; font "<<pimpl->fontname<<", size "<<size<<std::endl; |
|---|
| 140 | /* å¥ã®å€§ãããæ¢ã */ |
|---|
| 141 | int i; |
|---|
| 142 | for (i=0; i<size; i++) { |
|---|
| 143 | if (cache.find(size-i) != cache.end()) return cache[size-i]; |
|---|
| 144 | if (cache.find(size+i) != cache.end()) return cache[size+i]; |
|---|
| 145 | try { |
|---|
| 146 | Face* face = new Face(pimpl->fontname.c_str(), 0, size-i, size-i); |
|---|
| 147 | cache[size-i] = face; |
|---|
| 148 | return face; |
|---|
| 149 | } catch(...) {}; |
|---|
| 150 | try { |
|---|
| 151 | Face* face = new Face(pimpl->fontname.c_str(), 0, size+i, size+i); |
|---|
| 152 | cache[size+i] = face; |
|---|
| 153 | return face; |
|---|
| 154 | } catch(...) {}; |
|---|
| 155 | } |
|---|
| 156 | /* èŠã€ãããªã */ |
|---|
| 157 | throw; |
|---|
| 158 | } |
|---|
| 159 | } |
|---|
| 160 | |
|---|
| 161 | } /* namespace XKFont */ |
|---|