1
zero-epwing-go/font.c

540 lines
13 KiB
C
Raw Normal View History

2021-01-09 22:39:52 +00:00
/*
* Copyright (c) 1997-2006 Motoyuki Kasahara
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the project nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "build-pre.h"
#include "eb.h"
#include "error.h"
#include "font.h"
#include "build-post.h"
/*
* Initialize all fonts in the current subbook.
*/
void
eb_initialize_fonts(EB_Book *book)
{
EB_Subbook *subbook;
EB_Font *font;
int i;
LOG(("in: eb_initialize_fonts(book=%d)", (int)book->code));
subbook = book->subbook_current;
for (i = 0, font = subbook->narrow_fonts; i < EB_MAX_FONTS; i++, font++) {
font->font_code = EB_FONT_INVALID;
font->initialized = 0;
font->start = -1;
font->end = -1;
font->page = 0;
font->glyphs = NULL;
zio_initialize(&font->zio);
}
for (i = 0, font = subbook->wide_fonts; i < EB_MAX_FONTS; i++, font++) {
font->font_code = EB_FONT_INVALID;
font->initialized = 0;
font->start = -1;
font->end = -1;
font->page = 0;
font->glyphs = NULL;
zio_initialize(&font->zio);
}
LOG(("out: eb_initialize_fonts()"));
}
/*
* Load font files.
*/
void
eb_load_font_headers(EB_Book *book)
{
EB_Error_Code error_code;
EB_Subbook *subbook;
EB_Font_Code i;
LOG(("in: eb_load_fonts(book=%d)", (int)book->code));
subbook = book->subbook_current;
/*
* Load narrow font headers.
*/
for (i = 0; i < EB_MAX_FONTS; i++) {
if (subbook->narrow_fonts[i].font_code == EB_FONT_INVALID
|| subbook->narrow_fonts[i].initialized)
continue;
error_code = eb_open_narrow_font_file(book, i);
if (error_code == EB_SUCCESS)
error_code = eb_load_narrow_font_header(book, i);
if (error_code != EB_SUCCESS)
subbook->narrow_fonts[i].font_code = EB_FONT_INVALID;
subbook->narrow_fonts[i].initialized = 1;
zio_close(&subbook->narrow_fonts[i].zio);
}
/*
* Load wide font header.
*/
for (i = 0; i < EB_MAX_FONTS; i++) {
if (subbook->wide_fonts[i].font_code == EB_FONT_INVALID
|| subbook->wide_fonts[i].initialized)
continue;
error_code = eb_open_wide_font_file(book, i);
if (error_code == EB_SUCCESS)
error_code = eb_load_wide_font_header(book, i);
if (error_code != EB_SUCCESS)
subbook->wide_fonts[i].font_code = EB_FONT_INVALID;
subbook->wide_fonts[i].initialized = 1;
zio_close(&subbook->wide_fonts[i].zio);
}
LOG(("out: eb_load_font_headers()"));
}
/*
* Finalize all fonts in the current subbook.
*/
void
eb_finalize_fonts(EB_Book *book)
{
EB_Subbook *subbook;
EB_Font *font;
int i;
LOG(("in: eb_finalize_fonts(book=%d)", (int)book->code));
subbook = book->subbook_current;
for (i = 0, font = subbook->narrow_fonts; i < EB_MAX_FONTS; i++, font++) {
zio_finalize(&font->zio);
if (font->glyphs != NULL) {
free(font->glyphs);
font->glyphs = NULL;
}
}
for (i = 0, font = subbook->wide_fonts; i < EB_MAX_FONTS; i++, font++) {
zio_finalize(&font->zio);
if (font->glyphs != NULL) {
free(font->glyphs);
font->glyphs = NULL;
}
}
LOG(("out: eb_finalize_fonts()"));
}
/*
* Look up the height of the current font of the current subbook in
* `book'.
*/
EB_Error_Code
eb_font(EB_Book *book, EB_Font_Code *font_code)
{
EB_Error_Code error_code;
eb_lock(&book->lock);
LOG(("in: eb_font(book=%d)", (int)book->code));
/*
* Current subbook must have been set.
*/
if (book->subbook_current == NULL) {
error_code = EB_ERR_NO_CUR_SUB;
goto failed;
}
/*
* Look up the height of the current font.
*/
if (book->subbook_current->narrow_current != NULL)
*font_code = book->subbook_current->narrow_current->font_code;
else if (book->subbook_current->wide_current != NULL)
*font_code = book->subbook_current->wide_current->font_code;
else {
error_code = EB_ERR_NO_CUR_FONT;
goto failed;
}
LOG(("out: eb_font(font_code=%d) = %s", (int)*font_code,
eb_error_string(EB_SUCCESS)));
eb_unlock(&book->lock);
return EB_SUCCESS;
/*
* An error occurs...
*/
failed:
*font_code = EB_FONT_INVALID;
LOG(("out: eb_font() = %s", eb_error_string(error_code)));
eb_unlock(&book->lock);
return error_code;
}
/*
* Set the font with `font_code' as the current font of the current
* subbook in `book'.
*/
EB_Error_Code
eb_set_font(EB_Book *book, EB_Font_Code font_code)
{
EB_Error_Code error_code;
EB_Subbook *subbook;
eb_lock(&book->lock);
LOG(("in: eb_set_font(book=%d, font_code=%d)", (int)book->code,
(int)font_code));
/*
* Check `font_code'.
*/
if (font_code < 0 || EB_MAX_FONTS <= font_code) {
error_code = EB_ERR_NO_SUCH_FONT;
goto failed;
}
/*
* Current subbook must have been set.
*/
subbook = book->subbook_current;
if (subbook == NULL) {
error_code = EB_ERR_NO_CUR_SUB;
goto failed;
}
/*
* If the current font is the font with `font_code', return immediately.
* Otherwise close the current font and continue.
*/
if (subbook->narrow_current != NULL) {
if (subbook->narrow_current->font_code == font_code)
goto succeeded;
if (book->disc_code == EB_DISC_EPWING)
zio_close(&subbook->narrow_current->zio);
subbook->narrow_current = NULL;
}
if (subbook->wide_current != NULL) {
if (subbook->wide_current->font_code == font_code)
goto succeeded;
if (book->disc_code == EB_DISC_EPWING)
zio_close(&subbook->wide_current->zio);
subbook->wide_current = NULL;
}
/*
* Set the current font.
*/
if (subbook->narrow_fonts[font_code].font_code != EB_FONT_INVALID)
subbook->narrow_current = subbook->narrow_fonts + font_code;
if (subbook->wide_fonts[font_code].font_code != EB_FONT_INVALID)
subbook->wide_current = subbook->wide_fonts + font_code;
if (subbook->narrow_current == NULL && subbook->wide_current == NULL) {
error_code = EB_ERR_NO_SUCH_FONT;
goto failed;
}
/*
* Initialize current font informtaion.
*/
if (subbook->narrow_current != NULL) {
error_code = eb_open_narrow_font_file(book, font_code);
if (error_code != EB_SUCCESS)
goto failed;
}
if (subbook->wide_current != NULL) {
error_code = eb_open_wide_font_file(book, font_code);
if (error_code != EB_SUCCESS)
goto failed;
}
succeeded:
LOG(("out: eb_set_font() = %s", eb_error_string(EB_SUCCESS)));
eb_unlock(&book->lock);
return EB_SUCCESS;
/*
* An error occurs...
*/
failed:
eb_unset_font(book);
LOG(("out: eb_set_font() = %s", eb_error_string(error_code)));
return error_code;
}
/*
* Unset the font in the current subbook in `book'.
*/
void
eb_unset_font(EB_Book *book)
{
EB_Subbook *subbook;
eb_lock(&book->lock);
LOG(("in: eb_unset_font(book=%d)", (int)book->code));
subbook = book->subbook_current;
if (subbook == NULL)
goto succeeded;
/*
* Close font files.
*/
if (subbook->narrow_current != NULL) {
zio_close(&subbook->narrow_current->zio);
if (subbook->narrow_current->glyphs != NULL) {
free(subbook->narrow_current->glyphs);
subbook->narrow_current->glyphs = NULL;
}
}
if (subbook->wide_current != NULL) {
zio_close(&subbook->wide_current->zio);
if (subbook->wide_current->glyphs != NULL) {
free(subbook->wide_current->glyphs);
subbook->wide_current->glyphs = NULL;
}
}
book->subbook_current->narrow_current = NULL;
book->subbook_current->wide_current = NULL;
succeeded:
LOG(("out: eb_unset_font()"));
eb_unlock(&book->lock);
}
/*
* Make a list of fonts in the current subbook in `book'.
*/
EB_Error_Code
eb_font_list(EB_Book *book, EB_Font_Code *font_list, int *font_count)
{
EB_Error_Code error_code;
EB_Subbook *subbook;
EB_Font_Code *list_p;
int i;
eb_lock(&book->lock);
LOG(("in: eb_font_list(book=%d)", (int)book->code));
/*
* Current subbook must have been set.
*/
subbook = book->subbook_current;
if (subbook == NULL) {
error_code = EB_ERR_NO_CUR_SUB;
goto failed;
}
/*
* Scan the font table in the book.
*/
subbook = book->subbook_current;
list_p = font_list;
*font_count = 0;
for (i = 0; i < EB_MAX_FONTS; i++) {
if (subbook->narrow_fonts[i].font_code != EB_FONT_INVALID
|| subbook->wide_fonts[i].font_code != EB_FONT_INVALID) {
*list_p++ = i;
*font_count += 1;
}
}
LOG(("out: eb_font(font_count=%d) = %s", *font_count,
eb_error_string(EB_SUCCESS)));
eb_unlock(&book->lock);
return EB_SUCCESS;
/*
* An error occurs...
*/
failed:
LOG(("out: eb_font_list() = %s", eb_error_string(error_code)));
eb_unlock(&book->lock);
return error_code;
}
/*
* Test whether the current subbook in `book' has a font with
* `font_code' or not.
*/
int
eb_have_font(EB_Book *book, EB_Font_Code font_code)
{
EB_Subbook *subbook;
eb_lock(&book->lock);
LOG(("in: eb_have_font(book=%d, font_code=%d)", (int)book->code,
(int)font_code));
/*
* Check `font_code'.
*/
if (font_code < 0 || EB_MAX_FONTS <= font_code)
goto failed;
/*
* Current subbook must have been set.
*/
subbook = book->subbook_current;
if (subbook == NULL)
goto failed;
if (subbook->narrow_fonts[font_code].font_code == EB_FONT_INVALID
&& subbook->wide_fonts[font_code].font_code == EB_FONT_INVALID)
goto failed;
LOG(("out: eb_have_font() = %d", 1));
eb_unlock(&book->lock);
return 1;
/*
* An error occurs...
*/
failed:
LOG(("out: eb_have_font() = %d", 0));
eb_unlock(&book->lock);
return 0;
}
/*
* Get height of the font `font_code' in the current subbook of `book'.
*/
EB_Error_Code
eb_font_height(EB_Book *book, int *height)
{
EB_Error_Code error_code;
EB_Font_Code font_code;
eb_lock(&book->lock);
LOG(("in: eb_font_height(book=%d)", (int)book->code));
/*
* Current subbook must have been set.
*/
if (book->subbook_current == NULL) {
error_code = EB_ERR_NO_CUR_SUB;
goto failed;
}
/*
* The narrow font must exist in the current subbook.
*/
if (book->subbook_current->narrow_current != NULL)
font_code = book->subbook_current->narrow_current->font_code;
else if (book->subbook_current->wide_current != NULL)
font_code = book->subbook_current->wide_current->font_code;
else {
error_code = EB_ERR_NO_CUR_FONT;
goto failed;
}
/*
* Calculate height.
*/
error_code = eb_font_height2(font_code, height);
if (error_code != EB_SUCCESS)
goto failed;
LOG(("out: eb_font_heigt(height=%d) = %s", *height,
eb_error_string(EB_SUCCESS)));
eb_unlock(&book->lock);
return EB_SUCCESS;
/*
* An error occurs...
*/
failed:
*height = 0;
LOG(("out: eb_font_height() = %s", eb_error_string(error_code)));
eb_unlock(&book->lock);
return error_code;
}
/*
* Get height of the font `font_code'.
*/
EB_Error_Code
eb_font_height2(EB_Font_Code font_code, int *height)
{
EB_Error_Code error_code;
LOG(("in: eb_font_height2(font_code=%d)", (int)font_code));
switch (font_code) {
case EB_FONT_16:
*height = EB_HEIGHT_FONT_16;
break;
case EB_FONT_24:
*height = EB_HEIGHT_FONT_24;
break;
case EB_FONT_30:
*height = EB_HEIGHT_FONT_30;
break;
case EB_FONT_48:
*height = EB_HEIGHT_FONT_48;
break;
default:
error_code = EB_ERR_NO_SUCH_FONT;
goto failed;
}
LOG(("out: eb_font_heigt2(height=%d) = %s", *height,
eb_error_string(EB_SUCCESS)));
return EB_SUCCESS;
/*
* An error occurs...
*/
failed:
*height = 0;
LOG(("out: eb_font_height2() = %s", eb_error_string(error_code)));
return error_code;
}