class Paragraph(RecordModel): ''' 4.2.1. 문단 헤더 ''' tagid = HWPTAG_PARA_HEADER # 표 54 단 나누기 종류 SplitFlags = Flags(BYTE, 0, 'new_section', 1, 'new_columnsdef', 2, 'new_page', 3, 'new_column') ControlMask = Flags(UINT32, 2, 'unknown1', 11, 'control', 21, 'new_number') Flags = Flags(UINT32, 31, 'unknown', 0, 30, 'chars') def attributes(cls): ''' 표 53 문단 헤더 ''' yield cls.Flags, 'text', yield cls.ControlMask, 'controlmask', yield UINT16, 'parashape_id', yield BYTE, 'style_id', yield cls.SplitFlags, 'split', yield UINT16, 'charshapes', yield UINT16, 'rangetags', yield UINT16, 'linesegs', yield UINT32, 'instance_id', attributes = classmethod(attributes)
class FillImage(Fill): FillImageEnum = Enum(TILE_ALL=0, TILE_HORIZONTAL_TOP=1, TILE_HORIZONTAL_BOTTOM=2, TILE_VERTICAL_LEFT=3, TILE_VERTICAL_RIGHT=4, RESIZE=5, CENTER=6, CENTER_TOP=7, CENTER_BOTTOM=8, LEFT_MIDDLE=9, LEFT_TOP=10, LEFT_BOTTOM=11, RIGHT_MIDDLE=12, RIGHT_TOP=13, RIGHT_BOTTOM=14, NONE=15) FillImageFlags = Flags(BYTE, 0, 16, FillImageEnum, 'fillimage_type') EffectEnum = Enum(REAL_PIC=0, GRAY_SCALE=1, BLACK_WHITE=2, PATTERN8x8=3) EffectFlags = Flags(UINT8, 0, 8, EffectEnum, 'effect_type') def attributes(cls): yield cls.FillImageFlags, 'flags' yield INT8, 'brightness' yield INT8, 'contrast' yield cls.EffectFlags, 'effect' yield UINT16, 'bindata_id' attributes = classmethod(attributes)
def attributes(cls): yield BSTR, 'maintext' yield BSTR, 'subtext' yield Flags(UINT32, 0, 31, cls.Position, 'position'), 'position' yield UINT32, 'fsizeratio' yield UINT32, 'option' yield UINT32, 'stylenumber' yield Flags(UINT32, 0, 31, cls.Align, 'align'), 'align'
class BorderFill(RecordModel): ''' 4.1.5. 테두리/배경 ''' tagid = HWPTAG_BORDER_FILL # 표 19 테두리/배경 속성 BorderFlags = Flags(UINT16, 0, 'effect_3d', 1, 'effect_shadow', 2, 4, 'slash', 5, 6, 'backslash') # 표 23 채우기 정보 FillFlags = Flags(UINT32, 0, 'colorpattern', 1, 'image', 2, 'gradation') def attributes(cls): ''' 표 18 테두리/배경 속성 ''' yield cls.BorderFlags, 'borderflags' yield Border, 'left', yield Border, 'right', yield Border, 'top', yield Border, 'bottom', yield Border, 'diagonal' yield cls.FillFlags, 'fillflags' def fill_colorpattern(context, values): ''' fillflags.fill_colorpattern ''' return values['fillflags'].colorpattern def fill_image(context, values): ''' fillflags.fill_image ''' return values['fillflags'].image def fill_gradation(context, values): ''' fillflags.fill_gradation ''' return values['fillflags'].gradation yield dict(type=FillColorPattern, name='fill_colorpattern', condition=fill_colorpattern) yield dict(type=FillGradation, name='fill_gradation', condition=fill_gradation) yield dict(type=FillImage, name='fill_image', condition=fill_image) yield dict(type=UINT32, name='shape', condition=fill_gradation) yield dict(type=BYTE, name='blur_center', condition=fill_gradation) # 스펙 1.2의 표28 설명과는 달리, # 적어도 5.0.1.7에서, 있는 경우가 있고 없는 경우가 있음 # yield N_ARRAY(UINT32, BYTE), 'extended' # SPEC attributes = classmethod(attributes)
class MSOLEProperty(Struct): TypeFlags = Flags(UINT32, 0, 16, 'code') def attributes(cls): yield cls.TypeFlags, 'type' attributes = classmethod(attributes)
class SectionDef(Control): ''' 4.2.10.1. 구역 정의 ''' chid = CHID.SECD Flags = Flags(UINT32, 0, 'hide_header', 1, 'hide_footer', 2, 'hide_page', 3, 'hide_border', 4, 'hide_background', 5, 'hide_pagenumber', 8, 'show_border_on_first_page_only', 9, 'show_background_on_first_page_only', 16, 18, 'text_direction', 19, 'hide_blank_line', 20, 21, 'pagenum_on_split_section', 22, 'squared_manuscript_paper') def attributes(cls): yield cls.Flags, 'flags', yield HWPUNIT16, 'columnspacing', yield HWPUNIT16, 'grid_vertical', yield HWPUNIT16, 'grid_horizontal', yield HWPUNIT, 'defaultTabStops', yield UINT16, 'numbering_shape_id', yield UINT16, 'starting_pagenum', yield UINT16, 'starting_picturenum', yield UINT16, 'starting_tablenum', yield UINT16, 'starting_equationnum', yield dict(type=UINT32, name='unknown1', version=(5, 0, 1, 7)) yield dict(type=UINT32, name='unknown2', version=(5, 0, 1, 7)) attributes = classmethod(attributes)
class TypedPropertyValue(Struct): ''' [MS-OLEPS] 2.15 TypedPropertyValue ''' def __init__(self, code): self.code = code @classmethod def fromDict(cls, d): return cls(code=d['type'].code) TypeFlags = Flags(UINT32, 0, 16, 'code') def attributes(cls): yield cls.TypeFlags, 'type' attributes = classmethod(attributes) @property def vt_type(self): try: return vt_types[self.code] except KeyError: return None
class CharShape(RecordModel): ''' 4.1.6. 글자 모양 ''' tagid = HWPTAG_CHAR_SHAPE # 표 30 글자 모양 속성 Underline = Enum(NONE=0, UNDERLINE=1, UNKNOWN=2, UPPERLINE=3) Flags = Flags(UINT32, 0, 'italic', 1, 'bold', 2, 3, Underline, 'underline', 4, 7, 'underline_style', 8, 10, 'outline', 11, 13, 'shadow') def attributes(cls): ''' 표 28 글자 모양 ''' yield LanguageStruct('FontFace', WORD), 'font_face', yield (LanguageStruct('LetterWidthExpansion', UINT8), 'letter_width_expansion') yield LanguageStruct('LetterSpacing', INT8), 'letter_spacing' yield LanguageStruct('RelativeSize', INT8), 'relative_size' yield LanguageStruct('Position', INT8), 'position' yield INT32, 'basesize', yield cls.Flags, 'charshapeflags', yield ShadowSpace, 'shadow_space' yield COLORREF, 'text_color', yield COLORREF, 'underline_color', yield COLORREF, 'shade_color', yield COLORREF, 'shadow_color', # yield UINT16, 'borderfill_id', # DIFFSPEC # yield COLORREF, 'strikeoutColor', # DIFFSPEC attributes = classmethod(attributes)
class BorderLine(Struct): ''' 표 81 테두리 선 정보 ''' LineEnd = Enum('round', 'flat') ArrowShape = Enum('none', 'arrow', 'arrow2', 'diamond', 'circle', 'rect', 'diamondfilled', 'disc', 'rectfilled') ArrowSize = Enum('smallest', 'smaller', 'small', 'abitsmall', 'normal', 'abitlarge', 'large', 'larger', 'largest') ''' 표 82 테두리 선 정보 속성 ''' Flags = Flags(UINT32, 0, 5, Border.StrokeEnum, 'stroke', 6, 9, LineEnd, 'line_end', 10, 15, ArrowShape, 'arrow_start', 16, 21, ArrowShape, 'arrow_end', 22, 25, ArrowSize, 'arrow_start_size', 26, 29, ArrowSize, 'arrow_end_size', 30, 'arrow_start_fill', 31, 'arrow_end_fill') def attributes(cls): yield COLORREF, 'color' yield INT32, 'width' yield cls.Flags, 'flags' attributes = classmethod(attributes)
class TableCaption(ListHeader): ''' 표 66 캡션 리스트 ''' parent_model_type = TableControl before_tablebody = False # 표 68 캡션 속성 Position = Enum(LEFT=0, RIGHT=1, TOP=2, BOTTOM=3) Flags = Flags( UINT32, 0, 1, Position, 'position', # 캡션이 긴 경우 테이블 여백 영역까지 확장 2, 'expand_to_margin') def attributes(cls): ''' 표 67 캡션 ''' yield cls.Flags, 'flags', yield HWPUNIT, 'width', yield HWPUNIT16, 'separation', # 캡션과 틀 사이 간격 yield HWPUNIT, 'max_width', # expand_to_margin 고려한 최대 너비 attributes = classmethod(attributes)
class ColumnsDef(Control): ''' 4.2.10.2. 단 정의 ''' chid = CHID.COLD Kind = Enum('normal', 'distribute', 'parallel') Direction = Enum('l2r', 'r2l', 'both') Flags = Flags(UINT16, 0, 1, Kind, 'kind', 2, 9, 'count', 10, 11, Direction, 'direction', 12, 'same_widths') def attributes(cls): yield cls.Flags, 'flags' yield HWPUNIT16, 'spacing' def not_same_widths(context, values): ''' flags.same_widths == 0 ''' return not values['flags'].same_widths def n_entries(member_ref): def n_entries(context, values): n_columns = member_ref(context, values) return n_columns - 1 return n_entries yield dict(name='column0', type=Column0, condition=not_same_widths) yield dict(name='columns', type=X_ARRAY(Column, n_entries(ref_member_flag('flags', 'count'))), condition=not_same_widths) yield UINT16, 'attr2' yield Border, 'splitter' attributes = classmethod(attributes)
class TableBody(RecordModel): ''' 4.2.9.1. 표 개체 ''' tagid = HWPTAG_TABLE # 표 71 표 속성의 속성 Split = Enum(NONE=0, BY_CELL=1, SPLIT=2) Flags = Flags(UINT32, 0, 1, Split, 'split_page', 2, 'repeat_header') def attributes(cls): ''' 표 70 표 개체 속성 ''' yield cls.Flags, 'flags' yield UINT16, 'rows' yield UINT16, 'cols' yield HWPUNIT16, 'cellspacing' # 표 72 안쪽 여백 정보 yield Margin, 'padding' yield dict(type=X_ARRAY(UINT16, ref_member('rows')), name='rowcols') yield UINT16, 'borderfill_id' yield dict(type=N_ARRAY(UINT16, ZoneInfo), name='validZones', version=(5, 0, 0, 7)) attributes = classmethod(attributes)
class ShapeOLE(RecordModel): ''' 4.2.9.5 OLE 개체 ''' tagid = HWPTAG_SHAPE_COMPONENT_OLE Flags = Flags( UINT32, 0, 7, 'dvaspect', 8, 'moniker', # baseline: # 0 means defaut (85%) # 1 means 0% # 101 means 100% 9, 15, 'baseline') @classmethod def attributes(cls): yield cls.Flags, 'flags' yield INT32, 'extent_x' yield INT32, 'extent_y' yield BinStorageId, 'storage_id' yield BorderLine, 'border'
class LineSeg(Struct): Flags = Flags( UINT32, # 0, 'first_in_page', # 1, 'first_in_column', # 16, 'empty', 17, 'line_head', 18, 'line_tail', # 19, 'auto_hyphen', 20, 'indented', 21, 'bullet') def attributes(cls): yield INT32, 'chpos', yield SHWPUNIT, 'y', yield SHWPUNIT, 'height', yield SHWPUNIT, 'height_text', yield SHWPUNIT, 'height_baseline', yield SHWPUNIT, 'space_below', yield SHWPUNIT, 'x', yield SHWPUNIT, 'width' yield cls.Flags, 'lineseg_flags' attributes = classmethod(attributes)
class ListHeader(RecordModel): ''' 4.2.7. 문단 리스트 헤더 ''' __metaclass__ = ListHeaderType tagid = HWPTAG_LIST_HEADER VAlign = Enum(TOP=0, MIDDLE=1, BOTTOM=2) Flags = Flags(UINT32, 0, 2, 'textdirection', 3, 4, 'linebreak', 5, 6, VAlign, 'valign') def attributes(cls): ''' 표 60 문단 리스트 헤더 ''' yield UINT16, 'paragraphs', yield UINT16, 'unknown1', yield cls.Flags, 'listflags', attributes = classmethod(attributes) extension_types = list_header_models def get_extension_key(context, model): ''' (parent model type, after TableBody) ''' if 'parent' in context: context, model = context['parent'] seen_table_body = context.get('seen_table_body', False) return model['type'], seen_table_body get_extension_key = staticmethod(get_extension_key)
class PageDef(RecordModel): tagid = HWPTAG_PAGE_DEF Orientation = Enum(PORTRAIT=0, LANDSCAPE=1) BookBinding = Enum(LEFT=0, RIGHT=1, TOP=2, BOTTOM=3) Flags = Flags(UINT32, 0, Orientation, 'orientation', 1, 2, BookBinding, 'bookbinding') def attributes(cls): yield HWPUNIT, 'width', yield HWPUNIT, 'height', yield HWPUNIT, 'left_offset', yield HWPUNIT, 'right_offset', yield HWPUNIT, 'top_offset', yield HWPUNIT, 'bottom_offset', yield HWPUNIT, 'header_offset', yield HWPUNIT, 'footer_offset', yield HWPUNIT, 'bookbinding_offset', yield cls.Flags, 'attr', # yield UINT32, 'attr', attributes = classmethod(attributes) def getDimension(self): width = HWPUNIT(self.paper_width - self.offsetLeft - self.offsetRight) height = HWPUNIT(self.paper_height - (self.offsetTop + self.offsetHeader) - (self.offsetBottom + self.offsetFooter)) if self.attr.landscape: return (height, width) else: return (width, height) dimension = property(getDimension) def getHeight(self): if self.attr.landscape: width = HWPUNIT(self.paper_width - self.offsetLeft - self.offsetRight) return width else: height = HWPUNIT(self.paper_height - (self.offsetTop + self.offsetHeader) - (self.offsetBottom + self.offsetFooter)) return height height = property(getHeight) def getWidth(self): if self.attr.landscape: height = HWPUNIT(self.paper_height - (self.offsetTop + self.offsetHeader) - (self.offsetBottom + self.offsetFooter)) return height else: width = HWPUNIT(self.paper_width - self.offsetLeft - self.offsetRight) return width width = property(getWidth)
def test_bitfields(self): MyEnum = Enum(a=1, b=2) MyFlags = Flags(UINT32, 0, 1, 'field0', 2, 4, MyEnum, 'field2') bitfields = MyFlags.bitfields f = bitfields['field0'] self.assertEqual((0, 1, int), (f.lsb, f.msb, f.valuetype)) f = bitfields['field2'] self.assertEqual((2, 4, MyEnum), (f.lsb, f.msb, f.valuetype))
class PictureEffect(Struct): ''' 표 103 그림 효과 속성 ''' Flags = Flags(UINT32) @classmethod def attributes(cls): yield cls.Flags, 'flags'
class HeaderFooter(Control): ''' 4.2.10.3. 머리말/꼬리말 ''' Places = Enum(BOTH_PAGES=0, EVEN_PAGE=1, ODD_PAGE=2) Flags = Flags(UINT32, 0, 1, Places, 'places') def attributes(cls): yield cls.Flags, 'flags' attributes = classmethod(attributes)
class PageOddEven(Control): ''' 4.2.10.8 홀/짝수 조정 ''' chid = CHID.PGCT OddEven = Enum(BOTH_PAGES=0, EVEN_PAGE=1, ODD_PAGE=2) Flags = Flags(UINT32, 0, 1, OddEven, 'pages') def attributes(cls): yield cls.Flags, 'flags' attributes = classmethod(attributes)
class NumberingControl(Control): Kind = Enum(PAGE=0, FOOTNOTE=1, ENDNOTE=2, PICTURE=3, TABLE=4, EQUATION=5) Flags = Flags(UINT32, 0, 3, Kind, 'kind', 4, 11, 'footnoteshape', 12, 'superscript') def attributes(cls): yield cls.Flags, 'flags', yield UINT16, 'number', attributes = classmethod(attributes)
class Tab(Struct): Kind = Enum(LEFT=0, RIGHT=1, CENTER=2, FLOAT=3) Flags = Flags(UINT32, 0, 7, Kind, 'kind', 8, 15, 'fill_type') @classmethod def attributes(cls): yield HWPUNIT, 'pos', yield cls.Flags, 'flags'
class PageHide(Control): ''' 4.2.10.7 감추기 ''' chid = CHID.PGHD Flags = Flags(UINT32, 0, 'header', 1, 'footer', 2, 'basepage', 3, 'pageborder', 4, 'pagefill', 5, 'pagenumber') def attributes(cls): yield cls.Flags, 'flags' attributes = classmethod(attributes)
class TabDef(RecordModel): ''' 4.1.7. 탭 정의 ''' tagid = HWPTAG_TAB_DEF ''' 표 32 탭 정의 속성 ''' Flags = Flags(UINT32, 0, 'autotab_left', 1, 'autotab_right') @classmethod def attributes(cls): yield dict(type=cls.Flags, name='flags') yield dict(type=N_ARRAY(UINT32, Tab), name='tabs')
def test_bitfields(self): from hwp5.dataio import UINT32 from hwp5.dataio import Flags from hwp5.dataio import Enum MyEnum = Enum(a=1, b=2) MyFlags = Flags(UINT32, 0, 1, 'field0', 2, 4, MyEnum, 'field2') bitfields = MyFlags.bitfields f = bitfields['field0'] self.assertEquals((0, 1, int), (f.lsb, f.msb, f.valuetype)) f = bitfields['field2'] self.assertEquals((2, 4, MyEnum), (f.lsb, f.msb, f.valuetype))
class FillColorPattern(Fill): ''' 표 23 채우기 정보 ''' PatternTypeEnum = Enum(NONE=255, HORIZONTAL=0, VERTICAL=1, BACKSLASH=2, SLASH=3, GRID=4, CROSS=5) PatternTypeFlags = Flags(UINT32, 0, 7, PatternTypeEnum, 'pattern_type') def attributes(cls): yield COLORREF, 'background_color', yield COLORREF, 'pattern_color', yield cls.PatternTypeFlags, 'pattern_type_flags', attributes = classmethod(attributes)
class RangeTag(Struct): ''' 표 58 문단의 영역 태그 ''' Tag = Flags(UINT32, 0, 23, 'data', 24, 31, 'kind') @classmethod def attributes(cls): yield UINT32, 'start' yield UINT32, 'end' yield cls.Tag, 'tag'
class PageBorderFill(RecordModel): tagid = HWPTAG_PAGE_BORDER_FILL RelativeTo = Enum(BODY=0, PAPER=1) FillArea = Enum(PAPER=0, PAGE=1, BORDER=2) Flags = Flags(UINT32, 0, RelativeTo, 'relative_to', 1, 'include_header', 2, 'include_footer', 3, 4, FillArea, 'fill') def attributes(cls): yield cls.Flags, 'flags' yield Margin, 'margin' yield UINT16, 'borderfill_id' attributes = classmethod(attributes)
class Field(Control): ''' 4.2.10.15 필드 시작 ''' Flags = Flags(UINT32, 0, 'editableInReadOnly', 11, 14, 'visitedType', 15, 'modified') def attributes(cls): yield cls.Flags, 'flags', yield BYTE, 'extra_attr', yield BSTR, 'command', yield UINT32, 'id', attributes = classmethod(attributes)
class FileHeader(Struct): Flags = Flags(UINT32, 0, 'compressed', 1, 'password', 2, 'distributable', 3, 'script', 4, 'drm', 5, 'xmltemplate_storage', 6, 'history', 7, 'cert_signed', 8, 'cert_encrypted', 9, 'cert_signature_extra', 10, 'cert_drm', 11, 'ccl') def attributes(cls): yield BYTES(32), 'signature' yield VERSION, 'version' yield cls.Flags, 'flags' yield BYTES(216), 'reserved' attributes = classmethod(attributes)