From d3c6bf3c6ec490599860290fe51669fc2e8acaf9 Mon Sep 17 00:00:00 2001 From: stefan schippers Date: Sat, 21 Jan 2023 23:47:43 +0100 Subject: [PATCH 1/2] add postscript quality attrs to some example schematics --- XSchemWin/XSchemWin_cairo.vcxproj | 2 + src/cairo_jpg.c | 1266 ++++++++++--------- xschem_library/examples/mos_power_ampli.sch | 18 +- xschem_library/rom8k/rom2_ctrl.sch | 12 +- xschem_library/rom8k/rom2_sa.sch | 9 +- 5 files changed, 656 insertions(+), 651 deletions(-) diff --git a/XSchemWin/XSchemWin_cairo.vcxproj b/XSchemWin/XSchemWin_cairo.vcxproj index f5563fad..9320989d 100644 --- a/XSchemWin/XSchemWin_cairo.vcxproj +++ b/XSchemWin/XSchemWin_cairo.vcxproj @@ -223,6 +223,7 @@ + @@ -257,6 +258,7 @@ + diff --git a/src/cairo_jpg.c b/src/cairo_jpg.c index 5b4090b4..485a122a 100644 --- a/src/cairo_jpg.c +++ b/src/cairo_jpg.c @@ -1,631 +1,635 @@ -/* Copyright 2018 Bernhard R. Fischer, 4096R/8E24F29D - * - * This file is part of Cairo_JPG. - * - * Cairo_JPG is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Cairo_JPG 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 Lesser General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Cairo_JPG. If not, see . - */ - -/*! \file cairo_jpg.c - * This file contains two functions for reading and writing JPEG files from - * and to Cairo image surfaces. It uses the functions from the libjpeg. - * Most of the code is directly derived from the online example at - * http://libjpeg-turbo.virtualgl.org/Documentation/Documentation - * - * All prototypes are defined in cairo_jpg.h All functions and their parameters - * and return values are described below directly at the functions. You may - * also have a look at the preprocessor macros defined below. - * - * To compile this code you need to have installed the packages libcairo2-dev - * and libjpeg-dev. Compile with the following to create an object file to link - * with your code: - * gcc -std=c99 -Wall -c `pkg-config cairo libjpeg --cflags --libs` cairo_jpg.c - * Use the following command to include the main() function and create an - * executable for testing of this code: - * gcc -std=c99 -Wall -o cairo_jpg -DCAIRO_JPEG_MAIN `pkg-config cairo libjpeg --cflags --libs` cairo_jpg.c - * - * @author Bernhard R. Fischer, 4096R/8E24F29D bf@abenteuerland.at - * @version 2020/01/18 - * @license LGPL3. - */ - -#include "../config.h" -#if defined(HAS_LIBJPEG) && defined(HAS_CAIRO) -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -#include -#include -#include -#include -#include -#include -#include "unistd.h" -#include -#include - -#include "cairo_jpg.h" - -/*! Macro to activate main() function. This is only used for testing. Comment - * it out (#undef) if you link this file to your own program. - */ - -/* #define CAIRO_JPEG_MAIN */ - -/*! Define this to use an alternate implementation of - * cairo_image_surface_create_from_jpeg() which fstat(3)s the file before - * reading (see below). For huge files this /may/ be slightly faster. - */ -#undef CAIRO_JPEG_USE_FSTAT - -/*! This is the read block size for the stream reader - * cairo_image_surface_create_from_jpeg_stream(). - */ -#ifdef USE_CAIRO_READ_FUNC_LEN_T -#define CAIRO_JPEG_IO_BLOCK_SIZE 4096 -#else -/*! Block size has to be one if cairo_read_func_t is in use because of the lack - * to detect EOF (truncated reads). - */ -#define CAIRO_JPEG_IO_BLOCK_SIZE 1 -/*! In case of original cairo_read_func_t is used fstat() should be used for - * performance reasons (see CAIRO_JPEG_USE_FSTAT above). - */ -#define CAIRO_JPEG_USE_FSTAT -#endif - -/*! Define this to test jpeg creation with non-image surfaces. This is only for - * testing and is to be used together with CAIRO_JPEG_MAIN. - */ -#undef CAIRO_JPEG_TEST_SIMILAR -#if defined(CAIRO_JPEG_TEST_SIMILAR) && defined(CAIRO_JPEG_MAIN) -#include -#endif - - -#ifndef LIBJPEG_TURBO_VERSION -/*! This function makes a covnersion for "odd" pixel sizes which typically is a - * conversion from a 3-byte to a 4-byte (or more) pixel size or vice versa. - * The conversion is done from the source buffer src to the destination buffer - * dst. The caller MUST ensure that src and dst have the correct memory size. - * This is dw * num for dst and sw * num for src. src and dst may point to the - * same memory address. - * @param dst Pointer to destination buffer. - * @param dw Pixel width (in bytes) of pixels in destination buffer, dw >= 3. - * @param src Pointer to source buffer. - * @param sw Pixel width (in bytes) of pixels in source buffer, sw >= 3. - * @param num Number of pixels to convert, num >= 1; - */ -static void pix_conv(unsigned char *dst, int dw, const unsigned char *src, int sw, int num) -{ - int si, di; - - /* safety check */ - if (dw < 3 || sw < 3 || dst == NULL || src == NULL) - return; - - num--; - for (si = num * sw, di = num * dw; si >= 0; si -= sw, di -= dw) - { -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - dst[di + 2] = src[si ]; - dst[di + 1] = src[si + 1]; - dst[di + 0] = src[si + 2]; -#else - /* FIXME: This is untested, it may be wrong. */ - dst[di - 3] = src[si - 3]; - dst[di - 2] = src[si - 2]; - dst[di - 1] = src[si - 1]; -#endif - } -} -#endif - - -/*! This function creates a JPEG file in memory from a Cairo image surface. - * @param sfc Pointer to a Cairo surface. It should be an image surface of - * either CAIRO_FORMAT_ARGB32 or CAIRO_FORMAT_RGB24. Other formats are - * converted to CAIRO_FORMAT_RGB24 before compression. - * Please note that this may give unexpected results because JPEG does not - * support transparency. Thus, default background color is used to replace - * transparent regions. The default background color is black if not specified - * explicitly. Thus converting e.g. PDF surfaces without having any specific - * background color set will apear with black background and not white as you - * might expect. In such cases it is suggested to manually convert the surface - * to RGB24 before calling this function. - * @param data Pointer to a memory pointer. This parameter receives a pointer - * to the memory area where the final JPEG data is found in memory. This - * function reserves the memory properly and it has to be freed by the caller - * with free(3). - * @param len Pointer to a variable of type size_t which will receive the final - * lenght of the memory buffer. - * @param quality Compression quality, 0-100. - * @return On success the function returns CAIRO_STATUS_SUCCESS. In case of - * error CAIRO_STATUS_INVALID_FORMAT is returned. - */ -cairo_status_t cairo_image_surface_write_to_jpeg_mem(cairo_surface_t *sfc, unsigned char **data, size_t *len, int quality) -{ - struct jpeg_compress_struct cinfo; - struct jpeg_error_mgr jerr; - JSAMPROW row_pointer[1]; - cairo_surface_t *other = NULL; - cairo_t *ctx; - - /* check valid input format (must be IMAGE_SURFACE && (ARGB32 || RGB24)) */ - if (cairo_surface_get_type(sfc) != CAIRO_SURFACE_TYPE_IMAGE || - (cairo_image_surface_get_format(sfc) != CAIRO_FORMAT_ARGB32 && - cairo_image_surface_get_format(sfc) != CAIRO_FORMAT_RGB24)) - { - /* create a similar surface with a proper format if supplied input format */ - /* does not fulfill the requirements */ - double x1, y1, x2, y2; - other = sfc; - ctx = cairo_create(other); - /* get extents of original surface */ - cairo_clip_extents(ctx, &x1, &y1, &x2, &y2); - cairo_destroy(ctx); - - /* create new image surface */ - sfc = cairo_surface_create_similar_image(other, CAIRO_FORMAT_RGB24, (int)(x2 - x1), (int)(y2 - y1)); - if (cairo_surface_status(sfc) != CAIRO_STATUS_SUCCESS) - return CAIRO_STATUS_INVALID_FORMAT; - - /* paint original surface to new surface */ - ctx = cairo_create(sfc); - cairo_set_source_surface(ctx, other, 0, 0); - cairo_paint(ctx); - cairo_destroy(ctx); - } - - /* finish queued drawing operations */ - cairo_surface_flush(sfc); - - /* init jpeg compression structures */ - cinfo.err = jpeg_std_error(&jerr); - jpeg_create_compress(&cinfo); - - /* set compression parameters */ - jpeg_mem_dest(&cinfo, data, len); - cinfo.image_width = cairo_image_surface_get_width(sfc); - cinfo.image_height = cairo_image_surface_get_height(sfc); -#ifdef LIBJPEG_TURBO_VERSION -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - /* cinfo.in_color_space = JCS_EXT_BGRX; */ - cinfo.in_color_space = cairo_image_surface_get_format(sfc) == CAIRO_FORMAT_ARGB32 ? JCS_EXT_BGRA : JCS_EXT_BGRX; -#else - /* cinfo.in_color_space = JCS_EXT_XRGB; */ - cinfo.in_color_space = cairo_image_surface_get_format(sfc) == CAIRO_FORMAT_ARGB32 ? JCS_EXT_ARGB : JCS_EXT_XRGB; -#endif - cinfo.input_components = 4; -#else - cinfo.in_color_space = JCS_RGB; - cinfo.input_components = 3; -#endif - jpeg_set_defaults(&cinfo); - jpeg_set_quality(&cinfo, quality, TRUE); - - /* start compressor */ - jpeg_start_compress(&cinfo, TRUE); - - /* loop over all lines and compress */ - while (cinfo.next_scanline < cinfo.image_height) - { -#ifdef LIBJPEG_TURBO_VERSION - row_pointer[0] = cairo_image_surface_get_data(sfc) + (cinfo.next_scanline - * cairo_image_surface_get_stride(sfc)); -#else - unsigned char* row_buf = malloc(3 * cinfo.image_width); - /* unsigned char row_buf[3 * cinfo.image_width]; */ - pix_conv(row_buf, 3, cairo_image_surface_get_data(sfc) + - (cinfo.next_scanline * cairo_image_surface_get_stride(sfc)), 4, cinfo.image_width); - row_pointer[0] = row_buf; -#endif - (void) jpeg_write_scanlines(&cinfo, row_pointer, 1); - } - - /* finalize and close everything */ - jpeg_finish_compress(&cinfo); - jpeg_destroy_compress(&cinfo); - - /* destroy temporary image surface (if available) */ - if (other != NULL) - cairo_surface_destroy(sfc); - - return CAIRO_STATUS_SUCCESS; -} - - -/*! This is the internal write function which is called by - * cairo_image_surface_write_to_jpeg(). It is not exported. - */ -static cairo_status_t cj_write(void *closure, const unsigned char *data, unsigned int length) -{ - return write((int)(intptr_t) closure, data, length) < length ? - CAIRO_STATUS_WRITE_ERROR : CAIRO_STATUS_SUCCESS; -} - - -/*! This function writes JPEG file data from a Cairo image surface by using the - * user-supplied stream writer function write_func(). - * @param sfc Pointer to a Cairo *image* surface. Its format must either be - * CAIRO_FORMAT_ARGB32 or CAIRO_FORMAT_RGB24. Other formats are not supported - * by this function, yet. - * @param write_func Function pointer to a function which is actually writing - * the data. - * @param closure Pointer to user-supplied variable which is directly passed to - * write_func(). - * @param quality Compression quality, 0-100. - * @return This function calles cairo_image_surface_write_to_jpeg_mem() and - * returns its return value. - */ -cairo_status_t cairo_image_surface_write_to_jpeg_stream(cairo_surface_t *sfc, cairo_write_func_t write_func, void *closure, int quality) -{ - cairo_status_t e; - unsigned char *data = NULL; - size_t len = 0; - - /* create JPEG data in memory from surface */ - if ((e = cairo_image_surface_write_to_jpeg_mem(sfc, &data, &len, quality)) != CAIRO_STATUS_SUCCESS) - return e; - - /* write whole memory block with stream function */ - e = write_func(closure, data, (unsigned int)len); - - /* free JPEG memory again and return the return value */ - free(data); - return e; - -} - - -/*! This function creates a JPEG file from a Cairo image surface. - * @param sfc Pointer to a Cairo *image* surface. Its format must either be - * CAIRO_FORMAT_ARGB32 or CAIRO_FORMAT_RGB24. Other formats are not supported - * by this function, yet. - * @param filename Pointer to the filename. - * @param quality Compression quality, 0-100. - * @return In case of success CAIRO_STATUS_SUCCESS is returned. If an error - * occured while opening/creating the file CAIRO_STATUS_DEVICE_ERROR is - * returned. The error can be tracked down by inspecting errno(3). The function - * internally calles cairo_image_surface_write_to_jpeg_stream() and returnes - * its return value respectively (see there). - */ -cairo_status_t cairo_image_surface_write_to_jpeg(cairo_surface_t *sfc, const char *filename, int quality) -{ - cairo_status_t e; - int outfile; - - /* Open/create new file */ - if ((outfile = open(filename, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) == -1) - return CAIRO_STATUS_DEVICE_ERROR; - - /* write surface to file */ - e = cairo_image_surface_write_to_jpeg_stream(sfc, cj_write, (void*)(intptr_t) outfile, quality); - - /* close file again and return */ - close(outfile); - return e; -} - - - -/*! This function decompresses a JPEG image from a memory buffer and creates a - * Cairo image surface. - * @param data Pointer to JPEG data (i.e. the full contents of a JPEG file read - * into this buffer). - * @param len Length of buffer in bytes. - * @return Returns a pointer to a cairo_surface_t structure. It should be - * checked with cairo_surface_status() for errors. - */ -cairo_surface_t *cairo_image_surface_create_from_jpeg_mem(void *data, size_t len) -{ - struct jpeg_decompress_struct cinfo; - struct jpeg_error_mgr jerr; - JSAMPROW row_pointer[1]; - cairo_surface_t *sfc; - - /* initialize jpeg decompression structures */ - cinfo.err = jpeg_std_error(&jerr); - jpeg_create_decompress(&cinfo); - jpeg_mem_src(&cinfo, data, len); - (void) jpeg_read_header(&cinfo, TRUE); - -#ifdef LIBJPEG_TURBO_VERSION -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - cinfo.out_color_space = JCS_EXT_BGRA; -#else - cinfo.out_color_space = JCS_EXT_ARGB; -#endif -#else - cinfo.out_color_space = JCS_RGB; -#endif - - /* start decompressor */ - (void) jpeg_start_decompress(&cinfo); - - /* create Cairo image surface */ - sfc = cairo_image_surface_create(CAIRO_FORMAT_RGB24, cinfo.output_width, cinfo.output_height); - if (cairo_surface_status(sfc) != CAIRO_STATUS_SUCCESS) - { - jpeg_destroy_decompress(&cinfo); - return sfc; - } - - /* loop over all scanlines and fill Cairo image surface */ - while (cinfo.output_scanline < cinfo.output_height) - { - unsigned char *row_address = cairo_image_surface_get_data(sfc) + - (cinfo.output_scanline * cairo_image_surface_get_stride(sfc)); - row_pointer[0] = row_address; - (void) jpeg_read_scanlines(&cinfo, row_pointer, 1); -#ifndef LIBJPEG_TURBO_VERSION - pix_conv(row_address, 4, row_address, 3, cinfo.output_width); -#endif - } - - /* finish and close everything */ - cairo_surface_mark_dirty(sfc); - (void) jpeg_finish_decompress(&cinfo); - jpeg_destroy_decompress(&cinfo); - - /* set jpeg mime data */ - cairo_surface_set_mime_data(sfc, CAIRO_MIME_TYPE_JPEG, data, len, free, data); - - return sfc; -} - - -/*! This function reads a JPEG image from a stream and creates a Cairo image - * surface. - * @param read_func Pointer to function which reads data. - * @param closure Pointer which is passed to read_func(). - * @return Returns a pointer to a cairo_surface_t structure. It should be - * checked with cairo_surface_status() for errors. - * @note If the surface returned is invalid you can use errno(3) to determine - * further reasons. Errno is set according to realloc(3). If you - * intend to check errno you shall set it to 0 before calling this function - * because it modifies errno only in case of an error. - */ -#ifdef USE_CAIRO_READ_FUNC_LEN_T -cairo_surface_t *cairo_image_surface_create_from_jpeg_stream(cairo_read_func_len_t read_func, void *closure) -#else -cairo_surface_t *cairo_image_surface_create_from_jpeg_stream(cairo_read_func_t read_func, void *closure) -#endif -{ - cairo_surface_t *sfc; - unsigned char *data, *tmp; - ssize_t len, rlen; - int eof = 0; - - /* read all data into memory buffer in blocks of CAIRO_JPEG_IO_BLOCK_SIZE */ - for (len = 0, data = NULL; !eof; len += rlen) - { - /* grow memory buffer and check for error */ - if ((tmp = realloc(data, len + CAIRO_JPEG_IO_BLOCK_SIZE)) == NULL) - break; - data = tmp; - - /* read bytes into buffer and check for error */ - rlen = read_func(closure, data + len, CAIRO_JPEG_IO_BLOCK_SIZE); -#ifdef USE_CAIRO_READ_FUNC_LEN_T - /* check for error */ - if (rlen == -1) - break; - - /* check if EOF occured */ - if (rlen < CAIRO_JPEG_IO_BLOCK_SIZE) - eof++; -#else - /* check for error */ - if (rlen == CAIRO_STATUS_READ_ERROR) - eof++; -#endif - } - - /* check for error in read loop */ - if (!eof) - { - free(data); - return cairo_image_surface_create(CAIRO_FORMAT_INVALID, 0, 0); - } - - /* call jpeg decompression and return surface */ - sfc = cairo_image_surface_create_from_jpeg_mem(data, len); - if (cairo_surface_status(sfc) != CAIRO_STATUS_SUCCESS) - free(data); - - return sfc; -} - - -#ifdef CAIRO_JPEG_USE_FSTAT -/*! This function reads an JPEG image from a file an creates a Cairo image - * surface. Internally the filesize is determined with fstat(2) and then the - * whole data is read at once. - * @param filename Pointer to filename of JPEG file. - * @return Returns a pointer to a cairo_surface_t structure. It should be - * checked with cairo_surface_status() for errors. - * @note If the returned surface is invalid you can use errno to determine - * further reasons. Errno is set according to fopen(3) and malloc(3). If you - * intend to check errno you shall set it to 0 before calling this function - * because it does not modify errno itself. - */ -cairo_surface_t *cairo_image_surface_create_from_jpeg(const char *filename) -{ - void *data; - int infile; - struct stat stat; - int s; - - /* open input file */ - if ((infile = open(filename, O_RDONLY)) == -1) - return cairo_image_surface_create(CAIRO_FORMAT_INVALID, 0, 0); - - /* get stat structure for file size */ - if (fstat(infile, &stat) == -1) - return cairo_image_surface_create(CAIRO_FORMAT_INVALID, 0, 0); - - /* allocate memory */ - if ((data = malloc(stat.st_size)) == NULL) - return cairo_image_surface_create(CAIRO_FORMAT_INVALID, 0, 0); - - /* read data */ - s = (int)read(infile, data, stat.st_size); - if ( s < stat.st_size) - return cairo_image_surface_create(CAIRO_FORMAT_INVALID, 0, 0); - - close(infile); - - return cairo_image_surface_create_from_jpeg_mem(data, stat.st_size); -} - -#else - - -/*! This is the read function which is called by - * cairo_image_surface_create_from_jpeg_stream() (non-fstat-version below). It - * is not exported. - */ -#ifdef USE_CAIRO_READ_FUNC_LEN_T -static ssize_t cj_read(void *closure, unsigned char *data, unsigned int length) -{ - return read((intptr_t) closure, data, length); -} -#else -static cairo_status_t cj_read(void *closure, unsigned char *data, unsigned int length) -{ - return read((intptr_t) closure, data, length) < length ? CAIRO_STATUS_READ_ERROR : CAIRO_STATUS_SUCCESS; -} -#endif - - -/*! This function reads an JPEG image from a file an creates a Cairo image - * surface. Internally the function calls - * cairo_image_surface_create_from_jpeg_stream() to actually read the data. - * @param filename Pointer to filename of JPEG file. - * @return Returns a pointer to a cairo_surface_t structure. It should be - * checked with cairo_surface_status() for errors. - * @note If the returned surface is invalid you can use errno to determine - * further reasons. Errno is set according to fopen(3) and malloc(3). If you - * intend to check errno you shall set it to 0 before calling this function - * because it does not modify errno itself. - */ -cairo_surface_t *cairo_image_surface_create_from_jpeg(const char *filename) -{ - cairo_surface_t *sfc; - int infile; - - /* open input file */ - if ((infile = open(filename, O_RDONLY)) == -1) - return cairo_image_surface_create(CAIRO_FORMAT_INVALID, 0, 0); - - /* call stream loading function */ - sfc = cairo_image_surface_create_from_jpeg_stream(cj_read, (void*)(intptr_t) infile); - close(infile); - - return sfc; -} - -#endif - - -#ifdef CAIRO_JPEG_MAIN -#include -#include - -int strrcasecmp(const char *s1, const char *s2) -{ - int off = (int) strlen(s1) - (int) strlen(s2); /* typecast size_t to int because size_t typically is unsigned */ - return strcasecmp(s1 + (off < 0 ? 0 : off), s2); -} - -/*! Main routine, only for testing. #undef CAIRO_JPEG_MAIN or simply delete - * this part if you link this file to your own program. - */ -int main(int argc, char **argv) -{ - cairo_surface_t *sfc; - -#ifndef CAIRO_JPEG_TEST_SIMILAR - if (argc < 3) - { - fprintf(stderr, "usage: %s \n", argv[0]); - return 1; - } - - /* test input file type and read file */ - if (!strrcasecmp(argv[1], ".png")) - { - /* read PNG file */ - sfc = cairo_image_surface_create_from_png(argv[1]); - } - else if (!strrcasecmp(argv[1], ".jpg")) - { - /* read JPEG file */ - sfc = cairo_image_surface_create_from_jpeg(argv[1]); - } - else - { - fprintf(stderr, "source file is neither JPG nor PNG\n"); - return 1; - } - - /* check surface status */ - if (cairo_surface_status(sfc) != CAIRO_STATUS_SUCCESS) - { - fprintf(stderr, "error loading image: %s", cairo_status_to_string(cairo_surface_status(sfc))); - return 2; - } - - /* test output file type and write file */ - if (!strrcasecmp(argv[2], ".png")) - { - /* write PNG file */ - cairo_surface_write_to_png(sfc, argv[2]); - } - else if (!strrcasecmp(argv[2], ".jpg")) - { - /* write JPEG file */ - cairo_image_surface_write_to_jpeg(sfc, argv[2], 90); - } - else - { - fprintf(stderr, "destination file is neither JPG nor PNG\n"); - return 1; - } - - cairo_surface_destroy(sfc); - -#else - sfc = cairo_pdf_surface_create("xyz.pdf", 595.276, 841.890); - - cairo_t *ctx = cairo_create(sfc); - cairo_set_source_rgb(ctx, 1, 1, 1); - cairo_paint(ctx); - cairo_move_to(ctx, 100, 100); - cairo_set_source_rgb(ctx, 1, 0, 0); - cairo_set_line_width(ctx, 3); - cairo_line_to(ctx, 400, 400); - cairo_stroke(ctx); - cairo_destroy(ctx); - - cairo_image_surface_write_to_jpeg(sfc, "xyz.jpg", 90); - cairo_surface_destroy(sfc); -#endif - - return 0; -} - -#endif -#endif /* HAS_LIBJPEG && HAS_CAIRO */ -typedef int make_iso_compilers_happy; /* to avoid empty translation unit */ +/* Copyright 2018 Bernhard R. Fischer, 4096R/8E24F29D + * + * This file is part of Cairo_JPG. + * + * Cairo_JPG is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Cairo_JPG 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Cairo_JPG. If not, see . + */ + +/*! \file cairo_jpg.c + * This file contains two functions for reading and writing JPEG files from + * and to Cairo image surfaces. It uses the functions from the libjpeg. + * Most of the code is directly derived from the online example at + * http://libjpeg-turbo.virtualgl.org/Documentation/Documentation + * + * All prototypes are defined in cairo_jpg.h All functions and their parameters + * and return values are described below directly at the functions. You may + * also have a look at the preprocessor macros defined below. + * + * To compile this code you need to have installed the packages libcairo2-dev + * and libjpeg-dev. Compile with the following to create an object file to link + * with your code: + * gcc -std=c99 -Wall -c `pkg-config cairo libjpeg --cflags --libs` cairo_jpg.c + * Use the following command to include the main() function and create an + * executable for testing of this code: + * gcc -std=c99 -Wall -o cairo_jpg -DCAIRO_JPEG_MAIN `pkg-config cairo libjpeg --cflags --libs` cairo_jpg.c + * + * @author Bernhard R. Fischer, 4096R/8E24F29D bf@abenteuerland.at + * @version 2020/01/18 + * @license LGPL3. + */ + +#ifdef __unix__ +#include "../config.h" +#else +#include "../XSchemWin/config.h" +#endif +#if defined(HAS_LIBJPEG) && defined(HAS_CAIRO) +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include +#include +#include +#include +#include "unistd.h" +#include +#include + +#include "cairo_jpg.h" + +/*! Macro to activate main() function. This is only used for testing. Comment + * it out (#undef) if you link this file to your own program. + */ + +/* #define CAIRO_JPEG_MAIN */ + +/*! Define this to use an alternate implementation of + * cairo_image_surface_create_from_jpeg() which fstat(3)s the file before + * reading (see below). For huge files this /may/ be slightly faster. + */ +#undef CAIRO_JPEG_USE_FSTAT + +/*! This is the read block size for the stream reader + * cairo_image_surface_create_from_jpeg_stream(). + */ +#ifdef USE_CAIRO_READ_FUNC_LEN_T +#define CAIRO_JPEG_IO_BLOCK_SIZE 4096 +#else +/*! Block size has to be one if cairo_read_func_t is in use because of the lack + * to detect EOF (truncated reads). + */ +#define CAIRO_JPEG_IO_BLOCK_SIZE 1 +/*! In case of original cairo_read_func_t is used fstat() should be used for + * performance reasons (see CAIRO_JPEG_USE_FSTAT above). + */ +#define CAIRO_JPEG_USE_FSTAT +#endif + +/*! Define this to test jpeg creation with non-image surfaces. This is only for + * testing and is to be used together with CAIRO_JPEG_MAIN. + */ +#undef CAIRO_JPEG_TEST_SIMILAR +#if defined(CAIRO_JPEG_TEST_SIMILAR) && defined(CAIRO_JPEG_MAIN) +#include +#endif + + +#ifndef LIBJPEG_TURBO_VERSION +/*! This function makes a covnersion for "odd" pixel sizes which typically is a + * conversion from a 3-byte to a 4-byte (or more) pixel size or vice versa. + * The conversion is done from the source buffer src to the destination buffer + * dst. The caller MUST ensure that src and dst have the correct memory size. + * This is dw * num for dst and sw * num for src. src and dst may point to the + * same memory address. + * @param dst Pointer to destination buffer. + * @param dw Pixel width (in bytes) of pixels in destination buffer, dw >= 3. + * @param src Pointer to source buffer. + * @param sw Pixel width (in bytes) of pixels in source buffer, sw >= 3. + * @param num Number of pixels to convert, num >= 1; + */ +static void pix_conv(unsigned char *dst, int dw, const unsigned char *src, int sw, int num) +{ + int si, di; + + /* safety check */ + if (dw < 3 || sw < 3 || dst == NULL || src == NULL) + return; + + num--; + for (si = num * sw, di = num * dw; si >= 0; si -= sw, di -= dw) + { +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + dst[di + 2] = src[si ]; + dst[di + 1] = src[si + 1]; + dst[di + 0] = src[si + 2]; +#else + /* FIXME: This is untested, it may be wrong. */ + dst[di - 3] = src[si - 3]; + dst[di - 2] = src[si - 2]; + dst[di - 1] = src[si - 1]; +#endif + } +} +#endif + + +/*! This function creates a JPEG file in memory from a Cairo image surface. + * @param sfc Pointer to a Cairo surface. It should be an image surface of + * either CAIRO_FORMAT_ARGB32 or CAIRO_FORMAT_RGB24. Other formats are + * converted to CAIRO_FORMAT_RGB24 before compression. + * Please note that this may give unexpected results because JPEG does not + * support transparency. Thus, default background color is used to replace + * transparent regions. The default background color is black if not specified + * explicitly. Thus converting e.g. PDF surfaces without having any specific + * background color set will apear with black background and not white as you + * might expect. In such cases it is suggested to manually convert the surface + * to RGB24 before calling this function. + * @param data Pointer to a memory pointer. This parameter receives a pointer + * to the memory area where the final JPEG data is found in memory. This + * function reserves the memory properly and it has to be freed by the caller + * with free(3). + * @param len Pointer to a variable of type size_t which will receive the final + * lenght of the memory buffer. + * @param quality Compression quality, 0-100. + * @return On success the function returns CAIRO_STATUS_SUCCESS. In case of + * error CAIRO_STATUS_INVALID_FORMAT is returned. + */ +cairo_status_t cairo_image_surface_write_to_jpeg_mem(cairo_surface_t *sfc, unsigned char **data, size_t *len, int quality) +{ + struct jpeg_compress_struct cinfo; + struct jpeg_error_mgr jerr; + JSAMPROW row_pointer[1]; + cairo_surface_t *other = NULL; + cairo_t *ctx; + + /* check valid input format (must be IMAGE_SURFACE && (ARGB32 || RGB24)) */ + if (cairo_surface_get_type(sfc) != CAIRO_SURFACE_TYPE_IMAGE || + (cairo_image_surface_get_format(sfc) != CAIRO_FORMAT_ARGB32 && + cairo_image_surface_get_format(sfc) != CAIRO_FORMAT_RGB24)) + { + /* create a similar surface with a proper format if supplied input format */ + /* does not fulfill the requirements */ + double x1, y1, x2, y2; + other = sfc; + ctx = cairo_create(other); + /* get extents of original surface */ + cairo_clip_extents(ctx, &x1, &y1, &x2, &y2); + cairo_destroy(ctx); + + /* create new image surface */ + sfc = cairo_surface_create_similar_image(other, CAIRO_FORMAT_RGB24, (int)(x2 - x1), (int)(y2 - y1)); + if (cairo_surface_status(sfc) != CAIRO_STATUS_SUCCESS) + return CAIRO_STATUS_INVALID_FORMAT; + + /* paint original surface to new surface */ + ctx = cairo_create(sfc); + cairo_set_source_surface(ctx, other, 0, 0); + cairo_paint(ctx); + cairo_destroy(ctx); + } + + /* finish queued drawing operations */ + cairo_surface_flush(sfc); + + /* init jpeg compression structures */ + cinfo.err = jpeg_std_error(&jerr); + jpeg_create_compress(&cinfo); + + /* set compression parameters */ + jpeg_mem_dest(&cinfo, data, len); + cinfo.image_width = cairo_image_surface_get_width(sfc); + cinfo.image_height = cairo_image_surface_get_height(sfc); +#ifdef LIBJPEG_TURBO_VERSION +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + /* cinfo.in_color_space = JCS_EXT_BGRX; */ + cinfo.in_color_space = cairo_image_surface_get_format(sfc) == CAIRO_FORMAT_ARGB32 ? JCS_EXT_BGRA : JCS_EXT_BGRX; +#else + /* cinfo.in_color_space = JCS_EXT_XRGB; */ + cinfo.in_color_space = cairo_image_surface_get_format(sfc) == CAIRO_FORMAT_ARGB32 ? JCS_EXT_ARGB : JCS_EXT_XRGB; +#endif + cinfo.input_components = 4; +#else + cinfo.in_color_space = JCS_RGB; + cinfo.input_components = 3; +#endif + jpeg_set_defaults(&cinfo); + jpeg_set_quality(&cinfo, quality, TRUE); + + /* start compressor */ + jpeg_start_compress(&cinfo, TRUE); + + /* loop over all lines and compress */ + while (cinfo.next_scanline < cinfo.image_height) + { +#ifdef LIBJPEG_TURBO_VERSION + row_pointer[0] = cairo_image_surface_get_data(sfc) + (cinfo.next_scanline + * cairo_image_surface_get_stride(sfc)); +#else + unsigned char* row_buf = malloc(3 * cinfo.image_width); + /* unsigned char row_buf[3 * cinfo.image_width]; */ + pix_conv(row_buf, 3, cairo_image_surface_get_data(sfc) + + (cinfo.next_scanline * cairo_image_surface_get_stride(sfc)), 4, cinfo.image_width); + row_pointer[0] = row_buf; +#endif + (void) jpeg_write_scanlines(&cinfo, row_pointer, 1); + } + + /* finalize and close everything */ + jpeg_finish_compress(&cinfo); + jpeg_destroy_compress(&cinfo); + + /* destroy temporary image surface (if available) */ + if (other != NULL) + cairo_surface_destroy(sfc); + + return CAIRO_STATUS_SUCCESS; +} + + +/*! This is the internal write function which is called by + * cairo_image_surface_write_to_jpeg(). It is not exported. + */ +static cairo_status_t cj_write(void *closure, const unsigned char *data, unsigned int length) +{ + return write((int)(intptr_t) closure, data, length) < length ? + CAIRO_STATUS_WRITE_ERROR : CAIRO_STATUS_SUCCESS; +} + + +/*! This function writes JPEG file data from a Cairo image surface by using the + * user-supplied stream writer function write_func(). + * @param sfc Pointer to a Cairo *image* surface. Its format must either be + * CAIRO_FORMAT_ARGB32 or CAIRO_FORMAT_RGB24. Other formats are not supported + * by this function, yet. + * @param write_func Function pointer to a function which is actually writing + * the data. + * @param closure Pointer to user-supplied variable which is directly passed to + * write_func(). + * @param quality Compression quality, 0-100. + * @return This function calles cairo_image_surface_write_to_jpeg_mem() and + * returns its return value. + */ +cairo_status_t cairo_image_surface_write_to_jpeg_stream(cairo_surface_t *sfc, cairo_write_func_t write_func, void *closure, int quality) +{ + cairo_status_t e; + unsigned char *data = NULL; + size_t len = 0; + + /* create JPEG data in memory from surface */ + if ((e = cairo_image_surface_write_to_jpeg_mem(sfc, &data, &len, quality)) != CAIRO_STATUS_SUCCESS) + return e; + + /* write whole memory block with stream function */ + e = write_func(closure, data, (unsigned int)len); + + /* free JPEG memory again and return the return value */ + free(data); + return e; + +} + + +/*! This function creates a JPEG file from a Cairo image surface. + * @param sfc Pointer to a Cairo *image* surface. Its format must either be + * CAIRO_FORMAT_ARGB32 or CAIRO_FORMAT_RGB24. Other formats are not supported + * by this function, yet. + * @param filename Pointer to the filename. + * @param quality Compression quality, 0-100. + * @return In case of success CAIRO_STATUS_SUCCESS is returned. If an error + * occured while opening/creating the file CAIRO_STATUS_DEVICE_ERROR is + * returned. The error can be tracked down by inspecting errno(3). The function + * internally calles cairo_image_surface_write_to_jpeg_stream() and returnes + * its return value respectively (see there). + */ +cairo_status_t cairo_image_surface_write_to_jpeg(cairo_surface_t *sfc, const char *filename, int quality) +{ + cairo_status_t e; + int outfile; + + /* Open/create new file */ + if ((outfile = open(filename, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) == -1) + return CAIRO_STATUS_DEVICE_ERROR; + + /* write surface to file */ + e = cairo_image_surface_write_to_jpeg_stream(sfc, cj_write, (void*)(intptr_t) outfile, quality); + + /* close file again and return */ + close(outfile); + return e; +} + + + +/*! This function decompresses a JPEG image from a memory buffer and creates a + * Cairo image surface. + * @param data Pointer to JPEG data (i.e. the full contents of a JPEG file read + * into this buffer). + * @param len Length of buffer in bytes. + * @return Returns a pointer to a cairo_surface_t structure. It should be + * checked with cairo_surface_status() for errors. + */ +cairo_surface_t *cairo_image_surface_create_from_jpeg_mem(void *data, size_t len) +{ + struct jpeg_decompress_struct cinfo; + struct jpeg_error_mgr jerr; + JSAMPROW row_pointer[1]; + cairo_surface_t *sfc; + + /* initialize jpeg decompression structures */ + cinfo.err = jpeg_std_error(&jerr); + jpeg_create_decompress(&cinfo); + jpeg_mem_src(&cinfo, data, len); + (void) jpeg_read_header(&cinfo, TRUE); + +#ifdef LIBJPEG_TURBO_VERSION +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + cinfo.out_color_space = JCS_EXT_BGRA; +#else + cinfo.out_color_space = JCS_EXT_ARGB; +#endif +#else + cinfo.out_color_space = JCS_RGB; +#endif + + /* start decompressor */ + (void) jpeg_start_decompress(&cinfo); + + /* create Cairo image surface */ + sfc = cairo_image_surface_create(CAIRO_FORMAT_RGB24, cinfo.output_width, cinfo.output_height); + if (cairo_surface_status(sfc) != CAIRO_STATUS_SUCCESS) + { + jpeg_destroy_decompress(&cinfo); + return sfc; + } + + /* loop over all scanlines and fill Cairo image surface */ + while (cinfo.output_scanline < cinfo.output_height) + { + unsigned char *row_address = cairo_image_surface_get_data(sfc) + + (cinfo.output_scanline * cairo_image_surface_get_stride(sfc)); + row_pointer[0] = row_address; + (void) jpeg_read_scanlines(&cinfo, row_pointer, 1); +#ifndef LIBJPEG_TURBO_VERSION + pix_conv(row_address, 4, row_address, 3, cinfo.output_width); +#endif + } + + /* finish and close everything */ + cairo_surface_mark_dirty(sfc); + (void) jpeg_finish_decompress(&cinfo); + jpeg_destroy_decompress(&cinfo); + + /* set jpeg mime data */ + cairo_surface_set_mime_data(sfc, CAIRO_MIME_TYPE_JPEG, data, len, free, data); + + return sfc; +} + + +/*! This function reads a JPEG image from a stream and creates a Cairo image + * surface. + * @param read_func Pointer to function which reads data. + * @param closure Pointer which is passed to read_func(). + * @return Returns a pointer to a cairo_surface_t structure. It should be + * checked with cairo_surface_status() for errors. + * @note If the surface returned is invalid you can use errno(3) to determine + * further reasons. Errno is set according to realloc(3). If you + * intend to check errno you shall set it to 0 before calling this function + * because it modifies errno only in case of an error. + */ +#ifdef USE_CAIRO_READ_FUNC_LEN_T +cairo_surface_t *cairo_image_surface_create_from_jpeg_stream(cairo_read_func_len_t read_func, void *closure) +#else +cairo_surface_t *cairo_image_surface_create_from_jpeg_stream(cairo_read_func_t read_func, void *closure) +#endif +{ + cairo_surface_t *sfc; + unsigned char *data, *tmp; + ssize_t len, rlen; + int eof = 0; + + /* read all data into memory buffer in blocks of CAIRO_JPEG_IO_BLOCK_SIZE */ + for (len = 0, data = NULL; !eof; len += rlen) + { + /* grow memory buffer and check for error */ + if ((tmp = realloc(data, len + CAIRO_JPEG_IO_BLOCK_SIZE)) == NULL) + break; + data = tmp; + + /* read bytes into buffer and check for error */ + rlen = read_func(closure, data + len, CAIRO_JPEG_IO_BLOCK_SIZE); +#ifdef USE_CAIRO_READ_FUNC_LEN_T + /* check for error */ + if (rlen == -1) + break; + + /* check if EOF occured */ + if (rlen < CAIRO_JPEG_IO_BLOCK_SIZE) + eof++; +#else + /* check for error */ + if (rlen == CAIRO_STATUS_READ_ERROR) + eof++; +#endif + } + + /* check for error in read loop */ + if (!eof) + { + free(data); + return cairo_image_surface_create(CAIRO_FORMAT_INVALID, 0, 0); + } + + /* call jpeg decompression and return surface */ + sfc = cairo_image_surface_create_from_jpeg_mem(data, len); + if (cairo_surface_status(sfc) != CAIRO_STATUS_SUCCESS) + free(data); + + return sfc; +} + + +#ifdef CAIRO_JPEG_USE_FSTAT +/*! This function reads an JPEG image from a file an creates a Cairo image + * surface. Internally the filesize is determined with fstat(2) and then the + * whole data is read at once. + * @param filename Pointer to filename of JPEG file. + * @return Returns a pointer to a cairo_surface_t structure. It should be + * checked with cairo_surface_status() for errors. + * @note If the returned surface is invalid you can use errno to determine + * further reasons. Errno is set according to fopen(3) and malloc(3). If you + * intend to check errno you shall set it to 0 before calling this function + * because it does not modify errno itself. + */ +cairo_surface_t *cairo_image_surface_create_from_jpeg(const char *filename) +{ + void *data; + int infile; + struct stat stat; + int s; + + /* open input file */ + if ((infile = open(filename, O_RDONLY)) == -1) + return cairo_image_surface_create(CAIRO_FORMAT_INVALID, 0, 0); + + /* get stat structure for file size */ + if (fstat(infile, &stat) == -1) + return cairo_image_surface_create(CAIRO_FORMAT_INVALID, 0, 0); + + /* allocate memory */ + if ((data = malloc(stat.st_size)) == NULL) + return cairo_image_surface_create(CAIRO_FORMAT_INVALID, 0, 0); + + /* read data */ + s = (int)read(infile, data, stat.st_size); + if ( s < stat.st_size) + return cairo_image_surface_create(CAIRO_FORMAT_INVALID, 0, 0); + + close(infile); + + return cairo_image_surface_create_from_jpeg_mem(data, stat.st_size); +} + +#else + + +/*! This is the read function which is called by + * cairo_image_surface_create_from_jpeg_stream() (non-fstat-version below). It + * is not exported. + */ +#ifdef USE_CAIRO_READ_FUNC_LEN_T +static ssize_t cj_read(void *closure, unsigned char *data, unsigned int length) +{ + return read((intptr_t) closure, data, length); +} +#else +static cairo_status_t cj_read(void *closure, unsigned char *data, unsigned int length) +{ + return read((intptr_t) closure, data, length) < length ? CAIRO_STATUS_READ_ERROR : CAIRO_STATUS_SUCCESS; +} +#endif + + +/*! This function reads an JPEG image from a file an creates a Cairo image + * surface. Internally the function calls + * cairo_image_surface_create_from_jpeg_stream() to actually read the data. + * @param filename Pointer to filename of JPEG file. + * @return Returns a pointer to a cairo_surface_t structure. It should be + * checked with cairo_surface_status() for errors. + * @note If the returned surface is invalid you can use errno to determine + * further reasons. Errno is set according to fopen(3) and malloc(3). If you + * intend to check errno you shall set it to 0 before calling this function + * because it does not modify errno itself. + */ +cairo_surface_t *cairo_image_surface_create_from_jpeg(const char *filename) +{ + cairo_surface_t *sfc; + int infile; + + /* open input file */ + if ((infile = open(filename, O_RDONLY)) == -1) + return cairo_image_surface_create(CAIRO_FORMAT_INVALID, 0, 0); + + /* call stream loading function */ + sfc = cairo_image_surface_create_from_jpeg_stream(cj_read, (void*)(intptr_t) infile); + close(infile); + + return sfc; +} + +#endif + + +#ifdef CAIRO_JPEG_MAIN +#include +#include + +int strrcasecmp(const char *s1, const char *s2) +{ + int off = (int) strlen(s1) - (int) strlen(s2); /* typecast size_t to int because size_t typically is unsigned */ + return strcasecmp(s1 + (off < 0 ? 0 : off), s2); +} + +/*! Main routine, only for testing. #undef CAIRO_JPEG_MAIN or simply delete + * this part if you link this file to your own program. + */ +int main(int argc, char **argv) +{ + cairo_surface_t *sfc; + +#ifndef CAIRO_JPEG_TEST_SIMILAR + if (argc < 3) + { + fprintf(stderr, "usage: %s \n", argv[0]); + return 1; + } + + /* test input file type and read file */ + if (!strrcasecmp(argv[1], ".png")) + { + /* read PNG file */ + sfc = cairo_image_surface_create_from_png(argv[1]); + } + else if (!strrcasecmp(argv[1], ".jpg")) + { + /* read JPEG file */ + sfc = cairo_image_surface_create_from_jpeg(argv[1]); + } + else + { + fprintf(stderr, "source file is neither JPG nor PNG\n"); + return 1; + } + + /* check surface status */ + if (cairo_surface_status(sfc) != CAIRO_STATUS_SUCCESS) + { + fprintf(stderr, "error loading image: %s", cairo_status_to_string(cairo_surface_status(sfc))); + return 2; + } + + /* test output file type and write file */ + if (!strrcasecmp(argv[2], ".png")) + { + /* write PNG file */ + cairo_surface_write_to_png(sfc, argv[2]); + } + else if (!strrcasecmp(argv[2], ".jpg")) + { + /* write JPEG file */ + cairo_image_surface_write_to_jpeg(sfc, argv[2], 90); + } + else + { + fprintf(stderr, "destination file is neither JPG nor PNG\n"); + return 1; + } + + cairo_surface_destroy(sfc); + +#else + sfc = cairo_pdf_surface_create("xyz.pdf", 595.276, 841.890); + + cairo_t *ctx = cairo_create(sfc); + cairo_set_source_rgb(ctx, 1, 1, 1); + cairo_paint(ctx); + cairo_move_to(ctx, 100, 100); + cairo_set_source_rgb(ctx, 1, 0, 0); + cairo_set_line_width(ctx, 3); + cairo_line_to(ctx, 400, 400); + cairo_stroke(ctx); + cairo_destroy(ctx); + + cairo_image_surface_write_to_jpeg(sfc, "xyz.jpg", 90); + cairo_surface_destroy(sfc); +#endif + + return 0; +} + +#endif +#endif /* HAS_LIBJPEG && HAS_CAIRO */ +typedef int make_iso_compilers_happy; /* to avoid empty translation unit */ diff --git a/xschem_library/examples/mos_power_ampli.sch b/xschem_library/examples/mos_power_ampli.sch index bc113808..38ba77e5 100644 --- a/xschem_library/examples/mos_power_ampli.sch +++ b/xschem_library/examples/mos_power_ampli.sch @@ -22,11 +22,9 @@ divx=8 subdivx=1 dataset=0 unitx=m - - color=7 node=tcleval($\{path\}outi) -} +jpeg_quality=30} B 2 960 -980 1094 -893 {flags=image alpha=0.7 image_data=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} B 2 1520 -830 2440 -530 {flags=graph @@ -40,13 +38,9 @@ divx=8 subdivx=9 dataset=0 unitx=m - - - color="8 7" -node="tcleval(\\"Xm1 power;vpp $\{path\}outi - i(v.$\{path\}vu) *\\" -\\"Average;vpp $\{path\}outi - i(v.$\{path\}vu) * 200u ravg()\\")" -} +node=tcleval($\{path\}outi) +jpeg_quality=30} B 2 1520 -1130 2440 -830 {flags=graph y1=-0.19 y2=160 @@ -58,11 +52,9 @@ divx=8 subdivx=9 dataset=0 unitx=m - color="8 7" -node="tcleval(\\"Xm2 Power;$\{path\}outi vnn - i(v.$\{path\}vd) *\\" -\\"Average;$\{path\}outi vnn - i(v.$\{path\}vd) * 200u ravg()\\")" -} +node=tcleval($\{path\}outi) +jpeg_quality=30} B 2 960 -1050 1094 -987 {flags=image alpha=0.7 image=/home/schippes/x/3.png diff --git a/xschem_library/rom8k/rom2_ctrl.sch b/xschem_library/rom8k/rom2_ctrl.sch index c5451deb..c7c5036c 100644 --- a/xschem_library/rom8k/rom2_ctrl.sch +++ b/xschem_library/rom8k/rom2_ctrl.sch @@ -1,4 +1,5 @@ -v {xschem version=3.0.0 file_version=1.2 } +v {xschem version=3.1.0 file_version=1.2 +} G {} K {} V {} @@ -18,7 +19,8 @@ xctrl.ldprechref" color="12 11" digital=0 ypos1=-0.0691204 -ypos2=0.68559} +ypos2=0.68559 +jpeg_quality=30} B 2 580 -280 1200 -140 {flags=graph y1 = 0 y2 = 1.6 @@ -33,7 +35,8 @@ xctrl.ldcpb" color="12 11" digital=0 ypos1=0.071147 -ypos2=1.0465} +ypos2=1.0465 +jpeg_quality=30} B 2 580 -400 1200 -280 {flags=graph y1 = 0 y2 = 1.6 @@ -50,7 +53,8 @@ xctrl.ldoutib" color="12 5 11 8" digital=1 ypos1=0.1572 -ypos2=0.829851} +ypos2=0.829851 +jpeg_quality=30} N 360 -670 500 -670 {lab=LDCPB} N 240 -760 250 -760 {lab=LDCPB} N 240 -760 240 -670 {lab=LDCPB} diff --git a/xschem_library/rom8k/rom2_sa.sch b/xschem_library/rom8k/rom2_sa.sch index f58bee07..2e76e7ac 100644 --- a/xschem_library/rom8k/rom2_sa.sch +++ b/xschem_library/rom8k/rom2_sa.sch @@ -15,7 +15,8 @@ divx=8 node="tcleval($\{path\}ldqi $\{path\}ldqib $\{path\}ldsali)" -color="9 6 7"} +color="9 6 7" +jpeg_quality=30} B 2 380 -940 1060 -830 {flags=graph y1 = 0 y2 = 2 @@ -25,7 +26,8 @@ x2=3.4e-07 divx=8 node="v(ldcp) v(ldprech)" -color="12 10"} +color="12 10" +jpeg_quality=30} B 2 380 -650 1060 -510 {flags=graph y1 = 0 y2 = 2 @@ -36,7 +38,8 @@ divx=8 node="tcleval($\{path\}ldqiii $\{path\}ldqii $\{path\}ldsali)" -color="6 8 7"} +color="6 8 7" +jpeg_quality=30} T {Was: 60/24} 1420 -310 0 0 0.4 0.4 {} T {was: LDCP_B} 510 -410 0 0 0.4 0.4 {} From d7ddb17a507d34fbdf1b18048c4197a22949b693 Mon Sep 17 00:00:00 2001 From: stefan schippers Date: Sun, 22 Jan 2023 00:21:46 +0100 Subject: [PATCH 2/2] revert and fix regression (graphical artifacts due to wrong change_linewidth() --- src/xinit.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/xinit.c b/src/xinit.c index b81c6c21..09de49f8 100644 --- a/src/xinit.c +++ b/src/xinit.c @@ -1703,8 +1703,7 @@ int new_schematic(const char *what, const char *win_path, const char *fname) void change_linewidth(double w) { - int i, changed = 0, linew; - double oldw = xctx->lw; + int i, linew; /* choose line width automatically based on zoom */ if(w<0. || xctx->lw == -1.0) { @@ -1718,10 +1717,6 @@ void change_linewidth(double w) } else { xctx->lw=w; } - if(xctx->lw != oldw) { - changed = 1; - } - if(!changed) return; if(has_x) { linew = INT_WIDTH(xctx->lw); dbg(1, "Line width = %d\n", linew);