From 54d82e5796115c5f5dc750e7875a28d7cc9d2d4a Mon Sep 17 00:00:00 2001
From: maximiliank <kleinert.max@gmail.com>
Date: Mon, 22 Dec 2014 12:50:20 +0100
Subject: [PATCH] Added vertical alignment options to HPDF_TextRect functions.
Capable of multiple lines.
---
include/hpdf.h | 2 +-
include/hpdf_textlinelist.h | 45 ++++++++++++++++++++++++++
include/hpdf_types.h | 11 ++++---
src/CMakeLists.txt | 1 +
src/hpdf_page_operator.c | 64 +++++++++++++++++++++++++++++++------
src/hpdf_textlinelist.c | 61 +++++++++++++++++++++++++++++++++++
6 files changed, 169 insertions(+), 15 deletions(-)
create mode 100644 include/hpdf_textlinelist.h
create mode 100644 src/hpdf_textlinelist.c
diff --git a/include/hpdf.h b/include/hpdf.h
index 1cf0dd9..2dca446 100644
--- a/include/hpdf.h
+++ b/include/hpdf.h
@@ -1569,7 +1569,7 @@ HPDF_Page_TextRect (HPDF_Page page,
HPDF_REAL right,
HPDF_REAL bottom,
const char *text,
- HPDF_TextAlignment align,
+ HPDF_UINT align,
HPDF_UINT *len);
diff --git a/include/hpdf_textlinelist.h b/include/hpdf_textlinelist.h
new file mode 100644
index 0000000..a99c157
--- /dev/null
+++ b/include/hpdf_textlinelist.h
@@ -0,0 +1,45 @@
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include "hpdf_types.h"
+#include "hpdf_consts.h"
+
+/**
+ * The TextLine struct,
+ * contains item and the pointers that point to previous TextLine/next TextLine.
+ */
+typedef struct TextLine {
+ const char* item;
+ HPDF_UINT len, num_rest;
+ HPDF_BOOL LineBreak;
+ HPDF_REAL rw;
+ struct TextLine* next;
+} TextLine;
+/**
+ * The LinkedList struct, contains the pointers that
+ * point to first TextLine and last TextLine, the size of the LinkedList,
+ * and the function pointers.
+ */
+typedef struct LinkedList {
+ TextLine* head;
+ TextLine* tail;
+ // size of this LinkedList
+ HPDF_UINT size;
+
+ // add item after tail
+ void (*Append) (struct LinkedList*, const char*, HPDF_UINT, HPDF_UINT, HPDF_REAL, HPDF_BOOL);
+
+ // get first item
+ TextLine* (*getFirst) (struct LinkedList*);
+
+ // free allocated memory
+ void (*Delete) (struct LinkedList*);
+
+ // create a TextLine with item
+ TextLine* (*createTextLine) (const char*, HPDF_UINT, HPDF_UINT, HPDF_REAL, HPDF_BOOL);
+} LinkedList;
+
+void Append (LinkedList* _this, const char *str, HPDF_UINT len, HPDF_UINT num_rest, HPDF_REAL rw, HPDF_BOOL LineBreak);
+void Delete (LinkedList* _this);
+LinkedList createLinkedList ();
+TextLine* createTextLine (const char *str, HPDF_UINT len, HPDF_UINT num_rest, HPDF_REAL rw, HPDF_BOOL LineBreak);
diff --git a/include/hpdf_types.h b/include/hpdf_types.h
index a35fe8f..ae6fcb6 100644
--- a/include/hpdf_types.h
+++ b/include/hpdf_types.h
@@ -561,10 +561,13 @@ typedef enum _HPDF_ByteType {
typedef enum _HPDF_TextAlignment {
- HPDF_TALIGN_LEFT = 0,
- HPDF_TALIGN_RIGHT,
- HPDF_TALIGN_CENTER,
- HPDF_TALIGN_JUSTIFY
+ HPDF_TALIGN_LEFT = 0x00,
+ HPDF_TALIGN_RIGHT = 0x02,
+ HPDF_TALIGN_CENTER = 0x04,
+ HPDF_TALIGN_JUSTIFY = 0x08,
+ HPDF_TALIGN_TOP = 0x10,
+ HPDF_TALIGN_BOTTOM = 0x20,
+ HPDF_TALIGN_MIDDLE = 0x40
} HPDF_TextAlignment;
/*----------------------------------------------------------------------------*/
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 9d2a604..d98d5b3 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -65,6 +65,7 @@ set(
hpdf_3dmeasure.c
hpdf_exdata.c
hpdf_encoder_utf.c
+ hpdf_textlinelist.c
)
# =======================================================================
diff --git a/src/hpdf_page_operator.c b/src/hpdf_page_operator.c
index 23f5920..396fadb 100644
--- a/src/hpdf_page_operator.c
+++ b/src/hpdf_page_operator.c
@@ -20,6 +20,8 @@
#include "hpdf_pages.h"
#include "hpdf.h"
+#include "hpdf_textlinelist.h"
+
static const HPDF_Point INIT_POS = {0, 0};
static const HPDF_DashMode INIT_MODE = {{0, 0, 0, 0, 0, 0, 0, 0}, 0, 0};
@@ -2432,7 +2434,7 @@ HPDF_Page_TextRect (HPDF_Page page,
HPDF_REAL right,
HPDF_REAL bottom,
const char *text,
- HPDF_TextAlignment align,
+ HPDF_UINT align,
HPDF_UINT *len
)
{
@@ -2473,17 +2475,15 @@ HPDF_Page_TextRect (HPDF_Page page,
HPDF_Page_SetTextLeading (page, (bbox.top - bbox.bottom) / 1000 *
attr->gstate->font_size);
- top = top - bbox.top / 1000 * attr->gstate->font_size +
- attr->gstate->text_leading;
- bottom = bottom - bbox.bottom / 1000 * attr->gstate->font_size;
-
if (align == HPDF_TALIGN_JUSTIFY) {
save_char_space = attr->gstate->char_space;
attr->gstate->char_space = 0;
}
+ /* Create LinkedList of Text lines */
+ LinkedList list = createLinkedList();
+
for (;;) {
- HPDF_REAL x, y;
HPDF_UINT line_len, tmp_len;
HPDF_REAL rw;
HPDF_BOOL LineBreak;
@@ -2507,6 +2507,48 @@ HPDF_Page_TextRect (HPDF_Page page,
LineBreak = HPDF_TRUE;
}
}
+ list.Append(&list, ptr, tmp_len, num_rest, rw, LineBreak);
+ ptr += line_len;
+ }
+
+ HPDF_REAL total_height = list.size * attr->gstate->text_leading;
+
+ HPDF_REAL correction = bbox.bottom / 1000 * attr->gstate->font_size;
+
+ if ((align & HPDF_TALIGN_MIDDLE) == HPDF_TALIGN_MIDDLE)
+ {
+ HPDF_REAL adjustment = 0.5 * (top - bottom - total_height);
+ top = top - adjustment - correction;
+ bottom = bottom + adjustment - correction;
+ }
+ else if ((align & HPDF_TALIGN_BOTTOM) == HPDF_TALIGN_BOTTOM)
+ {
+ bottom = bottom - correction;
+ top = bottom + total_height;
+ }
+ else // HPDF_TALIGN_TOP or default
+ {
+ top = top - correction;
+ bottom = top - total_height;
+ }
+ // remove vertical alignment flags
+ align &= ~(HPDF_TALIGN_TOP|HPDF_TALIGN_MIDDLE|HPDF_TALIGN_BOTTOM);
+
+
+ TextLine* textline = list.getFirst(&list);
+
+ while (textline != NULL)
+ {
+ HPDF_REAL x, y;
+ HPDF_UINT tmp_len;
+ HPDF_REAL rw;
+ HPDF_BOOL LineBreak;
+
+ const char* _ptr = textline->item;
+ tmp_len = textline->len;
+ num_rest = textline->num_rest;
+ rw = textline->rw;
+ LineBreak = textline->LineBreak;
switch (align) {
@@ -2552,7 +2594,7 @@ HPDF_Page_TextRect (HPDF_Page page,
HPDF_UINT i = 0;
HPDF_UINT num_char = 0;
HPDF_Encoder encoder = ((HPDF_FontAttr)attr->gstate->font->attr)->encoder;
- const char *tmp_ptr = ptr;
+ const char *tmp_ptr = _ptr;
HPDF_Encoder_SetParseText (encoder, &state, (HPDF_BYTE *)tmp_ptr, tmp_len);
while (*tmp_ptr) {
HPDF_ByteType btype = HPDF_Encoder_ByteType (encoder, &state);
@@ -2580,20 +2622,22 @@ HPDF_Page_TextRect (HPDF_Page page,
}
}
- if (InternalShowTextNextLine (page, ptr, tmp_len) != HPDF_OK)
+ if (InternalShowTextNextLine (page, _ptr, tmp_len) != HPDF_OK)
return HPDF_CheckError (page->error);
if (num_rest <= 0)
break;
- if (attr->text_pos.y - attr->gstate->text_leading < bottom) {
+ if (attr->text_pos.y - attr->gstate->text_leading - bottom < -1e-4) {
is_insufficient_space = HPDF_TRUE;
break;
}
- ptr += line_len;
+ textline = textline->next;
}
+ list.Delete(&list);
+
if (char_space_changed && save_char_space != attr->gstate->char_space) {
if ((ret = HPDF_Page_SetCharSpace (page, save_char_space)) != HPDF_OK)
return ret;
diff --git a/src/hpdf_textlinelist.c b/src/hpdf_textlinelist.c
new file mode 100644
index 0000000..c4cea81
--- /dev/null
+++ b/src/hpdf_textlinelist.c
@@ -0,0 +1,61 @@
+#include "hpdf_textlinelist.h"
+/** add item to tail
+ */
+void Append (LinkedList* _this, const char *str, HPDF_UINT len, HPDF_UINT num_rest, HPDF_REAL rw, HPDF_BOOL LineBreak) {
+ TextLine* newTextLine = _this->createTextLine(str, len, num_rest, rw, LineBreak);
+ TextLine* head = _this->head;
+ TextLine* tail = _this->tail;
+ // list is empty
+ if (head == NULL)
+ _this->head = newTextLine;
+ else { // has item(s)
+ TextLine* lastTextLine = tail;
+ if (tail == NULL) // only head TextLine
+ lastTextLine = head;
+ lastTextLine->next = newTextLine;
+ _this->tail = newTextLine;
+ }
+ _this->size++;
+}
+/** get item from head
+ */
+TextLine* getFirst (LinkedList* _this) {
+ return _this->head;
+}
+/** free allocated memory
+ */
+void Delete (LinkedList* _this) {
+ TextLine* tmp;
+ TextLine* textline = _this->head;
+ while( textline != NULL)
+ {
+ tmp = textline->next;
+ free(textline);
+ textline = tmp;
+ }
+}
+/** create a LinkedList
+ */
+LinkedList createLinkedList () {
+ LinkedList list;
+ list.head = NULL;
+ list.tail = NULL;
+ list.size = 0;
+ list.Append = &Append;
+ list.getFirst = &getFirst;
+ list.createTextLine = &createTextLine;
+ list.Delete = &Delete;
+ return list;
+}
+/** create a TextLine
+ */
+TextLine* createTextLine (const char *str, HPDF_UINT len, HPDF_UINT num_rest, HPDF_REAL rw, HPDF_BOOL LineBreak) {
+ TextLine* textline = (TextLine*) malloc (sizeof(TextLine));
+ textline->item = str;
+ textline->len = len;
+ textline->num_rest = num_rest;
+ textline->rw = rw;
+ textline->LineBreak = LineBreak;
+ textline->next = NULL;
+ return textline;
+}
--
2.21.1 (Apple Git-122.3)