blob: c242e3dbe0a48346ebb0ef6123af7fc9d75eb485 [file]
/* Copyright 2010-2026 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. */
#include <stddef.h>
#include <string.h>
#include <stdio.h>
/* Avoid namespace conflicts. */
#define context perl_context
#define PERL_NO_GET_CONTEXT
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
/* ppport.h suggests to remove its include, but we need it to
replace G_LIST by G_ARRAY if G_LIST is not defined */
#include "ppport.h"
#undef context
#include "command_ids.h"
#include "tree_types.h"
#include "document_types.h"
#include "converter_types.h"
#include "plaintext_converter_state.h"
/* non_perl_* */
#include "xs_utils.h"
#include "base_utils.h"
#include "tree.h"
/* for collect_commands_list_in_tree xasprintf
*/
#include "utils.h"
/* for newSVpv_utf8 */
#include "build_perl_info.h"
#include "list_macros.h"
/* debugging
#include "debug.h"
#include "api_to_perl.h"
*/
/* for decl_list_fns(... math_element_image...) */
#include "convert_to_plaintext.h"
#include "call_plaintext_perl_function.h"
/* See the NOTE in build_perl_info.c on use of functions related to
memory allocation */
MATH_ELEMENTS_IMAGES *
call_latex_convert_math_to_images (CONVERTER *self, DOCUMENT *document,
const char *prefix,
const char *destination_directory)
{
int count;
SV *document_sv = 0;
SV *result_sv;
SV *collected_commands_sv;
MATH_ELEMENTS_IMAGES *result = 0;
dTHX;
dSP;
/* get the document and increase refcount */
if (document->hv)
{
/* reuse if the document hv already exists */
document_sv = newRV_inc ((SV *) document->hv);
}
else
{
document_sv = build_minimal_document (document);
SvREFCNT_inc (document_sv);
}
ENTER;
SAVETMPS;
PUSHMARK(SP);
EXTEND(SP, 4);
PUSHs(sv_2mortal (SvREFCNT_inc ((SV *) self->sv)));
PUSHs(sv_2mortal (document_sv));
PUSHs(sv_2mortal (newSVpv_utf8 (prefix, 0)));
PUSHs(sv_2mortal (newSVpv_utf8 (destination_directory, 0)));
PUTBACK;
count = call_pv (
"Texinfo::Convert::LaTeX::convert_math_to_images",
G_LIST);
SPAGAIN;
if (count != 2)
croak ("convert_math_to_images should return 2 items\n");
collected_commands_sv = POPs;
result_sv = POPs;
if (SvOK (result_sv))
{
SSize_t i;
AV *collected_commands_av = (AV *)SvRV (collected_commands_sv);
HV *result_hv = (HV *)SvRV (result_sv);
SSize_t collected_elements_nr = AvFILL (collected_commands_av) +1;
/* we collect math commands to be able to check that the Perl
element HV from the collected math elements is the same as
the one collected in Perl and returned by Perl.
It also allows to set the element in the MATH_ELEMENT_IMAGE.
*/
static const enum command_id math_commands_list[] = {
CM_math, CM_displaymath, 0
};
CONST_ELEMENT_LIST *math_elements_list
= collect_commands_list_in_tree (document->tree, math_commands_list);
if (math_elements_list->number != (size_t)collected_elements_nr)
{
fprintf (stderr, "BUG: math elements collected. C: %zu, Perl: %zd\n",
math_elements_list->number, collected_elements_nr);
}
result = (MATH_ELEMENTS_IMAGES *)
non_perl_malloc (sizeof (MATH_ELEMENTS_IMAGES));
memset (result, 0, sizeof (MATH_ELEMENTS_IMAGES));
for (i = 0; i < collected_elements_nr; i++)
{
SV **command_sv = av_fetch (collected_commands_av, i, 0);
const ELEMENT *element = math_elements_list->list[i];
if (command_sv)
{
MATH_ELEMENT_IMAGE_LIST *images_elements_list;
MATH_ELEMENT_IMAGE *element_image;
HE *result_element_image_he = hv_fetch_ent (result_hv,
*command_sv, 0, 0);
HV *command_hv = (HV *)SvRV (*command_sv);
HV *element_hv = (HV *)SvRV ((SV *) element->sv);
if (command_hv != element_hv)
{
char *msg;
xasprintf (&msg, "BUG: %zd: out of sync collected C and Perl"
" elements\n", i);
bug (msg);
non_perl_free (msg);
}
if (element->e.c->cmd == CM_math)
images_elements_list = &result->math_images;
else
images_elements_list = &result->displaymath_images;
reallocate_(math_element_image) (images_elements_list);
element_image
= &images_elements_list->list[images_elements_list->number];
images_elements_list->number++;
memset (element_image, 0, sizeof (MATH_ELEMENT_IMAGE));
element_image->element = element;
if (result_element_image_he)
{
SV *result_element_image_sv = HeVAL (result_element_image_he);
HV *result_element_image_hv
= (HV *)SvRV (result_element_image_sv);
SV **filename_sv;
SV **dpi_sv;
SV **depth_sv;
#define FETCH(key) key##_sv = hv_fetch (result_element_image_hv, #key, strlen (#key), 0);
FETCH (filename);
if (filename_sv)
{
STRLEN len;
char *filename_ret = SvPVutf8 (*filename_sv, len);
element_image->filename = non_perl_strndup (filename_ret,
len);
}
FETCH (dpi);
if (dpi_sv)
element_image->dpi = SvIV (*dpi_sv);
FETCH (depth);
if (depth_sv)
element_image->depth = SvIV (*depth_sv);
#undef FETCH
}
}
}
destroy_const_element_list (math_elements_list);
}
PUTBACK;
FREETMPS;
LEAVE;
return result;
}